@kerfjs/ui 5.0.0-beta.16 → 5.0.0-beta.18
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 +111 -81
- package/ai/component-catalog-extension.schema.json +79 -0
- package/ai/component-catalog.json +499 -0
- package/ai/component-catalog.schema.json +15 -0
- package/ai/public-api-signatures-v1.md +86 -32
- package/ai/skill.md +60 -51
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/dist/app-tab.d.ts +1 -1
- package/dist/app-tab.js +1 -1
- package/dist/catalog.d.ts +12 -3
- package/dist/catalog.js +283 -90
- package/dist/catalog.js.map +1 -1
- package/dist/chunk-43FUQH35.js +83 -0
- package/dist/chunk-43FUQH35.js.map +1 -0
- package/dist/{chunk-YGN7OMLT.js → chunk-4TRDV6RL.js} +2 -2
- package/dist/chunk-4TRDV6RL.js.map +1 -0
- package/dist/chunk-6ETZKKAE.js +38 -0
- package/dist/chunk-6ETZKKAE.js.map +1 -0
- package/dist/chunk-6WTETUZ6.js +21 -0
- package/dist/chunk-6WTETUZ6.js.map +1 -0
- package/dist/chunk-7L6EHUMV.js +31 -0
- package/dist/chunk-7L6EHUMV.js.map +1 -0
- package/dist/chunk-BBRXX6PF.js +108 -0
- package/dist/chunk-BBRXX6PF.js.map +1 -0
- package/dist/chunk-DPDBVKNA.js +113 -0
- package/dist/chunk-DPDBVKNA.js.map +1 -0
- package/dist/chunk-ELSJX4W7.js +68 -0
- package/dist/chunk-ELSJX4W7.js.map +1 -0
- package/dist/{chunk-LCOBDOCC.js → chunk-ENVTNLYC.js} +153 -67
- package/dist/chunk-ENVTNLYC.js.map +1 -0
- package/dist/{chunk-AHQI52QO.js → chunk-FEY65TBV.js} +6 -2
- package/dist/chunk-FEY65TBV.js.map +1 -0
- package/dist/chunk-JTHUXDN2.js +58 -0
- package/dist/chunk-JTHUXDN2.js.map +1 -0
- package/dist/chunk-LPOMRC4C.js +25 -0
- package/dist/chunk-LPOMRC4C.js.map +1 -0
- package/dist/chunk-NENBUYX5.js +79 -0
- package/dist/chunk-NENBUYX5.js.map +1 -0
- package/dist/{chunk-XXMOARTH.js → chunk-NVWXKU37.js} +57 -16
- package/dist/chunk-NVWXKU37.js.map +1 -0
- package/dist/chunk-PIDTEQ3U.js +105 -0
- package/dist/chunk-PIDTEQ3U.js.map +1 -0
- package/dist/chunk-PX3YSS5C.js +32 -0
- package/dist/chunk-PX3YSS5C.js.map +1 -0
- package/dist/chunk-PZQVSDLH.js +61 -0
- package/dist/chunk-PZQVSDLH.js.map +1 -0
- package/dist/chunk-QIRXYKCE.js +113 -0
- package/dist/chunk-QIRXYKCE.js.map +1 -0
- package/dist/chunk-QO55FN2Y.js +20 -0
- package/dist/chunk-QO55FN2Y.js.map +1 -0
- package/dist/chunk-QQFJMRIB.js +45 -0
- package/dist/chunk-QQFJMRIB.js.map +1 -0
- package/dist/chunk-S3HKPI7I.js +218 -0
- package/dist/chunk-S3HKPI7I.js.map +1 -0
- package/dist/chunk-S3PCZ7NV.js +38 -0
- package/dist/chunk-S3PCZ7NV.js.map +1 -0
- package/dist/{chunk-7BR3DO2A.js → chunk-SRSJO5QE.js} +13 -4
- package/dist/chunk-SRSJO5QE.js.map +1 -0
- package/dist/chunk-U5IFGQCD.js +117 -0
- package/dist/chunk-U5IFGQCD.js.map +1 -0
- package/dist/{chunk-56RJXPHG.js → chunk-Y6LYKFXY.js} +1 -1
- package/dist/{chunk-56RJXPHG.js.map → chunk-Y6LYKFXY.js.map} +1 -1
- package/dist/chunk-ZK2G3VR5.js +35 -0
- package/dist/chunk-ZK2G3VR5.js.map +1 -0
- package/dist/chunk-ZVI5YST2.js +41 -0
- package/dist/chunk-ZVI5YST2.js.map +1 -0
- package/dist/collapsible-panel.d.ts +2 -2
- package/dist/collapsible-panel.js +47 -6
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/device-class.js +33 -5
- package/dist/device-class.js.map +1 -1
- package/dist/disclosure-arrow.js +1 -1
- package/dist/empty-state.d.ts +1 -1
- package/dist/empty-state.js +1 -1
- package/dist/floating-toolbar.d.ts +1 -1
- package/dist/floating-toolbar.js +1 -1
- package/dist/index.js +25 -25
- package/dist/list-action-row.d.ts +1 -1
- package/dist/list-action-row.js +1 -1
- package/dist/list-header.d.ts +1 -1
- package/dist/list-header.js +1 -1
- package/dist/list-inset-control.d.ts +1 -1
- package/dist/list-inset-control.js +1 -1
- package/dist/list-inset-text.d.ts +1 -1
- package/dist/list-inset-text.js +1 -1
- package/dist/list-item.d.ts +1 -1
- package/dist/list-item.js +1 -1
- package/dist/loading-spinner.js +1 -1
- package/dist/nav-stack.d.ts +1 -1
- package/dist/nav-stack.js +1 -1
- package/dist/panel-header.d.ts +1 -1
- package/dist/panel-header.js +1 -1
- package/dist/resizable-region.d.ts +1 -1
- package/dist/resizable-region.js +1 -1
- package/dist/segmented-control.js +1 -1
- package/dist/select.d.ts +1 -1
- package/dist/select.js +1 -1
- package/dist/skeleton.d.ts +1 -1
- package/dist/skeleton.js +1 -1
- package/dist/split-view.d.ts +1 -1
- package/dist/split-view.js +70 -10
- package/dist/split-view.js.map +1 -1
- package/dist/state-banner.d.ts +1 -1
- package/dist/state-banner.js +1 -1
- package/dist/styles/catalog.css +48 -1
- package/dist/styles/toolbar-text.css +54 -2
- package/dist/styles/webawesome.css +131 -0
- package/dist/tab-bar.d.ts +1 -1
- package/dist/tab-bar.js +1 -1
- package/dist/tab-scaffold.d.ts +1 -1
- package/dist/tab-scaffold.js +43 -8
- package/dist/tab-scaffold.js.map +1 -1
- package/dist/token-search-field.js +1 -1
- package/dist/toolbar-control-group.d.ts +1 -1
- package/dist/toolbar-control-group.js +1 -1
- package/dist/toolbar-text.d.ts +17 -1
- package/dist/toolbar-text.js +1 -1
- package/dist/toolbar.d.ts +1 -1
- package/dist/toolbar.js +1 -1
- package/dist/value-table.d.ts +2 -2
- package/dist/value-table.js +1 -1
- package/dist/wire-catalog.d.ts +31 -2
- package/dist/wire-catalog.js +203 -8
- package/dist/wire-catalog.js.map +1 -1
- package/dist/wire-nav-stack.js +22 -7
- package/dist/wire-nav-stack.js.map +1 -1
- package/dist/wire-resizable-regions.d.ts +1 -1
- package/dist/wire-resizable-regions.js +1 -1
- package/dist/wire-sidebar.js +52 -41
- package/dist/wire-sidebar.js.map +1 -1
- package/dist/wire-tab-bars.js +1 -1
- package/dist/wire-tab-scaffold.js +9 -4
- package/dist/wire-tab-scaffold.js.map +1 -1
- package/dist/wire-token-search-fields.d.ts +1 -1
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/workbench.d.ts +1 -1
- package/dist/workbench.js +56 -9
- package/dist/workbench.js.map +1 -1
- package/docs/app-layouts.md +7 -7
- package/docs/catalog.md +110 -25
- package/docs/collapsible-panel.md +38 -11
- package/docs/component-contract.md +30 -2
- package/docs/component-selection.md +76 -65
- package/docs/design/templates.md +1 -1
- package/docs/design-philosophy.md +5 -5
- package/docs/device-class.md +8 -8
- package/docs/examples/command-palette-adapter.tsx +67 -17
- package/docs/examples/component-catalog-extension.json +45 -0
- package/docs/layout.md +19 -19
- package/docs/nav-stack.md +15 -6
- package/docs/recipes.md +4 -4
- package/docs/split-view.md +3 -3
- package/docs/tab-scaffold.md +16 -7
- package/docs/ux-demo.md +2 -2
- package/docs/webawesome-theme.md +73 -8
- package/docs/workbench.md +18 -5
- package/llms.txt +36 -15
- package/package.json +6 -4
- package/ux-demo/recipes/app-shell.tsx +206 -10
- package/ux-demo/recipes/collapsible-sidebar.tsx +167 -44
- package/ux-demo/recipes/compact-toolbar.tsx +114 -12
- package/ux-demo/recipes/composer-form.tsx +106 -18
- package/ux-demo/recipes/list-detail-dialog.tsx +144 -8
- package/ux-demo/recipes/list-workspace-states.tsx +165 -8
- package/ux-demo/recipes/loaders.ts +5 -2
- package/ux-demo/recipes/loading-inspector.tsx +124 -41
- package/ux-demo/recipes/mount-recipe.ts +27 -6
- package/ux-demo/recipes/navigation-sidebar.tsx +120 -9
- package/ux-demo/recipes/navigation-stack.tsx +61 -19
- package/ux-demo/recipes/types.ts +3 -1
- package/ux-demo/recipes/workspace-header.tsx +57 -2
- package/dist/chunk-2Z5TWHKQ.js +0 -34
- package/dist/chunk-2Z5TWHKQ.js.map +0 -1
- package/dist/chunk-37T3VNIZ.js +0 -19
- package/dist/chunk-37T3VNIZ.js.map +0 -1
- package/dist/chunk-55DATV3A.js +0 -10
- package/dist/chunk-55DATV3A.js.map +0 -1
- package/dist/chunk-5ATCDSQS.js +0 -42
- package/dist/chunk-5ATCDSQS.js.map +0 -1
- package/dist/chunk-5E2HVJ33.js +0 -10
- package/dist/chunk-5E2HVJ33.js.map +0 -1
- package/dist/chunk-7BR3DO2A.js.map +0 -1
- package/dist/chunk-7JB7VPRI.js +0 -34
- package/dist/chunk-7JB7VPRI.js.map +0 -1
- package/dist/chunk-7LDCTU7D.js +0 -134
- package/dist/chunk-7LDCTU7D.js.map +0 -1
- package/dist/chunk-AHQI52QO.js.map +0 -1
- package/dist/chunk-AQNKJRFH.js +0 -79
- package/dist/chunk-AQNKJRFH.js.map +0 -1
- package/dist/chunk-AVZHJN6C.js +0 -14
- package/dist/chunk-AVZHJN6C.js.map +0 -1
- package/dist/chunk-B24C4A6T.js +0 -22
- package/dist/chunk-B24C4A6T.js.map +0 -1
- package/dist/chunk-BLK3UEEI.js +0 -23
- package/dist/chunk-BLK3UEEI.js.map +0 -1
- package/dist/chunk-CH4SQ6H5.js +0 -39
- package/dist/chunk-CH4SQ6H5.js.map +0 -1
- package/dist/chunk-DAFFDO33.js +0 -14
- package/dist/chunk-DAFFDO33.js.map +0 -1
- package/dist/chunk-I7INRJO4.js +0 -17
- package/dist/chunk-I7INRJO4.js.map +0 -1
- package/dist/chunk-L4OKFDJY.js +0 -24
- package/dist/chunk-L4OKFDJY.js.map +0 -1
- package/dist/chunk-LCOBDOCC.js.map +0 -1
- package/dist/chunk-M5JRI6MN.js +0 -27
- package/dist/chunk-M5JRI6MN.js.map +0 -1
- package/dist/chunk-RNPGFQ33.js +0 -10
- package/dist/chunk-RNPGFQ33.js.map +0 -1
- package/dist/chunk-RUNWEPR4.js +0 -10
- package/dist/chunk-RUNWEPR4.js.map +0 -1
- package/dist/chunk-VPCTCUED.js +0 -10
- package/dist/chunk-VPCTCUED.js.map +0 -1
- package/dist/chunk-WVPYVDXY.js +0 -15
- package/dist/chunk-WVPYVDXY.js.map +0 -1
- package/dist/chunk-XE5ZLPCC.js +0 -20
- package/dist/chunk-XE5ZLPCC.js.map +0 -1
- package/dist/chunk-XXMOARTH.js.map +0 -1
- package/dist/chunk-YGN7OMLT.js.map +0 -1
package/docs/nav-stack.md
CHANGED
|
@@ -8,9 +8,9 @@ a `NavStack` with one entry**. It is one of the opt-in app layouts (see
|
|
|
8
8
|
Import the component and its companion stylesheet:
|
|
9
9
|
|
|
10
10
|
```ts
|
|
11
|
-
import { NavStack, type NavStackView } from
|
|
12
|
-
import { wireNavStack } from
|
|
13
|
-
import
|
|
11
|
+
import { NavStack, type NavStackView } from "@kerfjs/ui/nav-stack";
|
|
12
|
+
import { wireNavStack } from "@kerfjs/ui/wire-nav-stack";
|
|
13
|
+
import "@kerfjs/ui/nav-stack.css";
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
## State lives in the app
|
|
@@ -20,16 +20,25 @@ stack as a `signal<NavStackView[]>`, `NavStack({ views })` renders it, and
|
|
|
20
20
|
`wireNavStack` animates the transitions.
|
|
21
21
|
|
|
22
22
|
```tsx
|
|
23
|
-
const views = signal<NavStackView[]>([
|
|
23
|
+
const views = signal<NavStackView[]>([
|
|
24
|
+
{ key: "inbox", title: "Inbox", content: <InboxView /> },
|
|
25
|
+
]);
|
|
24
26
|
|
|
25
27
|
// render inside mount():
|
|
26
28
|
<NavStack id="mail" label="Mail" views={views.value} />;
|
|
27
29
|
|
|
28
30
|
// once, after first render:
|
|
29
|
-
const dispose = wireNavStack(root, {
|
|
31
|
+
const dispose = wireNavStack(root, {
|
|
32
|
+
onBack: () => {
|
|
33
|
+
views.value = views.value.slice(0, -1);
|
|
34
|
+
},
|
|
35
|
+
});
|
|
30
36
|
|
|
31
37
|
// push / pop by editing the signal:
|
|
32
|
-
views.value = [
|
|
38
|
+
views.value = [
|
|
39
|
+
...views.value,
|
|
40
|
+
{ key: id, title: "Message", content: <MessageView id={id} /> },
|
|
41
|
+
];
|
|
33
42
|
```
|
|
34
43
|
|
|
35
44
|
`NavStack` renders every entry stacked, the last one active and the rest kept
|
package/docs/recipes.md
CHANGED
|
@@ -14,12 +14,12 @@ the public `onCommit` callback, retains every disposer, and returns one
|
|
|
14
14
|
idempotent disposer:
|
|
15
15
|
|
|
16
16
|
```ts
|
|
17
|
-
import { createRecipe } from
|
|
18
|
-
import { mountRecipe } from
|
|
17
|
+
import { createRecipe } from "./navigation-sidebar.js";
|
|
18
|
+
import { mountRecipe } from "./mount-recipe.js";
|
|
19
19
|
|
|
20
|
-
const root = document.querySelector<HTMLElement>(
|
|
20
|
+
const root = document.querySelector<HTMLElement>("#navigation")!;
|
|
21
21
|
const stopRecipe = mountRecipe(root, createRecipe(announce));
|
|
22
|
-
window.addEventListener(
|
|
22
|
+
window.addEventListener("pagehide", stopRecipe, { once: true });
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
The adapter is delivered as reference source, not a new package runtime export.
|
package/docs/split-view.md
CHANGED
|
@@ -6,9 +6,9 @@ on compact ones. One of the opt-in app layouts (see
|
|
|
6
6
|
[`../../docs/23-app-layouts.md`](../../docs/23-app-layouts.md)).
|
|
7
7
|
|
|
8
8
|
```ts
|
|
9
|
-
import { SplitView } from
|
|
10
|
-
import { deviceClass } from
|
|
11
|
-
import
|
|
9
|
+
import { SplitView } from "@kerfjs/ui/split-view";
|
|
10
|
+
import { deviceClass } from "@kerfjs/ui/device-class";
|
|
11
|
+
import "@kerfjs/ui/split-view.css";
|
|
12
12
|
// plus nav-stack.css when the compact path is reachable, and
|
|
13
13
|
// wireResizableRegions / wireNavStack for the interactive behavior.
|
|
14
14
|
```
|
package/docs/tab-scaffold.md
CHANGED
|
@@ -7,9 +7,9 @@ opt-in app layouts (see [`../../docs/23-app-layouts.md`](../../docs/23-app-layou
|
|
|
7
7
|
It is distinct from `TabBar` (document-oriented, reorderable strips).
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
|
-
import { TabScaffold } from
|
|
11
|
-
import { wireTabScaffold } from
|
|
12
|
-
import
|
|
10
|
+
import { TabScaffold } from "@kerfjs/ui/tab-scaffold";
|
|
11
|
+
import { wireTabScaffold } from "@kerfjs/ui/wire-tab-scaffold";
|
|
12
|
+
import "@kerfjs/ui/tab-scaffold.css";
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
## Controlled selection
|
|
@@ -19,20 +19,29 @@ The app owns the active tab (a signal); `TabScaffold` renders every tab's scene
|
|
|
19
19
|
clicks.
|
|
20
20
|
|
|
21
21
|
```tsx
|
|
22
|
-
const active = signal(
|
|
22
|
+
const active = signal("home");
|
|
23
23
|
|
|
24
24
|
<TabScaffold
|
|
25
25
|
id="app"
|
|
26
26
|
label="Sections"
|
|
27
27
|
active={active.value}
|
|
28
28
|
tabs={[
|
|
29
|
-
{ id:
|
|
30
|
-
{
|
|
29
|
+
{ id: "home", label: "Home", icon: <HomeIcon />, content: <HomeStack /> },
|
|
30
|
+
{
|
|
31
|
+
id: "search",
|
|
32
|
+
label: "Search",
|
|
33
|
+
icon: <SearchIcon />,
|
|
34
|
+
content: <SearchStack />,
|
|
35
|
+
},
|
|
31
36
|
]}
|
|
32
37
|
/>;
|
|
33
38
|
|
|
34
39
|
// once, after first render:
|
|
35
|
-
const dispose = wireTabScaffold(root, {
|
|
40
|
+
const dispose = wireTabScaffold(root, {
|
|
41
|
+
onSelect: (id) => {
|
|
42
|
+
active.value = id;
|
|
43
|
+
},
|
|
44
|
+
});
|
|
36
45
|
```
|
|
37
46
|
|
|
38
47
|
Each `TabScaffoldTab` has an `id`, `label`, optional `icon`, and `content`. The
|
package/docs/ux-demo.md
CHANGED
|
@@ -10,9 +10,9 @@ deterministic state, and semantic layout owners from the [recipe guide](./recipe
|
|
|
10
10
|
- The `ListActionRow` route demonstrates sibling primary/trailing native controls, independent disabled states, controlled selection, first-line leading-icon alignment for wrapped labels, and an application-owned native popover relationship without nesting controls. The `ListItem` route demonstrates the same multiline leading-icon anchor alongside its single-control navigation contract.
|
|
11
11
|
- The `AppTab` route demonstrates a runtime-filtered domain metadata slot and a decorative replacement close icon without changing TabBar selection, close, reorder, or focus ownership. The `ResizableRegion` route likewise replaces only the decorative handle glyph while retaining separator semantics and shared wiring.
|
|
12
12
|
- Every first-party visual component and every free Web Awesome 3.12 component has its own stable `?component=<id>` URL and focused demo. Composite header, menu, feedback, and theme scenarios remain addressable alongside their subcomponents; the root opens the first Kerf component.
|
|
13
|
-
- `ai/component-catalog.json` is the canonical catalog metadata. A deterministic checked-in projection supplies the demo's unique id, category, kind (`component`, `composition`, or `recipe`), source (`kerf` or `webawesome`), name, description, direct `uses` dependencies, existing documentation path, and demo-source path; first-party, recipe, and Web Awesome renderer maps are exhaustively typed against its generated id unions. Demo paths resolve to `ui/ux-demo/
|
|
13
|
+
- `ai/component-catalog.json` is the canonical catalog metadata. A deterministic checked-in projection supplies the demo's unique id, category, kind (`component`, `composition`, or `recipe`), source (`kerf` or `webawesome`), name, description, recommendation, direct `uses` dependencies, existing documentation path, and demo-source path; first-party, recipe, and Web Awesome renderer maps are exhaustively typed against its generated id unions. Non-supported Web Awesome recommendations project to a visible `Discouraged` sidebar tag, with Popup as the deliberate conditional exception. Demo paths resolve to the matching `ui/ux-demo/demos/<id>.tsx` or `ui/ux-demo/recipes/*.tsx` file, or to `ui/ux-demo/webawesome-demos.tsx` for Web Awesome entries. `ui/ux-demo/main.tsx` owns only the catalog shell, shared state, routing, and interaction wiring. First-party component entries additionally derive `ui/src/<browser-subpath>.tsx` from their canonical `delivery.browserImport`.
|
|
14
14
|
- Every detail footer groups compact `Demo source` and `Guidance` actions; first-party component details also expose `Component source`. Web Awesome details say `Integration guidance` to distinguish the local integration contract from the upstream component implementation. Each button retains its repository-relative path in the DOM for verification and uses a deploy-safe absolute GitHub blob URL with a contextual new-tab name; the demo does not depend on a local source server or add a package runtime export. At phone widths, the resource group and related-component selector stack as full-width rows, with any resource overflow contained locally so labels cannot overlap the selector or widen the document.
|
|
15
|
-
- The master/detail shell groups first-party routes by category with production `ListHeader` and `ListItem` components. The 70 ecosystem components live in a separate `Web Awesome` disclosure with seven subgroups, so they remain discoverable without being presented as first-class `@kerfjs/ui` exports. Direct Web Awesome routes open the disclosure and reveal the selected row at wide sizes; narrow layouts keep the expanded list in document flow rather than introducing a competing nested scroller.
|
|
15
|
+
- The master/detail shell groups first-party routes by category with production `ListHeader` and `ListItem` components. Catalog entries can supply short reusable trailing tags; the Web Awesome projection uses them to label exactly the 15 discouraged choices. The 70 ecosystem components live in a separate `Web Awesome` disclosure with seven subgroups, so they remain discoverable without being presented as first-class `@kerfjs/ui` exports. Direct Web Awesome routes open the disclosure and reveal the selected row at wide sizes; narrow layouts keep the expanded list in document flow rather than introducing a competing nested scroller.
|
|
16
16
|
- The shell itself uses `@kerfjs/ui/layout.css`: sidebars, details, previews, dialogs, and resize specimens share unpadded panes plus self-contained content items. Its sidebar identity uses the Kerf logo beside a vertically centered title, with the subtitle in its own aligned row like `PanelHeader`; the current-view heading is also a toolbar. Collapsing the catalog removes the pane completely and moves its restore action to the main toolbar's leading edge instead of leaving an icon-only rail. The selected view description remains inset below the page toolbar. The checkerboard belongs to the complete scrollable preview region rather than a nested card. A lightly separated footer keeps live status above compact source, guidance, and relationship groups. The focused `ResizableRegion` specimen stretches its surface through the available stage height and reports committed width in that shared status footer; narrow layouts retain local horizontal access when the pane is resized wider than the stage, and the split remains readable at 200% root scaling. Geometry coverage checks wide, intermediate, narrow, and 200% zoom layouts.
|
|
17
17
|
- The composer-form recipe demonstrates one coherent visible form surface with `PanelHeader` title/summary hierarchy, fields and actions on the shared 8px control gutter, and 24px major rhythm. Its conditional error or success `StateBanner` is the only nested semantic surface. Reset synchronizes the upgraded Web Awesome fields' live value properties with their empty controlled attributes and announces `Draft reset`; browser coverage preserves behavior and verifies wide, narrow, dark, validation, success, reset, 200% zoom, and forced-colors states.
|
|
18
18
|
- The list-detail dialog recipe places its header directly on the dialog edge while preserving the header's internal inset, gives the selected project title the complete outer-plus-inner content gutter, lets the value table fill the available detail column between the shared outer margins, and keeps record actions on one outer gutter without an extra content-item inset. Browser geometry coverage protects those relationships at wide and narrow widths.
|
package/docs/webawesome-theme.md
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
free components and the Kerf/Hot Sheet 2 design system.
|
|
5
5
|
|
|
6
6
|
```ts
|
|
7
|
-
import type {} from
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
7
|
+
import type {} from "@kerfjs/ui/webawesome";
|
|
8
|
+
import "@kerfjs/ui/webawesome.css";
|
|
9
|
+
import "@awesome.me/webawesome/dist/components/button/button.js";
|
|
10
|
+
import "@awesome.me/webawesome/dist/components/input/input.js";
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
The type-only package import augments `kerfjs/jsx-runtime` with the 70
|
|
@@ -54,6 +54,71 @@ pointer targets. Override `--kui-wa-carousel-icon-size`,
|
|
|
54
54
|
`--kui-wa-carousel-dot-hit-size` on a carousel or containing scope when a
|
|
55
55
|
product needs different geometry.
|
|
56
56
|
|
|
57
|
+
Form fields carry the same content-item inset as the Kerf primitives: a 1px
|
|
58
|
+
border with 8px inside it (`--wa-form-control-border-width`,
|
|
59
|
+
`--wa-form-control-padding-block`, and `--wa-form-control-padding-inline` are set
|
|
60
|
+
to the `--kui-layout-item-border-width` / `--kui-layout-item-padding` values), so
|
|
61
|
+
a single-line control lands at the standard ~40px height and the value sits 9px
|
|
62
|
+
in from the field edge. Each field's top label is inset by that same border +
|
|
63
|
+
padding (9px) so it lines up with the value inside the field, and is styled
|
|
64
|
+
exactly like a `ListHeader` label — uppercase, `--kui-font-xs`, weight 650, quiet
|
|
65
|
+
foreground. This applies to every free field that exposes a top label
|
|
66
|
+
(`::part(form-control-label)` plus the Slider's `::part(label)`). OTP Input
|
|
67
|
+
exposes `label` instead of `form-control-label`; the theme gives it the same
|
|
68
|
+
uppercase 12px/650 treatment. Inline control labels (Checkbox, Switch) keep
|
|
69
|
+
their natural sentence case.
|
|
70
|
+
|
|
71
|
+
Known Date's field captions and bordered text-like field hints use the same 9px
|
|
72
|
+
inline inset, keeping secondary text aligned with the value rather than the
|
|
73
|
+
field's outer border. This covers Input, Known Date, Number Input, OTP Input,
|
|
74
|
+
Select, Textarea, and Time Input hints; unbordered group hints retain their own
|
|
75
|
+
natural geometry. OTP Input's label and hint both use the 9px field-text inset.
|
|
76
|
+
|
|
77
|
+
Checkbox Group and Radio Group option regions receive the shared 8px inline
|
|
78
|
+
outer inset through `::part(form-control-input)`. Unlike bordered fields, these
|
|
79
|
+
groups have no shell of their own, so the explicit margin places their controls
|
|
80
|
+
on the same content-item geometry without adding padding to each option. The
|
|
81
|
+
Color Picker trigger receives the same 8px inline outer inset because it also
|
|
82
|
+
has no bordered field shell. Slider's complete interactive region receives the
|
|
83
|
+
shared 8px logical inline outer inset through `::part(slider)`, keeping its
|
|
84
|
+
track, markers, references, and hint together without moving the label.
|
|
85
|
+
|
|
86
|
+
Non-field chrome follows explicit, overridable control, surface, and container
|
|
87
|
+
tiers:
|
|
88
|
+
|
|
89
|
+
- `--kui-wa-control-inset` defaults to the 8px content-item padding. It applies
|
|
90
|
+
to tabs, tree-item trailing content, tags, and dropdown items. Tree selection
|
|
91
|
+
also uses Kerf's 8px inline outer margin, so its background reads as an inset
|
|
92
|
+
list item instead of an edge-to-edge stripe. Buttons already consume the same
|
|
93
|
+
`--wa-form-control-padding-inline` 8px value at every size, so no extra part
|
|
94
|
+
override is needed.
|
|
95
|
+
- `--kui-wa-surface-margin` and `--kui-wa-surface-inset` default to 8px.
|
|
96
|
+
Accordion, Card, Details, Callout, and Include use the margin around their
|
|
97
|
+
complete surface and the inset within it. Accordion applies the outer margin
|
|
98
|
+
once to the group rather than separating connected items; Card's header,
|
|
99
|
+
body, and footer all receive the full inset.
|
|
100
|
+
- `--kui-wa-container-inset` defaults to the 16px homogeneous-group step. Tab
|
|
101
|
+
Panel retains this roomier tier for unframed panel content.
|
|
102
|
+
|
|
103
|
+
Badge remains intentionally compact at Web Awesome's intrinsic `0.375em` block /
|
|
104
|
+
`0.625em` inline padding (4.5px / 7.5px at its default 12px text size): it is a
|
|
105
|
+
short status or count, not a content item. Breadcrumb has no bordered or filled
|
|
106
|
+
container, and Scroller delegates item chrome to its slotted children, so both
|
|
107
|
+
retain their upstream geometry. Web Awesome 3.12's free catalog has
|
|
108
|
+
`wa-dropdown-item`, but no `wa-menu-item`; the theme therefore styles the
|
|
109
|
+
supported dropdown item rather than carrying a dead selector.
|
|
110
|
+
|
|
111
|
+
Override a tier for a product scope after importing the theme:
|
|
112
|
+
|
|
113
|
+
```css
|
|
114
|
+
.roomy-editor {
|
|
115
|
+
--kui-wa-control-inset: 0.75rem;
|
|
116
|
+
--kui-wa-surface-margin: 0.75rem;
|
|
117
|
+
--kui-wa-surface-inset: 0.75rem;
|
|
118
|
+
--kui-wa-container-inset: 1.5rem;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
57
122
|
Accordion, Details, Breadcrumb, and Kerf Select share
|
|
58
123
|
`--kui-disclosure-icon-scale` (default `.5`) so disclosure and traversal
|
|
59
124
|
chevrons keep the same visual weight. The Accordion and Details components
|
|
@@ -73,12 +138,12 @@ subtree, or for one instance after the theme import:
|
|
|
73
138
|
|
|
74
139
|
```css
|
|
75
140
|
:root {
|
|
76
|
-
--wa-tooltip-arrow-size: .375rem;
|
|
77
|
-
--kui-wa-popover-arrow-size: .375rem;
|
|
141
|
+
--wa-tooltip-arrow-size: 0.375rem;
|
|
142
|
+
--kui-wa-popover-arrow-size: 0.375rem;
|
|
78
143
|
}
|
|
79
144
|
|
|
80
145
|
.pointed-popover {
|
|
81
|
-
--arrow-size: .5rem;
|
|
146
|
+
--arrow-size: 0.5rem;
|
|
82
147
|
}
|
|
83
148
|
```
|
|
84
149
|
|
|
@@ -179,7 +244,7 @@ smallest subtree that needs a different identity:
|
|
|
179
244
|
:root {
|
|
180
245
|
--wa-color-brand-fill-loud: #7540a8;
|
|
181
246
|
--wa-color-focus: #7540a8;
|
|
182
|
-
--wa-form-control-border-radius: .5rem;
|
|
247
|
+
--wa-form-control-border-radius: 0.5rem;
|
|
183
248
|
}
|
|
184
249
|
|
|
185
250
|
.billing-workspace {
|
package/docs/workbench.md
CHANGED
|
@@ -8,8 +8,8 @@ sidebar. One of the opt-in app layouts (see
|
|
|
8
8
|
desktop-class devices.
|
|
9
9
|
|
|
10
10
|
```ts
|
|
11
|
-
import { Workbench } from
|
|
12
|
-
import
|
|
11
|
+
import { Workbench } from "@kerfjs/ui/workbench";
|
|
12
|
+
import "@kerfjs/ui/workbench.css";
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
## State lives in the app
|
|
@@ -25,9 +25,22 @@ const navCollapsed = signal(false);
|
|
|
25
25
|
id="studio"
|
|
26
26
|
label="Studio"
|
|
27
27
|
main={<Editor />}
|
|
28
|
-
leftRail={{
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
leftRail={{
|
|
29
|
+
content: <Navigator />,
|
|
30
|
+
label: "Navigator",
|
|
31
|
+
collapsed: navCollapsed.value,
|
|
32
|
+
size: 280,
|
|
33
|
+
}}
|
|
34
|
+
rightRail={{
|
|
35
|
+
content: <Inspector />,
|
|
36
|
+
label: "Inspector",
|
|
37
|
+
collapsed: inspectorCollapsed.value,
|
|
38
|
+
}}
|
|
39
|
+
bottomDrawer={{
|
|
40
|
+
content: <Console />,
|
|
41
|
+
label: "Console",
|
|
42
|
+
collapsed: consoleCollapsed.value,
|
|
43
|
+
}}
|
|
31
44
|
/>;
|
|
32
45
|
```
|
|
33
46
|
|
package/llms.txt
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
> generate correct, good-looking kerf UI — it is not a catalog to browse.
|
|
7
7
|
|
|
8
8
|
```bash
|
|
9
|
-
npm install kerfjs @kerfjs/ui
|
|
9
|
+
npm install kerfjs @kerfjs/ui # kerfjs is a peer; Web Awesome is an optional peer
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
Import each component from its own subpath (`@kerfjs/ui/list-item`, `@kerfjs/ui/toolbar`,
|
|
@@ -22,15 +22,18 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
22
22
|
[public-api-signatures-v1.md](./ai/public-api-signatures-v1.md) (real prop names,
|
|
23
23
|
callback shapes, disposer return types).
|
|
24
24
|
3. **For exhaustive, structured facts** (ids, exports, variants, `publicClasses`,
|
|
25
|
-
relationships, side effects) load the
|
|
25
|
+
relationships, side effects, and geometry ownership) load the
|
|
26
26
|
[Machine-readable component catalog](./ai/component-catalog.json) — the
|
|
27
|
-
canonical checked-in source; its schema is alongside it.
|
|
27
|
+
canonical checked-in source; its schema is alongside it. Also load the
|
|
28
|
+
consuming application's catalog extension when present; generate one from the
|
|
29
|
+
[Consumer catalog extension schema](./ai/component-catalog-extension.schema.json)
|
|
30
|
+
when app-owned components must participate in selection or alignment.
|
|
28
31
|
4. **Apply the rules below and in** [skill.md](./ai/skill.md).
|
|
29
32
|
|
|
30
33
|
## Core rules (do the right thing)
|
|
31
34
|
|
|
32
35
|
- **Reach for the primitive, not for CSS.** The package is built to look right
|
|
33
|
-
|
|
36
|
+
_unstyled_. Before adding `padding`, `margin`, `width`, `height`, `border`,
|
|
34
37
|
`background`, a wrapper card, or a decoration, check whether the component, the
|
|
35
38
|
pane, or the content-item already owns it — it almost always does. Prefer a
|
|
36
39
|
component prop or a `--kui-*` token; write CSS only for genuinely new structure,
|
|
@@ -40,6 +43,21 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
40
43
|
own the geometry (8px inline margin + 1px border + 8px padding). Do not add a
|
|
41
44
|
container padding on top of a content-item's own margin — pick one owner. Use
|
|
42
45
|
`.kui-content` for 24px major vertical rhythm.
|
|
46
|
+
- **Keep Web Awesome on the shared inset tiers.** `webawesome.css` uses
|
|
47
|
+
`--kui-wa-control-inset` (8px controls/items) and
|
|
48
|
+
`--kui-wa-surface-margin` / `--kui-wa-surface-inset` (8px around/inside
|
|
49
|
+
Accordion, Card, Details, Callout, and Include), while
|
|
50
|
+
`--kui-wa-container-inset` keeps Tab Panel at 16px. Override the tier at the
|
|
51
|
+
narrowest useful scope instead of restyling individual shadow parts.
|
|
52
|
+
Checkbox and Radio Group option regions also receive the shared 8px inline
|
|
53
|
+
outer inset because those groups have no bordered field shell. The Color
|
|
54
|
+
Picker trigger receives the same inset for the same unbordered geometry.
|
|
55
|
+
Slider's complete interactive region uses the shared 8px logical inline outer
|
|
56
|
+
inset without shifting its already-aligned label.
|
|
57
|
+
Known Date's Month/Day/Year captions and bordered text-like field hints align
|
|
58
|
+
with field values at the shared 9px border-plus-padding inset. OTP Input's
|
|
59
|
+
label uses the same uppercase xs/650 treatment and its label and hint share
|
|
60
|
+
that 9px alignment.
|
|
43
61
|
- **Trust the defaults.** Render a control at its natural size and color (a
|
|
44
62
|
`LucideIcon` is 24px); if it looks wrong, fix the surrounding layout, not the
|
|
45
63
|
control. Never force a component's width/height to size it — that leaves a halo
|
|
@@ -54,7 +72,7 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
54
72
|
popup menu. A toolbar popup menu is a `single` `ToolbarControlGroup` around a
|
|
55
73
|
`wa-dropdown` (its `slot="trigger"` `wa-button` is the toolbar button, kept under
|
|
56
74
|
`data-morph-skip-children`).
|
|
57
|
-
- **`PanelHeader` is
|
|
75
|
+
- **`PanelHeader` is _the_ panel/dialog/page heading.** A plain toolbar with an
|
|
58
76
|
optional bordered icon group, an extra-large `ToolbarText` title, the trailing
|
|
59
77
|
controls you pass, and an optional subtitle below — do not hand-build a heading
|
|
60
78
|
row or restyle a toolbar into one.
|
|
@@ -75,7 +93,7 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
75
93
|
- **App state is domain/persisted; helpers own only ephemeral mechanics.** Keep
|
|
76
94
|
navigation stacks, tab selection and order, pane sizes, and `collapsed`/`expanded`
|
|
77
95
|
disclosure flags in the app — they are data or persisted layout, and the app reads
|
|
78
|
-
them to render. The `wire…` helpers own the
|
|
96
|
+
them to render. The `wire…` helpers own the _ephemeral_ parts: `wireNavStack` the
|
|
79
97
|
push/pop animation, `wireTabBars` the overflow autoscroll and drag preview,
|
|
80
98
|
`wireResizableRegions` the live drag preview; they report committed changes via
|
|
81
99
|
callbacks. The one richer case is `wireTokenSearchFields`, which manages the
|
|
@@ -113,13 +131,16 @@ tree-shakeable, declarative with `wire…` helpers, each with a companion CSS im
|
|
|
113
131
|
`NavStack`, `SplitView`, `Workbench`, `TabScaffold`, driven by `deviceClass()` from
|
|
114
132
|
`@kerfjs/ui/device-class`. For a standalone collapsible rail/drawer outside a full
|
|
115
133
|
shell, `@kerfjs/ui/collapsible-panel` (`CollapsiblePanel`, `CollapsiblePanelToggle`)
|
|
116
|
-
|
|
117
|
-
`@kerfjs/ui/
|
|
118
|
-
`
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
134
|
+
|
|
135
|
+
- `@kerfjs/ui/wire-sidebar` (`wireSidebar`: toggle, focus, compact overlay, persistence).
|
|
136
|
+
`@kerfjs/ui/catalog` is another opt-in shell — a
|
|
137
|
+
`Catalog` component + `wireCatalog` helper for building a component-gallery catalog
|
|
138
|
+
(collapsible category sidebar + preview stage + resources footer, with an opt-in
|
|
139
|
+
transparent-bound and margin geometry overlay plus focus-preserving active-row
|
|
140
|
+
reveal for long desktop sidebars) from your own
|
|
141
|
+
entries; controlled/stateless like the layouts. `@kerfjs/ui/webawesome` is a
|
|
142
|
+
type-only boundary for `wa-*` JSX; `@kerfjs/ui/select/register` and the CSS are the
|
|
143
|
+
declared side effects.
|
|
123
144
|
|
|
124
145
|
## Reference
|
|
125
146
|
|
|
@@ -130,6 +151,6 @@ declared side effects.
|
|
|
130
151
|
- [accessibility.md](./docs/accessibility.md): keyboard and ARIA contracts per component.
|
|
131
152
|
- [recipes.md](./docs/recipes.md): production compositions (app shell, list-detail dialog, composer form, …) as copyable references.
|
|
132
153
|
- [app-layouts.md](./docs/app-layouts.md): choosing `NavStack`/`SplitView`/`Workbench`/`TabScaffold` by data + interaction + device, and dialog presentation.
|
|
133
|
-
- [webawesome-theme.md](./docs/webawesome-theme.md): the optional Web Awesome theme; catalog coverage means themed-and-supported, not preferred (prefer the Kerf primitive when one exists).
|
|
134
|
-
- [component-catalog.json](./ai/component-catalog.json) + [public-api-signatures-v1.md](./ai/public-api-signatures-v1.md) + [webawesome-jsx-signatures-v1.md](./ai/webawesome-jsx-signatures-v1.md): machine-readable facts and exact signatures.
|
|
154
|
+
- [webawesome-theme.md](./docs/webawesome-theme.md): the optional Web Awesome theme; catalog coverage means themed-and-supported, not preferred (prefer the Kerf primitive when one exists). The UX sidebar visibly tags superseded and exceptional Web Awesome choices as `Discouraged`; Popup remains an available conditional positioning primitive.
|
|
155
|
+
- [component-catalog.json](./ai/component-catalog.json) + [component-catalog-extension.schema.json](./ai/component-catalog-extension.schema.json) + [public-api-signatures-v1.md](./ai/public-api-signatures-v1.md) + [webawesome-jsx-signatures-v1.md](./ai/webawesome-jsx-signatures-v1.md): machine-readable facts, a reusable app-component extension contract, and exact signatures.
|
|
135
156
|
- [README.md](./README.md): package overview and the component subpath table.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kerfjs/ui",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.18",
|
|
4
4
|
"description": "Accessible, composable UI primitives for kerf applications.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -272,8 +272,9 @@
|
|
|
272
272
|
"dev": "npm run build && vite --config ux-demo/vite.config.ts",
|
|
273
273
|
"demo:build": "npm run build && vite build --config ux-demo/vite.config.ts && node scripts/check-demo-bundle.mjs",
|
|
274
274
|
"demo:serve": "vite preview --config ux-demo/vite.config.ts",
|
|
275
|
+
"format": "prettier --write . --ignore-unknown",
|
|
275
276
|
"format:css": "prettier --write \"src/**/*.css\" \"ux-demo/**/*.css\"",
|
|
276
|
-
"check:format": "prettier --check
|
|
277
|
+
"check:format": "prettier --check . --ignore-unknown",
|
|
277
278
|
"catalog:sync": "node scripts/sync-component-catalog.mjs",
|
|
278
279
|
"check:catalog": "node scripts/sync-component-catalog.mjs --check && node scripts/check-component-catalog.mjs",
|
|
279
280
|
"check:recipes": "node scripts/check-recipes.mjs",
|
|
@@ -285,14 +286,15 @@
|
|
|
285
286
|
"ai:regressions:record": "node scripts/record-ai-regression-run.mjs",
|
|
286
287
|
"ai:regressions:score": "node scripts/score-ai-regression.mjs",
|
|
287
288
|
"check:guidance": "node scripts/check-decision-guidance.mjs",
|
|
288
|
-
"lint": "eslint src tests ux-demo docs/examples --max-warnings 0",
|
|
289
|
+
"lint:eslint": "eslint src tests ux-demo docs/examples --max-warnings 0",
|
|
290
|
+
"lint": "npm run lint:eslint && npm run check:format",
|
|
289
291
|
"typecheck": "node node_modules/typescript7/bin/tsc --noEmit",
|
|
290
292
|
"test": "npm run test:unit && npm run test:bundle",
|
|
291
293
|
"test:unit": "vitest run tests/unit --coverage",
|
|
292
294
|
"test:bundle": "npm run build && vitest run tests/bundle",
|
|
293
295
|
"test:consumer-types": "npm run build && node node_modules/typescript7/bin/tsc -p tests/consumer-types/webawesome/tsconfig.json",
|
|
294
296
|
"test:e2e": "npm run demo:build && playwright test",
|
|
295
|
-
"check": "npm run check:
|
|
297
|
+
"check": "npm run check:catalog && npm run check:recipes && npm run check:guidance && npm run check:ai-regressions && npm run lint && npm run typecheck && npm test && npm run test:consumer-types && npm run check:ai-signatures && npm run demo:build && npm run check:design-templates && npm pack --dry-run",
|
|
296
298
|
"prepublishOnly": "npm run check",
|
|
297
299
|
"check:design-templates": "node scripts/check-design-templates.mjs",
|
|
298
300
|
"check:design-templates:drift": "node scripts/check-design-templates-drift.mjs",
|