@kerfjs/ui 5.0.0-beta.49 → 5.0.0-beta.50
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 +41 -11
- package/ai/catalog-authoring.json +12 -1
- package/ai/catalog-authoring.schema.json +49 -1
- package/ai/compile-time-contracts-v1.json +14 -0
- package/ai/compile-time-contracts-v1.schema.json +1 -0
- package/ai/component-catalog-v2-overrides.json +7 -0
- package/ai/component-catalog-v2.json +79 -23
- package/ai/component-catalog.json +86 -27
- package/ai/public-api-signatures-v1.md +217 -169
- package/ai/skill.md +23 -9
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/dist/app-tab.d.ts +3 -1
- package/dist/app-tab.js +1 -1
- package/dist/badge.d.ts +24 -0
- package/dist/badge.js +3 -0
- package/dist/badge.js.map +1 -0
- package/dist/browser/badge.js +3 -0
- package/dist/browser/list-header.js +1 -0
- package/dist/browser/state-banner.js +1 -0
- package/dist/catalog-resources.d.ts +2 -2
- package/dist/catalog.d.ts +24 -125
- package/dist/catalog.js +387 -261
- package/dist/catalog.js.map +1 -1
- package/dist/{chunk-OGTJNHRG.js → chunk-2WMSE4MK.js} +5 -3
- package/dist/chunk-2WMSE4MK.js.map +1 -0
- package/dist/{chunk-GYGM363P.js → chunk-2YOUUEWR.js} +16 -6
- package/dist/chunk-2YOUUEWR.js.map +1 -0
- package/dist/{chunk-UDHHKZWO.js → chunk-3V75EQIP.js} +8 -4
- package/dist/chunk-3V75EQIP.js.map +1 -0
- package/dist/{chunk-W2FK7ZNY.js → chunk-4R777DUZ.js} +10 -2
- package/dist/chunk-4R777DUZ.js.map +1 -0
- package/dist/{chunk-T7DOWS6T.js → chunk-54HM36IQ.js} +6 -3
- package/dist/chunk-54HM36IQ.js.map +1 -0
- package/dist/{chunk-DAO2VFTT.js → chunk-5CE64WGC.js} +6 -4
- package/dist/chunk-5CE64WGC.js.map +1 -0
- package/dist/{chunk-SOK5EUF7.js → chunk-6ZXOQEAN.js} +4 -2
- package/dist/chunk-6ZXOQEAN.js.map +1 -0
- package/dist/{chunk-OGNE3OFT.js → chunk-AQSKJ6U6.js} +4 -2
- package/dist/chunk-AQSKJ6U6.js.map +1 -0
- package/dist/{chunk-VDUJZF5G.js → chunk-CMUIXJZM.js} +2 -2
- package/dist/{chunk-VDUJZF5G.js.map → chunk-CMUIXJZM.js.map} +1 -1
- package/dist/{chunk-OMSRSL3B.js → chunk-COUPLRZG.js} +5 -3
- package/dist/chunk-COUPLRZG.js.map +1 -0
- package/dist/{chunk-2TYUFZUC.js → chunk-D7GWXIAS.js} +4 -2
- package/dist/chunk-D7GWXIAS.js.map +1 -0
- package/dist/{chunk-AQFWBG23.js → chunk-DARTMI5Z.js} +5 -3
- package/dist/chunk-DARTMI5Z.js.map +1 -0
- package/dist/{chunk-V6GQKOX2.js → chunk-DJKWFYAA.js} +5 -3
- package/dist/chunk-DJKWFYAA.js.map +1 -0
- package/dist/{chunk-6NDBE2OK.js → chunk-E36EVCKG.js} +5 -3
- package/dist/chunk-E36EVCKG.js.map +1 -0
- package/dist/{chunk-IU4QUY5I.js → chunk-ELRMBQEC.js} +4 -2
- package/dist/chunk-ELRMBQEC.js.map +1 -0
- package/dist/{chunk-TIGSG6BX.js → chunk-HJKRCKDR.js} +7 -3
- package/dist/chunk-HJKRCKDR.js.map +1 -0
- package/dist/{chunk-Y6LYKFXY.js → chunk-HMQ2ZDGG.js} +5 -3
- package/dist/chunk-HMQ2ZDGG.js.map +1 -0
- package/dist/{chunk-WN52USHV.js → chunk-J3EE6XWD.js} +2 -2
- package/dist/{chunk-WN52USHV.js.map → chunk-J3EE6XWD.js.map} +1 -1
- package/dist/{chunk-CK6P5AUK.js → chunk-KKNK3JUT.js} +7 -4
- package/dist/chunk-KKNK3JUT.js.map +1 -0
- package/dist/{chunk-ZPWZIVI6.js → chunk-N3GKMPDW.js} +7 -3
- package/dist/chunk-N3GKMPDW.js.map +1 -0
- package/dist/{chunk-DYBPI5O2.js → chunk-NDUGJ4TU.js} +4 -2
- package/dist/chunk-NDUGJ4TU.js.map +1 -0
- package/dist/{chunk-WSXUPSID.js → chunk-NN6GYOA2.js} +7 -3
- package/dist/chunk-NN6GYOA2.js.map +1 -0
- package/dist/{chunk-VXFGMDA7.js → chunk-OQI7RCRP.js} +10 -2
- package/dist/chunk-OQI7RCRP.js.map +1 -0
- package/dist/{chunk-E34TE2ZI.js → chunk-S6ZTTTV7.js} +5 -3
- package/dist/chunk-S6ZTTTV7.js.map +1 -0
- package/dist/{chunk-V6HCTCVD.js → chunk-SIU2AC5W.js} +8 -4
- package/dist/chunk-SIU2AC5W.js.map +1 -0
- package/dist/{chunk-WVLMZ5SG.js → chunk-UMGY5JSP.js} +4 -2
- package/dist/chunk-UMGY5JSP.js.map +1 -0
- package/dist/{chunk-I4V3UDSA.js → chunk-V6RZWDII.js} +7 -5
- package/dist/chunk-V6RZWDII.js.map +1 -0
- package/dist/{chunk-CAB6NQ2T.js → chunk-VOCPXGQN.js} +3 -1
- package/dist/chunk-VOCPXGQN.js.map +1 -0
- package/dist/chunk-XD7DWYXG.js +34 -0
- package/dist/chunk-XD7DWYXG.js.map +1 -0
- package/dist/{chunk-B6JYRX3P.js → chunk-ZIYOJFZD.js} +43 -4
- package/dist/chunk-ZIYOJFZD.js.map +1 -0
- package/dist/{chunk-EYALJQQD.js → chunk-ZK5EGVFP.js} +4 -2
- package/dist/chunk-ZK5EGVFP.js.map +1 -0
- package/dist/{chunk-6WTETUZ6.js → chunk-ZLWQZUGF.js} +8 -2
- package/dist/chunk-ZLWQZUGF.js.map +1 -0
- package/dist/{chunk-XKFRMGMW.js → chunk-ZNZ2JDBW.js} +3 -1
- package/dist/chunk-ZNZ2JDBW.js.map +1 -0
- package/dist/{chunk-I45QO2IZ.js → chunk-ZSYLBVWG.js} +6 -4
- package/dist/chunk-ZSYLBVWG.js.map +1 -0
- package/dist/collapsible-panel.d.ts +3 -1
- package/dist/collapsible-panel.js +4 -2
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/disclosure-arrow.d.ts +3 -1
- package/dist/disclosure-arrow.js +1 -1
- package/dist/empty-state.d.ts +3 -1
- package/dist/empty-state.js +1 -1
- package/dist/floating-toolbar.d.ts +3 -1
- package/dist/floating-toolbar.js +1 -1
- package/dist/grid.d.ts +3 -1
- package/dist/grid.js +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +33 -32
- package/dist/list-action-row.d.ts +3 -1
- package/dist/list-action-row.js +1 -1
- package/dist/list-header.d.ts +6 -1
- package/dist/list-header.js +2 -1
- package/dist/list-inset-control.d.ts +3 -1
- package/dist/list-inset-control.js +1 -1
- package/dist/list-inset-text.d.ts +3 -1
- package/dist/list-inset-text.js +1 -1
- package/dist/list-item.d.ts +3 -1
- package/dist/list-item.js +1 -1
- package/dist/list.d.ts +3 -1
- package/dist/list.js +1 -1
- package/dist/loading-spinner.d.ts +3 -1
- package/dist/loading-spinner.js +1 -1
- package/dist/lucide-icon.d.ts +3 -1
- package/dist/lucide-icon.js +1 -1
- package/dist/nav-stack.d.ts +3 -1
- package/dist/nav-stack.js +1 -1
- package/dist/pane.d.ts +3 -1
- package/dist/pane.js +1 -1
- package/dist/resizable-region.d.ts +5 -2
- package/dist/resizable-region.js +1 -1
- package/dist/row.d.ts +3 -1
- package/dist/row.js +1 -1
- package/dist/segmented-control.d.ts +3 -1
- package/dist/segmented-control.js +1 -1
- package/dist/select.d.ts +3 -1
- package/dist/select.js +1 -1
- package/dist/skeleton.d.ts +3 -1
- package/dist/skeleton.js +1 -1
- package/dist/spacer.d.ts +3 -1
- package/dist/spacer.js +1 -1
- package/dist/split-view.d.ts +3 -1
- package/dist/split-view.js +24 -5
- package/dist/split-view.js.map +1 -1
- package/dist/state-banner.d.ts +3 -1
- package/dist/state-banner.js +2 -1
- package/dist/styles/badge.css +86 -0
- package/dist/styles/catalog/components/catalog-detail.css +35 -0
- package/dist/styles/catalog/components/catalog-example-stack.css +6 -0
- package/dist/styles/catalog/components/catalog-example.css +35 -0
- package/dist/styles/catalog/components/catalog-resource-footer.css +37 -0
- package/dist/styles/catalog/components/catalog-secondary-sections.css +38 -0
- package/dist/styles/catalog/components/catalog-section-list.css +22 -0
- package/dist/styles/catalog/components/catalog-sidebar.css +82 -0
- package/dist/styles/catalog/components/catalog-stage.css +60 -0
- package/dist/styles/catalog/components/catalog.css +22 -0
- package/dist/styles/catalog.css +10 -587
- package/dist/styles/list-header.css +4 -60
- package/dist/styles/resizable-region.css +24 -0
- package/dist/styles/select.css +0 -3
- package/dist/styles/split-view.css +1 -1
- package/dist/styles/state-banner.css +0 -27
- package/dist/styles/styles.css +1 -0
- package/dist/styles/tab-bar.css +6 -1
- package/dist/styles/text.css +4 -0
- package/dist/styles/token-search-field.css +5 -40
- package/dist/styles/toolbar-control-group.css +110 -16
- package/dist/styles/toolbar-text.css +4 -0
- package/dist/styles/toolbar.css +72 -0
- package/dist/styles/webawesome.css +22 -7
- package/dist/sunken-panel.d.ts +3 -1
- package/dist/sunken-panel.js +1 -1
- package/dist/surface-scaffold.d.ts +6 -2
- package/dist/surface-scaffold.js +1 -1
- package/dist/tab-bar.d.ts +8 -1
- package/dist/tab-bar.js +1 -1
- package/dist/tab-scaffold.d.ts +3 -1
- package/dist/tab-scaffold.js +3 -1
- package/dist/tab-scaffold.js.map +1 -1
- package/dist/text.d.ts +5 -2
- package/dist/text.js +1 -1
- package/dist/token-search-field.d.ts +5 -1
- package/dist/token-search-field.js +1 -1
- package/dist/toolbar-control-group.d.ts +33 -3
- package/dist/toolbar-control-group.js +1 -1
- package/dist/toolbar-text.d.ts +3 -1
- package/dist/toolbar-text.js +1 -1
- package/dist/toolbar.d.ts +9 -1
- package/dist/toolbar.js +1 -1
- package/dist/types-CzgSrFXP.d.ts +64 -0
- package/dist/value-table.d.ts +6 -2
- package/dist/value-table.js +1 -1
- package/dist/wire-resizable-regions.js +1 -1
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/workbench.d.ts +3 -1
- package/dist/workbench.js +3 -1
- package/dist/workbench.js.map +1 -1
- package/docs/accessibility.md +11 -1
- package/docs/catalog.md +25 -7
- package/docs/component-contract.md +71 -22
- package/docs/component-selection.md +11 -9
- package/docs/design-philosophy.md +6 -5
- package/docs/recipes.md +5 -5
- package/docs/type-contracts.md +1 -0
- package/docs/ux-demo.md +4 -4
- package/docs/webawesome-theme.md +5 -4
- package/llms.txt +30 -10
- package/package.json +9 -2
- package/ux-demo/recipes/app-shell.css +87 -0
- package/ux-demo/recipes/app-shell.tsx +207 -178
- package/ux-demo/recipes/collapsible-sidebar.css +83 -0
- package/ux-demo/recipes/collapsible-sidebar.tsx +152 -122
- package/ux-demo/recipes/compact-toolbar.css +35 -0
- package/ux-demo/recipes/compact-toolbar.tsx +104 -100
- package/ux-demo/recipes/composer-form.css +19 -0
- package/ux-demo/recipes/composer-form.tsx +19 -15
- package/ux-demo/recipes/list-detail-dialog.css +42 -0
- package/ux-demo/recipes/list-detail-dialog.tsx +127 -125
- package/ux-demo/recipes/list-workspace-states.css +30 -0
- package/ux-demo/recipes/list-workspace-states.tsx +66 -60
- package/ux-demo/recipes/loading-inspector.css +7 -0
- package/ux-demo/recipes/loading-inspector.tsx +151 -131
- package/ux-demo/recipes/navigation-sidebar.css +12 -0
- package/ux-demo/recipes/navigation-sidebar.tsx +116 -105
- package/ux-demo/recipes/navigation-stack.css +12 -0
- package/ux-demo/recipes/navigation-stack.tsx +47 -37
- package/ux-demo/recipes/recipe-root.css +67 -0
- package/ux-demo/recipes/recipe-root.tsx +87 -0
- package/ux-demo/recipes/workspace-header.css +7 -0
- package/ux-demo/recipes/workspace-header.tsx +60 -61
- package/dist/chunk-2TYUFZUC.js.map +0 -1
- package/dist/chunk-6NDBE2OK.js.map +0 -1
- package/dist/chunk-6WTETUZ6.js.map +0 -1
- package/dist/chunk-AQFWBG23.js.map +0 -1
- package/dist/chunk-B6JYRX3P.js.map +0 -1
- package/dist/chunk-CAB6NQ2T.js.map +0 -1
- package/dist/chunk-CK6P5AUK.js.map +0 -1
- package/dist/chunk-DAO2VFTT.js.map +0 -1
- package/dist/chunk-DYBPI5O2.js.map +0 -1
- package/dist/chunk-E34TE2ZI.js.map +0 -1
- package/dist/chunk-EYALJQQD.js.map +0 -1
- package/dist/chunk-GYGM363P.js.map +0 -1
- package/dist/chunk-I45QO2IZ.js.map +0 -1
- package/dist/chunk-I4V3UDSA.js.map +0 -1
- package/dist/chunk-IU4QUY5I.js.map +0 -1
- package/dist/chunk-OGNE3OFT.js.map +0 -1
- package/dist/chunk-OGTJNHRG.js.map +0 -1
- package/dist/chunk-OMSRSL3B.js.map +0 -1
- package/dist/chunk-SOK5EUF7.js.map +0 -1
- package/dist/chunk-T7DOWS6T.js.map +0 -1
- package/dist/chunk-TIGSG6BX.js.map +0 -1
- package/dist/chunk-UDHHKZWO.js.map +0 -1
- package/dist/chunk-V6GQKOX2.js.map +0 -1
- package/dist/chunk-V6HCTCVD.js.map +0 -1
- package/dist/chunk-VXFGMDA7.js.map +0 -1
- package/dist/chunk-W2FK7ZNY.js.map +0 -1
- package/dist/chunk-WSXUPSID.js.map +0 -1
- package/dist/chunk-WVLMZ5SG.js.map +0 -1
- package/dist/chunk-XKFRMGMW.js.map +0 -1
- package/dist/chunk-Y6LYKFXY.js.map +0 -1
- package/dist/chunk-ZPWZIVI6.js.map +0 -1
- package/ux-demo/recipes/recipes.css +0 -453
package/ai/skill.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kerf-ui
|
|
3
3
|
description: Build interfaces with kerfjs and the @kerfjs/ui production component package. Use whenever code imports @kerfjs/ui or a task asks for Kerf UI components.
|
|
4
|
-
kerf-ui-skill-version: 1.
|
|
4
|
+
kerf-ui-skill-version: 1.42.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Building with @kerfjs/ui
|
|
@@ -51,6 +51,12 @@ are rejected unless a component explicitly exposes a text position such as
|
|
|
51
51
|
`ListInsetText`. These are typed props, not native `<slot>` elements,
|
|
52
52
|
wrapper slot components, or a generic `slots` object. Preserve dynamic
|
|
53
53
|
expressions as unknown when their content cannot be established statically.
|
|
54
|
+
Stable single-root Kerf UI components separately accept native `slot="name"`
|
|
55
|
+
for direct light-DOM composition inside a custom element and preserve it across
|
|
56
|
+
rerenders. This is the one explicit native interop attribute, not permission to
|
|
57
|
+
spread arbitrary native attributes. `ResizableRegion` and `CollapsiblePanel`
|
|
58
|
+
remain excluded because their optional restore control makes them multi-root;
|
|
59
|
+
use a slotted single-root child or `CollapsiblePanelToggle` instead.
|
|
54
60
|
|
|
55
61
|
Before selecting for an application, call the Node-side discovery API in
|
|
56
62
|
`./application-ui-profile.mjs` (or implement its documented filename/order)
|
|
@@ -69,7 +75,7 @@ Choose from the need, not from visual resemblance:
|
|
|
69
75
|
|
|
70
76
|
1. Search the consumer extension first, then the Kerf catalog and preferred Web Awesome subset.
|
|
71
77
|
2. Reuse a primitive when purpose, anatomy, state, and interaction match.
|
|
72
|
-
3. Compose primitives for recurring layout
|
|
78
|
+
3. Compose primitives for recurring layout through public props and tokens. Never select one component from another component's stylesheet.
|
|
73
79
|
4. Add a thin application adapter for copy, domain mapping, actions, routing, persistence, permissions, and transport.
|
|
74
80
|
5. Build custom markup only when the semantic contract differs; if it recurs across products, open an upstream component or recipe request.
|
|
75
81
|
|
|
@@ -84,6 +90,7 @@ Quick routing:
|
|
|
84
90
|
| Page, panel, or dialog heading | `Toolbar` + `ToolbarText` | Use a direct extra-large `ToolbarText`, optional grouped icon, grouped trailing controls, and app-owned supporting copy below. |
|
|
85
91
|
| Exclusive choice | `TabBar`, `SegmentedControl`, or `Select` | Tabs switch tabpanels; segments expose a few choices; Select handles a longer value list. |
|
|
86
92
|
| Status or absent content | `StateBanner` or `EmptyState` | `StateBanner` accepts an optional terse, tone-tinted `badge` beside its title for a count or compact status; do not rely on color alone. Web Awesome callouts suit ecosystem content; toasts are transient and never the only record of important state. |
|
|
93
|
+
| Compact metadata | `Badge` | Configure status, count, category, or metadata presentation with tone, appearance, shape, and size props. Do not build badges with application CSS or use them as interactive controls. |
|
|
87
94
|
| Loading placeholder | a component's `placeholder` prop, or `Skeleton` | Set `placeholder` on a value-bearing component (`Select`, `ListHeader`, `ListItem`, `ValueTableRow`, `SegmentedControl`, `StateBanner`, `AppTab`, `ToolbarText`, `ListActionRow`) to render its real chrome with value slots as subtle **unanimated** skeletons and interactivity disabled — do not hand-rebuild an empty state. `Skeleton` is the standalone block for a custom slot. Use `LoadingSpinner` for known busy activity, not a skeleton; never animate a skeleton; prefer it over `wa-skeleton`. |
|
|
88
95
|
| Adjustable or asymmetric columns | `ResizableRegion` or CSS grid | Use `ResizableRegion` only for a user-operable controlled separator, CSS grid for asymmetric/intrinsic tracks, and `Grid` for static equal-width tracks. |
|
|
89
96
|
| Structured or ordinary search | `TokenSearchField` or an input | Use token search only when text and ordered filter chips form one editor. |
|
|
@@ -113,26 +120,33 @@ choice that should remain only when application context justifies it. Apply the
|
|
|
113
120
|
same metadata when authoring consumer component catalogs so lint, analyzer, and
|
|
114
121
|
doctor feedback covers local components too.
|
|
115
122
|
|
|
123
|
+
Toolbar action links and menus are configuration, not application CSS: put
|
|
124
|
+
`ToolbarActionLink` inside `ToolbarControlGroup`, set `overflow="scroll"` for a
|
|
125
|
+
bounded action row, use `menuInset` for nested dropdown surface padding, and set
|
|
126
|
+
`visibility="compact-only"` when a group appears only below the Toolbar's compact
|
|
127
|
+
container breakpoint. Never add app-owned anchor chrome, width/visibility
|
|
128
|
+
repairs, or `::part(menu)` overrides.
|
|
129
|
+
|
|
116
130
|
Hard rules:
|
|
117
131
|
|
|
118
|
-
1. Import visual components from explicit JavaScript subpaths. In CSS-aware browser builds each subpath brings in its own reachable CSS, including UI subcomponents, while unrelated CSS remains out. The root barrel and `@kerfjs/ui/unstyled` are CSS-free; pair the root barrel with `styles.css` only when the complete layer is intentional. Manual CSS subpaths remain available for custom pipelines.
|
|
132
|
+
1. Import visual components from explicit JavaScript subpaths. In CSS-aware browser builds each subpath brings in its own reachable CSS, including UI subcomponents, while unrelated CSS remains out. The root barrel and `@kerfjs/ui/unstyled` are CSS-free; pair the root barrel with `styles.css` only when the complete layer is intentional. Manual CSS subpaths remain available for custom pipelines. When a public subpath exposes several visual components, implement it as a folder with one component per file and one owned stylesheet per visual component; compatibility entrypoints only re-export the component modules or import their owner stylesheets.
|
|
119
133
|
2. Components return Kerf `SafeHtml`. Never pass DOM nodes as children or use inline JSX event handlers.
|
|
120
134
|
3. Keep state, product copy, persistence, and domain mappings in the application. Do not add product-specific actions or fields to a generic component. Put ListItem/ListActionRow/ListHeader/AppTab domain `data-*` metadata in `rootAttributes`; use ListActionRow `trailingActionAttributes` and ListHeader `triggerAttributes` only for domain `data-*` or native popover target/action and `aria-controls`/`aria-haspopup`. These slots do not replace component-owned action, item/tab identity, selection, disclosure, naming, disabled, icon, or role semantics.
|
|
121
135
|
4. Wire `data-action` hooks from one stable root with `delegate()` or `delegateActions()` and retain disposers.
|
|
122
|
-
5. Use the opinionated `--kui-color-*` semantic ramps and component-level override properties. Use `pop` only for attractive non-status emphasis such as featured, novel, or celebratory content; never substitute it for info, success, warning, or danger. Override tokens at the narrowest useful scope and prefer equivalent props/tokens.
|
|
136
|
+
5. Use the opinionated `--kui-color-*` semantic ramps and component-level override properties. Use `pop` only for attractive non-status emphasis such as featured, novel, or celebratory content; never substitute it for info, success, warning, or danger. Override tokens at the narrowest useful scope and prefer equivalent props/tokens. `publicClasses` exist for diagnostics, tooling, tests, and package-owned composition, not application styling. Never target a Kerf or Web Awesome component from application CSS; add missing configuration to the owner.
|
|
123
137
|
6. `Select` is pure until the app explicitly imports `@kerfjs/ui/select/register`; do not import Web Awesome's full registration bundle. When an app writes direct `wa-*` JSX, add `import type {} from '@kerfjs/ui/webawesome'` for the catalog-supported intrinsic-element declarations, import the CSS-only `@kerfjs/ui/webawesome.css` theme once, and keep importing individual Web Awesome component modules so their JavaScript remains tree-shakeable. The type boundary emits no code and registers nothing. Pass icon-bearing `choices` and `renderSelected` content normally: `Select` preserves its slotted option icons across Kerf rerenders and keys selected content by the controlled value, so app wrappers must not add competing morph-control attributes. Give it a visible `label` or an `ariaLabel` for a visually hidden name; the nonempty visible label takes precedence and the package names the actual shadow combobox, including `renderSelected`, without adding label geometry. Use `hint` for persistent supporting text below the control and `placeholderText` only for the empty value inside the closed control; loading placeholders retain the hint. When testing name or description, target the element with the `combobox` role rather than the `wa-select` wrapper. Web Awesome's hint attribute and explicit hint slot both describe that shadow combobox across supported engines; do not add an `aria-description` mirror or application shadow-DOM patch.
|
|
124
138
|
7. Decorative icons are hidden; controls are named; focus is visible; state never relies on color alone; reduced motion and increased contrast remain usable. `DisclosureArrow` defaults to an 18px root-scaled visual and exposes `--kui-disclosure-arrow-size` for consumer sizing; it never becomes the interaction or accessible-name owner. Put it in an owning native control with a stable accessible name and controlled `aria-expanded`. `ListHeader` toggle mode supplies it when `actionIcon` is omitted, but the app must reveal matching content; a custom icon replaces it. Author replacement icon content facing right before its configured direction transform is applied. Direction changes take the shortest rotation path, with counterclockwise chosen for a 180-degree closed-to-open tie. Kerf `Select` separately keeps its intrinsic Web Awesome expand glyph at `--kui-disclosure-icon-scale: .5`.
|
|
125
|
-
8. `ResizableRegion` uses `wireResizableRegions()` for Arrow, Shift+Arrow, Home/End, and pointer behavior. The app owns size persistence. `handleIcon` replaces decorative dormant glyph content only.
|
|
139
|
+
8. `ResizableRegion` uses `wireResizableRegions()` for Arrow, Shift+Arrow, Home/End, and pointer behavior. The app owns size persistence. `handleIcon` replaces decorative dormant glyph content only. Set `responsiveFillAt="narrow"` or `"compact"` when a responsive composition exposes the pane as its only inline track; the component fills that track and hides its dormant separator. For compact overlays, set `presentation="overlay"` and the overlay maximum variables. Do not add descendant width/height overrides.
|
|
126
140
|
9. Use controlled `SegmentedControl` for a small exclusive choice set. Select `appearance="toolbar"` when nesting it inside `ToolbarControlGroup`; use rounded or pill shapes for standalone contexts. The package derives inset hover/selection radii from the owning outer shape through `--kui-layout-highlight-inset`; do not restyle an inner highlight to an independent radius. Handle its action, update `value`, keep meaningful choice labels, and preserve every enabled native button in sequential Tab order.
|
|
127
|
-
10. Compose `AppTab` inside controlled `TabBar`; call `wireTabBars()` once and retain its disposer. It owns same-bar drag mechanics, including proximity-based horizontal edge autoscroll, while the app applies `onReorder` and owns order, selection, panels, close policy, routing, and persistence. Arrow/Home/End select on move by default and restore focus by bar/tab identity when controlled activation replaces the strip; pass `activation: 'manual'` (or `TabBar activation="manual"` per strip) so arrow keys move focus only and the user selects with Enter/Space/click — use it when selecting a tab is a heavy action. Use runtime-filtered `rootAttributes` for domain metadata and keep an optional `closeIcon` decorative and noninteractive.
|
|
141
|
+
10. Compose `AppTab` inside controlled `TabBar`; call `wireTabBars()` once and retain its disposer. It owns same-bar drag mechanics, including proximity-based horizontal edge autoscroll, while the app applies `onReorder` and owns order, selection, panels, close policy, routing, and persistence. For a tab-local action followed by a separately pinned workspace action, set `trailingPlacement="adjacent"`, put the local action in `trailing`, and the workspace action in `end`; TabBar owns the shrinking/scrolling tabs and fixed action geometry, so do not add descendant flex overrides. Arrow/Home/End select on move by default and restore focus by bar/tab identity when controlled activation replaces the strip; pass `activation: 'manual'` (or `TabBar activation="manual"` per strip) so arrow keys move focus only and the user selects with Enter/Space/click — use it when selecting a tab is a heavy action. Use runtime-filtered `rootAttributes` for domain metadata and keep an optional `closeIcon` decorative and noninteractive.
|
|
128
142
|
11. Use token-controlled `TokenSearchField` when free text and removable structured filters share one editor. Editable text stays DOM-owned between token changes. The leading icon, first text line, clear action, and trailing slot share one fixed row when content wraps. The app owns parsing and suggestions; call `readTokenSearchField()` on input, empty `textContent` on clear, use `placeTokenSearchCaret()` after explicit controlled focus changes, and call `wireTokenSearchFields()` once so Enter submits without inserting a line break and keyboard chip deletion restores focus plus the text-relative caret after controlled replacement. Enable `collapsible` for an animated iconic closed state, standalone or inside `ToolbarControlGroup`; the field keeps text or tokens expanded, and `wireTokenSearchFields()` manages the transient expand/collapse/focus by default (activate to reveal + focus, Escape or empty blur to collapse). Bind the field's `expanded` to the returned handle's `expanded(id)` signal or adopt your own via `collapsible.signals`; opt a behavior out only when the app must own it. Do not hand-roll the open handler, the focusout collapse, a clear-button mousedown guard, or reopening after controlled clear or Select All deletion — the helper keeps the replacement editor open and focused. Clear and deletion restoration finish at the replacement mutation checkpoint before the next input task, so shortcut-letter typing cannot escape to the page and delayed animation frames cannot overwrite a later selection. Persist both query and tokens returned by the DOM read. For real-app adoption it also provides a focusout keep-open exception (`data-token-search-keep-open` regions or `collapsible.keepOpenOn(target)`, so a sibling suggestions/date/help surface does not collapse an empty field), opt-in atomic-chip keyboard (`keyboard`: Backspace/Delete remove the adjacent chip via `onRemoveToken`, ArrowRight moves the caret past a trailing chip), and an `onEdit({id, editor, event})` input callback (the `InputEvent` lets you gate on `inputType`/`data`) — reach for these instead of re-adding hand-rolled keydown/input handlers around the field.
|
|
129
|
-
12. Demo work uses public production component subpaths and their browser-selected CSS. Give every public visual component its own category-grouped catalog route; list themed third-party components under a clearly labeled collapsible ecosystem section, with a focused route for each. For the complete focused/composition decision, `CatalogExample` / `CatalogExampleStack` row/group nesting, exact specimen selection, geometry-overlay legend and exclusions, skip-marker behavior, and metadata ownership, follow the single [Catalog demo authoring contract](../docs/catalog.md#catalog-demo-authoring-contract), discovered machine-readably through [`catalog-authoring.json`](./catalog-authoring.json). Never infer structure from private `kui-catalog-*` classes. Project each component's deterministic repository-relative demo source and existing documentation path so the detail can expose `View demo source` and `Read guidance` links without a runtime export; also derive first-party component implementation paths from their canonical browser imports, and label Web Awesome documentation as Kerf integration guidance. Declare direct `uses` relationships so `Used by` stays derivable, and theme shell chrome through the same semantic tokens as the stage instead of drawing a substitute. Enable `wireCatalog({ revealSelection: true })` for long desktop sidebars so controlled selections remain visible without moving focus; keep its default compact media guard unless compact scrolling is an explicit product behavior, and use `revealCatalogEntry` for an initial deep link.
|
|
130
|
-
13. The Web Awesome theme makes Tooltip and Popover arrowless by default. Keep that default unless a pointer materially clarifies the anchor; opt back in with `--wa-tooltip-arrow-size`, `--kui-wa-popover-arrow-size`, or a popover's public `--arrow-size`, and use `without-arrow` when local no-arrow intent should survive theme changes. Its non-field chrome uses `--kui-wa-control-inset` (8px controls/items), `--kui-wa-surface-margin` / `--kui-wa-surface-inset` (8px around/inside Accordion, Card, Details, Callout, and Include), and `--kui-wa-container-inset` (16px Tab Panel content and
|
|
143
|
+
12. Demo work uses public production component subpaths and their browser-selected CSS. Use exactly three demo kinds: a `component` is one component with variants/states, a `composition` is a focused container of components commonly used together, and a `recipe` is the recommended production approach to a task. Organize catalog routes into product-important functional groups; within each group put all components before compositions, order each kind by importance with display-name alphabetical tie-breaking, and put recipes after every component/composition group. Show `Composition` as an entry tag instead of repeating the word in its name. Give every public visual component its own category-grouped catalog route; list themed third-party components under a clearly labeled collapsible ecosystem section, with a focused route for each. For the complete taxonomy, focused/composition decision, `CatalogExample` / `CatalogExampleStack` row/group nesting, exact specimen selection, geometry-overlay legend and exclusions, skip-marker behavior, and metadata ownership, follow the single [Catalog demo authoring contract](../docs/catalog.md#catalog-demo-authoring-contract), discovered machine-readably through [`catalog-authoring.json`](./catalog-authoring.json). Never infer structure from private `kui-catalog-*` classes. Project each component's deterministic repository-relative demo source and existing documentation path so the detail can expose `View demo source` and `Read guidance` links without a runtime export; also derive first-party component implementation paths from their canonical browser imports, and label Web Awesome documentation as Kerf integration guidance. Declare direct `uses` relationships so `Used by` stays derivable, and theme shell chrome through the same semantic tokens as the stage instead of drawing a substitute. Enable `wireCatalog({ revealSelection: true })` for long desktop sidebars so controlled selections remain visible without moving focus; keep its default compact media guard unless compact scrolling is an explicit product behavior, and use `revealCatalogEntry` for an initial deep link.
|
|
144
|
+
13. The Web Awesome theme makes Tooltip and Popover arrowless by default. Keep that default unless a pointer materially clarifies the anchor; opt back in with `--wa-tooltip-arrow-size`, `--kui-wa-popover-arrow-size`, or a popover's public `--arrow-size`, and use `without-arrow` when local no-arrow intent should survive theme changes. Its non-field chrome uses `--kui-wa-control-inset` (8px controls/items), `--kui-wa-surface-margin` / `--kui-wa-surface-inset` (8px around/inside Accordion, Card, Details, Callout, and Include), and `--kui-wa-container-inset` (16px Tab Panel content and framed disclosure regions). Plain Details use the 8px surface inset on the trigger and keep the body flush; plain Accordion items use it on both trigger and body. Outlined and sunken Details use the 16px container inset on the trigger and 8px on the body; framed Accordion items use 16px on both. Dialog maps its body to the 8px surface tier and its footer to the 16px container tier independently of `--spacing`. Override those tiers instead of restyling individual parts. Filled badges use each variant's quiet fill with normal text so their compact copy stays WCAG-AA readable; override the pair with `--kui-wa-badge-filled-background` / `--kui-wa-badge-filled-foreground`, not host selectors. When a dialog provides another dismissal affordance, put `hide-actions` on the `wa-dialog` host to hide its directly exported `header-actions` part; never chain `::part()` selectors through internal parts. Checkbox and Radio Group option regions, the Color Picker trigger, and Slider's complete interactive region receive the shared 8px logical inline outer inset because those controls have no bordered field shell. Known Date field captions and bordered text-like field hints align with values at the 9px border-plus-padding inset. OTP Input's label uses the same uppercase xs/650 treatment as other field labels, and both its label and hint use that 9px inset.
|
|
131
145
|
14. Treat the complete Web Awesome catalog as support coverage, not a recommendation list. Its UX sidebar marks superseded and exceptional entries `Discouraged`. Consider Popup when it replaces custom anchored positioning. Prefer Kerf `Select` over direct Dropdown/Dropdown Item/Select/Option composition, `SegmentedControl` over Button Group, `TabBar` or `SegmentedControl` over Web Awesome Tabs, `LucideIcon` over Web Awesome Icon, and `ResizableRegion` over Split Panel. Use Tree/Tree Item, Animated Image, and Comparison only for a specific required behavior; avoid Zoomable Frame.
|
|
132
146
|
15. Build sidebars, main areas, inspectors, and dialogs from `@kerfjs/ui/layout.css`: an unpadded `.kui-pane`, optional `.kui-pane__toolbar`, one scrolling `.kui-pane__content`, and optional `.kui-pane__footer`. Use `Row` instead of a hand-written flex-row wrapper, `List` instead of a hand-written flex-column wrapper, and `Grid` instead of repeated equal-track CSS when children need a fixed positive count of evenly distributed columns. `Row` defaults to left/full with an `xs` gap and no wrapping; Grid defaults to an `xs` gap and keeps each track at `minmax(0, 1fr)`; List retains full/top and zero-gap defaults. The app owns Grid's responsive column-count changes. Use `List` when rows or sections also need flex growth, one vertical scroll owner, or physical-edge dividers. `dividerSides`, `textInsets`, and `controlInsets` use canonical physical `t`/`r`/`b`/`l` order; text geometry wins where text and control selections overlap. `ListInsetText` and `ListInsetControl` inset all four sides by default and accept the same `sides` grammar for selective edges. A dialog body is generally a `List`: set `DialogSurface bodyInset="none"` when its list children own geometry, and wrap bare dialog prose in `ListInsetText` so it aligns with bordered siblings without a second inset. Add `.kui-content` for 24px major vertical separation and `.kui-content-item` for a child-owned 8px inline margin, 1px transparent-or-visible border, 8px padding, and 12px radius. Use the pill modifier for 22px. Do not pad pane shells, duplicate item geometry in wrappers, or create nested scroll owners.
|
|
133
147
|
15a. Use `Text` from `@kerfjs/ui/text` for ordinary headings and paragraphs outside toolbar title zones. Omit `variant` for the default `p`, or pass `h1`–`h6` according to the document outline; ordinary native attributes pass through. Express supporting, error, compact, or code text with the independent finite `tone="quiet|danger"`, `size="compact"`, and `font="monospace"` props instead of global utility classes or appearance-only heading choices. Text owns a transparent 1px border and the standard item padding. Keep toolbar identity/title content on `ToolbarText` and list-aligned bare prose on `ListInsetText`.
|
|
134
148
|
16. Keep a visible collapsible pane's collapse control in its own toolbar. When hidden, move its restore control into the adjacent main toolbar on the corresponding logical edge: leading for an inline-start sidebar and trailing for an inline-end inspector. Collapse the pane completely; do not preserve an empty icon-only rail.
|
|
135
|
-
17. The only direct children of a `Toolbar` zone (`leading`/`center`/`trailing`) are `ToolbarText` (identity/title text) and `ToolbarControlGroup`; never drop bare buttons, inputs, links, or arbitrary markup straight into a zone. Put identity/title text directly in the zone as `ToolbarText`; wrap interactive controls and icon tiles in `ToolbarControlGroup`. `SegmentedControl`, `Select`, a collapsible `TokenSearchField`, and Web Awesome controls all live inside a group. For an ordinary icon/action control inside a group, use a plain `<button>` (the group styles `> button` fully) — that is the default; reach for `wa-button` only when you need a Web Awesome feature, chiefly a `wa-dropdown` popup trigger. A popup menu in a toolbar is a `single` group wrapping a `wa-dropdown` whose `slot="trigger"` `wa-button` is the toolbar button and whose `wa-dropdown-item`s are the menu, with the dropdown kept under `data-morph-skip-children`. For a compact mixed group, keep the standard item padding and raised selected chrome; the selected item paints over the outer border without an internal separator. For an avatar control, set `content="avatar"` and `avatarImage` on the group instead of inserting an `img`: a lone control paints the contained image on the outer group and a multi-button group paints it only on the pressed selection highlight. Compose panel/dialog/page headings with a direct extra-large `ToolbarText`, optional grouped icon, grouped trailing controls, and app-owned supporting copy below. A group remains 44px outside (`calc(2px + remify(42px))`) when its border/background are transparent; use 8px between groups and inside items. Split dormant and interactive regions: `ListHeader` fills the available inline width by default; set `inline`
|
|
149
|
+
17. The only direct children of a `Toolbar` zone (`leading`/`center`/`trailing`) are `ToolbarText` (identity/title text) and `ToolbarControlGroup`; never drop bare buttons, inputs, links, or arbitrary markup straight into a zone. Put identity/title text directly in the zone as `ToolbarText`; wrap interactive controls and icon tiles in `ToolbarControlGroup`. `SegmentedControl`, `Select`, a collapsible `TokenSearchField`, and Web Awesome controls all live inside a group. Configure zone behavior with `Toolbar.centerAlign` and its `responsive` / `responsiveAt` policy instead of selecting toolbar zone classes. For an ordinary icon/action control inside a group, use a plain `<button>` (the group styles `> button` fully) — that is the default; reach for `wa-button` only when you need a Web Awesome feature, chiefly a `wa-dropdown` popup trigger. A popup menu in a toolbar is a `single` group wrapping a `wa-dropdown` whose `slot="trigger"` `wa-button` is the toolbar button and whose `wa-dropdown-item`s are the menu, with the dropdown kept under `data-morph-skip-children`. For a compact mixed group, keep the standard item padding and raised selected chrome; the selected item paints over the outer border without an internal separator. For an avatar control, set `content="avatar"` and `avatarImage` on the group instead of inserting an `img`: a lone control paints the contained image on the outer group and a multi-button group paints it only on the pressed selection highlight. Compose panel/dialog/page headings with a direct extra-large `ToolbarText`, optional grouped icon, grouped trailing controls, and app-owned supporting copy below. A group remains 44px outside (`calc(2px + remify(42px))`) when its border/background are transparent; use 8px between groups and inside items. Split dormant and interactive regions: `ListHeader` fills the available inline width by default; set `width="content"` to shrink-wrap while retaining its normal geometry, or `inline` when it belongs in surrounding text without outer margin, border, or padding. It keeps its label and mutually exclusive semantic count or non-count `badge` together, with an independent logical-end action unless disclosure mode makes the title cluster the button. Its action visual defaults to 18px through `--kui-list-header-action-icon-size`; never shrink the target to match it. Pass every non-negative safe-integer section quantity through `count` with a localized full spoken `countLabel`; never concatenate it into `label` or put a number in `badge`. `ListItem.trailing` is dormant; use `ListActionRow` when primary and trailing actions need sibling native buttons. Its `label`, `icon`, and `trailingActionIcon` slots are also dormant and cannot contain controls. Let panes relocate at narrow widths instead of shrinking targets.
|
|
136
150
|
18. When a recurring concept has no matching export or production recipe, keep its semantics in a thin application adapter while reusing the public layout vocabulary. The composer recipe uses one visible form surface, toolbar title/supporting-copy ids, shared 8px field/action gutters, 24px major rhythm, and a conditional StateBanner as its only nested semantic surface; do not turn every section into a card or double-inset intrinsically bordered controls. The application-local `../docs/examples/command-palette-adapter.tsx` is reference source for one such missing concept, not an `@kerfjs/ui` runtime export or catalog recipe. The application owns its registration, ranking, history, permissions, availability, shortcut policy, focus policy, dispatch, and copy. If a missing concept recurs across products, open an upstream component or recipe request.
|
|
137
151
|
19. Compose `ValueTable` from typed `ValueTableRow` entries instead of handwritten `dt`/`dd` wrappers. Pass `icon` for the optional 24px leading visual; the row owns 8px of root-scaled top and bottom padding, the 8px iconless or 40px icon-bearing separator start, and the common 8px right inset.
|
|
138
152
|
20. Use the standard direct `Toolbar` composition for a panel, dialog, or page heading, not a private wrapper or custom heading row. Put an optional icon in a `ToolbarControlGroup`, the title directly in the leading zone as extra-large `ToolbarText`, and actions in a trailing group. Set `headingLevel` for page/section landmarks. Supporting copy stays below the toolbar as app-owned content. The app owns modal behavior, focus, dismissal, command policy, ids, and action handling.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Web Awesome JSX signatures for the UI authoring corpus
|
|
2
2
|
|
|
3
|
-
Generated from the emitted `@kerfjs/ui@5.0.0-beta.
|
|
3
|
+
Generated from the emitted `@kerfjs/ui@5.0.0-beta.50` declaration boundary. Import `@kerfjs/ui/webawesome` for type effects when authoring direct `wa-*` JSX. The module emits no runtime behavior and does not register custom elements.
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
6
|
import { KerfCustomElement } from 'kerfjs/jsx-runtime';
|
package/dist/app-tab.d.ts
CHANGED
|
@@ -33,7 +33,9 @@ interface AppTabProps {
|
|
|
33
33
|
/** Render as an unanimated loading skeleton, disabling select/close and dragging. */
|
|
34
34
|
placeholder?: boolean;
|
|
35
35
|
rootAttributes?: AppTabRootAttributes;
|
|
36
|
+
/** Native named-slot assignment when composed inside a web component. */
|
|
37
|
+
slot?: string;
|
|
36
38
|
}
|
|
37
|
-
declare function AppTab({ id, name, selected, closable, draggable, leading, trailing, presentation, size, labelMaxWidth, closeIcon, selectAction, closeAction, className, placeholder, rootAttributes, }: AppTabProps): SafeHtml;
|
|
39
|
+
declare function AppTab({ id, name, selected, closable, draggable, leading, trailing, presentation, size, labelMaxWidth, closeIcon, selectAction, closeAction, className, placeholder, rootAttributes, slot, }: AppTabProps): SafeHtml;
|
|
38
40
|
|
|
39
41
|
export { AppTab, type AppTabPresentation, type AppTabProps, type AppTabSize };
|
package/dist/app-tab.js
CHANGED
package/dist/badge.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SafeHtml } from 'kerfjs';
|
|
2
|
+
|
|
3
|
+
type BadgeTone = 'neutral' | 'brand' | 'pop' | 'success' | 'warning' | 'danger';
|
|
4
|
+
type BadgeAppearance = 'quiet' | 'solid' | 'outline';
|
|
5
|
+
type BadgeShape = 'pill' | 'rounded';
|
|
6
|
+
type BadgeSize = 'compact' | 'default';
|
|
7
|
+
interface BadgeProps {
|
|
8
|
+
children: SafeHtml | string | number;
|
|
9
|
+
tone?: BadgeTone;
|
|
10
|
+
appearance?: BadgeAppearance;
|
|
11
|
+
shape?: BadgeShape;
|
|
12
|
+
size?: BadgeSize;
|
|
13
|
+
/** Optional accessible name when the visible content is abbreviated. */
|
|
14
|
+
label?: string;
|
|
15
|
+
/** Hide a repeated visual badge from assistive technology. */
|
|
16
|
+
ariaHidden?: boolean;
|
|
17
|
+
className?: string;
|
|
18
|
+
/** Native named-slot assignment when composed inside a web component. */
|
|
19
|
+
slot?: string;
|
|
20
|
+
}
|
|
21
|
+
/** Compact, non-interactive metadata whose tone, emphasis, and shape are configured by props. */
|
|
22
|
+
declare function Badge({ children, tone, appearance, shape, size, label, ariaHidden, className, slot, }: BadgeProps): SafeHtml;
|
|
23
|
+
|
|
24
|
+
export { Badge, type BadgeAppearance, type BadgeProps, type BadgeShape, type BadgeSize, type BadgeTone };
|
package/dist/badge.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"badge.js"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CatalogResource } from './
|
|
2
|
-
import 'kerfjs';
|
|
1
|
+
import { C as CatalogResource } from './types-CzgSrFXP.js';
|
|
3
2
|
import './semantic-content-BbzjvSu9.js';
|
|
3
|
+
import 'kerfjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Standard resource labels for a Kerf catalog detail footer. Keep these labels
|
package/dist/catalog.d.ts
CHANGED
|
@@ -1,102 +1,13 @@
|
|
|
1
|
+
import * as kerfjs from 'kerfjs';
|
|
1
2
|
import { SafeHtml } from 'kerfjs';
|
|
3
|
+
import { a as CatalogProps } from './types-CzgSrFXP.js';
|
|
4
|
+
export { b as CatalogBrand, c as CatalogEntry, d as CatalogRelated, C as CatalogResource, e as CatalogSecondaryGroup, f as CatalogSection } from './types-CzgSrFXP.js';
|
|
2
5
|
import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
|
|
3
6
|
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/** Optional monospace detail (e.g. a file path) shown after the label. */
|
|
9
|
-
detail?: string;
|
|
10
|
-
}
|
|
11
|
-
/** A related entry offered in the detail footer's "Related entries" popup menu. */
|
|
12
|
-
interface CatalogRelated {
|
|
13
|
-
id: string;
|
|
14
|
-
name: string;
|
|
15
|
-
/** Group heading in the menu, e.g. "Uses" / "Used by". */
|
|
16
|
-
group: string;
|
|
17
|
-
}
|
|
18
|
-
interface CatalogEntry {
|
|
19
|
-
id: string;
|
|
20
|
-
name: string;
|
|
21
|
-
description?: string;
|
|
22
|
-
/** Short metadata tags shown at the trailing edge of the sidebar row. */
|
|
23
|
-
tags?: readonly string[];
|
|
24
|
-
resources?: readonly CatalogResource[];
|
|
25
|
-
related?: readonly CatalogRelated[];
|
|
26
|
-
}
|
|
27
|
-
interface CatalogSection {
|
|
28
|
-
category: string;
|
|
29
|
-
entries: readonly CatalogEntry[];
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* A secondary group of sections shown below the primary sidebar sections with a
|
|
33
|
-
* quieter "ecosystem" treatment (e.g. third-party components). Optionally
|
|
34
|
-
* collapsible — the app owns `expanded` and toggles it from `wireCatalog`'s
|
|
35
|
-
* `onToggleSecondary`.
|
|
36
|
-
*/
|
|
37
|
-
interface CatalogSecondaryGroup {
|
|
38
|
-
label: string;
|
|
39
|
-
sections: readonly CatalogSection[];
|
|
40
|
-
/** When true, the group's label is a disclosure toggle controlling `expanded`. */
|
|
41
|
-
collapsible?: boolean;
|
|
42
|
-
/** Whether the group is expanded (controlled). Ignored unless `collapsible`. */
|
|
43
|
-
expanded?: boolean;
|
|
44
|
-
}
|
|
45
|
-
interface CatalogBrand {
|
|
46
|
-
title: string;
|
|
47
|
-
subtitle?: string;
|
|
48
|
-
/** Logo image URL (rendered decorative). Omit for a text-only brand. */
|
|
49
|
-
logoUrl?: string;
|
|
50
|
-
}
|
|
51
|
-
interface CatalogProps {
|
|
52
|
-
brand: CatalogBrand;
|
|
53
|
-
sections: readonly CatalogSection[];
|
|
54
|
-
/** The controlled active entry id — the app owns this signal. */
|
|
55
|
-
active: string;
|
|
56
|
-
/** The rendered preview for the active entry; the app computes it from `active`. */
|
|
57
|
-
content: KerfUiContent;
|
|
58
|
-
/** Whether the sidebar is collapsed (controlled). */
|
|
59
|
-
collapsed?: boolean;
|
|
60
|
-
/** Current theme; when set, a theme toggle is shown that switches to the opposite. Omit to hide it. */
|
|
61
|
-
theme?: 'light' | 'dark';
|
|
62
|
-
/** Extra header controls placed before the theme toggle (each a `ToolbarControlGroup`). */
|
|
63
|
-
headerActions?: KerfUiContent;
|
|
64
|
-
/** A secondary "ecosystem" group of sections below the primary category groups. */
|
|
65
|
-
secondarySections?: CatalogSecondaryGroup;
|
|
66
|
-
/** Extra sidebar content below the category groups (and the secondary group). */
|
|
67
|
-
sidebarFooter?: KerfUiContent;
|
|
68
|
-
/** Status line content shown at the start of the detail footer. */
|
|
69
|
-
status?: KerfUiContent;
|
|
70
|
-
/**
|
|
71
|
-
* Whether to highlight specimens' computed borders (or transparent outer
|
|
72
|
-
* bounds) and non-zero margins. Pass a boolean (rather than omitting the
|
|
73
|
-
* prop) when the active entry can switch between component and composition
|
|
74
|
-
* previews; `wireCatalogGeometryOverlay` keeps the overlay synchronized.
|
|
75
|
-
*/
|
|
76
|
-
geometryOverlay?: boolean;
|
|
77
|
-
selectAction?: string;
|
|
78
|
-
toggleSidebarAction?: string;
|
|
79
|
-
toggleThemeAction?: string;
|
|
80
|
-
/** Action fired by the secondary group's disclosure toggle (when collapsible). */
|
|
81
|
-
toggleSecondaryAction?: string;
|
|
82
|
-
className?: string;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* A reusable component-catalog shell: a collapsible category sidebar, a titled
|
|
86
|
-
* detail stage that renders the active entry's preview, and a footer with
|
|
87
|
-
* reference links and a related-entry popup menu. Built entirely from public
|
|
88
|
-
* `@kerfjs/ui` primitives. Controlled and stateless — the app owns the `active`,
|
|
89
|
-
* `collapsed`, and `theme` signals and computes `content` from `active` in its own
|
|
90
|
-
* render; wire the sidebar/collapse/theme actions with `wireCatalog`.
|
|
91
|
-
*/
|
|
92
|
-
declare function Catalog({ brand, sections, active, content, collapsed, theme, headerActions, secondarySections, sidebarFooter, status, geometryOverlay, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, className, }: CatalogProps): SafeHtml;
|
|
93
|
-
/**
|
|
94
|
-
* How a {@link CatalogExample}'s content aligns its visible left edge with the
|
|
95
|
-
* example's `ListHeader` label (which sits 16px in — 8px title + 8px label):
|
|
96
|
-
* - `'glyph'` — a bare glyph/text specimen with no inline geometry insets the full 16px.
|
|
97
|
-
* - `'inline-control'` — a control that already carries ~8px of its own inline padding insets 8px so its content lands on the same line.
|
|
98
|
-
* - `'none'` — a content-item / composition that owns its geometry and already aligns; no inset (default).
|
|
99
|
-
*/
|
|
7
|
+
/** Controlled, stateless component-catalog shell. */
|
|
8
|
+
declare function Catalog({ brand, sections, active, content, collapsed, theme, headerActions, secondarySections, sidebarFooter, status, geometryOverlay, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, className, slot, }: CatalogProps): kerfjs.SafeHtml;
|
|
9
|
+
|
|
10
|
+
/** How a specimen aligns its visible edge with its `ListHeader` label. */
|
|
100
11
|
type CatalogExampleAlign = 'glyph' | 'inline-control' | 'none';
|
|
101
12
|
type CatalogExampleRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
|
|
102
13
|
'data-catalog-example'?: never;
|
|
@@ -105,47 +16,35 @@ type CatalogExampleRootAttributes = Readonly<Record<`data-${string}`, string | u
|
|
|
105
16
|
'data-catalog-example-note'?: never;
|
|
106
17
|
'data-align'?: never;
|
|
107
18
|
}>;
|
|
108
|
-
type CatalogExampleStackRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
|
|
109
|
-
'data-catalog-example'?: never;
|
|
110
|
-
'data-catalog-example-stack'?: never;
|
|
111
|
-
'data-catalog-example-label'?: never;
|
|
112
|
-
'data-catalog-example-note'?: never;
|
|
113
|
-
'data-align'?: never;
|
|
114
|
-
}>;
|
|
115
19
|
interface CatalogExampleProps {
|
|
116
|
-
/** The example's label, shown as a `ListHeader` above the specimen. Omit for a bare specimen. */
|
|
117
20
|
label?: string;
|
|
118
|
-
/** Optional explanatory note between the label and the specimen. */
|
|
119
21
|
note?: SafeHtml | string;
|
|
120
|
-
/** Alignment inset for the specimen — see {@link CatalogExampleAlign}. Default `'none'`. */
|
|
121
22
|
align?: CatalogExampleAlign;
|
|
122
|
-
/** Safe authoring `data-*` metadata for the rendered section. Helper-owned structural attributes remain protected. */
|
|
123
23
|
rootAttributes?: CatalogExampleRootAttributes;
|
|
124
24
|
className?: string;
|
|
125
25
|
children?: KerfUiContent;
|
|
26
|
+
/** Native named-slot assignment when composed inside a web component. */
|
|
27
|
+
slot?: string;
|
|
126
28
|
}
|
|
127
|
-
/**
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
29
|
+
/** A labeled catalog specimen with optional explanatory text and alignment. */
|
|
30
|
+
declare function CatalogExample({ label, note, align, rootAttributes, className, children, slot, }: CatalogExampleProps): SafeHtml;
|
|
31
|
+
|
|
32
|
+
type CatalogExampleStackRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
|
|
33
|
+
'data-catalog-example'?: never;
|
|
34
|
+
'data-catalog-example-stack'?: never;
|
|
35
|
+
'data-catalog-example-label'?: never;
|
|
36
|
+
'data-catalog-example-note'?: never;
|
|
37
|
+
'data-align'?: never;
|
|
38
|
+
}>;
|
|
136
39
|
interface CatalogExampleStackProps {
|
|
137
|
-
/** Accessible label for the stack region. */
|
|
138
40
|
label?: string;
|
|
139
|
-
/** Safe authoring `data-*` metadata for the rendered stack. Helper-owned structural attributes remain protected. */
|
|
140
41
|
rootAttributes?: CatalogExampleStackRootAttributes;
|
|
141
42
|
className?: string;
|
|
142
43
|
children?: KerfUiContent;
|
|
44
|
+
/** Native named-slot assignment when composed inside a web component. */
|
|
45
|
+
slot?: string;
|
|
143
46
|
}
|
|
144
|
-
/**
|
|
145
|
-
|
|
146
|
-
* example rhythm. The semantic `section` becomes a named `region` when `label`
|
|
147
|
-
* is supplied; an unlabeled stack remains an ordinary grouping.
|
|
148
|
-
*/
|
|
149
|
-
declare function CatalogExampleStack({ label, rootAttributes, className, children, }: CatalogExampleStackProps): SafeHtml;
|
|
47
|
+
/** A vertically stacked group of catalog examples. */
|
|
48
|
+
declare function CatalogExampleStack({ label, rootAttributes, className, children, slot, }: CatalogExampleStackProps): kerfjs.SafeHtml;
|
|
150
49
|
|
|
151
|
-
export { Catalog,
|
|
50
|
+
export { Catalog, CatalogExample, type CatalogExampleAlign, type CatalogExampleProps, CatalogExampleStack, type CatalogExampleStackProps, CatalogProps };
|