-
-
Notifications
You must be signed in to change notification settings - Fork 430
/
SidebarItem.tsx
105 lines (96 loc) · 3.27 KB
/
SidebarItem.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import classNames from 'classnames';
import { ComponentProps, ElementType, FC, forwardRef, PropsWithChildren, ReactNode, useId } from 'react';
import { Badge } from '../Badge';
import type { FlowbiteColors } from '../Flowbite/FlowbiteTheme';
import { useTheme } from '../Flowbite/ThemeContext';
import { Tooltip } from '../Tooltip';
import { useSidebarContext } from './SidebarContext';
import { useSidebarItemContext } from './SidebarItemContext';
export interface SidebarItemProps
extends PropsWithChildren<Omit<ComponentProps<'div'>, 'ref'> & Record<string, unknown>> {
active?: boolean;
as?: ElementType;
href?: string;
icon?: FC<ComponentProps<'svg'>>;
label?: string;
labelColor?: keyof SidebarItemLabelColors;
}
export interface SidebarItemLabelColors extends Pick<FlowbiteColors, 'gray'> {
[key: string]: string;
}
const ListItem: FC<PropsWithChildren<{ id: string; isCollapsed: boolean; tooltipChildren: ReactNode | undefined }>> = ({
id,
isCollapsed,
tooltipChildren,
children: wrapperChildren,
}) => (
<li>
{isCollapsed ? (
<Tooltip content={<TooltipContent id={id}>{tooltipChildren}</TooltipContent>} placement="right">
{wrapperChildren}
</Tooltip>
) : (
wrapperChildren
)}
</li>
);
const TooltipContent: FC<PropsWithChildren<{ id: string }>> = ({ id, children }) => (
<Children id={id}>{children}</Children>
);
const Children: FC<PropsWithChildren<{ id: string }>> = ({ id, children }) => {
const theme = useTheme().theme.sidebar.item;
return (
<span
className={classNames(theme.content.base)}
data-testid="flowbite-sidebar-item-content"
id={`flowbite-sidebar-item-${id}`}
>
{children}
</span>
);
};
const SidebarItem = forwardRef<Element, SidebarItemProps>(
(
{ as: Component = 'a', children, icon: Icon, active: isActive, label, labelColor = 'info', className, ...props },
ref,
) => {
const id = useId();
const { isCollapsed } = useSidebarContext();
const { isInsideCollapse } = useSidebarItemContext();
const theme = useTheme().theme.sidebar.item;
return (
<ListItem id={id} isCollapsed={isCollapsed} tooltipChildren={children}>
<Component
aria-labelledby={`flowbite-sidebar-item-${id}`}
className={classNames(
theme.base,
isActive && theme.active,
!isCollapsed && isInsideCollapse && theme.collapsed.insideCollapse,
className,
)}
ref={ref}
{...props}
>
{Icon && (
<Icon
aria-hidden
className={classNames(theme.icon.base, isActive && theme.icon.active)}
data-testid="flowbite-sidebar-item-icon"
/>
)}
{isCollapsed && !Icon && (
<span className={theme.collapsed.noIcon}>{(children as string).charAt(0).toLocaleUpperCase() ?? '?'}</span>
)}
{!isCollapsed && <Children id={id}>{children}</Children>}
{!isCollapsed && label && (
<Badge color={labelColor} data-testid="flowbite-sidebar-label" hidden={isCollapsed} className={theme.label}>
{label}
</Badge>
)}
</Component>
</ListItem>
);
},
);
SidebarItem.displayName = 'Sidebar.Item';
export default SidebarItem;