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 {
export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
function Tooltip(props, ref) {
const {
showArrow = true,
showArrow: showArrowProp,
onOpenChange,
visual,
selected,
children,
disabled,
......@@ -33,9 +35,10 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
const isMobile = useIsMobile();
const triggerRef = useClickAway<HTMLButtonElement>(() => setOpen(false));
const handleOpenChange = React.useCallback(({ open }: { open: boolean }) => {
setOpen(open);
}, []);
const handleOpenChange = React.useCallback((details: { open: boolean }) => {
setOpen(details.open);
onOpenChange?.(details);
}, [ onOpenChange ]);
const handleTriggerClick = React.useCallback(() => {
setOpen((prev) => !prev);
......@@ -43,6 +46,9 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
if (disabled) return children;
const defaultShowArrow = visual === 'popover' ? false : true;
const showArrow = showArrowProp !== undefined ? showArrowProp : defaultShowArrow;
const positioning = {
...rest.positioning,
offset: {
......@@ -58,6 +64,7 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
open={ open }
onOpenChange={ isMobile ? undefined : handleOpenChange }
closeOnClick={ false }
visual={ visual }
{ ...rest }
positioning={ positioning }
>
......
......@@ -63,6 +63,16 @@ export const recipe = defineSlotRecipe({
display: 'none',
},
},
popover: {
content: {
bg: 'popover.bg',
color: 'popover.fg',
p: '4',
boxShadow: 'popover',
boxShadowColor: 'popover.shadow',
borderRadius: 'md',
},
},
},
},
defaultVariants: {
......
......@@ -3,7 +3,8 @@ import React from 'react';
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 LightningLabel from '../LightningLabel';
......@@ -14,83 +15,73 @@ interface Props {
}
const NavLinkGroup = ({ item }: Props) => {
const [ isOpen, setIsOpen ] = React.useState(false);
// const bgColor = item.isActive ? colors.bg.active : colors.bg.default;
// const color = item.isActive ? colors.text.active : colors.text.default;
const { open, onOpenChange } = useDisclosure();
const isHighlighted = checkRouteHighlight(item.subItems);
const hasGroups = item.subItems.some((subItem) => Array.isArray(subItem));
const handleOpenChange = React.useCallback(({ open }: { open: boolean }) => {
setIsOpen(open);
}, []);
const content = 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>
);
return (
<PopoverRoot
// TODO @tom2drum make menu open on hover
// trigger="hover"
onOpenChange={ handleOpenChange }
<Tooltip
visual="popover"
content={ content }
onOpenChange={ onOpenChange }
lazyMount
positioning={{
placement: 'bottom',
offset: { mainAxis: 8 },
}}
interactive
>
<PopoverTrigger>
<Link
as="li"
listStyleType="none"
display="flex"
alignItems="center"
px={ 2 }
py={ 1.5 }
textStyle="sm"
fontWeight={ 500 }
visual="navigation"
{ ...(item.isActive ? { 'data-selected': true } : {}) }
{ ...(isOpen ? { 'data-active': true } : {}) }
borderRadius="base"
>
{ item.text }
{ isHighlighted && (
<LightningLabel
iconColor={ item.isActive ? 'link.navigation.bg.selected' : 'link.navigation.bg' }
position={{ lg: 'static' }}
ml={{ lg: '2px' }}
/>
) }
<IconSvg name="arrows/east-mini" boxSize={ 5 } transform="rotate(-90deg)" ml={ 1 }/>
</Link>
</PopoverTrigger>
<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>
<Link
as="li"
listStyleType="none"
display="flex"
alignItems="center"
px={ 2 }
py={ 1.5 }
textStyle="sm"
fontWeight={ 500 }
visual="navigation"
{ ...(item.isActive ? { 'data-selected': true } : {}) }
{ ...(open ? { 'data-active': true } : {}) }
borderRadius="base"
>
{ item.text }
{ isHighlighted && (
<LightningLabel
iconColor={ item.isActive ? 'link.navigation.bg.selected' : 'link.navigation.bg' }
position={{ lg: 'static' }}
ml={{ lg: '2px' }}
/>
) }
<IconSvg name="arrows/east-mini" boxSize={ 5 } transform="rotate(-90deg)" ml={ 1 }/>
</Link>
</Tooltip>
);
};
......
......@@ -3,7 +3,7 @@ import React from 'react';
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 LightningLabel from '../LightningLabel';
......@@ -24,80 +24,80 @@ const NavLinkGroup = ({ item, isCollapsed }: Props) => {
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 (
<Box as="li" listStyleType="none" w="100%">
<PopoverRoot
// TODO @tom2drum fix trigger
// trigger="hover"
positioning={{ placement: 'right-start', offset: { crossAxis: 8, mainAxis: 8 } }}
<Tooltip
content={ content }
positioning={{ placement: 'right-start', offset: { crossAxis: 0, mainAxis: 8 } }}
// should not be lazy to help google indexing pages
lazyMount={ false }
visual="popover"
interactive
>
<PopoverTrigger>
<Box
{ ...styleProps.itemProps }
w={{ lg: isExpanded ? '180px' : '60px', xl: isCollapsed ? '60px' : '180px' }}
pl={{ lg: isExpanded ? 2 : '15px', xl: isCollapsed ? '15px' : 2 }}
pr={{ lg: isExpanded ? 0 : '15px', xl: isCollapsed ? '15px' : 0 }}
aria-label={ `${ item.text } link group` }
position="relative"
bgColor={ item.isActive ? 'link.navigation.bg.selected' : 'link.navigation.bg' }
>
<HStack gap={ 0 } overflow="hidden">
<NavLinkIcon item={ item }/>
<Text
{ ...styleProps.textProps }
ml={ 3 }
>
{ item.text }
</Text>
{ isHighlighted && (
<LightningLabel
iconColor={ item.isActive ? 'link.navigation.bg.selected' : 'link.navigation.bg' }
isCollapsed={ isCollapsed }
/>
) }
<IconSvg
name="arrows/east-mini"
position="absolute"
right="7px"
transform="rotate(180deg)"
boxSize={ 6 }
opacity={{ lg: isExpanded ? '1' : '0', xl: isCollapsed ? '0' : '1' }}
transitionProperty="opacity"
transitionDuration="normal"
transitionTimingFunction="ease"
/>
</HStack>
</Box>
</PopoverTrigger>
<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' }}>
<Box
{ ...styleProps.itemProps }
w={{ lg: isExpanded ? '180px' : '60px', xl: isCollapsed ? '60px' : '180px' }}
pl={{ lg: isExpanded ? 2 : '15px', xl: isCollapsed ? '15px' : 2 }}
pr={{ lg: isExpanded ? 0 : '15px', xl: isCollapsed ? '15px' : 0 }}
aria-label={ `${ item.text } link group` }
position="relative"
bgColor={ item.isActive ? 'link.navigation.bg.selected' : 'link.navigation.bg' }
>
<HStack gap={ 0 } overflow="hidden">
<NavLinkIcon item={ item }/>
<Text
{ ...styleProps.textProps }
ml={ 3 }
>
{ 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>
{ isHighlighted && (
<LightningLabel
iconColor={ item.isActive ? 'link.navigation.bg.selected' : 'link.navigation.bg' }
isCollapsed={ isCollapsed }
/>
) }
<IconSvg
name="arrows/east-mini"
position="absolute"
right="7px"
transform="rotate(180deg)"
boxSize={ 6 }
opacity={{ lg: isExpanded ? '1' : '0', xl: isCollapsed ? '0' : '1' }}
transitionProperty="opacity"
transitionDuration="normal"
transitionTimingFunction="ease"
/>
</HStack>
</Box>
</Tooltip>
</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