-
Notifications
You must be signed in to change notification settings - Fork 116
/
SidebarNavigationItem.tsx
125 lines (116 loc) · 4.09 KB
/
SidebarNavigationItem.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import { secureExternalLink } from "@twilio-paste/anchor";
import { Box, safelySpreadBoxProps } from "@twilio-paste/box";
import type { BoxProps } from "@twilio-paste/box";
import type { ButtonProps } from "@twilio-paste/button";
import type { HTMLPasteProps } from "@twilio-paste/types";
import * as React from "react";
import { SidebarContext } from "../SidebarContext";
import { SidebarNavigationContext } from "./SidebarNavigationContext";
import { SidebarNavigationDisclosureContext } from "./SidebarNavigationDisclosureContext";
import {
sidebarNavigationItemCollapsedStyles,
sidebarNavigationItemHierarchicalStyles,
sidebarNavigationItemNestedStyles,
sidebarNavigationItemSelectedStyles,
sidebarNavigationItemStyles,
} from "./styles";
export interface SidebarNavigationItemProps extends HTMLPasteProps<"a"> {
/**
* String for the url to link to.
*
* @type {ButtonProps["href"]}
* @memberof SidebarNavigationItemProps
*/
href: ButtonProps["href"];
children: React.ReactNode;
/**
* Overrides the default element name to apply unique styles with the Customization Provider
*
* @default "SIDEBAR_NAVIGATION_ITEM"
* @type {BoxProps["element"]}
* @memberof SidebarNavigationItemProps
*/
element?: BoxProps["element"];
/**
* Set to indicate this item matches to the current page the user is on
*
* @type {boolean}
* @memberof SidebarNavigationItemProps
*/
selected?: boolean;
/**
* Any product icons can be used here
*
* @type {React.ReactNode}
* @memberof SidebarNavigationItemProps
*/
icon?: React.ReactNode;
}
const SidebarNavigationItem = React.forwardRef<HTMLAnchorElement, SidebarNavigationItemProps>(
({ element = "SIDEBAR_NAVIGATION_ITEM", selected, children, icon, ...props }, ref) => {
const { collapsed, variant } = React.useContext(SidebarContext);
const { disclosure } = React.useContext(SidebarNavigationDisclosureContext);
const { hideItemsOnCollapse, hierarchical } = React.useContext(SidebarNavigationContext);
const isCompact = variant === "compact";
const [visible, setVisible] = React.useState(!isCompact ? true : !collapsed);
const timeout = React.useRef(0);
React.useEffect(() => {
clearTimeout(timeout.current);
// If not compact mode, we don't show/hide item titles
if (!isCompact) {
return;
}
// @ts-expect-error timeout is a number
timeout.current = setTimeout(() => {
setVisible(!collapsed);
}, 120);
}, [collapsed, isCompact]);
// If there is any disclosure context, that indicates that this component is nested
const isNested = disclosure != null;
const styles = React.useMemo(
() => ({
...sidebarNavigationItemStyles,
...(hierarchical && sidebarNavigationItemHierarchicalStyles),
...(isNested && sidebarNavigationItemNestedStyles),
...(collapsed && sidebarNavigationItemCollapsedStyles),
...(selected && sidebarNavigationItemSelectedStyles),
display: collapsed && hideItemsOnCollapse ? "none" : "flex",
width: collapsed ? "36px" : "100%",
}),
[isNested, selected, collapsed, hideItemsOnCollapse, hierarchical],
);
return (
<Box
{...safelySpreadBoxProps(props)}
{...(props.href ? secureExternalLink(props.href) : {})}
ref={ref}
element={element}
as="a"
aria-current={selected ? "page" : undefined}
{...styles}
>
{icon && (
<Box as="span" color={selected ? "colorTextInverse" : "colorTextIconInverse"}>
{icon}
</Box>
)}
<Box
as="span"
display="flex"
alignItems="center"
justifyContent="space-between"
columnGap="space20"
transition="all 120ms ease"
flexGrow={1}
float={visible ? "none" : "left"}
opacity={visible ? 1 : 0}
whiteSpace={visible ? "normal" : "nowrap"}
>
{collapsed ? null : children}
</Box>
</Box>
);
},
);
SidebarNavigationItem.displayName = "SidebarNavigationItem";
export { SidebarNavigationItem };