@wallarm-org/design-system 1.23.3-rc-fix-remote-shell-breadcrumb-transition.3 → 1.25.0
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/dist/components/AppShell/story-content/_storyAccountDropdown.d.ts +4 -1
- package/dist/components/AppShell/story-content/_storyAccountDropdown.js +64 -56
- package/dist/components/AppShell/story-content/_storyConfigRenderer.d.ts +4 -1
- package/dist/components/AppShell/story-content/_storyConfigRenderer.js +8 -5
- package/dist/components/AppShell/story-content/index.d.ts +1 -1
- package/dist/components/AppShell/story-content/index.js +1 -1
- package/dist/components/DropdownMenu/DropdownMenuRadioItem.js +1 -1
- package/dist/components/NavPanel/NavPanelBack.js +1 -1
- package/dist/components/NavPanel/NavPanelGroupLabel.js +1 -1
- package/dist/components/NavPanel/NavPanelSkeleton.js +1 -1
- package/dist/components/NavPanel/classes.js +4 -4
- package/dist/components/NavRail/NavRail.d.ts +7 -0
- package/dist/components/NavRail/NavRail.js +5 -3
- package/dist/components/NavRail/NavRailBody.js +6 -1
- package/dist/components/NavRail/NavRailContext.d.ts +2 -1
- package/dist/components/NavRail/NavRailContext.js +1 -1
- package/dist/components/NavRail/NavRailFooter.js +6 -1
- package/dist/components/NavRail/NavRailItem.d.ts +4 -0
- package/dist/components/NavRail/NavRailItem.js +31 -6
- package/dist/components/NavRail/NavRailSkeleton.js +24 -4
- package/dist/components/NavRail/classes.d.ts +12 -1
- package/dist/components/NavRail/classes.js +48 -7
- package/dist/components/NavRail/index.d.ts +1 -1
- package/dist/components/RemoteShell/NavPanelContent.d.ts +0 -5
- package/dist/components/RemoteShell/NavPanelContent.js +4 -6
- package/dist/components/RemoteShell/RemoteShell.js +3 -5
- package/dist/components/RemoteShell/RemoteShellPanel.js +4 -10
- package/dist/components/RemoteShell/model/index.d.ts +1 -1
- package/dist/components/RemoteShell/model/index.js +1 -1
- package/dist/components/RemoteShell/model/useDrillTransition.d.ts +1 -3
- package/dist/components/RemoteShell/model/useDrillTransition.js +11 -17
- package/dist/components/RemoteShell/model/useLocationPathname.d.ts +0 -2
- package/dist/components/RemoteShell/model/useLocationPathname.js +1 -4
- package/dist/components/SearchModal/SearchModal.js +1 -0
- package/dist/components/Skeleton/Skeleton.d.ts +1 -1
- package/dist/components/Skeleton/Skeleton.js +1 -0
- package/dist/components/SplashScreen/SplashScreen.js +17 -5
- package/dist/components/SplashScreen/index.d.ts +1 -1
- package/dist/components/SplashScreen/lib.d.ts +1 -1
- package/dist/components/SplashScreen/lib.js +7 -2
- package/dist/components/SplashScreen/types.d.ts +2 -1
- package/dist/components/SplashScreen/useContentHeight.d.ts +13 -0
- package/dist/components/SplashScreen/useContentHeight.js +33 -0
- package/dist/components/SplashScreen/useSplashPhase.d.ts +1 -1
- package/dist/components/SplashScreen/useSplashPhase.js +8 -2
- package/dist/index.d.ts +1 -1
- package/dist/metadata/components.json +52 -11
- package/dist/theme/radius.css +1 -0
- package/package.json +1 -1
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { type NavRailMode } from '../../NavRail';
|
|
1
2
|
import type { Theme } from '../../ThemeProvider';
|
|
2
|
-
export type SidebarMode = 'adaptive' | 'expanded';
|
|
3
|
+
export type SidebarMode = 'adaptive' | 'expanded' | 'collapsed' | 'compact';
|
|
4
|
+
/** Adaptive collapses the rail inside a product and expands it on Home; the other modes pin it. */
|
|
5
|
+
export declare const railModeFor: (mode: SidebarMode, onHome: boolean) => NavRailMode;
|
|
3
6
|
export declare const AccountDropdown: ({ sidebarMode, onSidebarModeChange, theme, onThemeChange, }: {
|
|
4
7
|
sidebarMode: SidebarMode;
|
|
5
8
|
onSidebarModeChange: (mode: SidebarMode) => void;
|
|
@@ -1,18 +1,42 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { Fragment } from "react";
|
|
3
|
+
import { LogOut, PanelLeftDashed, PencilRuler, Settings, User, UserRound } from "../../../icons/index.js";
|
|
4
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuItemContent, DropdownMenuItemIcon, DropdownMenuItemText, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger, DropdownMenuTriggerItem } from "../../DropdownMenu/index.js";
|
|
4
5
|
import { NavRailItem } from "../../NavRail/index.js";
|
|
5
6
|
import { HStack, VStack } from "../../Stack/index.js";
|
|
6
7
|
import { Text } from "../../Text/index.js";
|
|
8
|
+
const railModeFor = (mode, onHome)=>{
|
|
9
|
+
if ('adaptive' === mode) return onHome ? 'expanded' : 'collapsed';
|
|
10
|
+
return mode;
|
|
11
|
+
};
|
|
7
12
|
const USER_NAME = 'Meow Meow';
|
|
8
13
|
const USER_EMAIL = 'meow@meow.com';
|
|
14
|
+
const THEMES = [
|
|
15
|
+
'light',
|
|
16
|
+
'dark'
|
|
17
|
+
];
|
|
18
|
+
const SIDEBAR_MODE_GROUPS = [
|
|
19
|
+
[
|
|
20
|
+
'adaptive'
|
|
21
|
+
],
|
|
22
|
+
[
|
|
23
|
+
'expanded',
|
|
24
|
+
'collapsed'
|
|
25
|
+
],
|
|
26
|
+
[
|
|
27
|
+
'compact'
|
|
28
|
+
]
|
|
29
|
+
];
|
|
30
|
+
const SIDEBAR_MODES = SIDEBAR_MODE_GROUPS.flat();
|
|
9
31
|
const THEME_LABELS = {
|
|
10
32
|
light: 'Light',
|
|
11
33
|
dark: 'Dark'
|
|
12
34
|
};
|
|
13
35
|
const SIDEBAR_MODE_LABELS = {
|
|
14
36
|
adaptive: 'Adaptive',
|
|
15
|
-
expanded: 'Always expanded'
|
|
37
|
+
expanded: 'Always expanded',
|
|
38
|
+
collapsed: 'Always collapsed',
|
|
39
|
+
compact: 'Compact'
|
|
16
40
|
};
|
|
17
41
|
const AccountDropdown = ({ sidebarMode, onSidebarModeChange, theme, onThemeChange })=>/*#__PURE__*/ jsxs(DropdownMenu, {
|
|
18
42
|
positioning: {
|
|
@@ -25,8 +49,9 @@ const AccountDropdown = ({ sidebarMode, onSidebarModeChange, theme, onThemeChang
|
|
|
25
49
|
children: [
|
|
26
50
|
/*#__PURE__*/ jsx(DropdownMenuTrigger, {
|
|
27
51
|
children: /*#__PURE__*/ jsx(NavRailItem, {
|
|
28
|
-
icon:
|
|
29
|
-
label: USER_NAME
|
|
52
|
+
icon: UserRound,
|
|
53
|
+
label: USER_NAME,
|
|
54
|
+
avatar: true
|
|
30
55
|
})
|
|
31
56
|
}),
|
|
32
57
|
/*#__PURE__*/ jsxs(DropdownMenuContent, {
|
|
@@ -79,7 +104,7 @@ const AccountDropdown = ({ sidebarMode, onSidebarModeChange, theme, onThemeChang
|
|
|
79
104
|
/*#__PURE__*/ jsxs(DropdownMenuItemContent, {
|
|
80
105
|
children: [
|
|
81
106
|
/*#__PURE__*/ jsx(DropdownMenuItemText, {
|
|
82
|
-
children: "
|
|
107
|
+
children: "Appearance"
|
|
83
108
|
}),
|
|
84
109
|
/*#__PURE__*/ jsx(Text, {
|
|
85
110
|
size: "xs",
|
|
@@ -90,32 +115,21 @@ const AccountDropdown = ({ sidebarMode, onSidebarModeChange, theme, onThemeChang
|
|
|
90
115
|
})
|
|
91
116
|
]
|
|
92
117
|
}),
|
|
93
|
-
/*#__PURE__*/
|
|
118
|
+
/*#__PURE__*/ jsx(DropdownMenuContent, {
|
|
94
119
|
className: "w-132",
|
|
95
|
-
children:
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
120
|
+
children: /*#__PURE__*/ jsx(DropdownMenuRadioGroup, {
|
|
121
|
+
value: theme,
|
|
122
|
+
onValueChange: ({ value })=>{
|
|
123
|
+
const next = THEMES.find((t)=>t === value);
|
|
124
|
+
if (next) onThemeChange(next);
|
|
125
|
+
},
|
|
126
|
+
children: THEMES.map((t)=>/*#__PURE__*/ jsx(DropdownMenuRadioItem, {
|
|
127
|
+
value: t,
|
|
128
|
+
children: /*#__PURE__*/ jsx(DropdownMenuItemText, {
|
|
129
|
+
children: THEME_LABELS[t]
|
|
104
130
|
})
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
/*#__PURE__*/ jsxs(DropdownMenuItem, {
|
|
108
|
-
onSelect: ()=>onThemeChange('dark'),
|
|
109
|
-
children: [
|
|
110
|
-
/*#__PURE__*/ jsx(DropdownMenuItemText, {
|
|
111
|
-
children: "Dark"
|
|
112
|
-
}),
|
|
113
|
-
'dark' === theme && /*#__PURE__*/ jsx(DropdownMenuShortcut, {
|
|
114
|
-
children: /*#__PURE__*/ jsx(Check, {})
|
|
115
|
-
})
|
|
116
|
-
]
|
|
117
|
-
})
|
|
118
|
-
]
|
|
131
|
+
}, t))
|
|
132
|
+
})
|
|
119
133
|
})
|
|
120
134
|
]
|
|
121
135
|
}),
|
|
@@ -140,32 +154,26 @@ const AccountDropdown = ({ sidebarMode, onSidebarModeChange, theme, onThemeChang
|
|
|
140
154
|
})
|
|
141
155
|
]
|
|
142
156
|
}),
|
|
143
|
-
/*#__PURE__*/
|
|
157
|
+
/*#__PURE__*/ jsx(DropdownMenuContent, {
|
|
144
158
|
className: "w-200",
|
|
145
|
-
children:
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
'expanded' === sidebarMode && /*#__PURE__*/ jsx(DropdownMenuShortcut, {
|
|
164
|
-
children: /*#__PURE__*/ jsx(Check, {})
|
|
165
|
-
})
|
|
166
|
-
]
|
|
167
|
-
})
|
|
168
|
-
]
|
|
159
|
+
children: /*#__PURE__*/ jsx(DropdownMenuRadioGroup, {
|
|
160
|
+
value: sidebarMode,
|
|
161
|
+
onValueChange: ({ value })=>{
|
|
162
|
+
const next = SIDEBAR_MODES.find((m)=>m === value);
|
|
163
|
+
if (next) onSidebarModeChange(next);
|
|
164
|
+
},
|
|
165
|
+
children: SIDEBAR_MODE_GROUPS.map((group, index)=>/*#__PURE__*/ jsxs(Fragment, {
|
|
166
|
+
children: [
|
|
167
|
+
index > 0 && /*#__PURE__*/ jsx(DropdownMenuSeparator, {}),
|
|
168
|
+
group.map((m)=>/*#__PURE__*/ jsx(DropdownMenuRadioItem, {
|
|
169
|
+
value: m,
|
|
170
|
+
children: /*#__PURE__*/ jsx(DropdownMenuItemText, {
|
|
171
|
+
children: SIDEBAR_MODE_LABELS[m]
|
|
172
|
+
})
|
|
173
|
+
}, m))
|
|
174
|
+
]
|
|
175
|
+
}, group.join('-')))
|
|
176
|
+
})
|
|
169
177
|
})
|
|
170
178
|
]
|
|
171
179
|
}),
|
|
@@ -184,4 +192,4 @@ const AccountDropdown = ({ sidebarMode, onSidebarModeChange, theme, onThemeChang
|
|
|
184
192
|
})
|
|
185
193
|
]
|
|
186
194
|
});
|
|
187
|
-
export { AccountDropdown };
|
|
195
|
+
export { AccountDropdown, railModeFor };
|
|
@@ -3,7 +3,10 @@ import { type Product } from './_storyLib';
|
|
|
3
3
|
export interface ConfigRemoteProps {
|
|
4
4
|
config: NavConfig;
|
|
5
5
|
basePath?: string;
|
|
6
|
+
/** Fake a 2s load whenever the product changes, to show the panel and content skeletons. */
|
|
7
|
+
simulateLoading?: boolean;
|
|
6
8
|
}
|
|
7
|
-
export declare const RemoteForProduct: ({ product }: {
|
|
9
|
+
export declare const RemoteForProduct: ({ product, simulateLoading, }: {
|
|
8
10
|
product: Product;
|
|
11
|
+
simulateLoading?: boolean;
|
|
9
12
|
}) => import("react").JSX.Element;
|
|
@@ -31,16 +31,18 @@ const RemotePageContent = ()=>{
|
|
|
31
31
|
]
|
|
32
32
|
});
|
|
33
33
|
};
|
|
34
|
-
const ConfigRemote = ({ config, basePath })=>{
|
|
35
|
-
const [loading, setLoading] = useState(
|
|
34
|
+
const ConfigRemote = ({ config, basePath, simulateLoading = true })=>{
|
|
35
|
+
const [loading, setLoading] = useState(simulateLoading);
|
|
36
36
|
useEffect(()=>{
|
|
37
|
+
if (!simulateLoading) return;
|
|
37
38
|
setLoading(true);
|
|
38
39
|
const timer = setTimeout(()=>{
|
|
39
40
|
setLoading(false);
|
|
40
41
|
}, 2000);
|
|
41
42
|
return ()=>clearTimeout(timer);
|
|
42
43
|
}, [
|
|
43
|
-
config.productLabel
|
|
44
|
+
config.productLabel,
|
|
45
|
+
simulateLoading
|
|
44
46
|
]);
|
|
45
47
|
return /*#__PURE__*/ jsx(RemoteShell, {
|
|
46
48
|
config: config,
|
|
@@ -67,12 +69,13 @@ const ConfigRemote = ({ config, basePath })=>{
|
|
|
67
69
|
})
|
|
68
70
|
});
|
|
69
71
|
};
|
|
70
|
-
const RemoteForProduct = ({ product })=>{
|
|
72
|
+
const RemoteForProduct = ({ product, simulateLoading = true })=>{
|
|
71
73
|
if ('home' === product) return /*#__PURE__*/ jsx(HomeContent, {});
|
|
72
74
|
const { config } = PRODUCT_CONFIGS[product];
|
|
73
75
|
return /*#__PURE__*/ jsx(ConfigRemote, {
|
|
74
76
|
config: config,
|
|
75
|
-
basePath: `/${product}
|
|
77
|
+
basePath: `/${product}`,
|
|
78
|
+
simulateLoading: simulateLoading
|
|
76
79
|
});
|
|
77
80
|
};
|
|
78
81
|
export { RemoteForProduct };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { AccountDropdown, type SidebarMode } from './_storyAccountDropdown';
|
|
1
|
+
export { AccountDropdown, railModeFor, type SidebarMode } from './_storyAccountDropdown';
|
|
2
2
|
export { RemoteForProduct } from './_storyConfigRenderer';
|
|
3
3
|
export { HeaderActions } from './_storyHeaderActions';
|
|
4
4
|
export { HomeContent } from './_storyHomeContent';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { AccountDropdown } from "./_storyAccountDropdown.js";
|
|
1
|
+
export { AccountDropdown, railModeFor } from "./_storyAccountDropdown.js";
|
|
2
2
|
export { RemoteForProduct } from "./_storyConfigRenderer.js";
|
|
3
3
|
export { HeaderActions } from "./_storyHeaderActions.js";
|
|
4
4
|
export { HomeContent } from "./_storyHomeContent.js";
|
|
@@ -15,7 +15,7 @@ const DropdownMenuRadioItem = ({ children, value, disabled, closeOnSelect, varia
|
|
|
15
15
|
"data-testid": testId,
|
|
16
16
|
className: cn(dropdownMenuItemVariants({
|
|
17
17
|
variant
|
|
18
|
-
}), className),
|
|
18
|
+
}), 'data-[state=checked]:bg-states-primary-active', className),
|
|
19
19
|
children: [
|
|
20
20
|
children,
|
|
21
21
|
/*#__PURE__*/ jsx(DropdownMenuItemIndicator, {
|
|
@@ -11,7 +11,7 @@ const NavPanelBack = ({ ref, className, children, ...props })=>{
|
|
|
11
11
|
type: "button",
|
|
12
12
|
"data-slot": "nav-panel-back",
|
|
13
13
|
"data-testid": testId,
|
|
14
|
-
className: cn('overlay flex h-32 shrink-0 w-full cursor-pointer items-center gap-8 rounded-
|
|
14
|
+
className: cn('overlay flex h-32 shrink-0 w-full cursor-pointer items-center gap-8 rounded-10 p-8 text-sm text-text-primary transition-colors outline-none hover:overlay-states-primary-hover focus-visible:overlay-states-primary-hover active:overlay-states-primary-pressed', className),
|
|
15
15
|
children: [
|
|
16
16
|
/*#__PURE__*/ jsx(CornerUpLeft, {
|
|
17
17
|
size: "md"
|
|
@@ -22,7 +22,7 @@ const NavPanelGroupLabel = ({ ref, icon: Icon, className, children, ...props })=
|
|
|
22
22
|
style: {
|
|
23
23
|
paddingLeft: 8 + depth * indent
|
|
24
24
|
},
|
|
25
|
-
className: cn('overlay flex h-32 shrink-0 w-full cursor-pointer items-center gap-8 rounded-
|
|
25
|
+
className: cn('overlay flex h-32 shrink-0 w-full cursor-pointer items-center gap-8 rounded-10 py-8 pr-8 text-sm text-text-primary transition-colors outline-none hover:overlay-states-primary-hover focus-visible:overlay-states-primary-hover active:overlay-states-primary-pressed', className),
|
|
26
26
|
children: [
|
|
27
27
|
Icon && /*#__PURE__*/ jsx("span", {
|
|
28
28
|
className: "flex shrink-0 items-center justify-center",
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { cva } from "class-variance-authority";
|
|
2
|
-
const navPanelItemVariants = cva('overlay flex h-32 shrink-0 w-full cursor-pointer items-center gap-8 rounded-
|
|
2
|
+
const navPanelItemVariants = cva('overlay flex h-32 shrink-0 w-full cursor-pointer items-center gap-8 rounded-10 p-8 text-sm text-text-primary transition-colors outline-none', {
|
|
3
3
|
variants: {
|
|
4
4
|
active: {
|
|
5
5
|
true: 'overlay-states-primary-active font-semibold',
|
|
6
|
-
false: '
|
|
6
|
+
false: 'hover:overlay-states-primary-hover focus-visible:overlay-states-primary-hover active:overlay-states-primary-pressed'
|
|
7
7
|
}
|
|
8
8
|
},
|
|
9
9
|
defaultVariants: {
|
|
10
10
|
active: false
|
|
11
11
|
}
|
|
12
12
|
});
|
|
13
|
-
const navPanelGroupItemVariants = cva('overlay flex h-32 shrink-0 w-full cursor-pointer items-center gap-8 rounded-
|
|
13
|
+
const navPanelGroupItemVariants = cva('overlay flex h-32 shrink-0 w-full cursor-pointer items-center gap-8 rounded-10 py-8 pr-8 text-sm text-text-primary transition-colors outline-none', {
|
|
14
14
|
variants: {
|
|
15
15
|
active: {
|
|
16
16
|
true: 'overlay-states-primary-active font-semibold',
|
|
17
|
-
false: '
|
|
17
|
+
false: 'hover:overlay-states-primary-hover focus-visible:overlay-states-primary-hover active:overlay-states-primary-pressed'
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
defaultVariants: {
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import type { FC, HTMLAttributes, ReactNode, Ref } from 'react';
|
|
2
2
|
import { type TestableProps } from '../../utils/testId';
|
|
3
|
+
import { type NavRailMode } from './NavRailContext';
|
|
3
4
|
export interface NavRailProps extends HTMLAttributes<HTMLElement>, TestableProps {
|
|
4
5
|
ref?: Ref<HTMLElement>;
|
|
5
6
|
children?: ReactNode;
|
|
7
|
+
/**
|
|
8
|
+
* How the rail lays out its items: `expanded` (icon beside label), `collapsed` (icon only) or
|
|
9
|
+
* `compact` (icon over a short label). Wins over `collapsed` when both are set.
|
|
10
|
+
*/
|
|
11
|
+
mode?: NavRailMode;
|
|
12
|
+
/** Shorthand for `mode='collapsed'`, kept so existing hosts keep working. Prefer `mode`. */
|
|
6
13
|
collapsed?: boolean;
|
|
7
14
|
}
|
|
8
15
|
export declare const NavRail: FC<NavRailProps>;
|
|
@@ -6,8 +6,9 @@ import { cn } from "../../utils/cn.js";
|
|
|
6
6
|
import { TestIdProvider } from "../../utils/testId.js";
|
|
7
7
|
import { navRailVariants } from "./classes.js";
|
|
8
8
|
import { NavRailContextProvider } from "./NavRailContext.js";
|
|
9
|
-
const NavRail = ({ ref, collapsed = false, className, children, 'data-testid': testId, ...props })=>{
|
|
9
|
+
const NavRail = ({ ref, mode: modeProp, collapsed = false, className, children, 'data-testid': testId, ...props })=>{
|
|
10
10
|
const internalRef = useRef(null);
|
|
11
|
+
const mode = modeProp ?? (collapsed ? 'collapsed' : 'expanded');
|
|
11
12
|
const focusPanel = useCallback(()=>{
|
|
12
13
|
const panel = document.querySelector('[data-slot="nav-panel"]');
|
|
13
14
|
const target = panel?.querySelector('[tabindex="0"]');
|
|
@@ -37,16 +38,17 @@ const NavRail = ({ ref, collapsed = false, className, children, 'data-testid': t
|
|
|
37
38
|
value: testId,
|
|
38
39
|
children: /*#__PURE__*/ jsx(NavRailContextProvider, {
|
|
39
40
|
value: {
|
|
40
|
-
|
|
41
|
+
mode
|
|
41
42
|
},
|
|
42
43
|
children: /*#__PURE__*/ jsx("nav", {
|
|
43
44
|
...props,
|
|
44
45
|
ref: composeRefs(internalRef, ref),
|
|
45
46
|
"aria-label": "Global navigation",
|
|
46
47
|
"data-slot": "nav-rail",
|
|
48
|
+
"data-mode": mode,
|
|
47
49
|
"data-testid": testId,
|
|
48
50
|
className: cn(navRailVariants({
|
|
49
|
-
|
|
51
|
+
mode
|
|
50
52
|
}), className),
|
|
51
53
|
children: children
|
|
52
54
|
})
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cn } from "../../utils/cn.js";
|
|
3
3
|
import { useTestId } from "../../utils/testId.js";
|
|
4
|
+
import { navRailBodyVariants } from "./classes.js";
|
|
5
|
+
import { useNavRailContext } from "./NavRailContext.js";
|
|
4
6
|
const NavRailBody = ({ ref, className, children, ...props })=>{
|
|
7
|
+
const { mode } = useNavRailContext();
|
|
5
8
|
const testId = useTestId('body');
|
|
6
9
|
return /*#__PURE__*/ jsx("div", {
|
|
7
10
|
...props,
|
|
8
11
|
ref: ref,
|
|
9
12
|
"data-slot": "nav-rail-body",
|
|
10
13
|
"data-testid": testId,
|
|
11
|
-
className: cn(
|
|
14
|
+
className: cn(navRailBodyVariants({
|
|
15
|
+
mode
|
|
16
|
+
}), className),
|
|
12
17
|
children: children
|
|
13
18
|
});
|
|
14
19
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
export type NavRailMode = 'expanded' | 'collapsed' | 'compact';
|
|
1
2
|
interface NavRailContextValue {
|
|
2
|
-
|
|
3
|
+
mode: NavRailMode;
|
|
3
4
|
}
|
|
4
5
|
export declare const NavRailContextProvider: import("react").Provider<NavRailContextValue>;
|
|
5
6
|
export declare function useNavRailContext(): NavRailContextValue;
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cn } from "../../utils/cn.js";
|
|
3
3
|
import { useTestId } from "../../utils/testId.js";
|
|
4
|
+
import { navRailFooterVariants } from "./classes.js";
|
|
5
|
+
import { useNavRailContext } from "./NavRailContext.js";
|
|
4
6
|
const NavRailFooter = ({ ref, className, children, ...props })=>{
|
|
7
|
+
const { mode } = useNavRailContext();
|
|
5
8
|
const testId = useTestId('footer');
|
|
6
9
|
return /*#__PURE__*/ jsx("div", {
|
|
7
10
|
...props,
|
|
8
11
|
ref: ref,
|
|
9
12
|
"data-slot": "nav-rail-footer",
|
|
10
13
|
"data-testid": testId,
|
|
11
|
-
className: cn(
|
|
14
|
+
className: cn(navRailFooterVariants({
|
|
15
|
+
mode
|
|
16
|
+
}), className),
|
|
12
17
|
children: children
|
|
13
18
|
});
|
|
14
19
|
};
|
|
@@ -8,5 +8,9 @@ export interface NavRailItemProps extends AnchorHTMLAttributes<HTMLAnchorElement
|
|
|
8
8
|
label: ReactNode;
|
|
9
9
|
shortcut?: string[];
|
|
10
10
|
active?: boolean;
|
|
11
|
+
/** Seats the icon on a soft plate, for the signed-in user's item at the foot of the rail. */
|
|
12
|
+
avatar?: boolean;
|
|
13
|
+
/** User photo for the plate (implies `avatar`). The icon stays underneath and returns if the photo fails to load. */
|
|
14
|
+
avatarSrc?: string;
|
|
11
15
|
}
|
|
12
16
|
export declare const NavRailItem: FC<NavRailItemProps>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Fragment, useRef } from "react";
|
|
2
|
+
import { Fragment, useRef, useState } from "react";
|
|
3
3
|
import { composeRefs } from "@radix-ui/react-compose-refs";
|
|
4
4
|
import { Slot, Slottable } from "@radix-ui/react-slot";
|
|
5
5
|
import { cn } from "../../utils/cn.js";
|
|
@@ -8,35 +8,60 @@ import { Kbd } from "../Kbd/index.js";
|
|
|
8
8
|
import { Tooltip } from "../Tooltip/index.js";
|
|
9
9
|
import { TooltipContent } from "../Tooltip/TooltipContent.js";
|
|
10
10
|
import { TooltipTrigger } from "../Tooltip/TooltipTrigger.js";
|
|
11
|
-
import { navRailItemVariants } from "./classes.js";
|
|
11
|
+
import { navRailItemCompactLabelClassName, navRailItemVariants } from "./classes.js";
|
|
12
12
|
import { useNavRailContext } from "./NavRailContext.js";
|
|
13
13
|
import { useShortcut } from "./useShortcut.js";
|
|
14
|
-
const NavRailItem = ({ ref, asChild = false, icon: Icon, label, shortcut, active = false, className, children, 'data-testid': testIdProp, ...props })=>{
|
|
15
|
-
const {
|
|
14
|
+
const NavRailItem = ({ ref, asChild = false, icon: Icon, label, shortcut, active = false, avatar = false, avatarSrc, className, children, 'data-testid': testIdProp, ...props })=>{
|
|
15
|
+
const { mode } = useNavRailContext();
|
|
16
16
|
const testId = useTestId('item', testIdProp);
|
|
17
17
|
const Comp = asChild ? Slot : 'a';
|
|
18
18
|
const internalRef = useRef(null);
|
|
19
|
+
const [failedSrc, setFailedSrc] = useState();
|
|
20
|
+
const photo = avatarSrc && avatarSrc !== failedSrc ? avatarSrc : void 0;
|
|
21
|
+
const hasPlate = avatar || void 0 !== avatarSrc;
|
|
22
|
+
const showsLabel = 'expanded' === mode || 'compact' === mode && !hasPlate;
|
|
23
|
+
const fallbackName = showsLabel || 'string' != typeof label ? void 0 : label;
|
|
19
24
|
useShortcut(shortcut, internalRef);
|
|
20
25
|
const element = /*#__PURE__*/ jsxs(Comp, {
|
|
21
26
|
...props,
|
|
22
27
|
ref: composeRefs(internalRef, ref),
|
|
28
|
+
"aria-label": props['aria-label'] ?? fallbackName,
|
|
23
29
|
"aria-current": active ? 'page' : void 0,
|
|
24
30
|
"data-slot": "nav-rail-item",
|
|
25
31
|
"data-testid": testId,
|
|
26
32
|
className: cn(navRailItemVariants({
|
|
33
|
+
mode,
|
|
27
34
|
active
|
|
28
35
|
}), className),
|
|
29
36
|
children: [
|
|
30
37
|
/*#__PURE__*/ jsx("span", {
|
|
31
38
|
className: "flex shrink-0 items-center justify-center",
|
|
32
|
-
children: /*#__PURE__*/
|
|
39
|
+
children: hasPlate ? /*#__PURE__*/ jsxs("span", {
|
|
40
|
+
"data-slot": "nav-rail-item-avatar",
|
|
41
|
+
className: cn('-m-4 grid size-24 place-items-center overflow-hidden rounded-8 bg-states-primary-hover *:col-start-1 *:row-start-1', !photo && 'border border-border-primary'),
|
|
42
|
+
children: [
|
|
43
|
+
/*#__PURE__*/ jsx(Icon, {
|
|
44
|
+
size: "md"
|
|
45
|
+
}),
|
|
46
|
+
photo && /*#__PURE__*/ jsx("img", {
|
|
47
|
+
src: photo,
|
|
48
|
+
alt: "",
|
|
49
|
+
className: "size-full object-cover",
|
|
50
|
+
onError: ()=>setFailedSrc(photo)
|
|
51
|
+
})
|
|
52
|
+
]
|
|
53
|
+
}) : /*#__PURE__*/ jsx(Icon, {
|
|
33
54
|
size: "md"
|
|
34
55
|
})
|
|
35
56
|
}),
|
|
36
|
-
|
|
57
|
+
'expanded' === mode && /*#__PURE__*/ jsx("span", {
|
|
37
58
|
className: cn('truncate whitespace-nowrap transition-[opacity,width] duration-200 pl-8'),
|
|
38
59
|
children: label
|
|
39
60
|
}),
|
|
61
|
+
showsLabel && 'compact' === mode && /*#__PURE__*/ jsx("span", {
|
|
62
|
+
className: navRailItemCompactLabelClassName,
|
|
63
|
+
children: label
|
|
64
|
+
}),
|
|
40
65
|
/*#__PURE__*/ jsx(Slottable, {
|
|
41
66
|
children: children
|
|
42
67
|
})
|
|
@@ -2,20 +2,40 @@ import { jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { cn } from "../../utils/cn.js";
|
|
3
3
|
import { useTestId } from "../../utils/testId.js";
|
|
4
4
|
import { Skeleton } from "../Skeleton/index.js";
|
|
5
|
+
import { navRailSkeletonVariants } from "./classes.js";
|
|
6
|
+
import { useNavRailContext } from "./NavRailContext.js";
|
|
7
|
+
const SKELETON_BARS = {
|
|
8
|
+
expanded: {
|
|
9
|
+
width: '100%',
|
|
10
|
+
height: '28px'
|
|
11
|
+
},
|
|
12
|
+
collapsed: {
|
|
13
|
+
width: '28px',
|
|
14
|
+
height: '28px'
|
|
15
|
+
},
|
|
16
|
+
compact: {
|
|
17
|
+
width: '54px',
|
|
18
|
+
height: '38px'
|
|
19
|
+
}
|
|
20
|
+
};
|
|
5
21
|
const NavRailSkeleton = ({ ref, className, count = 4, ...props })=>{
|
|
22
|
+
const { mode } = useNavRailContext();
|
|
6
23
|
const testId = useTestId('skeleton');
|
|
24
|
+
const bar = SKELETON_BARS[mode];
|
|
7
25
|
return /*#__PURE__*/ jsx("div", {
|
|
8
26
|
...props,
|
|
9
27
|
ref: ref,
|
|
10
28
|
"data-slot": "nav-rail-skeleton",
|
|
11
29
|
"data-testid": testId,
|
|
12
|
-
className: cn(
|
|
30
|
+
className: cn(navRailSkeletonVariants({
|
|
31
|
+
mode
|
|
32
|
+
}), className),
|
|
13
33
|
children: Array.from({
|
|
14
34
|
length: count
|
|
15
35
|
}, (_, i)=>/*#__PURE__*/ jsx(Skeleton, {
|
|
16
|
-
width:
|
|
17
|
-
height:
|
|
18
|
-
rounded:
|
|
36
|
+
width: bar.width,
|
|
37
|
+
height: bar.height,
|
|
38
|
+
rounded: 10
|
|
19
39
|
}, i))
|
|
20
40
|
});
|
|
21
41
|
};
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
export declare const navRailVariants: (props?: ({
|
|
2
|
-
|
|
2
|
+
mode?: "collapsed" | "compact" | "expanded" | null | undefined;
|
|
3
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
4
|
+
export declare const navRailBodyVariants: (props?: ({
|
|
5
|
+
mode?: "collapsed" | "compact" | "expanded" | null | undefined;
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
+
export declare const navRailFooterVariants: (props?: ({
|
|
8
|
+
mode?: "collapsed" | "compact" | "expanded" | null | undefined;
|
|
9
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
10
|
+
export declare const navRailSkeletonVariants: (props?: ({
|
|
11
|
+
mode?: "collapsed" | "compact" | "expanded" | null | undefined;
|
|
3
12
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
4
13
|
export declare const navRailItemVariants: (props?: ({
|
|
14
|
+
mode?: "collapsed" | "compact" | "expanded" | null | undefined;
|
|
5
15
|
active?: boolean | null | undefined;
|
|
6
16
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
17
|
+
export declare const navRailItemCompactLabelClassName = "line-clamp-2 w-56 shrink-0 text-center text-2xs font-medium text-ellipsis break-normal";
|