@astryxdesign/core 0.4.1 → 0.4.2-canary.356d2f9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -0
- package/dist/Avatar/Avatar.d.ts +4 -1
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +19 -23
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +7 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +9 -7
- package/dist/Chat/ChatMessage.d.ts +7 -0
- package/dist/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/Chat/ChatMessageBubble.d.ts +13 -1
- package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
- package/dist/Chat/ChatMessageBubble.js +19 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +5 -0
- package/dist/CommandPalette/CommandPaletteFooter.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteFooter.js +5 -3
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +2 -2
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +19 -15
- package/dist/HoverCard/HoverCard.d.ts +1 -1
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +5 -13
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +6 -5
- package/dist/InputGroup/groupStyles.d.ts.map +1 -1
- package/dist/InputGroup/groupStyles.js +7 -2
- package/dist/Layer/layerHost.d.ts +24 -0
- package/dist/Layer/layerHost.d.ts.map +1 -0
- package/dist/Layer/layerHost.js +79 -0
- package/dist/Layer/useLayer.d.ts +14 -6
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +158 -30
- package/dist/NavItem/navItemStyles.stylex.d.ts +17 -5
- package/dist/NavItem/navItemStyles.stylex.d.ts.map +1 -1
- package/dist/NavItem/navItemStyles.stylex.js +11 -5
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +5 -0
- package/dist/SideNav/SideNav.d.ts +7 -9
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +32 -5
- package/dist/SideNav/SideNavCollapseButton.d.ts +25 -9
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +39 -15
- package/dist/SideNav/SideNavCollapseContext.d.ts +21 -0
- package/dist/SideNav/SideNavCollapseContext.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseContext.js +16 -2
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +89 -32
- package/dist/SideNav/SideNavItem.d.ts +7 -2
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +119 -75
- package/dist/SideNav/SideNavSection.d.ts.map +1 -1
- package/dist/SideNav/SideNavSection.js +7 -16
- package/dist/SideNav/index.d.ts +1 -1
- package/dist/SideNav/index.d.ts.map +1 -1
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +56 -15
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +5 -0
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +5 -0
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +14 -6
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +25 -93
- package/dist/TopNav/TopNavMegaMenuItem.js +1 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +10 -5
- package/dist/astryx.css +40 -8
- package/dist/astryx.umd.js +50 -50
- package/dist/astryx.umd.js.map +4 -4
- package/dist/hooks/containerReveal.stylex.d.ts +71 -4
- package/dist/hooks/containerReveal.stylex.d.ts.map +1 -1
- package/dist/hooks/containerReveal.stylex.js +57 -5
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/useContainerReveal.d.ts +60 -3
- package/dist/hooks/useContainerReveal.d.ts.map +1 -1
- package/dist/hooks/useContainerReveal.js +27 -5
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +16 -2
- package/dist/hooks/useMenuHover.d.ts +50 -5
- package/dist/hooks/useMenuHover.d.ts.map +1 -1
- package/dist/hooks/useMenuHover.js +171 -51
- package/dist/theme/defineTheme.d.ts +16 -5
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/defineTheme.js +44 -48
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +7 -0
- package/dist/theme/expandColorScale.d.ts.map +1 -1
- package/dist/theme/expandColorScale.js +1 -0
- package/dist/theme/expandMotionScale.d.ts +1 -0
- package/dist/theme/expandMotionScale.d.ts.map +1 -1
- package/dist/theme/expandMotionScale.js +1 -0
- package/dist/theme/expandRadiusScale.d.ts +1 -0
- package/dist/theme/expandRadiusScale.d.ts.map +1 -1
- package/dist/theme/expandRadiusScale.js +1 -0
- package/dist/theme/expandTypeScale.d.ts +1 -0
- package/dist/theme/expandTypeScale.d.ts.map +1 -1
- package/dist/theme/expandTypeScale.js +1 -0
- package/dist/theme/mergeComponents.d.ts +20 -0
- package/dist/theme/mergeComponents.d.ts.map +1 -0
- package/dist/theme/mergeComponents.js +56 -0
- package/dist/theme/onMediaTokens.d.ts +6 -1
- package/dist/theme/onMediaTokens.d.ts.map +1 -1
- package/dist/theme/onMediaTokens.js +11 -3
- package/dist/theme/tokens.stylex.d.ts +3 -1
- package/dist/theme/tokens.stylex.d.ts.map +1 -1
- package/dist/theme/tokens.stylex.js +3 -1
- package/locales/en.json +84 -0
- package/locales/pseudo.json +63 -0
- package/package.json +3 -3
- package/src/Avatar/Avatar.doc.mjs +5 -2
- package/src/Avatar/Avatar.test.tsx +51 -0
- package/src/Avatar/Avatar.tsx +30 -20
- package/src/AvatarGroup/AvatarGroup.doc.mjs +1 -1
- package/src/AvatarGroup/AvatarGroup.test.tsx +14 -0
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +3 -2
- package/src/Button/Button.tsx +5 -3
- package/src/ButtonGroup/ButtonGroup.test.tsx +7 -4
- package/src/Card/Card.doc.mjs +2 -0
- package/src/Chat/Chat.doc.mjs +4 -1
- package/src/Chat/ChatMessage.doc.mjs +3 -3
- package/src/Chat/ChatMessage.tsx +7 -0
- package/src/Chat/ChatMessageBubble.doc.mjs +7 -0
- package/src/Chat/ChatMessageBubble.test.tsx +95 -6
- package/src/Chat/ChatMessageBubble.tsx +25 -0
- package/src/CheckboxInput/CheckboxInput.tsx +20 -0
- package/src/CodeBlock/CodeBlock.doc.mjs +3 -0
- package/src/CommandPalette/CommandPaletteFooter.tsx +6 -3
- package/src/DateTimeInput/DateTimeInput.tsx +4 -2
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +72 -1
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +24 -20
- package/src/HoverCard/HoverCard.doc.mjs +3 -3
- package/src/HoverCard/HoverCard.test.tsx +283 -55
- package/src/HoverCard/HoverCard.tsx +5 -13
- package/src/HoverCard/useHoverCard.tsx +8 -11
- package/src/InputGroup/groupStyles.ts +7 -8
- package/src/Item/Item.doc.mjs +4 -0
- package/src/Layer/layerHost.test.ts +99 -0
- package/src/Layer/layerHost.ts +141 -0
- package/src/Layer/useLayer.doc.mjs +14 -4
- package/src/Layer/useLayer.test.tsx +332 -7
- package/src/Layer/useLayer.tsx +235 -36
- package/src/MobileNav/MobileNav.doc.mjs +7 -0
- package/src/NavItem/navItemStyles.stylex.ts +31 -5
- package/src/RadioList/RadioListItem.tsx +20 -0
- package/src/SideNav/SideNav.doc.mjs +13 -4
- package/src/SideNav/SideNav.test.tsx +858 -2
- package/src/SideNav/SideNav.tsx +37 -16
- package/src/SideNav/SideNavCollapseButton.doc.mjs +28 -6
- package/src/SideNav/SideNavCollapseButton.tsx +67 -15
- package/src/SideNav/SideNavCollapseContext.ts +29 -9
- package/src/SideNav/SideNavHeading.tsx +53 -25
- package/src/SideNav/SideNavItem.doc.mjs +13 -0
- package/src/SideNav/SideNavItem.tsx +97 -84
- package/src/SideNav/SideNavSection.tsx +6 -20
- package/src/SideNav/index.ts +2 -0
- package/src/Slider/Slider.test.tsx +69 -33
- package/src/Slider/Slider.tsx +65 -13
- package/src/Switch/Switch.tsx +20 -0
- package/src/TabList/TabList.doc.mjs +3 -0
- package/src/Text/Text.doc.mjs +1 -1
- package/src/Thumbnail/Thumbnail.doc.mjs +3 -0
- package/src/Thumbnail/Thumbnail.tsx +10 -0
- package/src/Timestamp/Timestamp.test.tsx +40 -22
- package/src/Toolbar/Toolbar.test.tsx +14 -14
- package/src/TopNav/TopNav.test.tsx +86 -1
- package/src/TopNav/TopNavHeading.tsx +21 -14
- package/src/TopNav/TopNavMegaMenu.test.tsx +43 -0
- package/src/TopNav/TopNavMegaMenu.tsx +29 -105
- package/src/TopNav/TopNavMegaMenuItem.tsx +1 -1
- package/src/TopNav/TopNavMenu.test.tsx +41 -0
- package/src/TopNav/TopNavMenu.tsx +14 -4
- package/src/TreeList/TreeList.doc.mjs +1 -0
- package/src/hooks/containerReveal.stylex.ts +140 -9
- package/src/hooks/index.ts +6 -1
- package/src/hooks/useContainerReveal.doc.mjs +11 -5
- package/src/hooks/useContainerReveal.test.tsx +70 -3
- package/src/hooks/useContainerReveal.ts +86 -7
- package/src/hooks/useFocusTrap.test.tsx +16 -0
- package/src/hooks/useFocusTrap.ts +20 -2
- package/src/hooks/useMenuHover.test.tsx +364 -0
- package/src/hooks/useMenuHover.ts +243 -47
- package/src/theme/defineTheme.test.ts +127 -0
- package/src/theme/defineTheme.ts +57 -51
- package/src/theme/derivedVarRegistry.test.ts +78 -12
- package/src/theme/derivedVarRegistry.ts +4 -0
- package/src/theme/expandColorScale.ts +1 -0
- package/src/theme/expandMotionScale.ts +1 -0
- package/src/theme/expandRadiusScale.ts +1 -0
- package/src/theme/expandTypeScale.ts +1 -0
- package/src/theme/mergeComponents.ts +59 -0
- package/src/theme/onMediaTokens.ts +9 -2
- package/src/theme/themingTargets.test.ts +152 -26
- package/src/theme/tokens.stylex.ts +3 -1
- package/src/theme/tokens.test.ts +12 -0
- package/src/theme/useTheme.test.tsx +18 -0
package/src/SideNav/SideNav.tsx
CHANGED
|
@@ -36,6 +36,7 @@ import {mergeProps, mergeRefs} from '../utils';
|
|
|
36
36
|
import {
|
|
37
37
|
SideNavCollapseContext,
|
|
38
38
|
type SideNavCollapseState,
|
|
39
|
+
type SideNavCollapsibleConfig,
|
|
39
40
|
type SideNavImperativeCollapseHandle,
|
|
40
41
|
} from './SideNavCollapseContext';
|
|
41
42
|
import {SideNavCollapseButton} from './SideNavCollapseButton';
|
|
@@ -45,6 +46,7 @@ import {useResizable} from '../Resizable/useResizable';
|
|
|
45
46
|
import type {ResizableConfig} from '../Resizable/useResizable';
|
|
46
47
|
import {ResizeHandle} from '../Resizable/ResizeHandle';
|
|
47
48
|
import {themeProps} from '../utils/themeProps';
|
|
49
|
+
import {SizeProvider} from '../SizeContext/SizeContext';
|
|
48
50
|
import {useTranslator} from '../i18n';
|
|
49
51
|
|
|
50
52
|
// =============================================================================
|
|
@@ -185,6 +187,13 @@ const styles = stylex.create({
|
|
|
185
187
|
},
|
|
186
188
|
});
|
|
187
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Cascaded to the icon rows through `SizeContext` so the built-in collapse
|
|
192
|
+
* button and the consumer's `footerIcons` come out one height. An explicit
|
|
193
|
+
* `size` on a child still wins.
|
|
194
|
+
*/
|
|
195
|
+
const FOOTER_ICON_SIZE = 'sm';
|
|
196
|
+
|
|
188
197
|
// =============================================================================
|
|
189
198
|
// Types
|
|
190
199
|
// =============================================================================
|
|
@@ -197,6 +206,9 @@ export interface SideNavProps extends BaseProps<HTMLElement> {
|
|
|
197
206
|
* Imperative collapse handle for SideNavCollapseButton instances rendered
|
|
198
207
|
* outside this SideNav. This intentionally stays separate from `ref`, which
|
|
199
208
|
* continues to expose the root HTMLElement.
|
|
209
|
+
*
|
|
210
|
+
* @deprecated Hand the same controlled `collapsible` config to SideNav and
|
|
211
|
+
* to the outside button instead.
|
|
200
212
|
*/
|
|
201
213
|
handleRef?: React.Ref<SideNavImperativeCollapseHandle>;
|
|
202
214
|
|
|
@@ -270,21 +282,14 @@ export interface SideNavProps extends BaseProps<HTMLElement> {
|
|
|
270
282
|
* - `true` — enables collapse with default toggle button and uncontrolled state
|
|
271
283
|
* - Object — enables collapse with advanced configuration:
|
|
272
284
|
* - `defaultIsCollapsed` — start collapsed (uncontrolled)
|
|
273
|
-
* - `isCollapsed` + `onCollapsedChange` — controlled mode
|
|
285
|
+
* - `isCollapsed` + `onCollapsedChange` — controlled mode. Pass the same
|
|
286
|
+
* object to a `SideNavCollapseButton` rendered outside this SideNav
|
|
274
287
|
* - `hasButton` — render built-in collapse button (default: true)
|
|
275
288
|
* - `buttonLabel` — accessibility label for the collapse button
|
|
276
289
|
*
|
|
277
290
|
* @default false
|
|
278
291
|
*/
|
|
279
|
-
collapsible?:
|
|
280
|
-
| boolean
|
|
281
|
-
| {
|
|
282
|
-
defaultIsCollapsed?: boolean;
|
|
283
|
-
isCollapsed?: boolean;
|
|
284
|
-
onCollapsedChange?: (isCollapsed: boolean) => void;
|
|
285
|
-
hasButton?: boolean;
|
|
286
|
-
buttonLabel?: string;
|
|
287
|
-
};
|
|
292
|
+
collapsible?: boolean | SideNavCollapsibleConfig;
|
|
288
293
|
}
|
|
289
294
|
|
|
290
295
|
// =============================================================================
|
|
@@ -375,6 +380,8 @@ export function SideNav({
|
|
|
375
380
|
const toggle = useCallback(() => {
|
|
376
381
|
const next = !collapsed;
|
|
377
382
|
|
|
383
|
+
// Deprecated `handleRef` path only: an out-of-tree button reads this
|
|
384
|
+
// snapshot while rendering, which can happen before SideNav re-renders.
|
|
378
385
|
collapseStateRef.current = {
|
|
379
386
|
...collapseStateRef.current,
|
|
380
387
|
isCollapsed: next,
|
|
@@ -429,7 +436,9 @@ export function SideNav({
|
|
|
429
436
|
style,
|
|
430
437
|
)}>
|
|
431
438
|
{header}
|
|
432
|
-
<div {...stylex.props(styles.topbarIcons)}>
|
|
439
|
+
<div {...stylex.props(styles.topbarIcons)}>
|
|
440
|
+
<SizeProvider value={FOOTER_ICON_SIZE}>{footerIcons}</SizeProvider>
|
|
441
|
+
</div>
|
|
433
442
|
</div>
|
|
434
443
|
);
|
|
435
444
|
}
|
|
@@ -441,7 +450,13 @@ export function SideNav({
|
|
|
441
450
|
|
|
442
451
|
if (renderMode === 'drawer') {
|
|
443
452
|
return (
|
|
444
|
-
<MobileNav
|
|
453
|
+
<MobileNav
|
|
454
|
+
header={header}
|
|
455
|
+
data-testid={testId}
|
|
456
|
+
xstyle={xstyle}
|
|
457
|
+
className={className}
|
|
458
|
+
style={style}
|
|
459
|
+
{...props}>
|
|
445
460
|
{topContent}
|
|
446
461
|
{children}
|
|
447
462
|
{hasDrawerFooter && (
|
|
@@ -449,7 +464,9 @@ export function SideNav({
|
|
|
449
464
|
{footer}
|
|
450
465
|
{footerIcons && (
|
|
451
466
|
<div {...stylex.props(styles.drawerFooterIcons)}>
|
|
452
|
-
{
|
|
467
|
+
<SizeProvider value={FOOTER_ICON_SIZE}>
|
|
468
|
+
{footerIcons}
|
|
469
|
+
</SizeProvider>
|
|
453
470
|
</div>
|
|
454
471
|
)}
|
|
455
472
|
</div>
|
|
@@ -472,7 +489,9 @@ export function SideNav({
|
|
|
472
489
|
{footer}
|
|
473
490
|
{footerIcons && (
|
|
474
491
|
<div {...stylex.props(styles.drawerFooterIcons)}>
|
|
475
|
-
{
|
|
492
|
+
<SizeProvider value={FOOTER_ICON_SIZE}>
|
|
493
|
+
{footerIcons}
|
|
494
|
+
</SizeProvider>
|
|
476
495
|
</div>
|
|
477
496
|
)}
|
|
478
497
|
</div>
|
|
@@ -544,8 +563,10 @@ export function SideNav({
|
|
|
544
563
|
styles.footerRow,
|
|
545
564
|
collapsed && styles.footerRowCollapsed,
|
|
546
565
|
)}>
|
|
547
|
-
|
|
548
|
-
|
|
566
|
+
<SizeProvider value={FOOTER_ICON_SIZE}>
|
|
567
|
+
{showCollapseButton && <SideNavCollapseButton />}
|
|
568
|
+
{footerIcons}
|
|
569
|
+
</SizeProvider>
|
|
549
570
|
</div>
|
|
550
571
|
</div>
|
|
551
572
|
)}
|
|
@@ -7,18 +7,28 @@ export const docs = {
|
|
|
7
7
|
subComponentOf: 'SideNav',
|
|
8
8
|
displayName: 'Side Nav Collapse Button',
|
|
9
9
|
isHiddenFromOverview: true,
|
|
10
|
-
description: 'Toggle button for sidenav collapse. Place inside SideNav (reads context automatically) or outside (
|
|
10
|
+
description: 'Toggle button for sidenav collapse. Place inside SideNav (reads context automatically) or outside it (hand the same controlled collapsible config to both). Renders as an icon-only ghost button by default.',
|
|
11
11
|
props: [
|
|
12
|
+
{
|
|
13
|
+
name: 'collapsible',
|
|
14
|
+
type: '{isCollapsed: boolean, onCollapsedChange: (isCollapsed: boolean) => void}',
|
|
15
|
+
description: 'The same controlled collapsible config passed to SideNav. Only needed when the button is rendered outside the sidenav, where collapse context cannot reach it.',
|
|
16
|
+
},
|
|
12
17
|
{
|
|
13
18
|
name: 'handleRef',
|
|
14
19
|
type: 'RefObject<SideNavImperativeCollapseHandle | null>',
|
|
15
|
-
description: 'Imperative collapse handle from SideNav
|
|
20
|
+
description: 'Deprecated. Imperative collapse handle from SideNav; pass collapsible instead.',
|
|
16
21
|
},
|
|
17
22
|
{
|
|
18
23
|
name: 'label',
|
|
19
24
|
type: 'string',
|
|
20
25
|
description: 'Custom button label. When provided, renders as a text button with chevron. When omitted, renders icon-only.',
|
|
21
26
|
},
|
|
27
|
+
{
|
|
28
|
+
name: 'size',
|
|
29
|
+
type: "'sm' | 'md' | 'lg'",
|
|
30
|
+
description: "Button size. Defaults to the size its container cascades ('sm' inside a SideNav footer) and to 'md' with no container. Set it when the button sits outside a sized container and has to match its neighbours.",
|
|
31
|
+
},
|
|
22
32
|
{
|
|
23
33
|
name: 'children',
|
|
24
34
|
type: 'ReactNode',
|
|
@@ -31,18 +41,28 @@ export const docsZh = {
|
|
|
31
41
|
name: 'SideNavCollapseButton',
|
|
32
42
|
isHiddenFromOverview: true,
|
|
33
43
|
displayName: 'Side Nav Collapse Button',
|
|
34
|
-
description: '侧边栏折叠切换按钮。放置在 SideNav
|
|
44
|
+
description: '侧边栏折叠切换按钮。放置在 SideNav 内部(自动读取上下文)或外部(向两者传入同一个受控 collapsible 配置)。默认渲染为仅图标的 ghost 按钮。',
|
|
35
45
|
props: [
|
|
46
|
+
{
|
|
47
|
+
name: 'collapsible',
|
|
48
|
+
type: '{isCollapsed: boolean, onCollapsedChange: (isCollapsed: boolean) => void}',
|
|
49
|
+
description: '与 SideNav 相同的受控 collapsible 配置。仅在按钮渲染在侧边栏外部、无法读取折叠上下文时需要。',
|
|
50
|
+
},
|
|
36
51
|
{
|
|
37
52
|
name: 'handleRef',
|
|
38
53
|
type: 'RefObject<SideNavImperativeCollapseHandle | null>',
|
|
39
|
-
description: '
|
|
54
|
+
description: '已废弃。来自 SideNav 的命令式折叠句柄;请改用 collapsible。',
|
|
40
55
|
},
|
|
41
56
|
{
|
|
42
57
|
name: 'label',
|
|
43
58
|
type: 'string',
|
|
44
59
|
description: '自定义按钮标签。提供时渲染为带箭头的文本按钮。省略时渲染为仅图标按钮。',
|
|
45
60
|
},
|
|
61
|
+
{
|
|
62
|
+
name: 'size',
|
|
63
|
+
type: "'sm' | 'md' | 'lg'",
|
|
64
|
+
description: "按钮尺寸。默认使用容器级联的尺寸(SideNav 页脚内为 'sm'),无容器时为 'md'。当按钮位于已设定尺寸的容器之外且需要与相邻元素保持一致时显式设置。",
|
|
65
|
+
},
|
|
46
66
|
{
|
|
47
67
|
name: 'children',
|
|
48
68
|
type: 'ReactNode',
|
|
@@ -55,10 +75,12 @@ export const docsDense = {
|
|
|
55
75
|
name: 'SideNavCollapseButton',
|
|
56
76
|
isHiddenFromOverview: true,
|
|
57
77
|
displayName: 'Side Nav Collapse Button',
|
|
58
|
-
description: 'Toggle button for sidenav collapse. Place inside SideNav (reads context) or outside (pass
|
|
78
|
+
description: 'Toggle button for sidenav collapse. Place inside SideNav (reads context) or outside (pass the same controlled collapsible config both get). Icon-only ghost button by default.',
|
|
59
79
|
propDescriptions: {
|
|
60
|
-
|
|
80
|
+
collapsible: 'Controlled collapsible config, same object SideNav gets. Only needed when button rendered outside sidenav.',
|
|
81
|
+
handleRef: 'Deprecated. Pass collapsible instead.',
|
|
61
82
|
label: 'Custom label. Text button w/ chevron when provided, icon-only when omitted.',
|
|
83
|
+
size: "Button size. Inherits from the container ('sm' in a SideNav footer), else 'md'.",
|
|
62
84
|
children: 'Custom content. Overrides default chevron icon + label.',
|
|
63
85
|
},
|
|
64
86
|
};
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* @position Composable toggle button for sidenav collapse
|
|
10
10
|
*
|
|
11
11
|
* Place inside SideNav (reads context automatically) or outside
|
|
12
|
-
* (pass
|
|
12
|
+
* (pass the same controlled `collapsible` config both get).
|
|
13
13
|
*
|
|
14
14
|
* SYNC: When modified, update:
|
|
15
15
|
* - /packages/core/src/SideNav/SideNav.doc.mjs
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* - /packages/cli/assets/templates/blocks/components/SideNav/ (showcase blocks)
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import React, {type ReactNode} from 'react';
|
|
20
|
+
import React, {useCallback, type ReactNode} from 'react';
|
|
21
21
|
import * as stylex from '@stylexjs/stylex';
|
|
22
22
|
import {durationVars, easeVars} from '../theme/tokens.stylex';
|
|
23
23
|
import {Icon} from '../Icon';
|
|
@@ -27,21 +27,34 @@ import {composeEventHandlers, rtlStyles} from '../utils';
|
|
|
27
27
|
import {
|
|
28
28
|
useSideNavCollapse,
|
|
29
29
|
type SideNavCollapseState,
|
|
30
|
+
type SideNavControlledCollapsible,
|
|
30
31
|
type SideNavImperativeCollapseHandle,
|
|
31
32
|
} from './SideNavCollapseContext';
|
|
32
33
|
import {useAppShellMobile} from '../AppShell/AppShellMobileContext';
|
|
33
34
|
import {useTranslator} from '../i18n';
|
|
35
|
+
import type {ElementSize} from '../SizeContext/SizeContext';
|
|
34
36
|
|
|
35
37
|
// =============================================================================
|
|
36
38
|
// Styles
|
|
37
39
|
// =============================================================================
|
|
38
40
|
|
|
39
41
|
const styles = stylex.create({
|
|
42
|
+
// A flex container, so the glyph is a flex item. Left to blockify as a flex
|
|
43
|
+
// item of Button's icon slot, this span gets a line box and seats the
|
|
44
|
+
// chevron on its text baseline — 2.42px above the button's centre.
|
|
45
|
+
chevronMirror: {
|
|
46
|
+
display: 'flex',
|
|
47
|
+
alignItems: 'center',
|
|
48
|
+
justifyContent: 'center',
|
|
49
|
+
},
|
|
40
50
|
chevron: {
|
|
41
51
|
display: 'inline-flex',
|
|
42
52
|
alignItems: 'center',
|
|
43
53
|
transitionProperty: 'transform',
|
|
44
|
-
transitionDuration:
|
|
54
|
+
transitionDuration: {
|
|
55
|
+
default: durationVars['--duration-fast'],
|
|
56
|
+
'@media (prefers-reduced-motion: reduce)': '0s',
|
|
57
|
+
},
|
|
45
58
|
transitionTimingFunction: easeVars['--ease-standard'],
|
|
46
59
|
},
|
|
47
60
|
chevronCollapsed: {
|
|
@@ -56,8 +69,16 @@ const styles = stylex.create({
|
|
|
56
69
|
export interface SideNavCollapseButtonProps extends BaseProps<HTMLButtonElement> {
|
|
57
70
|
ref?: React.Ref<HTMLButtonElement>;
|
|
58
71
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
72
|
+
* The same controlled `collapsible` config given to SideNav
|
|
73
|
+
* (`{isCollapsed, onCollapsedChange}`). Needed only when the button is
|
|
74
|
+
* rendered outside the sidenav, where collapse context cannot reach it.
|
|
75
|
+
*/
|
|
76
|
+
collapsible?: SideNavControlledCollapsible;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Imperative handle from SideNav.
|
|
80
|
+
*
|
|
81
|
+
* @deprecated Pass `collapsible` instead.
|
|
61
82
|
*/
|
|
62
83
|
handleRef?: React.RefObject<SideNavImperativeCollapseHandle | null>;
|
|
63
84
|
|
|
@@ -67,6 +88,13 @@ export interface SideNavCollapseButtonProps extends BaseProps<HTMLButtonElement>
|
|
|
67
88
|
*/
|
|
68
89
|
label?: string;
|
|
69
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Button size. Defaults to the size its container cascades — `sm` in a
|
|
93
|
+
* SideNav footer — or `md` outside one. Set it for placements with no row
|
|
94
|
+
* to inherit from, e.g. a button placed in a `TopNav`.
|
|
95
|
+
*/
|
|
96
|
+
size?: ElementSize;
|
|
97
|
+
|
|
70
98
|
/**
|
|
71
99
|
* Custom button content. Overrides the default chevron icon and label.
|
|
72
100
|
*/
|
|
@@ -82,7 +110,8 @@ export interface SideNavCollapseButtonProps extends BaseProps<HTMLButtonElement>
|
|
|
82
110
|
*
|
|
83
111
|
* Place anywhere inside SideNav (header, topContent, footer, footerIcons)
|
|
84
112
|
* and it reads collapse state from context automatically. For placement
|
|
85
|
-
* outside the sidenav (e.g. in TopNav or content area),
|
|
113
|
+
* outside the sidenav (e.g. in TopNav or content area), hold the state and
|
|
114
|
+
* hand the same `collapsible` config to both.
|
|
86
115
|
*
|
|
87
116
|
* @example
|
|
88
117
|
* ```
|
|
@@ -93,22 +122,27 @@ export interface SideNavCollapseButtonProps extends BaseProps<HTMLButtonElement>
|
|
|
93
122
|
*
|
|
94
123
|
* @example
|
|
95
124
|
* ```
|
|
96
|
-
* const
|
|
97
|
-
*
|
|
98
|
-
* <
|
|
125
|
+
* const [isCollapsed, setIsCollapsed] = useState(false);
|
|
126
|
+
* const collapsible = {isCollapsed, onCollapsedChange: setIsCollapsed};
|
|
127
|
+
* <TopNav endContent={<SideNavCollapseButton collapsible={collapsible} />} />
|
|
128
|
+
* <SideNav collapsible={{...collapsible, hasButton: false}}>...</SideNav>
|
|
99
129
|
* ```
|
|
100
130
|
*/
|
|
101
131
|
export function SideNavCollapseButton({
|
|
102
132
|
ref,
|
|
133
|
+
collapsible,
|
|
103
134
|
handleRef,
|
|
104
135
|
label,
|
|
136
|
+
size,
|
|
105
137
|
children,
|
|
106
138
|
onClick: onClickProp,
|
|
107
139
|
...props
|
|
108
140
|
}: SideNavCollapseButtonProps) {
|
|
109
141
|
const t = useTranslator();
|
|
110
|
-
const {isCollapsed, toggle, isCollapsible} =
|
|
111
|
-
|
|
142
|
+
const {isCollapsed, toggle, isCollapsible} = useSideNavCollapseState(
|
|
143
|
+
collapsible,
|
|
144
|
+
handleRef,
|
|
145
|
+
);
|
|
112
146
|
const {isMobile} = useAppShellMobile();
|
|
113
147
|
|
|
114
148
|
// Hide when not collapsible, or when in mobile mode (sidenav is in
|
|
@@ -127,6 +161,7 @@ export function SideNavCollapseButton({
|
|
|
127
161
|
: t('@astryx.sideNavCollapseButton.collapseSidebar'))
|
|
128
162
|
}
|
|
129
163
|
variant="ghost"
|
|
164
|
+
size={size}
|
|
130
165
|
{...props}
|
|
131
166
|
onClick={composeEventHandlers(onClickProp, toggle)}
|
|
132
167
|
icon={
|
|
@@ -135,7 +170,7 @@ export function SideNavCollapseButton({
|
|
|
135
170
|
// into) the state rotation: both are `transform`, so on a single
|
|
136
171
|
// element one would overwrite the other and the chevron would stop
|
|
137
172
|
// mirroring under RTL. See utils/rtlStyles.ts.
|
|
138
|
-
<span {...stylex.props(rtlStyles.mirror)}>
|
|
173
|
+
<span {...stylex.props(styles.chevronMirror, rtlStyles.mirror)}>
|
|
139
174
|
{/* `sm` (1rem) matches what this glyph already renders at: Button's
|
|
140
175
|
icon slot pins its wrapper to 16px, and the registry SVG is
|
|
141
176
|
1em, so the chevron is 16px today. */}
|
|
@@ -156,11 +191,30 @@ export function SideNavCollapseButton({
|
|
|
156
191
|
SideNavCollapseButton.displayName = 'SideNavCollapseButton';
|
|
157
192
|
|
|
158
193
|
function useSideNavCollapseState(
|
|
194
|
+
collapsible: SideNavControlledCollapsible | undefined,
|
|
159
195
|
handleRef:
|
|
160
196
|
React.RefObject<SideNavImperativeCollapseHandle | null> | undefined,
|
|
161
197
|
): SideNavCollapseState {
|
|
162
198
|
const contextCollapseState = useSideNavCollapse();
|
|
163
199
|
|
|
200
|
+
const {isCollapsed, onCollapsedChange} = collapsible ?? {};
|
|
201
|
+
const toggleCollapsible = useCallback(
|
|
202
|
+
() => onCollapsedChange?.(!isCollapsed),
|
|
203
|
+
[isCollapsed, onCollapsedChange],
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
const toggleHandle = useCallback(() => {
|
|
207
|
+
handleRef?.current?.getCollapseState()?.toggle();
|
|
208
|
+
}, [handleRef]);
|
|
209
|
+
|
|
210
|
+
if (collapsible != null) {
|
|
211
|
+
return {
|
|
212
|
+
isCollapsed: isCollapsed ?? false,
|
|
213
|
+
toggle: toggleCollapsible,
|
|
214
|
+
isCollapsible: true,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
164
218
|
if (handleRef == null) {
|
|
165
219
|
return contextCollapseState;
|
|
166
220
|
}
|
|
@@ -169,9 +223,7 @@ function useSideNavCollapseState(
|
|
|
169
223
|
|
|
170
224
|
return {
|
|
171
225
|
isCollapsed: externalCollapseState?.isCollapsed ?? false,
|
|
172
|
-
toggle:
|
|
173
|
-
handleRef.current?.getCollapseState()?.toggle();
|
|
174
|
-
},
|
|
226
|
+
toggle: toggleHandle,
|
|
175
227
|
isCollapsible: externalCollapseState?.isCollapsible ?? true,
|
|
176
228
|
};
|
|
177
229
|
}
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Provides collapse state to SideNavCollapseButton and other
|
|
12
12
|
* sidenav children. Set by SideNav when isCollapsible is true.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* A button rendered outside the SideNav tree is out of context's reach and
|
|
14
|
+
* takes the controlled `collapsible` config as a prop instead.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import {createContext, use} from 'react';
|
|
@@ -25,18 +25,38 @@ export interface SideNavCollapseState {
|
|
|
25
25
|
isCollapsible: boolean;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/** Object form of SideNav's `collapsible` prop. */
|
|
29
|
+
export interface SideNavCollapsibleConfig {
|
|
30
|
+
defaultIsCollapsed?: boolean;
|
|
31
|
+
isCollapsed?: boolean;
|
|
32
|
+
onCollapsedChange?: (isCollapsed: boolean) => void;
|
|
33
|
+
hasButton?: boolean;
|
|
34
|
+
buttonLabel?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The controlled form: the consumer holds the state, so it can be handed to
|
|
39
|
+
* both SideNav and a SideNavCollapseButton rendered outside it.
|
|
40
|
+
*/
|
|
41
|
+
export interface SideNavControlledCollapsible extends SideNavCollapsibleConfig {
|
|
42
|
+
isCollapsed: boolean;
|
|
43
|
+
onCollapsedChange: (isCollapsed: boolean) => void;
|
|
44
|
+
}
|
|
28
45
|
|
|
46
|
+
/**
|
|
47
|
+
* @deprecated Pass the same controlled `collapsible` config to SideNav and to
|
|
48
|
+
* the out-of-tree SideNavCollapseButton instead. The state then reaches the
|
|
49
|
+
* button through props rather than through a ref.
|
|
50
|
+
*/
|
|
29
51
|
export interface SideNavImperativeCollapseHandle {
|
|
30
52
|
getCollapseState: () => SideNavCollapseState | null;
|
|
31
53
|
}
|
|
32
54
|
|
|
33
|
-
export const SideNavCollapseContext = createContext<SideNavCollapseState>(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
},
|
|
39
|
-
);
|
|
55
|
+
export const SideNavCollapseContext = createContext<SideNavCollapseState>({
|
|
56
|
+
isCollapsed: false,
|
|
57
|
+
toggle: () => {},
|
|
58
|
+
isCollapsible: false,
|
|
59
|
+
});
|
|
40
60
|
SideNavCollapseContext.displayName = 'SideNavCollapseContext';
|
|
41
61
|
|
|
42
62
|
/**
|
|
@@ -36,6 +36,7 @@ import {Link} from '../Link';
|
|
|
36
36
|
import {Icon} from '../Icon';
|
|
37
37
|
import {Tooltip} from '../Tooltip';
|
|
38
38
|
import {navItemStyles} from '../NavItem/navItemStyles.stylex';
|
|
39
|
+
import {focusOutlineProps} from '../utils/focusOutline.stylex';
|
|
39
40
|
import {useSideNavCollapse} from './SideNavCollapseContext';
|
|
40
41
|
import {useLinkComponent} from '../Link/useLinkComponent';
|
|
41
42
|
import type {LinkComponentType} from '../Link/types';
|
|
@@ -370,23 +371,27 @@ export function SideNavHeading({
|
|
|
370
371
|
hasCloseButton: false,
|
|
371
372
|
});
|
|
372
373
|
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
374
|
+
const {
|
|
375
|
+
triggerProps,
|
|
376
|
+
contentProps,
|
|
377
|
+
menuRef,
|
|
378
|
+
setTriggerEl,
|
|
379
|
+
close: closeMenu,
|
|
380
|
+
} = useMenuHover<HTMLDivElement>({
|
|
381
|
+
show: popover.show,
|
|
382
|
+
hide: popover.hide,
|
|
383
|
+
isOpen: popover.isOpen,
|
|
384
|
+
isEnabled: !!menu,
|
|
385
|
+
showDelay: 0,
|
|
386
|
+
});
|
|
377
387
|
|
|
378
|
-
const
|
|
379
|
-
useMenuHover<HTMLDivElement>({
|
|
380
|
-
show: popover.show,
|
|
381
|
-
hide: popover.hide,
|
|
382
|
-
isOpen: popover.isOpen,
|
|
383
|
-
isEnabled: !!menu,
|
|
384
|
-
showDelay: 0,
|
|
385
|
-
});
|
|
388
|
+
const closeMenuCtx = useMemo(() => ({closeMenu}), [closeMenu]);
|
|
386
389
|
|
|
390
|
+
// setTriggerEl belongs on the chevron button, not this root: it is the
|
|
391
|
+
// focus-restore target and a <div> cannot take focus. triggerRef stays here
|
|
392
|
+
// because the panel anchors to the whole heading.
|
|
387
393
|
const setRef = mergeRefs<HTMLDivElement>(
|
|
388
394
|
rootRef,
|
|
389
|
-
setTriggerEl,
|
|
390
395
|
ref,
|
|
391
396
|
menu ? popover.triggerRef : undefined,
|
|
392
397
|
);
|
|
@@ -401,7 +406,9 @@ export function SideNavHeading({
|
|
|
401
406
|
const collapsedSetRef = mergeRefs<HTMLElement>(
|
|
402
407
|
collapsedItemRef,
|
|
403
408
|
ref,
|
|
409
|
+
// Collapsed, this button is the trigger, so it takes both roles.
|
|
404
410
|
menu ? popover.triggerRef : undefined,
|
|
411
|
+
menu ? setTriggerEl : undefined,
|
|
405
412
|
);
|
|
406
413
|
|
|
407
414
|
let collapsedElement: ReactNode;
|
|
@@ -415,7 +422,11 @@ export function SideNavHeading({
|
|
|
415
422
|
data-testid={testId}
|
|
416
423
|
{...mergeProps(
|
|
417
424
|
themeProps('side-nav-heading'),
|
|
418
|
-
|
|
425
|
+
focusOutlineProps.focusVisible(
|
|
426
|
+
navItemStyles.item,
|
|
427
|
+
styles.rootCollapsed,
|
|
428
|
+
xstyle,
|
|
429
|
+
),
|
|
419
430
|
className,
|
|
420
431
|
style,
|
|
421
432
|
)}>
|
|
@@ -434,7 +445,7 @@ export function SideNavHeading({
|
|
|
434
445
|
{...triggerProps}
|
|
435
446
|
{...mergeProps(
|
|
436
447
|
themeProps('side-nav-heading'),
|
|
437
|
-
|
|
448
|
+
focusOutlineProps.focusVisible(
|
|
438
449
|
navItemStyles.item,
|
|
439
450
|
styles.rootCollapsed,
|
|
440
451
|
styles.menuTrigger,
|
|
@@ -452,8 +463,9 @@ export function SideNavHeading({
|
|
|
452
463
|
{...contentProps}>
|
|
453
464
|
<button
|
|
454
465
|
type="button"
|
|
455
|
-
{...
|
|
456
|
-
|
|
466
|
+
{...focusOutlineProps.focusVisible(styles.popoverHeading)}
|
|
467
|
+
// A close affordance, not the trigger: dismiss only.
|
|
468
|
+
onClick={closeMenu}>
|
|
457
469
|
{icon && <span {...stylex.props(styles.icon)}>{icon}</span>}
|
|
458
470
|
<span {...stylex.props(styles.textContainer)}>
|
|
459
471
|
{superheading && (
|
|
@@ -549,7 +561,10 @@ export function SideNavHeading({
|
|
|
549
561
|
{hasAnyHref && headingHref && menu ? (
|
|
550
562
|
<LinkComponent
|
|
551
563
|
href={headingHref}
|
|
552
|
-
{...
|
|
564
|
+
{...focusOutlineProps.focusVisible(
|
|
565
|
+
styles.heading,
|
|
566
|
+
styles.headingLink,
|
|
567
|
+
)}>
|
|
553
568
|
{heading}
|
|
554
569
|
</LinkComponent>
|
|
555
570
|
) : (
|
|
@@ -586,8 +601,9 @@ export function SideNavHeading({
|
|
|
586
601
|
const popoverHeadingContent = (
|
|
587
602
|
<button
|
|
588
603
|
type="button"
|
|
589
|
-
{...
|
|
590
|
-
|
|
604
|
+
{...focusOutlineProps.focusVisible(styles.popoverHeading)}
|
|
605
|
+
// A close affordance, not the trigger: dismiss only.
|
|
606
|
+
onClick={closeMenu}>
|
|
591
607
|
{icon && <span {...stylex.props(styles.icon)}>{icon}</span>}
|
|
592
608
|
{renderTextContent(
|
|
593
609
|
<Icon
|
|
@@ -609,7 +625,11 @@ export function SideNavHeading({
|
|
|
609
625
|
data-testid={testId}
|
|
610
626
|
{...mergeProps(
|
|
611
627
|
themeProps('side-nav-heading'),
|
|
612
|
-
|
|
628
|
+
focusOutlineProps.focusVisible(
|
|
629
|
+
styles.root,
|
|
630
|
+
styles.menuTrigger,
|
|
631
|
+
xstyle,
|
|
632
|
+
),
|
|
613
633
|
className,
|
|
614
634
|
style,
|
|
615
635
|
)}
|
|
@@ -639,6 +659,7 @@ export function SideNavHeading({
|
|
|
639
659
|
{icon && <span {...stylex.props(styles.icon)}>{icon}</span>}
|
|
640
660
|
{renderTextContent(
|
|
641
661
|
<button
|
|
662
|
+
ref={setTriggerEl}
|
|
642
663
|
type="button"
|
|
643
664
|
aria-label={t('@astryx.sideNav.heading.openMenu')}
|
|
644
665
|
onClick={e => {
|
|
@@ -646,7 +667,10 @@ export function SideNavHeading({
|
|
|
646
667
|
triggerProps.onClick();
|
|
647
668
|
}}
|
|
648
669
|
{...popover.triggerProps}
|
|
649
|
-
{...
|
|
670
|
+
{...focusOutlineProps.focusVisible(
|
|
671
|
+
styles.chevron,
|
|
672
|
+
styles.interactive,
|
|
673
|
+
)}>
|
|
650
674
|
<Icon
|
|
651
675
|
icon="chevronDown"
|
|
652
676
|
size="sm"
|
|
@@ -701,7 +725,7 @@ export function SideNavHeading({
|
|
|
701
725
|
<LinkComponent
|
|
702
726
|
href={headingHref}
|
|
703
727
|
aria-label={heading}
|
|
704
|
-
{...
|
|
728
|
+
{...focusOutlineProps.focusVisible(styles.icon)}>
|
|
705
729
|
{icon}
|
|
706
730
|
</LinkComponent>
|
|
707
731
|
) : (
|
|
@@ -710,6 +734,7 @@ export function SideNavHeading({
|
|
|
710
734
|
{renderTextContent(
|
|
711
735
|
showChevron ? (
|
|
712
736
|
<button
|
|
737
|
+
ref={setTriggerEl}
|
|
713
738
|
type="button"
|
|
714
739
|
aria-label={t('@astryx.sideNav.heading.openMenu')}
|
|
715
740
|
onClick={e => {
|
|
@@ -717,7 +742,10 @@ export function SideNavHeading({
|
|
|
717
742
|
triggerProps.onClick();
|
|
718
743
|
}}
|
|
719
744
|
{...popover.triggerProps}
|
|
720
|
-
{...
|
|
745
|
+
{...focusOutlineProps.focusVisible(
|
|
746
|
+
styles.chevron,
|
|
747
|
+
styles.interactive,
|
|
748
|
+
)}>
|
|
721
749
|
<Icon
|
|
722
750
|
icon="chevronDown"
|
|
723
751
|
size="sm"
|
|
@@ -770,7 +798,7 @@ export function SideNavHeading({
|
|
|
770
798
|
<LinkComponent
|
|
771
799
|
href={headingHref}
|
|
772
800
|
aria-label={heading}
|
|
773
|
-
{...
|
|
801
|
+
{...focusOutlineProps.focusVisible(styles.icon)}>
|
|
774
802
|
{icon}
|
|
775
803
|
</LinkComponent>
|
|
776
804
|
) : (
|
|
@@ -91,6 +91,12 @@ export const docs = {
|
|
|
91
91
|
description: 'Enables collapse behavior for items with children. Pass true for uncontrolled (starts expanded), or an object for controlled mode.',
|
|
92
92
|
default: 'false',
|
|
93
93
|
},
|
|
94
|
+
{
|
|
95
|
+
name: 'size',
|
|
96
|
+
type: "'sm' | 'md' | 'lg'",
|
|
97
|
+
description: 'Size variant for the nav item row.',
|
|
98
|
+
default: "'md'",
|
|
99
|
+
},
|
|
94
100
|
],
|
|
95
101
|
};
|
|
96
102
|
|
|
@@ -159,6 +165,12 @@ export const docsZh = {
|
|
|
159
165
|
description: '启用带子项的折叠行为。传 true 为非受控模式(默认展开),或传对象用于受控模式。',
|
|
160
166
|
default: 'false',
|
|
161
167
|
},
|
|
168
|
+
{
|
|
169
|
+
name: 'size',
|
|
170
|
+
type: "'sm' | 'md' | 'lg'",
|
|
171
|
+
description: '导航项的尺寸变体。',
|
|
172
|
+
default: "'md'",
|
|
173
|
+
},
|
|
162
174
|
],
|
|
163
175
|
};
|
|
164
176
|
|
|
@@ -179,5 +191,6 @@ export const docsDense = {
|
|
|
179
191
|
endContent: 'Right-side content such as badges or counts.',
|
|
180
192
|
children: 'Sub-items for nesting.',
|
|
181
193
|
collapsible: 'Enables collapse for items w/ children. true=uncontrolled, object=controlled mode.',
|
|
194
|
+
size: "Row size variant: 'sm' | 'md' | 'lg'.",
|
|
182
195
|
},
|
|
183
196
|
};
|