@@ -18,10 +18,11 @@ import { getFocusRingStyles } from '~utils/getFocusRingStyles';
18
18
import { useIsomorphicLayoutEffect } from '~utils/useIsomorphicLayoutEffect' ;
19
19
import { throwBladeError } from '~utils/logger' ;
20
20
import { makeAnalyticsAttribute } from '~utils/makeAnalyticsAttribute' ;
21
+ import { Text } from '~components/Typography' ;
21
22
22
23
const { SHOW_ON_LINK_HOVER , HIDE_WHEN_COLLAPSED , STYLED_NAV_LINK } = classes ;
23
24
24
- const StyledNavLinkContainer = styled ( BaseBox ) ( ( props ) => {
25
+ const StyledNavLinkContainer = styled ( BaseBox ) < { $hasDescription : boolean } > ( ( props ) => {
25
26
return {
26
27
width : '100%' ,
27
28
[ `.${ SHOW_ON_LINK_HOVER } ` ] : {
@@ -45,14 +46,15 @@ const StyledNavLinkContainer = styled(BaseBox)((props) => {
45
46
display : 'flex' ,
46
47
flexDirection : 'row' ,
47
48
alignItems : 'center' ,
48
- justifyContent : 'space-between' ,
49
- height : makeSize ( NAV_ITEM_HEIGHT ) ,
49
+ height : props . $hasDescription ? undefined : makeSize ( NAV_ITEM_HEIGHT ) ,
50
50
width : '100%' ,
51
51
textDecoration : 'none' ,
52
52
overflow : 'hidden' ,
53
53
flexWrap : 'nowrap' ,
54
54
cursor : 'pointer' ,
55
- padding : `${ makeSpace ( props . theme . spacing [ 0 ] ) } ${ makeSpace ( props . theme . spacing [ 4 ] ) } ` ,
55
+ padding : `${ makeSpace ( props . theme . spacing [ props . $hasDescription ? 3 : 0 ] ) } ${ makeSpace (
56
+ props . theme . spacing [ 4 ] ,
57
+ ) } `,
56
58
margin : `${ makeSpace ( props . theme . spacing [ 1 ] ) } ${ makeSpace ( props . theme . spacing [ 0 ] ) } ` ,
57
59
color : props . theme . colors . interactive . text . gray . subtle ,
58
60
borderRadius : props . theme . border . radius . medium ,
@@ -77,40 +79,66 @@ const StyledNavLinkContainer = styled(BaseBox)((props) => {
77
79
const NavLinkIconTitle = ( {
78
80
icon : Icon ,
79
81
title,
82
+ description,
80
83
titleSuffix,
84
+ isActive,
85
+ trailing,
81
86
isL1Item,
82
- } : Pick < SideNavLinkProps , 'title' | 'icon' | 'titleSuffix' > & {
87
+ } : Pick <
88
+ SideNavLinkProps ,
89
+ 'title' | 'isActive' | 'trailing' | 'description' | 'icon' | 'titleSuffix'
90
+ > & {
83
91
isL1Item : boolean ;
84
92
} ) : React . ReactElement => {
85
93
return (
86
- < Box display = "flex" flexDirection = "row" gap = "spacing.3" >
87
- { Icon ? (
88
- < BaseBox display = "flex" flexDirection = "row" alignItems = "center" justifyContent = "center" >
89
- < Icon size = "medium" color = "currentColor" />
90
- </ BaseBox >
91
- ) : null }
92
- < BaseText
93
- truncateAfterLines = { 1 }
94
- color = "currentColor"
95
- fontWeight = "medium"
96
- fontSize = { 100 }
97
- lineHeight = { 100 }
98
- as = "p"
99
- className = { isL1Item ? HIDE_WHEN_COLLAPSED : '' }
100
- >
101
- { title }
102
- </ BaseText >
103
- { titleSuffix ? (
104
- < BaseBox display = "flex" alignItems = "center" >
105
- { titleSuffix }
106
- </ BaseBox >
94
+ < Box width = "100%" textAlign = "left" >
95
+ < Box display = "flex" justifyContent = "space-between" width = "100%" >
96
+ < Box display = "flex" flexDirection = "row" gap = "spacing.3" alignItems = "center" >
97
+ { Icon ? (
98
+ < BaseBox display = "flex" flexDirection = "row" alignItems = "center" >
99
+ < Icon size = "medium" color = "currentColor" />
100
+ </ BaseBox >
101
+ ) : null }
102
+ < BaseText
103
+ truncateAfterLines = { 1 }
104
+ color = "currentColor"
105
+ fontWeight = "medium"
106
+ fontSize = { 100 }
107
+ lineHeight = { 100 }
108
+ as = "p"
109
+ className = { isL1Item ? HIDE_WHEN_COLLAPSED : '' }
110
+ >
111
+ { title }
112
+ </ BaseText >
113
+ { titleSuffix ? (
114
+ < BaseBox display = "flex" alignItems = "center" >
115
+ { titleSuffix }
116
+ </ BaseBox >
117
+ ) : null }
118
+ </ Box >
119
+ < Box display = "flex" alignItems = "center" >
120
+ { trailing }
121
+ </ Box >
122
+ </ Box >
123
+ { ! isL1Item && description ? (
124
+ < Text
125
+ size = "small"
126
+ marginLeft = "spacing.7"
127
+ textAlign = "left"
128
+ weight = "medium"
129
+ color = { isActive ? 'interactive.text.primary.muted' : 'interactive.text.gray.muted' }
130
+ truncateAfterLines = { 1 }
131
+ >
132
+ { description }
133
+ </ Text >
107
134
) : null }
108
135
</ Box >
109
136
) ;
110
137
} ;
111
138
112
139
const L3Trigger = ( {
113
140
title,
141
+ description,
114
142
icon,
115
143
as,
116
144
href,
@@ -120,7 +148,15 @@ const L3Trigger = ({
120
148
onClick,
121
149
} : Pick <
122
150
SideNavLinkProps ,
123
- 'title' | 'icon' | 'as' | 'href' | 'titleSuffix' | 'tooltip' | 'target' | 'onClick'
151
+ | 'title'
152
+ | 'description'
153
+ | 'icon'
154
+ | 'as'
155
+ | 'href'
156
+ | 'titleSuffix'
157
+ | 'tooltip'
158
+ | 'target'
159
+ | 'onClick'
124
160
> ) : React . ReactElement => {
125
161
const { onExpandChange, isExpanded, collapsibleBodyId } = useCollapsible ( ) ;
126
162
@@ -135,7 +171,7 @@ const L3Trigger = ({
135
171
136
172
return (
137
173
< TooltipifyNavItem tooltip = { tooltip } >
138
- < StyledNavLinkContainer >
174
+ < StyledNavLinkContainer $hasDescription = { Boolean ( description ) } >
139
175
< BaseBox
140
176
className = { STYLED_NAV_LINK }
141
177
as = { href ? as : 'button' }
@@ -144,10 +180,16 @@ const L3Trigger = ({
144
180
onClick = { ( e : React . MouseEvent ) => toggleCollapse ( e ) }
145
181
{ ...makeAccessible ( { expanded : isExpanded , controls : collapsibleBodyId } ) }
146
182
>
147
- < NavLinkIconTitle title = { title } icon = { icon } isL1Item = { false } titleSuffix = { titleSuffix } />
148
- < BaseBox display = "flex" alignItems = "center" >
149
- { isExpanded ? < ChevronUpIcon { ...iconProps } /> : < ChevronDownIcon { ...iconProps } /> }
150
- </ BaseBox >
183
+ < NavLinkIconTitle
184
+ title = { title }
185
+ description = { description }
186
+ icon = { icon }
187
+ isL1Item = { false }
188
+ titleSuffix = { titleSuffix }
189
+ trailing = {
190
+ isExpanded ? < ChevronUpIcon { ...iconProps } /> : < ChevronDownIcon { ...iconProps } />
191
+ }
192
+ />
151
193
</ BaseBox >
152
194
</ StyledNavLinkContainer >
153
195
</ TooltipifyNavItem >
@@ -178,6 +220,7 @@ const CurvedVerticalLine = styled(BaseBox)((props) => {
178
220
179
221
const SideNavLink = ( {
180
222
title,
223
+ description,
181
224
href,
182
225
children,
183
226
titleSuffix,
@@ -211,6 +254,13 @@ const SideNavLink = ({
211
254
moduleName : 'SideNavLink' ,
212
255
} ) ;
213
256
}
257
+
258
+ if ( currentLevel === 1 && Boolean ( description ) ) {
259
+ throwBladeError ( {
260
+ message : 'Description is not supported for L1 items' ,
261
+ moduleName : 'SideNavLink' ,
262
+ } ) ;
263
+ }
214
264
}
215
265
216
266
const isFirstRender = useFirstRender ( ) ;
@@ -240,6 +290,7 @@ const SideNavLink = ({
240
290
>
241
291
< L3Trigger
242
292
title = { title }
293
+ description = { description }
243
294
icon = { icon }
244
295
as = { as }
245
296
href = { href }
@@ -252,7 +303,10 @@ const SideNavLink = ({
252
303
</ Collapsible >
253
304
) : (
254
305
< >
255
- < StyledNavLinkContainer position = "relative" >
306
+ < StyledNavLinkContainer
307
+ $hasDescription = { currentLevel !== 1 && Boolean ( description ) }
308
+ position = "relative"
309
+ >
256
310
< TooltipifyNavItem tooltip = { tooltip } >
257
311
< BaseBox
258
312
className = { STYLED_NAV_LINK }
@@ -296,6 +350,8 @@ const SideNavLink = ({
296
350
< NavLinkIconTitle
297
351
icon = { icon }
298
352
title = { title }
353
+ description = { description }
354
+ isActive = { isActive }
299
355
isL1Item = { currentLevel === 1 }
300
356
titleSuffix = { titleSuffix }
301
357
/>
@@ -321,7 +377,6 @@ const SideNavLink = ({
321
377
) : null }
322
378
{ currentLevel === 3 && isActive ? < CurvedVerticalLine /> : null }
323
379
</ StyledNavLinkContainer >
324
-
325
380
{ children ? (
326
381
< FloatingPortal root = { l2PortalContainerRef } >
327
382
{ isActive && isL1Collapsed ? (
0 commit comments