Refactor Group Layout selection
This commit is contained in:
parent
f3251d146e
commit
607e91e8cf
|
@ -0,0 +1,42 @@
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { HStack, Icon } from 'soapbox/components/ui';
|
||||||
|
|
||||||
|
enum GroupLayout {
|
||||||
|
LIST = 'LIST',
|
||||||
|
GRID = 'GRID'
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ILayoutButtons {
|
||||||
|
layout: GroupLayout
|
||||||
|
onSelect(layout: GroupLayout): void
|
||||||
|
}
|
||||||
|
|
||||||
|
const LayoutButtons = ({ layout, onSelect }: ILayoutButtons) => (
|
||||||
|
<HStack alignItems='center' space={1}>
|
||||||
|
<button onClick={() => onSelect(GroupLayout.LIST)}>
|
||||||
|
<Icon
|
||||||
|
src={require('@tabler/icons/layout-list.svg')}
|
||||||
|
className={
|
||||||
|
clsx('h-5 w-5 text-gray-600', {
|
||||||
|
'text-primary-600': layout === GroupLayout.LIST,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button onClick={() => onSelect(GroupLayout.GRID)}>
|
||||||
|
<Icon
|
||||||
|
src={require('@tabler/icons/layout-grid.svg')}
|
||||||
|
className={
|
||||||
|
clsx('h-5 w-5 text-gray-600', {
|
||||||
|
'text-primary-600': layout === GroupLayout.GRID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</HStack>
|
||||||
|
);
|
||||||
|
|
||||||
|
export { LayoutButtons as default, GroupLayout };
|
|
@ -3,22 +3,19 @@ import React, { useCallback, useState } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { Components, Virtuoso, VirtuosoGrid } from 'react-virtuoso';
|
import { Components, Virtuoso, VirtuosoGrid } from 'react-virtuoso';
|
||||||
|
|
||||||
import { HStack, Icon, Stack, Text } from 'soapbox/components/ui';
|
import { HStack, Stack, Text } from 'soapbox/components/ui';
|
||||||
import { useGroupSearch } from 'soapbox/hooks/api';
|
import { useGroupSearch } from 'soapbox/hooks/api';
|
||||||
import { Group } from 'soapbox/types/entities';
|
|
||||||
|
|
||||||
import GroupGridItem from '../group-grid-item';
|
import GroupGridItem from '../group-grid-item';
|
||||||
import GroupListItem from '../group-list-item';
|
import GroupListItem from '../group-list-item';
|
||||||
|
import LayoutButtons, { GroupLayout } from '../layout-buttons';
|
||||||
|
|
||||||
|
import type { Group } from 'soapbox/types/entities';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
groupSearchResult: ReturnType<typeof useGroupSearch>
|
groupSearchResult: ReturnType<typeof useGroupSearch>
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Layout {
|
|
||||||
LIST = 'LIST',
|
|
||||||
GRID = 'GRID'
|
|
||||||
}
|
|
||||||
|
|
||||||
const GridList: Components['List'] = React.forwardRef((props, ref) => {
|
const GridList: Components['List'] = React.forwardRef((props, ref) => {
|
||||||
const { context, ...rest } = props;
|
const { context, ...rest } = props;
|
||||||
return <div ref={ref} {...rest} className='flex flex-wrap' />;
|
return <div ref={ref} {...rest} className='flex flex-wrap' />;
|
||||||
|
@ -27,7 +24,7 @@ const GridList: Components['List'] = React.forwardRef((props, ref) => {
|
||||||
export default (props: Props) => {
|
export default (props: Props) => {
|
||||||
const { groupSearchResult } = props;
|
const { groupSearchResult } = props;
|
||||||
|
|
||||||
const [layout, setLayout] = useState<Layout>(Layout.LIST);
|
const [layout, setLayout] = useState<GroupLayout>(GroupLayout.LIST);
|
||||||
|
|
||||||
const { groups, hasNextPage, isFetching, fetchNextPage } = groupSearchResult;
|
const { groups, hasNextPage, isFetching, fetchNextPage } = groupSearchResult;
|
||||||
|
|
||||||
|
@ -65,32 +62,13 @@ export default (props: Props) => {
|
||||||
/>
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<HStack alignItems='center'>
|
<LayoutButtons
|
||||||
<button onClick={() => setLayout(Layout.LIST)}>
|
layout={layout}
|
||||||
<Icon
|
onSelect={(selectedLayout) => setLayout(selectedLayout)}
|
||||||
src={require('@tabler/icons/layout-list.svg')}
|
/>
|
||||||
className={
|
|
||||||
clsx('h-5 w-5 text-gray-600', {
|
|
||||||
'text-primary-600': layout === Layout.LIST,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button onClick={() => setLayout(Layout.GRID)}>
|
|
||||||
<Icon
|
|
||||||
src={require('@tabler/icons/layout-grid.svg')}
|
|
||||||
className={
|
|
||||||
clsx('h-5 w-5 text-gray-600', {
|
|
||||||
'text-primary-600': layout === Layout.GRID,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</HStack>
|
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
{layout === Layout.LIST ? (
|
{layout === GroupLayout.LIST ? (
|
||||||
<Virtuoso
|
<Virtuoso
|
||||||
useWindowScroll
|
useWindowScroll
|
||||||
data={groups}
|
data={groups}
|
||||||
|
|
|
@ -3,11 +3,12 @@ import React, { useCallback, useState } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
import { Components, Virtuoso, VirtuosoGrid } from 'react-virtuoso';
|
import { Components, Virtuoso, VirtuosoGrid } from 'react-virtuoso';
|
||||||
|
|
||||||
import { Column, HStack, Icon } from 'soapbox/components/ui';
|
import { Column } from 'soapbox/components/ui';
|
||||||
import { usePopularGroups } from 'soapbox/hooks/api/usePopularGroups';
|
import { usePopularGroups } from 'soapbox/hooks/api/usePopularGroups';
|
||||||
|
|
||||||
import GroupGridItem from './components/discover/group-grid-item';
|
import GroupGridItem from './components/discover/group-grid-item';
|
||||||
import GroupListItem from './components/discover/group-list-item';
|
import GroupListItem from './components/discover/group-list-item';
|
||||||
|
import LayoutButtons, { GroupLayout } from './components/discover/layout-buttons';
|
||||||
|
|
||||||
import type { Group } from 'soapbox/schemas';
|
import type { Group } from 'soapbox/schemas';
|
||||||
|
|
||||||
|
@ -15,21 +16,15 @@ const messages = defineMessages({
|
||||||
label: { id: 'groups.popular.label', defaultMessage: 'Popular Groups' },
|
label: { id: 'groups.popular.label', defaultMessage: 'Popular Groups' },
|
||||||
});
|
});
|
||||||
|
|
||||||
enum Layout {
|
|
||||||
LIST = 'LIST',
|
|
||||||
GRID = 'GRID'
|
|
||||||
}
|
|
||||||
|
|
||||||
const GridList: Components['List'] = React.forwardRef((props, ref) => {
|
const GridList: Components['List'] = React.forwardRef((props, ref) => {
|
||||||
const { context, ...rest } = props;
|
const { context, ...rest } = props;
|
||||||
return <div ref={ref} {...rest} className='flex flex-wrap' />;
|
return <div ref={ref} {...rest} className='flex flex-wrap' />;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const Popular: React.FC = () => {
|
const Popular: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const [layout, setLayout] = useState<Layout>(Layout.LIST);
|
const [layout, setLayout] = useState<GroupLayout>(GroupLayout.LIST);
|
||||||
|
|
||||||
const { groups, hasNextPage, fetchNextPage } = usePopularGroups();
|
const { groups, hasNextPage, fetchNextPage } = usePopularGroups();
|
||||||
|
|
||||||
|
@ -61,32 +56,13 @@ const Popular: React.FC = () => {
|
||||||
<Column
|
<Column
|
||||||
label={intl.formatMessage(messages.label)}
|
label={intl.formatMessage(messages.label)}
|
||||||
action={
|
action={
|
||||||
<HStack alignItems='center'>
|
<LayoutButtons
|
||||||
<button onClick={() => setLayout(Layout.LIST)}>
|
layout={layout}
|
||||||
<Icon
|
onSelect={(selectedLayout) => setLayout(selectedLayout)}
|
||||||
src={require('@tabler/icons/layout-list.svg')}
|
/>
|
||||||
className={
|
|
||||||
clsx('h-5 w-5 text-gray-600', {
|
|
||||||
'text-primary-600': layout === Layout.LIST,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button onClick={() => setLayout(Layout.GRID)}>
|
|
||||||
<Icon
|
|
||||||
src={require('@tabler/icons/layout-grid.svg')}
|
|
||||||
className={
|
|
||||||
clsx('h-5 w-5 text-gray-600', {
|
|
||||||
'text-primary-600': layout === Layout.GRID,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</HStack>
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{layout === Layout.LIST ? (
|
{layout === GroupLayout.LIST ? (
|
||||||
<Virtuoso
|
<Virtuoso
|
||||||
useWindowScroll
|
useWindowScroll
|
||||||
data={groups}
|
data={groups}
|
||||||
|
|
|
@ -3,11 +3,12 @@ import React, { useCallback, useState } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
import { Components, Virtuoso, VirtuosoGrid } from 'react-virtuoso';
|
import { Components, Virtuoso, VirtuosoGrid } from 'react-virtuoso';
|
||||||
|
|
||||||
import { Column, HStack, Icon } from 'soapbox/components/ui';
|
import { Column } from 'soapbox/components/ui';
|
||||||
import { useSuggestedGroups } from 'soapbox/hooks/api/useSuggestedGroups';
|
import { useSuggestedGroups } from 'soapbox/hooks/api/useSuggestedGroups';
|
||||||
|
|
||||||
import GroupGridItem from './components/discover/group-grid-item';
|
import GroupGridItem from './components/discover/group-grid-item';
|
||||||
import GroupListItem from './components/discover/group-list-item';
|
import GroupListItem from './components/discover/group-list-item';
|
||||||
|
import LayoutButtons, { GroupLayout } from './components/discover/layout-buttons';
|
||||||
|
|
||||||
import type { Group } from 'soapbox/schemas';
|
import type { Group } from 'soapbox/schemas';
|
||||||
|
|
||||||
|
@ -15,21 +16,15 @@ const messages = defineMessages({
|
||||||
label: { id: 'groups.popular.label', defaultMessage: 'Suggested Groups' },
|
label: { id: 'groups.popular.label', defaultMessage: 'Suggested Groups' },
|
||||||
});
|
});
|
||||||
|
|
||||||
enum Layout {
|
|
||||||
LIST = 'LIST',
|
|
||||||
GRID = 'GRID'
|
|
||||||
}
|
|
||||||
|
|
||||||
const GridList: Components['List'] = React.forwardRef((props, ref) => {
|
const GridList: Components['List'] = React.forwardRef((props, ref) => {
|
||||||
const { context, ...rest } = props;
|
const { context, ...rest } = props;
|
||||||
return <div ref={ref} {...rest} className='flex flex-wrap' />;
|
return <div ref={ref} {...rest} className='flex flex-wrap' />;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const Suggested: React.FC = () => {
|
const Suggested: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const [layout, setLayout] = useState<Layout>(Layout.LIST);
|
const [layout, setLayout] = useState<GroupLayout>(GroupLayout.LIST);
|
||||||
|
|
||||||
const { groups, hasNextPage, fetchNextPage } = useSuggestedGroups();
|
const { groups, hasNextPage, fetchNextPage } = useSuggestedGroups();
|
||||||
|
|
||||||
|
@ -61,32 +56,13 @@ const Suggested: React.FC = () => {
|
||||||
<Column
|
<Column
|
||||||
label={intl.formatMessage(messages.label)}
|
label={intl.formatMessage(messages.label)}
|
||||||
action={
|
action={
|
||||||
<HStack alignItems='center'>
|
<LayoutButtons
|
||||||
<button onClick={() => setLayout(Layout.LIST)}>
|
layout={layout}
|
||||||
<Icon
|
onSelect={(selectedLayout) => setLayout(selectedLayout)}
|
||||||
src={require('@tabler/icons/layout-list.svg')}
|
/>
|
||||||
className={
|
|
||||||
clsx('h-5 w-5 text-gray-600', {
|
|
||||||
'text-primary-600': layout === Layout.LIST,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button onClick={() => setLayout(Layout.GRID)}>
|
|
||||||
<Icon
|
|
||||||
src={require('@tabler/icons/layout-grid.svg')}
|
|
||||||
className={
|
|
||||||
clsx('h-5 w-5 text-gray-600', {
|
|
||||||
'text-primary-600': layout === Layout.GRID,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</HStack>
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{layout === Layout.LIST ? (
|
{layout === GroupLayout.LIST ? (
|
||||||
<Virtuoso
|
<Virtuoso
|
||||||
useWindowScroll
|
useWindowScroll
|
||||||
data={groups}
|
data={groups}
|
||||||
|
|
Loading…
Reference in New Issue