@kerfjs/ui 5.0.0-beta.50 → 5.0.0-beta.51
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/README.md +29 -5
- package/ai/compile-time-contracts-v1.json +5 -2
- package/ai/component-catalog-v2.d.ts +19 -1
- package/ai/component-catalog-v2.json +842 -127
- package/ai/component-catalog-v2.schema.json +33 -1
- package/ai/component-catalog.json +603 -126
- package/ai/component-catalog.schema.json +21 -1
- package/ai/public-api-signatures-v1.md +201 -29
- package/ai/skill.md +12 -9
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/analyzer/index.mjs +105 -35
- package/dist/app-tab.js +1 -1
- package/dist/catalog-resources.d.ts +1 -1
- package/dist/catalog.d.ts +28 -5
- package/dist/catalog.js +66 -25
- package/dist/catalog.js.map +1 -1
- package/dist/{chunk-COUPLRZG.js → chunk-5FZZMIMD.js} +3 -3
- package/dist/{chunk-COUPLRZG.js.map → chunk-5FZZMIMD.js.map} +1 -1
- package/dist/{chunk-DARTMI5Z.js → chunk-5PMGQDG7.js} +2 -2
- package/dist/{chunk-DARTMI5Z.js.map → chunk-5PMGQDG7.js.map} +1 -1
- package/dist/{chunk-V6RZWDII.js → chunk-7GUQYHKA.js} +19 -2
- package/dist/chunk-7GUQYHKA.js.map +1 -0
- package/dist/{chunk-ZNZ2JDBW.js → chunk-7IUSV4XG.js} +1 -1
- package/dist/chunk-7IUSV4XG.js.map +1 -0
- package/dist/{chunk-ELRMBQEC.js → chunk-AEPXGCNF.js} +17 -2
- package/dist/chunk-AEPXGCNF.js.map +1 -0
- package/dist/{chunk-5CE64WGC.js → chunk-D547PH4L.js} +3 -3
- package/dist/{chunk-5CE64WGC.js.map → chunk-D547PH4L.js.map} +1 -1
- package/dist/{chunk-S6ZTTTV7.js → chunk-DVZCMMB3.js} +3 -3
- package/dist/{chunk-S6ZTTTV7.js.map → chunk-DVZCMMB3.js.map} +1 -1
- package/dist/chunk-EKYZCRCX.js +256 -0
- package/dist/chunk-EKYZCRCX.js.map +1 -0
- package/dist/{chunk-3V75EQIP.js → chunk-JM53SMVF.js} +3 -3
- package/dist/{chunk-3V75EQIP.js.map → chunk-JM53SMVF.js.map} +1 -1
- package/dist/{chunk-2WMSE4MK.js → chunk-JMGKM7RK.js} +2 -2
- package/dist/{chunk-2WMSE4MK.js.map → chunk-JMGKM7RK.js.map} +1 -1
- package/dist/{chunk-2YOUUEWR.js → chunk-KX7DP2GO.js} +4 -4
- package/dist/{chunk-2YOUUEWR.js.map → chunk-KX7DP2GO.js.map} +1 -1
- package/dist/{chunk-OL4TC3U2.js → chunk-MO56ZZLG.js} +6 -2
- package/dist/chunk-MO56ZZLG.js.map +1 -0
- package/dist/{chunk-OQI7RCRP.js → chunk-MTM43SJO.js} +7 -1
- package/dist/chunk-MTM43SJO.js.map +1 -0
- package/dist/{chunk-ZSYLBVWG.js → chunk-NMGTHYW3.js} +3 -3
- package/dist/{chunk-ZSYLBVWG.js.map → chunk-NMGTHYW3.js.map} +1 -1
- package/dist/{chunk-AQSKJ6U6.js → chunk-NZXWU4R5.js} +21 -2
- package/dist/chunk-NZXWU4R5.js.map +1 -0
- package/dist/{chunk-DJKWFYAA.js → chunk-O3RCCSQJ.js} +3 -3
- package/dist/{chunk-DJKWFYAA.js.map → chunk-O3RCCSQJ.js.map} +1 -1
- package/dist/{chunk-UMGY5JSP.js → chunk-S4QRSBFI.js} +22 -2
- package/dist/chunk-S4QRSBFI.js.map +1 -0
- package/dist/{chunk-KKNK3JUT.js → chunk-UBH743HV.js} +5 -5
- package/dist/chunk-UBH743HV.js.map +1 -0
- package/dist/{chunk-54HM36IQ.js → chunk-ULCDZTWL.js} +2 -2
- package/dist/{chunk-54HM36IQ.js.map → chunk-ULCDZTWL.js.map} +1 -1
- package/dist/{chunk-SIU2AC5W.js → chunk-UPZ6EEJN.js} +3 -3
- package/dist/{chunk-SIU2AC5W.js.map → chunk-UPZ6EEJN.js.map} +1 -1
- package/dist/collapsible-panel.d.ts +1 -1
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/css-values.d.ts +39 -3
- package/dist/css-values.js +1 -1
- package/dist/grid.d.ts +15 -1
- package/dist/grid.js +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +19 -19
- package/dist/list-action-row.js +1 -1
- package/dist/list-header.js +1 -1
- package/dist/list-item.js +1 -1
- package/dist/list.d.ts +21 -2
- package/dist/list.js +2 -1
- package/dist/nav-stack.js +1 -1
- package/dist/pane.d.ts +17 -2
- package/dist/pane.js +1 -1
- package/dist/row.d.ts +19 -1
- package/dist/row.js +2 -1
- package/dist/segmented-control.js +1 -1
- package/dist/select.d.ts +13 -3
- package/dist/select.js +1 -1
- package/dist/skeleton.js +1 -1
- package/dist/spacer.js +1 -1
- package/dist/split-view.js +1 -1
- package/dist/state-banner.js +1 -1
- package/dist/styles/catalog/components/catalog-example-stack.css +4 -1
- package/dist/styles/catalog/components/catalog-example.css +145 -0
- package/dist/styles/collapsible-panel.css +132 -4
- package/dist/styles/document.css +23 -0
- package/dist/styles/foundation.css +21 -7
- package/dist/styles/grid.css +10 -0
- package/dist/styles/list-header.css +45 -0
- package/dist/styles/list-inset-control.css +8 -1
- package/dist/styles/list-item.css +6 -0
- package/dist/styles/list.css +11 -0
- package/dist/styles/nav-stack.css +89 -2
- package/dist/styles/pane.css +86 -1
- package/dist/styles/resizable-region.css +93 -5
- package/dist/styles/row.css +10 -0
- package/dist/styles/select.css +39 -4
- package/dist/styles/split-view.css +107 -1
- package/dist/styles/tab-scaffold.css +64 -1
- package/dist/styles/text.css +6 -0
- package/dist/styles/toolbar-control-group.css +90 -11
- package/dist/styles/toolbar-text.css +4 -1
- package/dist/styles/toolbar.css +130 -38
- package/dist/styles/webawesome.css +48 -2
- package/dist/styles/workbench.css +136 -4
- package/dist/text.d.ts +4 -3
- package/dist/text.js +1 -1
- package/dist/toolbar-text.js +1 -1
- package/dist/toolbar.d.ts +24 -3
- package/dist/toolbar.js +1 -1
- package/dist/{types-CzgSrFXP.d.ts → types-CEsieBZi.d.ts} +6 -1
- package/dist/value-table.js +1 -1
- package/dist/wire-resizable-regions.js +1 -1
- package/dist/wire-sidebar.d.ts +18 -3
- package/dist/wire-sidebar.js +95 -14
- package/dist/wire-sidebar.js.map +1 -1
- package/docs/accessibility.md +45 -8
- package/docs/app-layouts.md +73 -0
- package/docs/catalog.md +23 -2
- package/docs/collapsible-panel.md +81 -8
- package/docs/component-contract.md +28 -9
- package/docs/component-integration.md +9 -4
- package/docs/component-selection.md +25 -6
- package/docs/design/templates/list/stack-dark.svg +1 -1
- package/docs/design/templates/list/stack.svg +1 -1
- package/docs/design/templates/list-dark.svg +1 -1
- package/docs/design/templates/list-header/action-dark.svg +1 -1
- package/docs/design/templates/list-header/action.svg +1 -1
- package/docs/design/templates/list-header/count-dark.svg +1 -1
- package/docs/design/templates/list-header/count.svg +1 -1
- package/docs/design/templates/list-header/inline-action-dark.svg +1 -1
- package/docs/design/templates/list-header/inline-action.svg +1 -1
- package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -1
- package/docs/design/templates/list-header/toggle-expanded.svg +1 -1
- package/docs/design/templates/list-header-dark.svg +1 -1
- package/docs/design/templates/list-header.svg +1 -1
- package/docs/design/templates/list.svg +1 -1
- package/docs/design/templates/state-banner/info-badge-dark.svg +1 -1
- package/docs/design/templates/state-banner/info-badge.svg +1 -1
- package/docs/design/templates/state-banner-dark.svg +1 -1
- package/docs/design/templates/state-banner.svg +1 -1
- package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -1
- package/docs/design/templates/toolbar/title-and-actions.svg +1 -1
- package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -1
- package/docs/design/templates/toolbar-control-group/with-text.svg +1 -1
- package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
- package/docs/design/templates/toolbar-control-group.svg +1 -1
- package/docs/design/templates/toolbar-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/default-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/default.svg +1 -1
- package/docs/design/templates/toolbar-text/large-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/large.svg +1 -1
- package/docs/design/templates/toolbar-text/small-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/small.svg +1 -1
- package/docs/design/templates/toolbar-text-dark.svg +1 -1
- package/docs/design/templates/toolbar-text.svg +1 -1
- package/docs/design/templates/toolbar.svg +1 -1
- package/docs/document-baseline.md +31 -0
- package/docs/layout.md +86 -21
- package/docs/nav-stack.md +8 -0
- package/docs/recipes.md +78 -43
- package/docs/split-view.md +8 -0
- package/docs/tab-scaffold.md +4 -2
- package/docs/type-contracts.md +21 -17
- package/docs/ui-analyzer.md +19 -0
- package/docs/ui-evaluator.md +17 -0
- package/docs/ux-demo.md +4 -4
- package/docs/webawesome-theme.md +20 -2
- package/docs/workbench.md +20 -1
- package/evaluator/index.mjs +73 -8
- package/llms.txt +32 -14
- package/package.json +4 -2
- package/ux-demo/recipes/app-shell.tsx +209 -178
- package/ux-demo/recipes/collapsible-sidebar.tsx +188 -159
- package/ux-demo/recipes/compact-toolbar.tsx +48 -35
- package/ux-demo/recipes/composer-form.tsx +85 -79
- package/ux-demo/recipes/list-detail-dialog.tsx +124 -142
- package/ux-demo/recipes/list-workspace-states.tsx +83 -83
- package/ux-demo/recipes/loaders.ts +5 -2
- package/ux-demo/recipes/loading-inspector.tsx +157 -160
- package/ux-demo/recipes/navigation-sidebar.tsx +111 -109
- package/ux-demo/recipes/navigation-stack.tsx +50 -49
- package/ux-demo/recipes/types.ts +14 -0
- package/ux-demo/recipes/workspace-header.tsx +73 -56
- package/dist/chunk-AQSKJ6U6.js.map +0 -1
- package/dist/chunk-ELRMBQEC.js.map +0 -1
- package/dist/chunk-J3EE6XWD.js +0 -115
- package/dist/chunk-J3EE6XWD.js.map +0 -1
- package/dist/chunk-KKNK3JUT.js.map +0 -1
- package/dist/chunk-OL4TC3U2.js.map +0 -1
- package/dist/chunk-OQI7RCRP.js.map +0 -1
- package/dist/chunk-UMGY5JSP.js.map +0 -1
- package/dist/chunk-V6RZWDII.js.map +0 -1
- package/dist/chunk-ZNZ2JDBW.js.map +0 -1
- package/ux-demo/recipes/app-shell.css +0 -87
- package/ux-demo/recipes/collapsible-sidebar.css +0 -83
- package/ux-demo/recipes/compact-toolbar.css +0 -35
- package/ux-demo/recipes/composer-form.css +0 -19
- package/ux-demo/recipes/list-detail-dialog.css +0 -42
- package/ux-demo/recipes/list-workspace-states.css +0 -30
- package/ux-demo/recipes/loading-inspector.css +0 -7
- package/ux-demo/recipes/navigation-sidebar.css +0 -12
- package/ux-demo/recipes/navigation-stack.css +0 -12
- package/ux-demo/recipes/recipe-root.css +0 -67
- package/ux-demo/recipes/recipe-root.tsx +0 -87
- package/ux-demo/recipes/workspace-header.css +0 -7
|
@@ -1,33 +1,44 @@
|
|
|
1
1
|
import '@kerfjs/ui/layout.css';
|
|
2
2
|
import '@kerfjs/ui/collapsible-panel.css';
|
|
3
|
-
import './collapsible-sidebar.css';
|
|
4
3
|
|
|
5
4
|
import {
|
|
6
5
|
CollapsiblePanel,
|
|
7
6
|
CollapsiblePanelToggle,
|
|
8
7
|
} from '@kerfjs/ui/collapsible-panel';
|
|
9
8
|
import { deviceClass } from '@kerfjs/ui/device-class';
|
|
9
|
+
import { Grid } from '@kerfjs/ui/grid';
|
|
10
|
+
import { List } from '@kerfjs/ui/list';
|
|
10
11
|
import { ListHeader } from '@kerfjs/ui/list-header';
|
|
11
12
|
import { ListItem } from '@kerfjs/ui/list-item';
|
|
12
13
|
import { LucideIcon } from '@kerfjs/ui/lucide-icon';
|
|
13
14
|
import { Pane } from '@kerfjs/ui/pane';
|
|
15
|
+
import { Row } from '@kerfjs/ui/row';
|
|
16
|
+
import { Text } from '@kerfjs/ui/text';
|
|
14
17
|
import { Toolbar } from '@kerfjs/ui/toolbar';
|
|
15
18
|
import { ToolbarControlGroup } from '@kerfjs/ui/toolbar-control-group';
|
|
16
19
|
import { ToolbarText } from '@kerfjs/ui/toolbar-text';
|
|
20
|
+
import { ValueTable, ValueTableRow } from '@kerfjs/ui/value-table';
|
|
17
21
|
import { type SidebarStorage, wireSidebar } from '@kerfjs/ui/wire-sidebar';
|
|
18
22
|
import { signal } from 'kerfjs';
|
|
19
23
|
import { Bell, Folder, Inbox, Users } from 'lucide';
|
|
20
24
|
|
|
21
|
-
import {
|
|
22
|
-
RecipeMutedText,
|
|
23
|
-
RecipeOwnershipNote,
|
|
24
|
-
RecipeRoot,
|
|
25
|
-
} from './recipe-root.js';
|
|
26
|
-
import type { RecipeFactory } from './types.js';
|
|
25
|
+
import type { RecipeFactory, RecipePresentation } from './types.js';
|
|
27
26
|
|
|
28
27
|
const RAIL_ACTION = 'recipe-sidebar-rail';
|
|
29
28
|
const DRAWER_ACTION = 'recipe-sidebar-drawer';
|
|
30
29
|
|
|
30
|
+
export const presentation: RecipePresentation = {
|
|
31
|
+
viewport: {
|
|
32
|
+
width: 'full',
|
|
33
|
+
height: 'app',
|
|
34
|
+
frame: 'solid',
|
|
35
|
+
surface: 'default',
|
|
36
|
+
overflow: 'hidden',
|
|
37
|
+
shadow: true,
|
|
38
|
+
},
|
|
39
|
+
note: "The app owns each panel's collapsed signal, sizes, and content; wireSidebar owns the toggle, focus move/restore, the compact overlay, and persistence.",
|
|
40
|
+
};
|
|
41
|
+
|
|
31
42
|
/**
|
|
32
43
|
* A memory-backed store so the recipe demonstrates the persistence hook without
|
|
33
44
|
* writing to the shared `localStorage` the catalog page runs in.
|
|
@@ -42,23 +53,31 @@ function memoryStorage(): SidebarStorage {
|
|
|
42
53
|
};
|
|
43
54
|
}
|
|
44
55
|
|
|
56
|
+
const labels: Record<string, string> = {
|
|
57
|
+
inbox: 'Inbox',
|
|
58
|
+
projects: 'Projects',
|
|
59
|
+
shared: 'Shared with me',
|
|
60
|
+
};
|
|
61
|
+
|
|
45
62
|
export const createRecipe: RecipeFactory = (announce) => {
|
|
46
63
|
const selected = signal('inbox');
|
|
47
|
-
const railCollapsed = signal(false);
|
|
48
|
-
const drawerCollapsed = signal(true);
|
|
49
|
-
const storage = memoryStorage();
|
|
50
64
|
// A shared window-backed device class: when the viewport is compact the wire
|
|
51
65
|
// switches the rail/drawer to a dismissable overlay presentation.
|
|
52
66
|
const device = deviceClass();
|
|
67
|
+
// A compact overlay only opens on a user action, so the first render already
|
|
68
|
+
// matches: collapsed on a compact device, open inline otherwise. The wire's
|
|
69
|
+
// `inlineCollapsed` keeps the open inline default for a later wide crossing.
|
|
70
|
+
const railCollapsed = signal(device.value.compact);
|
|
71
|
+
const drawerCollapsed = signal(true);
|
|
72
|
+
const storage = memoryStorage();
|
|
53
73
|
|
|
54
|
-
const railToggle = (
|
|
74
|
+
const railToggle = () => (
|
|
55
75
|
<CollapsiblePanelToggle
|
|
56
76
|
side="left"
|
|
57
77
|
collapsed={railCollapsed.value}
|
|
58
78
|
action={RAIL_ACTION}
|
|
59
79
|
panelId="sidebar-rail"
|
|
60
80
|
label={railCollapsed.value ? 'Show navigation' : 'Hide navigation'}
|
|
61
|
-
className={inPanel ? '' : 'recipe-collapsible-sidebar__reveal'}
|
|
62
81
|
/>
|
|
63
82
|
);
|
|
64
83
|
const drawerToggle = () => (
|
|
@@ -71,158 +90,167 @@ export const createRecipe: RecipeFactory = (announce) => {
|
|
|
71
90
|
/>
|
|
72
91
|
);
|
|
73
92
|
|
|
93
|
+
const rail = () => (
|
|
94
|
+
<CollapsiblePanel
|
|
95
|
+
id="sidebar-rail"
|
|
96
|
+
side="left"
|
|
97
|
+
size={232}
|
|
98
|
+
collapsed={railCollapsed.value}
|
|
99
|
+
label="Workspace navigation"
|
|
100
|
+
>
|
|
101
|
+
<Pane
|
|
102
|
+
contentElement="nav"
|
|
103
|
+
contentLabel="Workspace"
|
|
104
|
+
header={
|
|
105
|
+
<Toolbar
|
|
106
|
+
label="Workspace navigation"
|
|
107
|
+
dividerSides=""
|
|
108
|
+
leading={<ToolbarText text="Atlas" />}
|
|
109
|
+
trailing={
|
|
110
|
+
<ToolbarControlGroup appearance="borderless" single>
|
|
111
|
+
{railToggle()}
|
|
112
|
+
</ToolbarControlGroup>
|
|
113
|
+
}
|
|
114
|
+
/>
|
|
115
|
+
}
|
|
116
|
+
>
|
|
117
|
+
<section>
|
|
118
|
+
<ListHeader label="Workspace" />
|
|
119
|
+
<ListItem
|
|
120
|
+
action="recipe-action"
|
|
121
|
+
itemId="inbox"
|
|
122
|
+
label="Inbox"
|
|
123
|
+
icon={<LucideIcon icon={Inbox} name="inbox" />}
|
|
124
|
+
trailing={<span>12</span>}
|
|
125
|
+
selected={selected.value === 'inbox'}
|
|
126
|
+
/>
|
|
127
|
+
<ListItem
|
|
128
|
+
action="recipe-action"
|
|
129
|
+
itemId="projects"
|
|
130
|
+
label="Projects"
|
|
131
|
+
icon={<LucideIcon icon={Folder} name="folder" />}
|
|
132
|
+
selected={selected.value === 'projects'}
|
|
133
|
+
/>
|
|
134
|
+
<ListItem
|
|
135
|
+
action="recipe-action"
|
|
136
|
+
itemId="shared"
|
|
137
|
+
label="Shared with me"
|
|
138
|
+
icon={<LucideIcon icon={Users} name="users" />}
|
|
139
|
+
selected={selected.value === 'shared'}
|
|
140
|
+
/>
|
|
141
|
+
</section>
|
|
142
|
+
</Pane>
|
|
143
|
+
</CollapsiblePanel>
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
// Each panel's own header holds its collapse toggle; the always-visible main
|
|
147
|
+
// header holds its expand toggle only while it is collapsed, so exactly one
|
|
148
|
+
// control owns each action. wireSidebar hands focus between them.
|
|
149
|
+
const main = () => (
|
|
150
|
+
<Pane
|
|
151
|
+
element="main"
|
|
152
|
+
header={
|
|
153
|
+
<Toolbar
|
|
154
|
+
label="Current navigation view"
|
|
155
|
+
dividerSides=""
|
|
156
|
+
leading={
|
|
157
|
+
<>
|
|
158
|
+
{railCollapsed.value ? (
|
|
159
|
+
<ToolbarControlGroup appearance="borderless" single>
|
|
160
|
+
{railToggle()}
|
|
161
|
+
</ToolbarControlGroup>
|
|
162
|
+
) : null}
|
|
163
|
+
<ToolbarText
|
|
164
|
+
text={labels[selected.value] ?? 'Inbox'}
|
|
165
|
+
size="xlarge"
|
|
166
|
+
id="recipe-collapsible-main-title"
|
|
167
|
+
/>
|
|
168
|
+
</>
|
|
169
|
+
}
|
|
170
|
+
trailing={
|
|
171
|
+
drawerCollapsed.value ? (
|
|
172
|
+
<ToolbarControlGroup appearance="borderless" single>
|
|
173
|
+
{drawerToggle()}
|
|
174
|
+
</ToolbarControlGroup>
|
|
175
|
+
) : undefined
|
|
176
|
+
}
|
|
177
|
+
/>
|
|
178
|
+
}
|
|
179
|
+
>
|
|
180
|
+
<div class="kui-content-item">
|
|
181
|
+
<List gap="2xs">
|
|
182
|
+
<Text variant="span">
|
|
183
|
+
<strong>Narrow the window to a compact width</strong>
|
|
184
|
+
</Text>
|
|
185
|
+
<Text variant="span" tone="quiet" size="compact">
|
|
186
|
+
The rail and drawer start closed and open as a dismissable overlay:
|
|
187
|
+
a backdrop, Escape, and a trapped Tab ring, all managed by the wire.
|
|
188
|
+
</Text>
|
|
189
|
+
</List>
|
|
190
|
+
</div>
|
|
191
|
+
</Pane>
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
const drawer = () => (
|
|
195
|
+
<CollapsiblePanel
|
|
196
|
+
id="sidebar-console"
|
|
197
|
+
side="bottom"
|
|
198
|
+
size={168}
|
|
199
|
+
collapsed={drawerCollapsed.value}
|
|
200
|
+
label="Activity"
|
|
201
|
+
>
|
|
202
|
+
<Pane
|
|
203
|
+
header={
|
|
204
|
+
<Toolbar
|
|
205
|
+
label="Activity"
|
|
206
|
+
dividerSides="b"
|
|
207
|
+
leading={<ToolbarText text="Activity" size="small" />}
|
|
208
|
+
trailing={
|
|
209
|
+
<ToolbarControlGroup appearance="borderless" single>
|
|
210
|
+
{drawerToggle()}
|
|
211
|
+
</ToolbarControlGroup>
|
|
212
|
+
}
|
|
213
|
+
/>
|
|
214
|
+
}
|
|
215
|
+
>
|
|
216
|
+
<ValueTable label="Recent activity">
|
|
217
|
+
<ValueTableRow
|
|
218
|
+
label="Deploy finished"
|
|
219
|
+
value="2m ago"
|
|
220
|
+
icon={<LucideIcon icon={Bell} name="bell" />}
|
|
221
|
+
/>
|
|
222
|
+
<ValueTableRow
|
|
223
|
+
label="Review requested"
|
|
224
|
+
value="9m ago"
|
|
225
|
+
icon={<LucideIcon icon={Bell} name="bell" />}
|
|
226
|
+
/>
|
|
227
|
+
</ValueTable>
|
|
228
|
+
</Pane>
|
|
229
|
+
</CollapsiblePanel>
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
// The root Row fills the frame's definite height with the rail beside a
|
|
233
|
+
// column whose main pane grows above the bottom drawer. Each CollapsiblePanel
|
|
234
|
+
// docks to a real frame edge, so it paints through that edge's safe area and
|
|
235
|
+
// hands the edge back to its siblings when it collapses.
|
|
74
236
|
const render = () => (
|
|
75
|
-
<
|
|
76
|
-
|
|
77
|
-
|
|
237
|
+
<Row
|
|
238
|
+
gap="none"
|
|
239
|
+
fill
|
|
240
|
+
rootAttributes={{
|
|
241
|
+
'data-recipe': 'recipe-collapsible-sidebar',
|
|
78
242
|
'data-rail-collapsed': String(railCollapsed.value),
|
|
79
243
|
'data-drawer-collapsed': String(drawerCollapsed.value),
|
|
80
244
|
}}
|
|
81
245
|
>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
>
|
|
91
|
-
<Pane
|
|
92
|
-
contentElement="nav"
|
|
93
|
-
contentClassName="recipe-collapsible-sidebar__nav"
|
|
94
|
-
contentLabel="Workspace"
|
|
95
|
-
header={
|
|
96
|
-
<Toolbar
|
|
97
|
-
label="Workspace navigation"
|
|
98
|
-
dividerSides=""
|
|
99
|
-
leading={<ToolbarText text="Atlas" />}
|
|
100
|
-
trailing={
|
|
101
|
-
<ToolbarControlGroup appearance="borderless" single>
|
|
102
|
-
{railToggle(true)}
|
|
103
|
-
</ToolbarControlGroup>
|
|
104
|
-
}
|
|
105
|
-
/>
|
|
106
|
-
}
|
|
107
|
-
>
|
|
108
|
-
<section>
|
|
109
|
-
<ListHeader label="Workspace" />
|
|
110
|
-
<ListItem
|
|
111
|
-
action="recipe-action"
|
|
112
|
-
itemId="inbox"
|
|
113
|
-
label="Inbox"
|
|
114
|
-
icon={<LucideIcon icon={Inbox} name="inbox" />}
|
|
115
|
-
trailing={<span>12</span>}
|
|
116
|
-
selected={selected.value === 'inbox'}
|
|
117
|
-
/>
|
|
118
|
-
<ListItem
|
|
119
|
-
action="recipe-action"
|
|
120
|
-
itemId="projects"
|
|
121
|
-
label="Projects"
|
|
122
|
-
icon={<LucideIcon icon={Folder} name="folder" />}
|
|
123
|
-
selected={selected.value === 'projects'}
|
|
124
|
-
/>
|
|
125
|
-
<ListItem
|
|
126
|
-
action="recipe-action"
|
|
127
|
-
itemId="shared"
|
|
128
|
-
label="Shared with me"
|
|
129
|
-
icon={<LucideIcon icon={Users} name="users" />}
|
|
130
|
-
selected={selected.value === 'shared'}
|
|
131
|
-
/>
|
|
132
|
-
</section>
|
|
133
|
-
</Pane>
|
|
134
|
-
</CollapsiblePanel>
|
|
135
|
-
</div>
|
|
136
|
-
<div class="recipe-collapsible-sidebar__main">
|
|
137
|
-
<Pane
|
|
138
|
-
element="main"
|
|
139
|
-
contentClassName="recipe-collapsible-sidebar__body"
|
|
140
|
-
header={
|
|
141
|
-
<Toolbar
|
|
142
|
-
label="Current navigation view"
|
|
143
|
-
dividerSides=""
|
|
144
|
-
leading={
|
|
145
|
-
<>
|
|
146
|
-
<ToolbarControlGroup appearance="borderless" single>
|
|
147
|
-
{railToggle(false)}
|
|
148
|
-
</ToolbarControlGroup>
|
|
149
|
-
<ToolbarText
|
|
150
|
-
text={
|
|
151
|
-
selected.value === 'projects'
|
|
152
|
-
? 'Projects'
|
|
153
|
-
: selected.value === 'shared'
|
|
154
|
-
? 'Shared with me'
|
|
155
|
-
: 'Inbox'
|
|
156
|
-
}
|
|
157
|
-
size="xlarge"
|
|
158
|
-
id="recipe-collapsible-main-title"
|
|
159
|
-
/>
|
|
160
|
-
</>
|
|
161
|
-
}
|
|
162
|
-
trailing={
|
|
163
|
-
<ToolbarControlGroup appearance="borderless" single>
|
|
164
|
-
{drawerToggle()}
|
|
165
|
-
</ToolbarControlGroup>
|
|
166
|
-
}
|
|
167
|
-
/>
|
|
168
|
-
}
|
|
169
|
-
>
|
|
170
|
-
<RecipeOwnershipNote>
|
|
171
|
-
The app owns each panel's <code>collapsed</code> signal, sizes,
|
|
172
|
-
and content; <code>wireSidebar</code> owns the toggle, focus
|
|
173
|
-
move/restore, the compact overlay, and persistence.
|
|
174
|
-
</RecipeOwnershipNote>
|
|
175
|
-
<article class="recipe-collapsible-sidebar__card kui-content-item">
|
|
176
|
-
<strong>Narrow the window to a compact width</strong>
|
|
177
|
-
<RecipeMutedText>
|
|
178
|
-
The rail and drawer become a dismissable overlay: a backdrop,
|
|
179
|
-
Escape, and a trapped Tab ring, all managed by the wire.
|
|
180
|
-
</RecipeMutedText>
|
|
181
|
-
</article>
|
|
182
|
-
</Pane>
|
|
183
|
-
</div>
|
|
184
|
-
<div class="recipe-collapsible-sidebar__drawer">
|
|
185
|
-
<CollapsiblePanel
|
|
186
|
-
id="sidebar-console"
|
|
187
|
-
side="bottom"
|
|
188
|
-
size={168}
|
|
189
|
-
collapsed={drawerCollapsed.value}
|
|
190
|
-
label="Activity"
|
|
191
|
-
>
|
|
192
|
-
<Pane
|
|
193
|
-
contentClassName="recipe-collapsible-sidebar__drawer-body"
|
|
194
|
-
header={
|
|
195
|
-
<Toolbar
|
|
196
|
-
label="Activity"
|
|
197
|
-
dividerSides="b"
|
|
198
|
-
leading={<ToolbarText text="Activity" size="small" />}
|
|
199
|
-
trailing={
|
|
200
|
-
<ToolbarControlGroup appearance="borderless" single>
|
|
201
|
-
{drawerToggle()}
|
|
202
|
-
</ToolbarControlGroup>
|
|
203
|
-
}
|
|
204
|
-
/>
|
|
205
|
-
}
|
|
206
|
-
>
|
|
207
|
-
<ul class="recipe-collapsible-sidebar__log">
|
|
208
|
-
<li>
|
|
209
|
-
<span class="recipe-collapsible-sidebar__log-icon">
|
|
210
|
-
<LucideIcon icon={Bell} name="bell" />
|
|
211
|
-
</span>
|
|
212
|
-
Deploy finished · 2m ago
|
|
213
|
-
</li>
|
|
214
|
-
<li>
|
|
215
|
-
<span class="recipe-collapsible-sidebar__log-icon">
|
|
216
|
-
<LucideIcon icon={Bell} name="bell" />
|
|
217
|
-
</span>
|
|
218
|
-
Review requested · 9m ago
|
|
219
|
-
</li>
|
|
220
|
-
</ul>
|
|
221
|
-
</Pane>
|
|
222
|
-
</CollapsiblePanel>
|
|
223
|
-
</div>
|
|
224
|
-
</div>
|
|
225
|
-
</RecipeRoot>
|
|
246
|
+
{rail()}
|
|
247
|
+
<List flex>
|
|
248
|
+
<Grid columns={1} gap="none" flex>
|
|
249
|
+
{main()}
|
|
250
|
+
</Grid>
|
|
251
|
+
{drawer()}
|
|
252
|
+
</List>
|
|
253
|
+
</Row>
|
|
226
254
|
);
|
|
227
255
|
|
|
228
256
|
return {
|
|
@@ -246,6 +274,7 @@ export const createRecipe: RecipeFactory = (announce) => {
|
|
|
246
274
|
collapsed: railCollapsed,
|
|
247
275
|
toggleAction: RAIL_ACTION,
|
|
248
276
|
storageKey: 'recipe-sidebar-rail',
|
|
277
|
+
inlineCollapsed: false,
|
|
249
278
|
},
|
|
250
279
|
{
|
|
251
280
|
id: 'sidebar-console',
|
|
@@ -1,30 +1,48 @@
|
|
|
1
1
|
import '@kerfjs/ui/layout.css';
|
|
2
2
|
import '@kerfjs/ui/select/register';
|
|
3
|
-
import './compact-toolbar.css';
|
|
4
3
|
|
|
4
|
+
import { deviceClass } from '@kerfjs/ui/device-class';
|
|
5
|
+
import { Grid } from '@kerfjs/ui/grid';
|
|
6
|
+
import { List } from '@kerfjs/ui/list';
|
|
7
|
+
import { ListInsetText } from '@kerfjs/ui/list-inset-text';
|
|
5
8
|
import { LucideIcon } from '@kerfjs/ui/lucide-icon';
|
|
6
9
|
import { SegmentedControl } from '@kerfjs/ui/segmented-control';
|
|
7
10
|
import { Select } from '@kerfjs/ui/select';
|
|
11
|
+
import { Text } from '@kerfjs/ui/text';
|
|
8
12
|
import { Toolbar } from '@kerfjs/ui/toolbar';
|
|
9
13
|
import { ToolbarControlGroup } from '@kerfjs/ui/toolbar-control-group';
|
|
10
14
|
import { ToolbarText } from '@kerfjs/ui/toolbar-text';
|
|
11
15
|
import { signal } from 'kerfjs';
|
|
12
16
|
import { Filter, MoreHorizontal, RefreshCw } from 'lucide';
|
|
13
17
|
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
import type { RecipeFactory, RecipePresentation } from './types.js';
|
|
19
|
+
|
|
20
|
+
const guide = [
|
|
21
|
+
['ToolbarControlGroup', 'Related commands or pressed tools.'],
|
|
22
|
+
['SegmentedControl', 'A few visible exclusive choices.'],
|
|
23
|
+
['Select', 'A longer controlled value list.'],
|
|
24
|
+
['Ordinary button', 'One independent command.'],
|
|
25
|
+
] as const;
|
|
26
|
+
|
|
27
|
+
export const presentation: RecipePresentation = {
|
|
28
|
+
viewport: {
|
|
29
|
+
width: 'full',
|
|
30
|
+
frame: 'solid',
|
|
31
|
+
surface: 'default',
|
|
32
|
+
overflow: 'hidden',
|
|
33
|
+
shadow: true,
|
|
34
|
+
},
|
|
35
|
+
note: 'The recipe owns control semantics and wrapping. The app owns values, actions, persistence, and responsive priority.',
|
|
36
|
+
};
|
|
20
37
|
|
|
21
38
|
export const createRecipe: RecipeFactory = (announce) => {
|
|
22
39
|
const view = signal('list');
|
|
23
40
|
const sort = signal('updated');
|
|
24
41
|
const filtered = signal(false);
|
|
42
|
+
const device = deviceClass();
|
|
25
43
|
const render = () => (
|
|
26
|
-
<
|
|
27
|
-
<
|
|
44
|
+
<section data-recipe="recipe-compact-toolbar" aria-label="Task workspace">
|
|
45
|
+
<List gap="l" controlInsets="b">
|
|
28
46
|
<Toolbar
|
|
29
47
|
label="Task workspace controls"
|
|
30
48
|
responsive="stack"
|
|
@@ -99,32 +117,27 @@ export const createRecipe: RecipeFactory = (announce) => {
|
|
|
99
117
|
</>
|
|
100
118
|
}
|
|
101
119
|
/>
|
|
102
|
-
<
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
The recipe owns control semantics and wrapping. The app owns values,
|
|
124
|
-
actions, persistence, and responsive priority.
|
|
125
|
-
</RecipeOwnershipNote>
|
|
126
|
-
</div>
|
|
127
|
-
</RecipeRoot>
|
|
120
|
+
<Grid
|
|
121
|
+
columns={
|
|
122
|
+
device.value.compact ? 1 : device.value.atLeast('desktop') ? 4 : 2
|
|
123
|
+
}
|
|
124
|
+
gap="none"
|
|
125
|
+
>
|
|
126
|
+
{guide.map(([name, use]) => (
|
|
127
|
+
<ListInsetText>
|
|
128
|
+
<List gap="2xs">
|
|
129
|
+
<Text variant="span">
|
|
130
|
+
<strong>{name}</strong>
|
|
131
|
+
</Text>
|
|
132
|
+
<Text variant="span" tone="quiet" size="compact">
|
|
133
|
+
{use}
|
|
134
|
+
</Text>
|
|
135
|
+
</List>
|
|
136
|
+
</ListInsetText>
|
|
137
|
+
))}
|
|
138
|
+
</Grid>
|
|
139
|
+
</List>
|
|
140
|
+
</section>
|
|
128
141
|
);
|
|
129
142
|
return {
|
|
130
143
|
render,
|