@setsquare/ui 0.6.0 → 0.8.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/CHANGELOG.md +102 -0
- package/README.md +9 -5
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/cn.d.ts.map +1 -1
- package/dist/lib/cn.js +1 -0
- package/dist/lib/cn.js.map +1 -1
- package/dist/lib/english.d.ts.map +1 -1
- package/dist/lib/english.js +2 -0
- package/dist/lib/english.js.map +1 -1
- package/dist/lib/keyshortcuts.d.ts +13 -0
- package/dist/lib/keyshortcuts.d.ts.map +1 -0
- package/dist/lib/keyshortcuts.js +21 -0
- package/dist/lib/keyshortcuts.js.map +1 -0
- package/dist/lib/locale.d.ts +4 -1
- package/dist/lib/locale.d.ts.map +1 -1
- package/dist/lib/locale.js.map +1 -1
- package/dist/lib/search-match.d.ts +31 -0
- package/dist/lib/search-match.d.ts.map +1 -0
- package/dist/lib/search-match.js +82 -0
- package/dist/lib/search-match.js.map +1 -0
- package/dist/lib/search-shortcut.d.ts +16 -0
- package/dist/lib/search-shortcut.d.ts.map +1 -0
- package/dist/lib/search-shortcut.js +49 -0
- package/dist/lib/search-shortcut.js.map +1 -0
- package/dist/shell/app-header.d.ts +4 -1
- package/dist/shell/app-header.d.ts.map +1 -1
- package/dist/shell/app-header.js +6 -3
- package/dist/shell/app-header.js.map +1 -1
- package/dist/shell/dashboard-shell.d.ts +13 -2
- package/dist/shell/dashboard-shell.d.ts.map +1 -1
- package/dist/shell/dashboard-shell.js +5 -2
- package/dist/shell/dashboard-shell.js.map +1 -1
- package/dist/shell/nav-status.d.ts +46 -0
- package/dist/shell/nav-status.d.ts.map +1 -0
- package/dist/shell/nav-status.js +26 -0
- package/dist/shell/nav-status.js.map +1 -0
- package/dist/shell/rail.d.ts +73 -0
- package/dist/shell/rail.d.ts.map +1 -0
- package/dist/shell/rail.js +87 -0
- package/dist/shell/rail.js.map +1 -0
- package/dist/shell/sidebar.d.ts +31 -6
- package/dist/shell/sidebar.d.ts.map +1 -1
- package/dist/shell/sidebar.js +45 -8
- package/dist/shell/sidebar.js.map +1 -1
- package/dist/styles/theme.css +78 -0
- package/dist/styles/tokens.css +4 -4
- package/dist/tokens.json +4 -4
- package/dist/ui/button.d.ts +3 -2
- package/dist/ui/button.d.ts.map +1 -1
- package/dist/ui/button.js +7 -4
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/search.d.ts +19 -3
- package/dist/ui/search.d.ts.map +1 -1
- package/dist/ui/search.js +55 -23
- package/dist/ui/search.js.map +1 -1
- package/dist/ui/tree.d.ts +5 -3
- package/dist/ui/tree.d.ts.map +1 -1
- package/dist/ui/tree.js +4 -2
- package/dist/ui/tree.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ⌘K / Ctrl+K for `AppSearch`. One search on a page has the shortcut: the first mounted that asks for it, usually
|
|
3
|
+
* the layout's, which outlives the pages under it. The key is left alone when something else wants it: a handler
|
|
4
|
+
* that already took it (`preventDefault`), a field or editor being typed in (Ctrl+K deletes to the end of the line
|
|
5
|
+
* in a macOS text field, and inserts a link in most editors), or an input method composing.
|
|
6
|
+
*/
|
|
7
|
+
const owners = [];
|
|
8
|
+
const listeners = new Set();
|
|
9
|
+
const notify = () => listeners.forEach((l) => l());
|
|
10
|
+
/** Asks for the shortcut; the first to ask has it until it lets go. Returns the letting go. */
|
|
11
|
+
export function claimSearchShortcut(id) {
|
|
12
|
+
owners.push(id);
|
|
13
|
+
notify();
|
|
14
|
+
return () => {
|
|
15
|
+
const at = owners.indexOf(id);
|
|
16
|
+
if (at >= 0)
|
|
17
|
+
owners.splice(at, 1);
|
|
18
|
+
notify();
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export const subscribeSearchShortcut = (listener) => {
|
|
22
|
+
listeners.add(listener);
|
|
23
|
+
return () => {
|
|
24
|
+
listeners.delete(listener);
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
/** Whether `id` has the shortcut. Before anything has asked (the first render), each one that will ask has it. */
|
|
28
|
+
export const hasSearchShortcut = (id) => owners.length === 0 || owners[0] === id;
|
|
29
|
+
const TEXT_INPUT = new Set(['text', 'search', 'email', 'url', 'tel', 'password', 'number']);
|
|
30
|
+
/** A field or editor that takes typing, where Ctrl+K and ⌘K may already mean something. */
|
|
31
|
+
export function isTextEntry(target) {
|
|
32
|
+
if (!target || typeof target.tagName !== 'string')
|
|
33
|
+
return false;
|
|
34
|
+
const el = target;
|
|
35
|
+
if (el.isContentEditable || el.tagName === 'TEXTAREA')
|
|
36
|
+
return true;
|
|
37
|
+
return el.tagName === 'INPUT' && TEXT_INPUT.has(el.type);
|
|
38
|
+
}
|
|
39
|
+
/** ⌘K or Ctrl+K, alone, that nothing else has claimed. */
|
|
40
|
+
export function isSearchShortcut(e) {
|
|
41
|
+
return ((e.metaKey || e.ctrlKey) &&
|
|
42
|
+
!e.altKey &&
|
|
43
|
+
!e.shiftKey &&
|
|
44
|
+
e.key.toLowerCase() === 'k' &&
|
|
45
|
+
!e.defaultPrevented &&
|
|
46
|
+
!e.isComposing &&
|
|
47
|
+
!isTextEntry(e.composedPath?.()[0] ?? e.target));
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=search-shortcut.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-shortcut.js","sourceRoot":"","sources":["../../src/lib/search-shortcut.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,GAAa,EAAE,CAAC;AAC5B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;AACxC,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AAEnD,+FAA+F;AAC/F,MAAM,UAAU,mBAAmB,CAAC,EAAU;IAC5C,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChB,MAAM,EAAE,CAAC;IACT,OAAO,GAAG,EAAE;QACV,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,EAAE,IAAI,CAAC;YAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAClC,MAAM,EAAE,CAAC;IACX,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,QAAoB,EAAE,EAAE;IAC9D,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,GAAG,EAAE;QACV,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,kHAAkH;AAClH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;AAEzF,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;AAE5F,2FAA2F;AAC3F,MAAM,UAAU,WAAW,CAAC,MAA0B;IACpD,IAAI,CAAC,MAAM,IAAI,OAAQ,MAAkB,CAAC,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC7E,MAAM,EAAE,GAAG,MAAqB,CAAC;IACjC,IAAI,EAAE,CAAC,iBAAiB,IAAI,EAAE,CAAC,OAAO,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IACnE,OAAO,EAAE,CAAC,OAAO,KAAK,OAAO,IAAI,UAAU,CAAC,GAAG,CAAE,EAAuB,CAAC,IAAI,CAAC,CAAC;AACjF,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,gBAAgB,CAAC,CAAgB;IAC/C,OAAO,CACL,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC;QACxB,CAAC,CAAC,CAAC,MAAM;QACT,CAAC,CAAC,CAAC,QAAQ;QACX,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,GAAG;QAC3B,CAAC,CAAC,CAAC,gBAAgB;QACnB,CAAC,CAAC,CAAC,WAAW;QACd,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAChD,CAAC;AACJ,CAAC"}
|
|
@@ -17,6 +17,9 @@ export interface AppHeaderProps {
|
|
|
17
17
|
labels?: Partial<SidebarTriggerLabels>;
|
|
18
18
|
className?: string;
|
|
19
19
|
}
|
|
20
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* The inset's top bar: the navigation trigger, where you are, search and the fixed actions. With a Sidebar the
|
|
22
|
+
* trigger collapses it (or opens it on phones); with a Rail it is there on phones only.
|
|
23
|
+
*/
|
|
21
24
|
export declare function AppHeader({ breadcrumbs, brand, search, actions, labels, className, }: AppHeaderProps): import("react").JSX.Element;
|
|
22
25
|
//# sourceMappingURL=app-header.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-header.d.ts","sourceRoot":"","sources":["../../src/shell/app-header.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,EAAkB,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEzE,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,2BAA2B;IAC3B,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,qHAAqH;IACrH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED
|
|
1
|
+
{"version":3,"file":"app-header.d.ts","sourceRoot":"","sources":["../../src/shell/app-header.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,EAAkB,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEzE,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,2BAA2B;IAC3B,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,qHAAqH;IACrH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,EACxB,WAAW,EACX,KAAK,EACL,MAAM,EACN,OAAO,EACP,MAAM,EACN,SAAS,GACV,EAAE,cAAc,+BA0BhB"}
|
package/dist/shell/app-header.js
CHANGED
|
@@ -3,10 +3,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { cn } from '../lib/cn.js';
|
|
4
4
|
import { useShell } from './dashboard-shell.js';
|
|
5
5
|
import { SidebarTrigger } from './sidebar.js';
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* The inset's top bar: the navigation trigger, where you are, search and the fixed actions. With a Sidebar the
|
|
8
|
+
* trigger collapses it (or opens it on phones); with a Rail it is there on phones only.
|
|
9
|
+
*/
|
|
7
10
|
export function AppHeader({ breadcrumbs, brand, search, actions, labels, className, }) {
|
|
8
|
-
const { size, productName } = useShell();
|
|
9
|
-
return (_jsxs("header", { style: { viewTransitionName: 'shell-header' }, className: cn('flex h-header shrink-0 items-center gap-2 border-b border-border px-3 @min-[48rem]/shell:px-4', className), children: [_jsx(SidebarTrigger, { labels: labels }), _jsx("span", { "aria-hidden": "true", className: "mx-1 h-6 w-px bg-border @max-[48rem]/shell:hidden" }), _jsx("div", { className: "flex min-w-0 flex-1 items-center", children: size === 'mobile'
|
|
11
|
+
const { size, productName, navigation } = useShell();
|
|
12
|
+
return (_jsxs("header", { style: { viewTransitionName: 'shell-header' }, className: cn('flex h-header shrink-0 items-center gap-2 border-b border-border px-3 @min-[48rem]/shell:px-4', className), children: [_jsx(SidebarTrigger, { labels: labels }), navigation !== 'rail' && (_jsx("span", { "aria-hidden": "true", className: "mx-1 h-6 w-px bg-border @max-[48rem]/shell:hidden" })), _jsx("div", { className: "flex min-w-0 flex-1 items-center", children: size === 'mobile'
|
|
10
13
|
? (brand ?? _jsx("span", { className: "truncate text-base font-bold", children: productName }))
|
|
11
14
|
: breadcrumbs }), _jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [search, actions] })] }));
|
|
12
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-header.js","sourceRoot":"","sources":["../../src/shell/app-header.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAGb,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,cAAc,EAA6B,MAAM,cAAc,CAAC;AAoBzE
|
|
1
|
+
{"version":3,"file":"app-header.js","sourceRoot":"","sources":["../../src/shell/app-header.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAGb,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,cAAc,EAA6B,MAAM,cAAc,CAAC;AAoBzE;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,EACxB,WAAW,EACX,KAAK,EACL,MAAM,EACN,OAAO,EACP,MAAM,EACN,SAAS,GACM;IACf,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,QAAQ,EAAE,CAAC;IACrD,OAAO,CACL,kBACE,KAAK,EAAE,EAAE,kBAAkB,EAAE,cAAc,EAAE,EAC7C,SAAS,EAAE,EAAE,CACX,+FAA+F,EAC/F,SAAS,CACV,aAED,KAAC,cAAc,IAAC,MAAM,EAAE,MAAM,GAAI,EAEjC,UAAU,KAAK,MAAM,IAAI,CACxB,8BAAkB,MAAM,EAAC,SAAS,EAAC,mDAAmD,GAAG,CAC1F,EACD,cAAK,SAAS,EAAC,kCAAkC,YAC9C,IAAI,KAAK,QAAQ;oBAChB,CAAC,CAAC,CAAC,KAAK,IAAI,eAAM,SAAS,EAAC,8BAA8B,YAAE,WAAW,GAAQ,CAAC;oBAChF,CAAC,CAAC,WAAW,GACX,EACN,eAAK,SAAS,EAAC,kCAAkC,aAC9C,MAAM,EACN,OAAO,IACJ,IACC,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -2,6 +2,8 @@ import { type CSSProperties, type ReactNode, type RefObject } from 'react';
|
|
|
2
2
|
import { type ShellLabels } from './landmarks.js';
|
|
3
3
|
export type ShellSize = 'mobile' | 'tablet' | 'laptop' | 'desktop';
|
|
4
4
|
export type PanelMode = 'inline' | 'sheet';
|
|
5
|
+
/** What the shell's navigation is: `Sidebar` (option B) or `Rail` (option C). */
|
|
6
|
+
export type ShellNavigation = 'sidebar' | 'rail';
|
|
5
7
|
export interface ShellContextValue {
|
|
6
8
|
size: ShellSize;
|
|
7
9
|
sidebarCollapsed: boolean;
|
|
@@ -13,6 +15,8 @@ export interface ShellContextValue {
|
|
|
13
15
|
panelMode: PanelMode;
|
|
14
16
|
panelToggleRef: RefObject<HTMLButtonElement | null>;
|
|
15
17
|
productName: string;
|
|
18
|
+
/** The navigation the shell holds, from its `navigation` prop. */
|
|
19
|
+
navigation: ShellNavigation;
|
|
16
20
|
/** True when `size` was forced, so container-query fallbacks stand down. */
|
|
17
21
|
isSizeForced: boolean;
|
|
18
22
|
}
|
|
@@ -30,6 +34,12 @@ export interface DashboardShellProps {
|
|
|
30
34
|
defaultSidebarCollapsed?: boolean;
|
|
31
35
|
/** Force a size instead of measuring (previews, tests, Storybook). */
|
|
32
36
|
size?: ShellSize;
|
|
37
|
+
/**
|
|
38
|
+
* The navigation it holds: `sidebar` (default) or `rail`. With `rail`, AppHeader's trigger only appears where it
|
|
39
|
+
* opens the phone's Sheet, since a rail has nothing to collapse. A prop rather than the Rail registering itself,
|
|
40
|
+
* so the server renders the right header and nothing changes when the page hydrates.
|
|
41
|
+
*/
|
|
42
|
+
navigation?: ShellNavigation;
|
|
33
43
|
/** @deprecated Use `labels.skipLink`. Kept for one release. */
|
|
34
44
|
skipLinkLabel?: string;
|
|
35
45
|
labels?: Partial<ShellLabels>;
|
|
@@ -37,12 +47,13 @@ export interface DashboardShellProps {
|
|
|
37
47
|
style?: CSSProperties;
|
|
38
48
|
}
|
|
39
49
|
/**
|
|
40
|
-
*
|
|
50
|
+
* The inset shell. Measures its own width and decides:
|
|
41
51
|
* desktop ≥ bp-xl: sidebar expanded, panel inline · laptop ≥ bp-lg: sidebar icons, panel inline ·
|
|
42
52
|
* tablet ≥ bp-md: sidebar icons, panel as a Sheet · mobile: sidebar and panel both Sheets.
|
|
53
|
+
* With `navigation="rail"` (option C) the Rail stays as it is at every width from bp-md, and is a Sheet on phones.
|
|
43
54
|
* CSS container queries on `shell` do the first layout, so there is no flash before measuring.
|
|
44
55
|
*/
|
|
45
|
-
export declare function DashboardShell({ children, productName, defaultPanelOpen, defaultMobileNavOpen, defaultSidebarCollapsed, size: forcedSize, skipLinkLabel, labels, className, style, }: DashboardShellProps): import("react").JSX.Element;
|
|
56
|
+
export declare function DashboardShell({ children, productName, defaultPanelOpen, defaultMobileNavOpen, defaultSidebarCollapsed, size: forcedSize, navigation, skipLinkLabel, labels, className, style, }: DashboardShellProps): import("react").JSX.Element;
|
|
46
57
|
/** The raised surface that holds the header, the page and the right panel. Edge to edge on phones. */
|
|
47
58
|
export declare function ShellInset({ children, className }: {
|
|
48
59
|
children: ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-shell.d.ts","sourceRoot":"","sources":["../../src/shell/dashboard-shell.tsx"],"names":[],"mappings":"AAEA,OAAO,EASL,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE5D,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AACnE,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"dashboard-shell.d.ts","sourceRoot":"","sources":["../../src/shell/dashboard-shell.tsx"],"names":[],"mappings":"AAEA,OAAO,EASL,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE5D,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AACnE,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AAC3C,iFAAiF;AACjF,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,MAAM,CAAC;AAEjD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,SAAS,CAAC;IAChB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,SAAS,EAAE,SAAS,CAAC;IACrB,cAAc,EAAE,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,UAAU,EAAE,eAAe,CAAC;IAC5B,4EAA4E;IAC5E,YAAY,EAAE,OAAO,CAAC;CACvB;AAID,wBAAgB,QAAQ,IAAI,iBAAiB,CAI5C;AACD,wFAAwF;AACxF,wBAAgB,gBAAgB,IAAI,iBAAiB,GAAG,IAAI,CAE3D;AAeD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,SAAS,CAAC;IACpB,wFAAwF;IACxF,WAAW,EAAE,MAAM,CAAC;IACpB,+FAA+F;IAC/F,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,kFAAkF;IAClF,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,sEAAsE;IACtE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,oBAA4B,EAC5B,uBAAuB,EACvB,IAAI,EAAE,UAAU,EAChB,UAAsB,EACtB,aAAa,EACb,MAAM,EACN,SAAS,EACT,KAAK,GACN,EAAE,mBAAmB,+BA8FrB;AAED,sGAAsG;AACtG,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAY9F;AAED,6DAA6D;AAC7D,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAE7F;AAMD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,EACxB,QAAQ,EACR,SAAS,EACT,iBAAiB,EAAE,UAAU,GAC9B,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,+BAsDA"}
|
|
@@ -30,12 +30,13 @@ function sizeFor(width, bp) {
|
|
|
30
30
|
return 'desktop';
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
33
|
+
* The inset shell. Measures its own width and decides:
|
|
34
34
|
* desktop ≥ bp-xl: sidebar expanded, panel inline · laptop ≥ bp-lg: sidebar icons, panel inline ·
|
|
35
35
|
* tablet ≥ bp-md: sidebar icons, panel as a Sheet · mobile: sidebar and panel both Sheets.
|
|
36
|
+
* With `navigation="rail"` (option C) the Rail stays as it is at every width from bp-md, and is a Sheet on phones.
|
|
36
37
|
* CSS container queries on `shell` do the first layout, so there is no flash before measuring.
|
|
37
38
|
*/
|
|
38
|
-
export function DashboardShell({ children, productName, defaultPanelOpen, defaultMobileNavOpen = false, defaultSidebarCollapsed, size: forcedSize, skipLinkLabel, labels, className, style, }) {
|
|
39
|
+
export function DashboardShell({ children, productName, defaultPanelOpen, defaultMobileNavOpen = false, defaultSidebarCollapsed, size: forcedSize, navigation = 'sidebar', skipLinkLabel, labels, className, style, }) {
|
|
39
40
|
const ref = useRef(null);
|
|
40
41
|
const [measured, setMeasured] = useState(null);
|
|
41
42
|
const size = forcedSize ?? measured ?? 'desktop';
|
|
@@ -87,6 +88,7 @@ export function DashboardShell({ children, productName, defaultPanelOpen, defaul
|
|
|
87
88
|
panelMode,
|
|
88
89
|
panelToggleRef,
|
|
89
90
|
productName,
|
|
91
|
+
navigation,
|
|
90
92
|
isSizeForced: !!forcedSize,
|
|
91
93
|
}), [
|
|
92
94
|
size,
|
|
@@ -97,6 +99,7 @@ export function DashboardShell({ children, productName, defaultPanelOpen, defaul
|
|
|
97
99
|
setPanelOpen,
|
|
98
100
|
panelMode,
|
|
99
101
|
productName,
|
|
102
|
+
navigation,
|
|
100
103
|
forcedSize,
|
|
101
104
|
]);
|
|
102
105
|
return (_jsx(ShellContext.Provider, { value: value, children: _jsxs("div", { ref: ref, "data-size": size, style: style, className: cn('@container/shell relative flex h-dvh min-h-0 w-full overflow-hidden bg-sidebar text-foreground', className), children: [_jsx(SkipLink, { href: "#main", shell: "dashboardShell", label: skipLinkLabel, labels: labels }), children] }) }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-shell.js","sourceRoot":"","sources":["../../src/shell/dashboard-shell.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EACL,aAAa,EACb,WAAW,EACX,UAAU,EACV,SAAS,EACT,eAAe,EACf,OAAO,EACP,MAAM,EACN,QAAQ,GAIT,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAoB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"dashboard-shell.js","sourceRoot":"","sources":["../../src/shell/dashboard-shell.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import { type IconProp } from '../ui/icon.js';
|
|
3
|
+
/** What a nav item is doing: something is being worked on, or something waits for the person. */
|
|
4
|
+
export type NavStatus = 'working' | 'attention';
|
|
5
|
+
/** A detail's tone. `warning` adds an icon, the warning colour and words in the item's name. */
|
|
6
|
+
export type NavDetailTone = 'neutral' | 'warning';
|
|
7
|
+
/**
|
|
8
|
+
* A nav item's live status and detail, on SidebarItem and RailItem. `statusLabel` comes with `status`: it is said as
|
|
9
|
+
* part of the item's name, and is in the tooltip where the name is one.
|
|
10
|
+
*/
|
|
11
|
+
export type NavItemLiveProps = {
|
|
12
|
+
/**
|
|
13
|
+
* A short value: "4/8", "$1.20". Under the name in a rail, after it in the sidebar; read as part of the name, in
|
|
14
|
+
* tabular numbers.
|
|
15
|
+
*/
|
|
16
|
+
detail?: string;
|
|
17
|
+
/** Default `neutral`. `warning` ("near the budget") adds an icon and the label's words to the name. */
|
|
18
|
+
detailTone?: NavDetailTone;
|
|
19
|
+
} & ({
|
|
20
|
+
status?: undefined;
|
|
21
|
+
statusLabel?: undefined;
|
|
22
|
+
} | {
|
|
23
|
+
/** A badge on the icon: `working` is a ring that pulses as it appears, `attention` a dot in a ring. */
|
|
24
|
+
status: NavStatus;
|
|
25
|
+
/** Said as part of the name: "Claude is working", "A draft is waiting for you". */
|
|
26
|
+
statusLabel: string;
|
|
27
|
+
});
|
|
28
|
+
/** A status with no words to say it would be colour and shape alone: say so in the console. */
|
|
29
|
+
export declare function warnUnlabelledStatus(component: string, status?: NavStatus, label?: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* The item's icon in a box that holds its status badge. The icon is rendered by `renderIcon`, so a component, an
|
|
32
|
+
* element or a custom drawing (a progress ring) all work; the box carries the colour, so a drawing that uses
|
|
33
|
+
* `currentColor` turns brand on the current page even if it ignores `className`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function NavIcon({ icon, status, className, }: {
|
|
36
|
+
icon: IconProp;
|
|
37
|
+
status?: NavStatus;
|
|
38
|
+
className?: string;
|
|
39
|
+
}): ReactElement;
|
|
40
|
+
/** The detail as shown: muted and tabular, or the warning colour after a warning icon. Hidden from assistive tech. */
|
|
41
|
+
export declare function NavDetail({ detail, tone, className, }: {
|
|
42
|
+
detail: string;
|
|
43
|
+
tone?: NavDetailTone;
|
|
44
|
+
className?: string;
|
|
45
|
+
}): ReactElement;
|
|
46
|
+
//# sourceMappingURL=nav-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nav-status.d.ts","sourceRoot":"","sources":["../../src/shell/nav-status.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1C,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE1D,iGAAiG;AACjG,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAChD,gGAAgG;AAChG,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,CAAC;AAElD;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uGAAuG;IACvG,UAAU,CAAC,EAAE,aAAa,CAAC;CAC5B,GAAG,CACA;IAAE,MAAM,CAAC,EAAE,SAAS,CAAC;IAAC,WAAW,CAAC,EAAE,SAAS,CAAA;CAAE,GAC/C;IACE,uGAAuG;IACvG,MAAM,EAAE,SAAS,CAAC;IAClB,mFAAmF;IACnF,WAAW,EAAE,MAAM,CAAC;CACrB,CACJ,CAAC;AAIF,+FAA+F;AAC/F,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,QAMzF;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,EACtB,IAAI,EACJ,MAAM,EACN,SAAS,GACV,EAAE;IACD,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,YAAY,CAUf;AAED,sHAAsH;AACtH,wBAAgB,SAAS,CAAC,EACxB,MAAM,EACN,IAAI,EACJ,SAAS,GACV,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,YAAY,CAef"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { TriangleAlert } from 'lucide-react';
|
|
3
|
+
import { cn } from '../lib/cn.js';
|
|
4
|
+
import { renderIcon } from '../ui/icon.js';
|
|
5
|
+
// Developer-facing: said once per page.
|
|
6
|
+
let warned = false;
|
|
7
|
+
/** A status with no words to say it would be colour and shape alone: say so in the console. */
|
|
8
|
+
export function warnUnlabelledStatus(component, status, label) {
|
|
9
|
+
if (!status || label || warned)
|
|
10
|
+
return;
|
|
11
|
+
warned = true;
|
|
12
|
+
console.error(`<${component} status="${status}"> has no statusLabel: the badge is then shown but never said. Give it statusLabel.`);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The item's icon in a box that holds its status badge. The icon is rendered by `renderIcon`, so a component, an
|
|
16
|
+
* element or a custom drawing (a progress ring) all work; the box carries the colour, so a drawing that uses
|
|
17
|
+
* `currentColor` turns brand on the current page even if it ignores `className`.
|
|
18
|
+
*/
|
|
19
|
+
export function NavIcon({ icon, status, className, }) {
|
|
20
|
+
return (_jsxs("span", { className: cn('nav-icon size-5', className), children: [renderIcon(icon, 'size-5 shrink-0'), status && (_jsx("span", { "aria-hidden": "true", "data-status": status, className: "nav-status" }, status))] }));
|
|
21
|
+
}
|
|
22
|
+
/** The detail as shown: muted and tabular, or the warning colour after a warning icon. Hidden from assistive tech. */
|
|
23
|
+
export function NavDetail({ detail, tone, className, }) {
|
|
24
|
+
return (_jsxs("span", { "aria-hidden": "true", "data-tone": tone ?? 'neutral', className: cn('inline-flex items-center gap-1 text-[13px] leading-4 font-medium whitespace-nowrap text-muted-foreground tabular-nums', tone === 'warning' && 'font-semibold text-warning', className), children: [tone === 'warning' && _jsx(TriangleAlert, { className: "size-3.5 shrink-0" }), detail] }));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=nav-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nav-status.js","sourceRoot":"","sources":["../../src/shell/nav-status.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,UAAU,EAAiB,MAAM,eAAe,CAAC;AA6B1D,wCAAwC;AACxC,IAAI,MAAM,GAAG,KAAK,CAAC;AACnB,+FAA+F;AAC/F,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE,MAAkB,EAAE,KAAc;IACxF,IAAI,CAAC,MAAM,IAAI,KAAK,IAAI,MAAM;QAAE,OAAO;IACvC,MAAM,GAAG,IAAI,CAAC;IACd,OAAO,CAAC,KAAK,CACX,IAAI,SAAS,YAAY,MAAM,qFAAqF,CACrH,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,EACtB,IAAI,EACJ,MAAM,EACN,SAAS,GAKV;IACC,OAAO,CACL,gBAAM,SAAS,EAAE,EAAE,CAAC,iBAAiB,EAAE,SAAS,CAAC,aAC9C,UAAU,CAAC,IAAI,EAAE,iBAAiB,CAAC,EACnC,MAAM,IAAI,CAET,8BAA+B,MAAM,iBAAc,MAAM,EAAE,SAAS,EAAC,YAAY,IAAtE,MAAM,CAAmE,CACrF,IACI,CACR,CAAC;AACJ,CAAC;AAED,sHAAsH;AACtH,MAAM,UAAU,SAAS,CAAC,EACxB,MAAM,EACN,IAAI,EACJ,SAAS,GAKV;IACC,OAAO,CACL,+BACc,MAAM,eACP,IAAI,IAAI,SAAS,EAC5B,SAAS,EAAE,EAAE,CACX,uHAAuH,EACvH,IAAI,KAAK,SAAS,IAAI,4BAA4B,EAClD,SAAS,CACV,aAEA,IAAI,KAAK,SAAS,IAAI,KAAC,aAAa,IAAC,SAAS,EAAC,mBAAmB,GAAG,EACrE,MAAM,IACF,CACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { IconProp } from '../ui/icon.js';
|
|
3
|
+
import { type NavItemLiveProps } from './nav-status.js';
|
|
4
|
+
/** The rail's words, for the `labels` prop. App-wide, `SetsquareLabels.rail` over `SetsquareLabels.sidebar`. */
|
|
5
|
+
export interface RailLabels {
|
|
6
|
+
/** Names the Sheet it becomes on phones; `{product}` is the shell's `productName`. */
|
|
7
|
+
navigation: string;
|
|
8
|
+
/** Names the navigation landmark. */
|
|
9
|
+
primary: string;
|
|
10
|
+
/** Added to an item's name for its `detail`: "Spend, $1.20". */
|
|
11
|
+
detail: string;
|
|
12
|
+
/** The same for a `detailTone="warning"` detail, with words for the warning: "Spend, $1.20, warning". */
|
|
13
|
+
detailWarning: string;
|
|
14
|
+
/** Added to an item's name for its `statusLabel`: "Scenes, Claude is working". */
|
|
15
|
+
status: string;
|
|
16
|
+
}
|
|
17
|
+
export declare const railLabels: RailLabels;
|
|
18
|
+
export interface RailProps {
|
|
19
|
+
children: ReactNode;
|
|
20
|
+
labels?: Partial<RailLabels>;
|
|
21
|
+
className?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Layout option C: a labelled navigation rail, `--rail-width` wide, used in a DashboardShell instead of Sidebar. Every
|
|
25
|
+
* item shows its icon over its name, so every destination is visible without the sidebar's width. It never
|
|
26
|
+
* collapses or expands. On phones it is the same Sheet the Sidebar becomes, with the items as rows. Give the shell
|
|
27
|
+
* `navigation="rail"`, so AppHeader shows its trigger only where it opens that Sheet.
|
|
28
|
+
*/
|
|
29
|
+
export declare function Rail({ children, labels: given, className }: RailProps): import("react").JSX.Element;
|
|
30
|
+
/** The product's mark, at the top. In the phone's Sheet it sits at the start of the row, as the items do. */
|
|
31
|
+
export declare function RailHeader({ children, className }: {
|
|
32
|
+
children: ReactNode;
|
|
33
|
+
className?: string;
|
|
34
|
+
}): import("react").JSX.Element;
|
|
35
|
+
/**
|
|
36
|
+
* The items. Scrolls when they are taller than the shell, and is positioned, so the visually hidden group names
|
|
37
|
+
* inside it scroll with it rather than being laid out against the shell.
|
|
38
|
+
*/
|
|
39
|
+
export declare function RailContent({ children, className }: {
|
|
40
|
+
children: ReactNode;
|
|
41
|
+
className?: string;
|
|
42
|
+
}): import("react").JSX.Element;
|
|
43
|
+
/** Pinned to the bottom: help, settings, the account. Put items in a `RailList`, as in a SidebarFooter. */
|
|
44
|
+
export declare function RailFooter({ children, className }: {
|
|
45
|
+
children: ReactNode;
|
|
46
|
+
className?: string;
|
|
47
|
+
}): import("react").JSX.Element;
|
|
48
|
+
/**
|
|
49
|
+
* A labelled group of items. Its name is visually hidden and names the group for assistive technology; a rule above
|
|
50
|
+
* it separates it from what comes before. Groups are `role="group"`, not landmarks, so the landmark list stays short.
|
|
51
|
+
*/
|
|
52
|
+
export declare function RailGroup({ label, children, className, }: {
|
|
53
|
+
label: string;
|
|
54
|
+
children: ReactNode;
|
|
55
|
+
className?: string;
|
|
56
|
+
}): import("react").JSX.Element;
|
|
57
|
+
/** Items outside a group: a list, as a group's are. */
|
|
58
|
+
export declare function RailList({ children, className }: {
|
|
59
|
+
children: ReactNode;
|
|
60
|
+
className?: string;
|
|
61
|
+
}): import("react").JSX.Element;
|
|
62
|
+
export type RailItemProps = {
|
|
63
|
+
href?: string;
|
|
64
|
+
onPress?: () => void;
|
|
65
|
+
/** A component, an element, or a drawing of the product's own (a progress ring) that takes `className`. */
|
|
66
|
+
icon: IconProp;
|
|
67
|
+
/** The name, always shown under the icon: two lines at most, hyphenated rather than cut off. */
|
|
68
|
+
children: string;
|
|
69
|
+
/** Marks the current page: brand-subtle fill, a marker edge, the icon and name in brand at weight 700, and aria-current. */
|
|
70
|
+
isCurrent?: boolean;
|
|
71
|
+
} & NavItemLiveProps;
|
|
72
|
+
export declare function RailItem({ href, onPress, icon, children, isCurrent, detail, detailTone, status, statusLabel, }: RailItemProps): import("react").JSX.Element;
|
|
73
|
+
//# sourceMappingURL=rail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rail.d.ts","sourceRoot":"","sources":["../../src/shell/rail.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG9C,OAAO,EAA4C,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAElG,gHAAgH;AAChH,MAAM,WAAW,UAAU;IACzB,sFAAsF;IACtF,UAAU,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,yGAAyG;IACzG,aAAa,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,UAAU,EAAE,UAMxB,CAAC;AAEF,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,SAAS,+BA4CrE;AAED,6GAA6G;AAC7G,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAY9F;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAY/F;AAED,2GAA2G;AAC3G,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAY9F;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,SAAS,GACV,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BAcA;AAED,uDAAuD;AACvD,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAE5F;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,2GAA2G;IAC3G,IAAI,EAAE,QAAQ,CAAC;IACf,gGAAgG;IAChG,QAAQ,EAAE,MAAM,CAAC;IACjB,4HAA4H;IAC5H,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GAAG,gBAAgB,CAAC;AAErB,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,MAAM,EACN,UAAU,EACV,MAAM,EACN,WAAW,GACZ,EAAE,aAAa,+BAkEf"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useId } from 'react';
|
|
4
|
+
import { Link } from 'react-aria-components';
|
|
5
|
+
import { cn } from '../lib/cn.js';
|
|
6
|
+
import { useLabels } from '../lib/locale.js';
|
|
7
|
+
import { Sheet } from '../ui/sheet.js';
|
|
8
|
+
import { useShell } from './dashboard-shell.js';
|
|
9
|
+
import { NavDetail, NavIcon, warnUnlabelledStatus } from './nav-status.js';
|
|
10
|
+
export const railLabels = {
|
|
11
|
+
navigation: '{product} navigation',
|
|
12
|
+
primary: 'Primary',
|
|
13
|
+
detail: ', {detail}',
|
|
14
|
+
detailWarning: ', {detail}, warning',
|
|
15
|
+
status: ', {status}',
|
|
16
|
+
};
|
|
17
|
+
// Developer-facing: said once per page, not once per render.
|
|
18
|
+
let warned = false;
|
|
19
|
+
/**
|
|
20
|
+
* Layout option C: a labelled navigation rail, `--rail-width` wide, used in a DashboardShell instead of Sidebar. Every
|
|
21
|
+
* item shows its icon over its name, so every destination is visible without the sidebar's width. It never
|
|
22
|
+
* collapses or expands. On phones it is the same Sheet the Sidebar becomes, with the items as rows. Give the shell
|
|
23
|
+
* `navigation="rail"`, so AppHeader shows its trigger only where it opens that Sheet.
|
|
24
|
+
*/
|
|
25
|
+
export function Rail({ children, labels: given, className }) {
|
|
26
|
+
const { size, mobileNavOpen, setMobileNavOpen, productName, isSizeForced, navigation } = useShell();
|
|
27
|
+
// The sidebar's app-wide words, then the rail's: a product that switches keeps its translations.
|
|
28
|
+
const t = useLabels(['sidebar', 'rail'], railLabels, given);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (navigation === 'rail' || warned)
|
|
31
|
+
return;
|
|
32
|
+
warned = true;
|
|
33
|
+
console.error('<Rail> is inside a <DashboardShell> without navigation="rail": AppHeader will show a sidebar toggle that does nothing. Pass navigation="rail" to the shell.');
|
|
34
|
+
}, [navigation]);
|
|
35
|
+
if (size === 'mobile') {
|
|
36
|
+
return (_jsx(Sheet, { side: "left", isOpen: mobileNavOpen, onOpenChange: setMobileNavOpen, "aria-label": t('navigation', { product: productName }), children: _jsx("nav", { "aria-label": t('primary'), "data-layout": "rows", className: "group/rail flex h-full min-h-0 flex-col text-sidebar-foreground", children: children }) }));
|
|
37
|
+
}
|
|
38
|
+
return (_jsx("nav", { "aria-label": t('primary'), "data-layout": "tiles", style: { viewTransitionName: 'shell-sidebar' }, className: cn('group/rail flex h-full min-h-0 w-rail shrink-0 flex-col text-sidebar-foreground', !isSizeForced && '@max-[48rem]/shell:hidden', className), children: children }));
|
|
39
|
+
}
|
|
40
|
+
/** The product's mark, at the top. In the phone's Sheet it sits at the start of the row, as the items do. */
|
|
41
|
+
export function RailHeader({ children, className }) {
|
|
42
|
+
return (_jsx("div", { className: cn('flex min-h-[calc(var(--nav-item-height)+12px)] shrink-0 items-center justify-center px-1 pt-3', 'group-data-[layout=rows]/rail:justify-start group-data-[layout=rows]/rail:px-[22px]', className), children: children }));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The items. Scrolls when they are taller than the shell, and is positioned, so the visually hidden group names
|
|
46
|
+
* inside it scroll with it rather than being laid out against the shell.
|
|
47
|
+
*/
|
|
48
|
+
export function RailContent({ children, className }) {
|
|
49
|
+
return (_jsx("div", { className: cn('relative flex min-h-0 flex-1 flex-col gap-(--nav-item-gap) overflow-y-auto px-1 py-3', 'group-data-[layout=rows]/rail:px-3', className), children: children }));
|
|
50
|
+
}
|
|
51
|
+
/** Pinned to the bottom: help, settings, the account. Put items in a `RailList`, as in a SidebarFooter. */
|
|
52
|
+
export function RailFooter({ children, className }) {
|
|
53
|
+
return (_jsx("div", { className: cn('flex shrink-0 flex-col gap-(--nav-item-gap) border-t border-sidebar-border px-1 py-3', 'group-data-[layout=rows]/rail:px-3', className), children: children }));
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* A labelled group of items. Its name is visually hidden and names the group for assistive technology; a rule above
|
|
57
|
+
* it separates it from what comes before. Groups are `role="group"`, not landmarks, so the landmark list stays short.
|
|
58
|
+
*/
|
|
59
|
+
export function RailGroup({ label, children, className, }) {
|
|
60
|
+
const id = useId();
|
|
61
|
+
return (_jsxs("div", { role: "group", "aria-labelledby": id, className: cn('not-first:border-t not-first:border-sidebar-border not-first:pt-3', className), children: [_jsx("h2", { id: id, className: "sr-only", children: label }), _jsx(RailList, { children: children })] }));
|
|
62
|
+
}
|
|
63
|
+
/** Items outside a group: a list, as a group's are. */
|
|
64
|
+
export function RailList({ children, className }) {
|
|
65
|
+
return _jsx("ul", { className: cn('flex flex-col gap-(--nav-item-gap)', className), children: children });
|
|
66
|
+
}
|
|
67
|
+
export function RailItem({ href, onPress, icon, children, isCurrent, detail, detailTone, status, statusLabel, }) {
|
|
68
|
+
const t = useLabels(['sidebar', 'rail'], railLabels, undefined);
|
|
69
|
+
warnUnlabelledStatus('RailItem', status, statusLabel);
|
|
70
|
+
return (_jsx("li", { children: _jsx(Link, { href: href, onPress: onPress, "aria-current": isCurrent ? 'page' : undefined, className: cn(
|
|
71
|
+
// Layer 1: the row is the target, the rail's full width and at least --target-min tall.
|
|
72
|
+
'group/item relative flex min-h-target w-full cursor-pointer items-center text-sidebar-foreground no-underline outline-none'), children: _jsxs("span", { className: cn('relative flex w-full min-w-0 flex-col items-center gap-1 rounded-md px-0.5 py-2', 'group-data-hovered/item:bg-sidebar-accent group-data-hovered/item:text-sidebar-accent-foreground group-data-focus-visible/item:focus-ring', 'group-aria-[current=page]/item:bg-brand-subtle group-aria-[current=page]/item:text-foreground',
|
|
73
|
+
// The marker: a 3px edge along the tile's start, an inset shadow so it follows the rounded corners.
|
|
74
|
+
'group-aria-[current=page]/item:shadow-[inset_3px_0_0_var(--sidebar-primary)]',
|
|
75
|
+
// Hovered, the current page keeps its fill: the hover ground under brand text would be a pair the audit doesn't
|
|
76
|
+
// promise. Stacked variants, so this is more specific than the hover rule whatever order they're written in.
|
|
77
|
+
'group-data-hovered/item:group-aria-[current=page]/item:bg-brand-subtle group-data-hovered/item:group-aria-[current=page]/item:text-foreground',
|
|
78
|
+
// Forced colours drop shadows and fills: there the marker is a bar in Highlight.
|
|
79
|
+
'forced-colors:group-aria-[current=page]/item:before:absolute forced-colors:group-aria-[current=page]/item:before:inset-y-0 forced-colors:group-aria-[current=page]/item:before:start-0 forced-colors:group-aria-[current=page]/item:before:w-[3px] forced-colors:group-aria-[current=page]/item:before:rounded-s-md forced-colors:group-aria-[current=page]/item:before:bg-[Highlight] forced-colors:group-aria-[current=page]/item:before:forced-color-adjust-none',
|
|
80
|
+
// In the phone's Sheet, a row: the icon beside the name, as the Sidebar's are.
|
|
81
|
+
'group-data-[layout=rows]/rail:min-h-nav-item group-data-[layout=rows]/rail:flex-row group-data-[layout=rows]/rail:gap-3 group-data-[layout=rows]/rail:px-3 group-data-[layout=rows]/rail:py-0',
|
|
82
|
+
// The status badge's cut-out follows the ground: the rail, the hovered tile, the current one.
|
|
83
|
+
'[--nav-cut:var(--sidebar)] group-data-hovered/item:[--nav-cut:var(--sidebar-accent)] group-aria-[current=page]/item:[--nav-cut:var(--brand-subtle)] group-data-hovered/item:group-aria-[current=page]/item:[--nav-cut:var(--brand-subtle)]'), children: [_jsx(NavIcon, { icon: icon, status: status, className: "group-aria-[current=page]/item:text-brand" }), _jsxs("span", { "data-name": "", className: cn('w-full min-w-0 text-center text-[13px] leading-4 font-medium [overflow-wrap:anywhere] hyphens-auto', 'group-aria-[current=page]/item:font-bold group-aria-[current=page]/item:text-brand', 'group-data-[layout=rows]/rail:flex-1 group-data-[layout=rows]/rail:text-start group-data-[layout=rows]/rail:text-sm group-data-[layout=rows]/rail:leading-5'), children: [children, detail && (_jsx("span", { className: "sr-only", children: t(detailTone === 'warning' ? 'detailWarning' : 'detail', { detail }) })), statusLabel && _jsx("span", { className: "sr-only", children: t('status', { status: statusLabel }) })] }), detail && (_jsx(NavDetail, { detail: detail, tone: detailTone,
|
|
84
|
+
// Under the name in a tile, wrapping rather than running out of it; after the name in a row.
|
|
85
|
+
className: "max-w-full flex-wrap justify-center text-center whitespace-normal [overflow-wrap:anywhere] group-data-[layout=rows]/rail:whitespace-nowrap" }))] }) }) }));
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=rail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rail.js","sourceRoot":"","sources":["../../src/shell/rail.tsx"],"names":[],"mappings":"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"}
|
package/dist/shell/sidebar.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import { type Key } from 'react-aria-components';
|
|
3
3
|
import { type IconProp } from '../ui/icon.js';
|
|
4
|
+
import { type NavItemLiveProps } from './nav-status.js';
|
|
4
5
|
/** True when the sidebar shows icons only (never inside the mobile Sheet). */
|
|
5
6
|
export declare const useSidebarCollapsed: () => boolean;
|
|
6
7
|
/** The sidebar's words, for the `labels` prop. */
|
|
@@ -13,6 +14,18 @@ export interface SidebarLabels {
|
|
|
13
14
|
count: string;
|
|
14
15
|
/** A collapsed item's tooltip, with its count: "Projects (12)". */
|
|
15
16
|
tipCount: string;
|
|
17
|
+
/** Added to an item's name for its `detail`: "Spend, $1.20". */
|
|
18
|
+
detail: string;
|
|
19
|
+
/** The same for a `detailTone="warning"` detail, with words for the warning: "Spend, $1.20, warning". */
|
|
20
|
+
detailWarning: string;
|
|
21
|
+
/** Added to an item's name for its `statusLabel`: "Drafts, A draft is waiting for you". */
|
|
22
|
+
status: string;
|
|
23
|
+
/** A collapsed item's tooltip with its detail: `{name}` is the tooltip so far. "Spend ($1.20)". */
|
|
24
|
+
tipDetail: string;
|
|
25
|
+
/** The same for a warning detail: "Spend ($1.20, warning)". */
|
|
26
|
+
tipDetailWarning: string;
|
|
27
|
+
/** A collapsed item's tooltip with its status: `{tip}` is the tooltip so far. "Scenes: Claude is working". */
|
|
28
|
+
tipStatus: string;
|
|
16
29
|
}
|
|
17
30
|
export declare const sidebarLabels: SidebarLabels;
|
|
18
31
|
export interface SidebarProps {
|
|
@@ -49,17 +62,25 @@ export declare function SidebarList({ children, className }: {
|
|
|
49
62
|
children: ReactNode;
|
|
50
63
|
className?: string;
|
|
51
64
|
}): import("react").JSX.Element;
|
|
52
|
-
export
|
|
65
|
+
export type SidebarItemProps = {
|
|
53
66
|
href?: string;
|
|
67
|
+
/** A component, an element, or a drawing of the product's own (a progress ring) that takes `className`. */
|
|
54
68
|
icon: IconProp;
|
|
55
69
|
children: string;
|
|
56
|
-
/** Marks the current page: brand-subtle fill, marker
|
|
70
|
+
/** Marks the current page: brand-subtle fill, a marker edge, the icon and name in brand at weight 700, and aria-current. */
|
|
57
71
|
isCurrent?: boolean;
|
|
58
72
|
/** Shown beside the label and read as part of it: "Projects, 12". */
|
|
59
73
|
count?: number;
|
|
60
74
|
onPress?: () => void;
|
|
61
|
-
}
|
|
62
|
-
|
|
75
|
+
} & NavItemLiveProps;
|
|
76
|
+
/** A collapsed item's tooltip: its name, then its count, detail and status, each through its own template. */
|
|
77
|
+
export declare function navTooltip(t: (key: 'tipCount' | 'tipDetail' | 'tipDetailWarning' | 'tipStatus', values: Record<string, string | number>) => string, name: string, { count, detail, detailTone, statusLabel, }: {
|
|
78
|
+
count?: number;
|
|
79
|
+
detail?: string;
|
|
80
|
+
detailTone?: string;
|
|
81
|
+
statusLabel?: string;
|
|
82
|
+
}): string;
|
|
83
|
+
export declare function SidebarItem({ href, icon, children, isCurrent, count, onPress, detail, detailTone, status, statusLabel, }: SidebarItemProps): import("react").JSX.Element;
|
|
63
84
|
export interface SidebarSubItem {
|
|
64
85
|
href: string;
|
|
65
86
|
label: string;
|
|
@@ -105,9 +126,13 @@ export interface SidebarTriggerLabels {
|
|
|
105
126
|
toggleSidebar: string;
|
|
106
127
|
}
|
|
107
128
|
export declare const sidebarTriggerLabels: SidebarTriggerLabels;
|
|
108
|
-
/**
|
|
129
|
+
/**
|
|
130
|
+
* Collapses the sidebar to icons, or opens it as a Sheet on phones. In a shell with `navigation="rail"` there is
|
|
131
|
+
* nothing to collapse, so it is only there on phones, where it opens the rail's Sheet: before the shell has measured
|
|
132
|
+
* itself a container query hides it from bp-md up, and once it has (or its size is forced) it isn't rendered there.
|
|
133
|
+
*/
|
|
109
134
|
export declare function SidebarTrigger({ labels: given, className, }: {
|
|
110
135
|
labels?: Partial<SidebarTriggerLabels>;
|
|
111
136
|
className?: string;
|
|
112
|
-
}): import("react").JSX.Element;
|
|
137
|
+
}): import("react").JSX.Element | null;
|
|
113
138
|
//# sourceMappingURL=sidebar.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../src/shell/sidebar.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACzE,OAAO,EAML,KAAK,GAAG,EACT,MAAM,uBAAuB,CAAC;AAK/B,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../src/shell/sidebar.tsx"],"names":[],"mappings":"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"}
|