Commit 388ec42a authored by tom's avatar tom

use tooltips for navigation groups

parent 989cb7c4
...@@ -17,7 +17,9 @@ export interface TooltipProps extends ChakraTooltip.RootProps { ...@@ -17,7 +17,9 @@ export interface TooltipProps extends ChakraTooltip.RootProps {
export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>( export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
function Tooltip(props, ref) { function Tooltip(props, ref) {
const { const {
showArrow = true, showArrow: showArrowProp,
onOpenChange,
visual,
selected, selected,
children, children,
disabled, disabled,
...@@ -33,9 +35,10 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>( ...@@ -33,9 +35,10 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const triggerRef = useClickAway<HTMLButtonElement>(() => setOpen(false)); const triggerRef = useClickAway<HTMLButtonElement>(() => setOpen(false));
const handleOpenChange = React.useCallback(({ open }: { open: boolean }) => { const handleOpenChange = React.useCallback((details: { open: boolean }) => {
setOpen(open); setOpen(details.open);
}, []); onOpenChange?.(details);
}, [ onOpenChange ]);
const handleTriggerClick = React.useCallback(() => { const handleTriggerClick = React.useCallback(() => {
setOpen((prev) => !prev); setOpen((prev) => !prev);
...@@ -43,6 +46,9 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>( ...@@ -43,6 +46,9 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
if (disabled) return children; if (disabled) return children;
const defaultShowArrow = visual === 'popover' ? false : true;
const showArrow = showArrowProp !== undefined ? showArrowProp : defaultShowArrow;
const positioning = { const positioning = {
...rest.positioning, ...rest.positioning,
offset: { offset: {
...@@ -58,6 +64,7 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>( ...@@ -58,6 +64,7 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
open={ open } open={ open }
onOpenChange={ isMobile ? undefined : handleOpenChange } onOpenChange={ isMobile ? undefined : handleOpenChange }
closeOnClick={ false } closeOnClick={ false }
visual={ visual }
{ ...rest } { ...rest }
positioning={ positioning } positioning={ positioning }
> >
......
...@@ -63,6 +63,16 @@ export const recipe = defineSlotRecipe({ ...@@ -63,6 +63,16 @@ export const recipe = defineSlotRecipe({
display: 'none', display: 'none',
}, },
}, },
popover: {
content: {
bg: 'popover.bg',
color: 'popover.fg',
p: '4',
boxShadow: 'popover',
boxShadowColor: 'popover.shadow',
borderRadius: 'md',
},
},
}, },
}, },
defaultVariants: { defaultVariants: {
......
...@@ -3,7 +3,8 @@ import React from 'react'; ...@@ -3,7 +3,8 @@ import React from 'react';
import type { NavGroupItem } from 'types/client/navigation'; import type { NavGroupItem } from 'types/client/navigation';
import { PopoverRoot, PopoverBody, PopoverContent, PopoverTrigger } from 'toolkit/chakra/popover'; import { Tooltip } from 'toolkit/chakra/tooltip';
import { useDisclosure } from 'toolkit/hooks/useDisclosure';
import IconSvg from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg';
import LightningLabel from '../LightningLabel'; import LightningLabel from '../LightningLabel';
...@@ -14,29 +15,48 @@ interface Props { ...@@ -14,29 +15,48 @@ interface Props {
} }
const NavLinkGroup = ({ item }: Props) => { const NavLinkGroup = ({ item }: Props) => {
const [ isOpen, setIsOpen ] = React.useState(false); const { open, onOpenChange } = useDisclosure();
// const bgColor = item.isActive ? colors.bg.active : colors.bg.default;
// const color = item.isActive ? colors.text.active : colors.text.default;
const isHighlighted = checkRouteHighlight(item.subItems); const isHighlighted = checkRouteHighlight(item.subItems);
const hasGroups = item.subItems.some((subItem) => Array.isArray(subItem)); const hasGroups = item.subItems.some((subItem) => Array.isArray(subItem));
const handleOpenChange = React.useCallback(({ open }: { open: boolean }) => { const content = hasGroups ? (
setIsOpen(open); <HStack separator={ <Separator/> } alignItems="flex-start">
}, []); { item.subItems.map((subItem, index) => {
if (!Array.isArray(subItem)) {
return <NavLink key={ subItem.text } item={ subItem }/>;
}
return (
<chakra.ul key={ index } display="flex" flexDir="column" rowGap={ 1 }>
{ subItem.map((navItem) => <NavLink key={ navItem.text } item={ navItem }/>) }
</chakra.ul>
);
}) }
</HStack>
) : (
<chakra.ul display="flex" flexDir="column" rowGap={ 1 }>
{ item.subItems.map((subItem) => {
if (Array.isArray(subItem)) {
return null;
}
return <NavLink key={ subItem.text } item={ subItem }/>;
}) }
</chakra.ul>
);
return ( return (
<PopoverRoot <Tooltip
// TODO @tom2drum make menu open on hover visual="popover"
// trigger="hover" content={ content }
onOpenChange={ handleOpenChange } onOpenChange={ onOpenChange }
lazyMount lazyMount
positioning={{ positioning={{
placement: 'bottom', placement: 'bottom',
offset: { mainAxis: 8 }, offset: { mainAxis: 8 },
}} }}
interactive
> >
<PopoverTrigger>
<Link <Link
as="li" as="li"
listStyleType="none" listStyleType="none"
...@@ -48,7 +68,7 @@ const NavLinkGroup = ({ item }: Props) => { ...@@ -48,7 +68,7 @@ const NavLinkGroup = ({ item }: Props) => {
fontWeight={ 500 } fontWeight={ 500 }
visual="navigation" visual="navigation"
{ ...(item.isActive ? { 'data-selected': true } : {}) } { ...(item.isActive ? { 'data-selected': true } : {}) }
{ ...(isOpen ? { 'data-active': true } : {}) } { ...(open ? { 'data-active': true } : {}) }
borderRadius="base" borderRadius="base"
> >
{ item.text } { item.text }
...@@ -61,36 +81,7 @@ const NavLinkGroup = ({ item }: Props) => { ...@@ -61,36 +81,7 @@ const NavLinkGroup = ({ item }: Props) => {
) } ) }
<IconSvg name="arrows/east-mini" boxSize={ 5 } transform="rotate(-90deg)" ml={ 1 }/> <IconSvg name="arrows/east-mini" boxSize={ 5 } transform="rotate(-90deg)" ml={ 1 }/>
</Link> </Link>
</PopoverTrigger> </Tooltip>
<PopoverContent>
<PopoverBody>
{ hasGroups ? (
<HStack separator={ <Separator/> } alignItems="flex-start">
{ item.subItems.map((subItem, index) => {
if (!Array.isArray(subItem)) {
return <NavLink key={ subItem.text } item={ subItem }/>;
}
return (
<chakra.ul key={ index } display="flex" flexDir="column" rowGap={ 1 }>
{ subItem.map((navItem) => <NavLink key={ navItem.text } item={ navItem }/>) }
</chakra.ul>
);
}) }
</HStack>
) : (
<chakra.ul display="flex" flexDir="column" rowGap={ 1 }>
{ item.subItems.map((subItem) => {
if (Array.isArray(subItem)) {
return null;
}
return <NavLink key={ subItem.text } item={ subItem }/>;
}) }
</chakra.ul>
) }
</PopoverBody>
</PopoverContent>
</PopoverRoot>
); );
}; };
......
...@@ -3,7 +3,7 @@ import React from 'react'; ...@@ -3,7 +3,7 @@ import React from 'react';
import type { NavGroupItem } from 'types/client/navigation'; import type { NavGroupItem } from 'types/client/navigation';
import { PopoverBody, PopoverContent, PopoverRoot, PopoverTrigger } from 'toolkit/chakra/popover'; import { Tooltip } from 'toolkit/chakra/tooltip';
import IconSvg from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg';
import LightningLabel from '../LightningLabel'; import LightningLabel from '../LightningLabel';
...@@ -24,16 +24,43 @@ const NavLinkGroup = ({ item, isCollapsed }: Props) => { ...@@ -24,16 +24,43 @@ const NavLinkGroup = ({ item, isCollapsed }: Props) => {
const isHighlighted = checkRouteHighlight(item.subItems); const isHighlighted = checkRouteHighlight(item.subItems);
const content = (
<Box width="220px" top={{ lg: isExpanded ? '-16px' : 0, xl: isCollapsed ? 0 : '-16px' }}>
<Text color="text.secondary" fontSize="sm" mb={ 1 } display={{ lg: isExpanded ? 'none' : 'block', xl: isCollapsed ? 'block' : 'none' }}>
{ item.text }
</Text>
<VStack gap={ 1 } alignItems="start" as="ul">
{ item.subItems.map((subItem, index) => Array.isArray(subItem) ? (
<Box
key={ index }
w="100%"
as="ul"
_notLast={{
mb: 2,
pb: 2,
borderBottomWidth: '1px',
borderColor: 'border.divider',
}}
>
{ subItem.map(subSubItem => <NavLink key={ subSubItem.text } item={ subSubItem } isCollapsed={ false }/>) }
</Box>
) :
<NavLink key={ subItem.text } item={ subItem } isCollapsed={ false }/>,
) }
</VStack>
</Box>
);
return ( return (
<Box as="li" listStyleType="none" w="100%"> <Box as="li" listStyleType="none" w="100%">
<PopoverRoot <Tooltip
// TODO @tom2drum fix trigger content={ content }
// trigger="hover" positioning={{ placement: 'right-start', offset: { crossAxis: 0, mainAxis: 8 } }}
positioning={{ placement: 'right-start', offset: { crossAxis: 8, mainAxis: 8 } }}
// should not be lazy to help google indexing pages // should not be lazy to help google indexing pages
lazyMount={ false } lazyMount={ false }
visual="popover"
interactive
> >
<PopoverTrigger>
<Box <Box
{ ...styleProps.itemProps } { ...styleProps.itemProps }
w={{ lg: isExpanded ? '180px' : '60px', xl: isCollapsed ? '60px' : '180px' }} w={{ lg: isExpanded ? '180px' : '60px', xl: isCollapsed ? '60px' : '180px' }}
...@@ -70,34 +97,7 @@ const NavLinkGroup = ({ item, isCollapsed }: Props) => { ...@@ -70,34 +97,7 @@ const NavLinkGroup = ({ item, isCollapsed }: Props) => {
/> />
</HStack> </HStack>
</Box> </Box>
</PopoverTrigger> </Tooltip>
<PopoverContent width="252px" top={{ lg: isExpanded ? '-16px' : 0, xl: isCollapsed ? 0 : '-16px' }}>
<PopoverBody p={ 4 }>
<Text color="text.secondary" fontSize="sm" mb={ 1 } display={{ lg: isExpanded ? 'none' : 'block', xl: isCollapsed ? 'block' : 'none' }}>
{ item.text }
</Text>
<VStack gap={ 1 } alignItems="start" as="ul">
{ item.subItems.map((subItem, index) => Array.isArray(subItem) ? (
<Box
key={ index }
w="100%"
as="ul"
_notLast={{
mb: 2,
pb: 2,
borderBottomWidth: '1px',
borderColor: 'border.divider',
}}
>
{ subItem.map(subSubItem => <NavLink key={ subSubItem.text } item={ subSubItem } isCollapsed={ false }/>) }
</Box>
) :
<NavLink key={ subItem.text } item={ subItem } isCollapsed={ false }/>,
) }
</VStack>
</PopoverBody>
</PopoverContent>
</PopoverRoot>
</Box> </Box>
); );
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment