feat(Filters): use RovingTabIndex to navigate filter sections

This commit is contained in:
Aminejv 2022-01-03 19:07:08 +01:00
parent 8a442d5cad
commit 41c8ddffd5

View File

@ -7,6 +7,7 @@ import * as Utilities from "~/common/utilities";
import * as Tooltip from "~/components/system/components/fragments/Tooltip"; import * as Tooltip from "~/components/system/components/fragments/Tooltip";
import * as System from "~/components/system"; import * as System from "~/components/system";
import * as Actions from "~/common/actions"; import * as Actions from "~/common/actions";
import * as RovingTabIndex from "~/components/core/RovingTabIndex";
import ProfilePhoto from "~/components/core/ProfilePhoto"; import ProfilePhoto from "~/components/core/ProfilePhoto";
@ -15,6 +16,7 @@ import { useFilterContext } from "~/components/core/Filter/Provider";
import { Link } from "~/components/core/Link"; import { Link } from "~/components/core/Link";
import { ButtonPrimary, ButtonSecondary } from "~/components/system/components/Buttons"; import { ButtonPrimary, ButtonSecondary } from "~/components/system/components/Buttons";
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { FocusRing } from "../FocusRing";
/* ------------------------------------------------------------------------------------------------- /* -------------------------------------------------------------------------------------------------
* Shared components between filters * Shared components between filters
@ -63,9 +65,8 @@ const STYLES_FILTERS_GROUP = css`
} }
`; `;
const FilterButton = ({ children, Icon, image, isSelected, ...props }) => ( const FilterButton = React.forwardRef(({ children, Icon, image, isSelected, ...props }, ref) => (
<li> <Link {...props} ref={ref}>
<Link {...props}>
<span as="span" css={[STYLES_FILTER_BUTTON, isSelected && STYLES_FILTER_BUTTON_HIGHLIGHTED]}> <span as="span" css={[STYLES_FILTER_BUTTON, isSelected && STYLES_FILTER_BUTTON_HIGHLIGHTED]}>
{Icon ? <Icon height={16} width={16} style={{ flexShrink: 0 }} /> : null} {Icon ? <Icon height={16} width={16} style={{ flexShrink: 0 }} /> : null}
{image ? image : null} {image ? image : null}
@ -74,19 +75,19 @@ const FilterButton = ({ children, Icon, image, isSelected, ...props }) => (
</Typography.P2> </Typography.P2>
</span> </span>
</Link> </Link>
</li> ));
);
const FilterSection = ({ title, children, ...props }) => { const FilterSection = React.forwardRef(({ title, children, ...props }, ref) => {
const [isExpanded, setExpanded] = React.useState(true); const [isExpanded, setExpanded] = React.useState(true);
const toggleExpandState = () => setExpanded((prev) => !prev); const toggleExpandState = () => setExpanded((prev) => !prev);
const titleButtonId = `sidebar-${title}-button`; const titleButtonId = `sidebar-${title}-button`;
return ( return (
<div {...props}> <div {...props} ref={ref}>
{title && ( {title && (
<Tooltip.Root vertical="above" horizontal="right"> <Tooltip.Root vertical="above" horizontal="right">
<Tooltip.Trigger aria-describedby={titleButtonId} aria-expanded={isExpanded}> <Tooltip.Trigger aria-describedby={titleButtonId} aria-expanded={isExpanded}>
<FocusRing>
<Typography.H6 <Typography.H6
as={motion.button} as={motion.button}
layoutId={title + "title"} layoutId={title + "title"}
@ -97,6 +98,7 @@ const FilterSection = ({ title, children, ...props }) => {
> >
{title} {title}
</Typography.H6> </Typography.H6>
</FocusRing>
</Tooltip.Trigger> </Tooltip.Trigger>
<Tooltip.Content css={Styles.HORIZONTAL_CONTAINER_CENTERED} style={{ marginTop: -4.5 }}> <Tooltip.Content css={Styles.HORIZONTAL_CONTAINER_CENTERED} style={{ marginTop: -4.5 }}>
<System.H6 id={titleButtonId} as="p" color="textGrayDark"> <System.H6 id={titleButtonId} as="p" color="textGrayDark">
@ -117,7 +119,7 @@ const FilterSection = ({ title, children, ...props }) => {
) : null} ) : null}
</div> </div>
); );
}; });
/* ------------------------------------------------------------------------------------------------- /* -------------------------------------------------------------------------------------------------
* InitialFilters * InitialFilters
@ -149,10 +151,13 @@ function Tags({ viewer, data, onAction, ...props }) {
const [, { hidePopup }] = useFilterContext(); const [, { hidePopup }] = useFilterContext();
return ( return (
<RovingTabIndex.Provider axis="vertical">
<RovingTabIndex.List>
<FilterSection title="Tags" {...props}> <FilterSection title="Tags" {...props}>
{viewer.slates.map((slate) => ( {viewer.slates.map((slate, index) => (
<li key={slate.id}>
<RovingTabIndex.Item index={index}>
<FilterButton <FilterButton
key={slate.id}
href={`/$/slate/${slate.id}`} href={`/$/slate/${slate.id}`}
isSelected={slate.id === data?.id} isSelected={slate.id === data?.id}
onAction={onAction} onAction={onAction}
@ -161,8 +166,12 @@ function Tags({ viewer, data, onAction, ...props }) {
> >
{slate.slatename} {slate.slatename}
</FilterButton> </FilterButton>
</RovingTabIndex.Item>
</li>
))} ))}
</FilterSection> </FilterSection>
</RovingTabIndex.List>
</RovingTabIndex.Provider>
); );
} }
@ -170,10 +179,13 @@ function Following({ viewer, onAction, ...props }) {
const [, { hidePopup }] = useFilterContext(); const [, { hidePopup }] = useFilterContext();
return ( return (
<RovingTabIndex.Provider axis="vertical">
<RovingTabIndex.List>
<FilterSection title="Following" {...props}> <FilterSection title="Following" {...props}>
{viewer.following.map((user) => ( {viewer.following.map((user, index) => (
<li key={user.id}>
<RovingTabIndex.Item index={index}>
<FilterButton <FilterButton
key={user.id}
href={`/${user.username}`} href={`/${user.username}`}
isSelected={false} isSelected={false}
onAction={onAction} onAction={onAction}
@ -183,8 +195,12 @@ function Following({ viewer, onAction, ...props }) {
> >
{user.username} {user.username}
</FilterButton> </FilterButton>
</RovingTabIndex.Item>
</li>
))} ))}
</FilterSection> </FilterSection>
</RovingTabIndex.List>
</RovingTabIndex.Provider>
); );
} }
@ -281,10 +297,13 @@ function ProfileTags({ data, page, onAction, ...props }) {
} }
return ( return (
<RovingTabIndex.Provider axis="vertical">
<RovingTabIndex.List>
<FilterSection {...props}> <FilterSection {...props}>
{user?.slates?.map((slate) => ( {user?.slates?.map((slate, index) => (
<li key={slate.id}>
<RovingTabIndex.Item index={index}>
<FilterButton <FilterButton
key={slate.id}
href={`/$/slate/${slate.id}`} href={`/$/slate/${slate.id}`}
isSelected={slate.id === data?.id} isSelected={slate.id === data?.id}
onAction={onAction} onAction={onAction}
@ -293,8 +312,12 @@ function ProfileTags({ data, page, onAction, ...props }) {
> >
{slate.slatename} {slate.slatename}
</FilterButton> </FilterButton>
</RovingTabIndex.Item>
</li>
))} ))}
</FilterSection> </FilterSection>
</RovingTabIndex.List>
</RovingTabIndex.Provider>
); );
} }