@kerfjs/ui 5.0.0-beta.29 → 5.0.0-beta.30
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 +43 -8
- package/ai/application-ui-diagnostic-ids-v1.json +5 -0
- package/ai/compile-time-contracts-v1.json +37 -0
- package/ai/compile-time-contracts-v1.schema.json +3 -1
- package/ai/component-catalog-v2-overrides.json +198 -1
- package/ai/component-catalog-v2.d.ts +22 -0
- package/ai/component-catalog-v2.json +488 -32
- package/ai/component-catalog-v2.schema.json +51 -0
- package/ai/component-catalog.json +251 -36
- package/ai/component-catalog.schema.json +23 -0
- package/ai/public-api-signatures-v1.md +231 -84
- package/ai/skill.md +32 -10
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/analyzer/index.mjs +247 -5
- package/dist/app-tab.d.ts +3 -2
- package/dist/app-tab.js +2 -1
- package/dist/catalog-resources.d.ts +1 -0
- package/dist/catalog.d.ts +7 -6
- package/dist/catalog.js +8 -7
- package/dist/catalog.js.map +1 -1
- package/dist/{chunk-PX3YSS5C.js → chunk-6NDBE2OK.js} +1 -1
- package/dist/chunk-6NDBE2OK.js.map +1 -0
- package/dist/{chunk-B3A3IVO5.js → chunk-AQFWBG23.js} +3 -3
- package/dist/chunk-AQFWBG23.js.map +1 -0
- package/dist/{chunk-WNWD54GR.js → chunk-B6JYRX3P.js} +4 -2
- package/dist/chunk-B6JYRX3P.js.map +1 -0
- package/dist/{chunk-HP2B2L26.js → chunk-CAB6NQ2T.js} +1 -1
- package/dist/chunk-CAB6NQ2T.js.map +1 -0
- package/dist/{chunk-2NMQW7FX.js → chunk-CK6P5AUK.js} +4 -3
- package/dist/chunk-CK6P5AUK.js.map +1 -0
- package/dist/{chunk-VCE4MPVE.js → chunk-DAO2VFTT.js} +5 -6
- package/dist/chunk-DAO2VFTT.js.map +1 -0
- package/dist/{chunk-LPOMRC4C.js → chunk-DYBPI5O2.js} +1 -1
- package/dist/chunk-DYBPI5O2.js.map +1 -0
- package/dist/{chunk-IJBSZ4NX.js → chunk-E34TE2ZI.js} +4 -3
- package/dist/chunk-E34TE2ZI.js.map +1 -0
- package/dist/{chunk-4EF2CMYS.js → chunk-I45QO2IZ.js} +8 -7
- package/dist/chunk-I45QO2IZ.js.map +1 -0
- package/dist/{chunk-JRKSK2HX.js → chunk-I4V3UDSA.js} +1 -1
- package/dist/chunk-I4V3UDSA.js.map +1 -0
- package/dist/{chunk-FEY65TBV.js → chunk-KFUUFNTS.js} +1 -1
- package/dist/chunk-KFUUFNTS.js.map +1 -0
- package/dist/{chunk-QO55FN2Y.js → chunk-MFR2IIFG.js} +1 -1
- package/dist/chunk-MFR2IIFG.js.map +1 -0
- package/dist/{chunk-GWEAPEZI.js → chunk-OC275HHS.js} +4 -3
- package/dist/chunk-OC275HHS.js.map +1 -0
- package/dist/chunk-OL4TC3U2.js +156 -0
- package/dist/chunk-OL4TC3U2.js.map +1 -0
- package/dist/{chunk-OT6RPYAP.js → chunk-OMSRSL3B.js} +4 -3
- package/dist/chunk-OMSRSL3B.js.map +1 -0
- package/dist/{chunk-J5BFYY7Q.js → chunk-RL6COPKF.js} +12 -3
- package/dist/chunk-RL6COPKF.js.map +1 -0
- package/dist/{chunk-TB6DY7H5.js → chunk-SOK5EUF7.js} +1 -1
- package/dist/chunk-SOK5EUF7.js.map +1 -0
- package/dist/{chunk-RKVQEH4J.js → chunk-T7DOWS6T.js} +3 -3
- package/dist/chunk-T7DOWS6T.js.map +1 -0
- package/dist/{chunk-7KEUJIIC.js → chunk-TIGSG6BX.js} +1 -1
- package/dist/chunk-TIGSG6BX.js.map +1 -0
- package/dist/{chunk-W5L2JSBY.js → chunk-UDHHKZWO.js} +6 -5
- package/dist/chunk-UDHHKZWO.js.map +1 -0
- package/dist/{chunk-R7ZWUN64.js → chunk-V6GQKOX2.js} +4 -3
- package/dist/chunk-V6GQKOX2.js.map +1 -0
- package/dist/{chunk-KWWR5VMS.js → chunk-V6HCTCVD.js} +4 -3
- package/dist/chunk-V6HCTCVD.js.map +1 -0
- package/dist/{chunk-JFGXQBIP.js → chunk-VDUJZF5G.js} +76 -13
- package/dist/chunk-VDUJZF5G.js.map +1 -0
- package/dist/{chunk-SYDMYBPG.js → chunk-VXFGMDA7.js} +1 -1
- package/dist/chunk-VXFGMDA7.js.map +1 -0
- package/dist/{chunk-YMKH5XTF.js → chunk-WN52USHV.js} +2 -2
- package/dist/{chunk-YMKH5XTF.js.map → chunk-WN52USHV.js.map} +1 -1
- package/dist/{chunk-OBLTAKSX.js → chunk-WSXUPSID.js} +1 -1
- package/dist/chunk-WSXUPSID.js.map +1 -0
- package/dist/{chunk-X2U3QJCJ.js → chunk-ZPWZIVI6.js} +1 -1
- package/dist/chunk-ZPWZIVI6.js.map +1 -0
- package/dist/collapsible-panel.d.ts +5 -2
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/css-values.d.ts +75 -0
- package/dist/css-values.js +3 -0
- package/dist/css-values.js.map +1 -0
- package/dist/empty-state.d.ts +2 -1
- package/dist/empty-state.js +1 -1
- package/dist/floating-toolbar.d.ts +4 -3
- package/dist/floating-toolbar.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +26 -25
- package/dist/list-action-row.d.ts +1 -2
- package/dist/list-action-row.js +2 -1
- package/dist/list-header.d.ts +1 -1
- package/dist/list-header.js +2 -1
- package/dist/list-inset-control.d.ts +4 -3
- package/dist/list-inset-control.js +1 -1
- package/dist/list-inset-text.d.ts +4 -3
- package/dist/list-inset-text.js +1 -1
- package/dist/list-item.d.ts +4 -3
- package/dist/list-item.js +2 -1
- package/dist/list.d.ts +10 -8
- package/dist/list.js +2 -1
- package/dist/nav-stack.d.ts +9 -6
- package/dist/nav-stack.js +2 -1
- package/dist/pane.d.ts +6 -5
- package/dist/pane.js +1 -1
- package/dist/resizable-region.d.ts +2 -1
- package/dist/resizable-region.js +1 -1
- package/dist/segmented-control.d.ts +4 -3
- package/dist/segmented-control.js +2 -1
- package/dist/select.d.ts +3 -1
- package/dist/select.js +2 -1
- package/dist/semantic-content-BbzjvSu9.d.ts +14 -0
- package/dist/skeleton.d.ts +7 -6
- package/dist/skeleton.js +2 -1
- package/dist/split-view.d.ts +5 -4
- package/dist/split-view.js +3 -2
- package/dist/split-view.js.map +1 -1
- package/dist/state-banner.d.ts +3 -2
- package/dist/state-banner.js +2 -1
- package/dist/styles/catalog.css +8 -1
- package/dist/styles/collapsible-panel.css +6 -2
- package/dist/styles/foundation.css +44 -0
- package/dist/styles/list-header.css +6 -0
- package/dist/styles/list-item.css +9 -0
- package/dist/styles/nav-stack.css +32 -2
- package/dist/styles/segmented-control.css +8 -1
- package/dist/styles/select.css +2 -1
- package/dist/styles/state-banner.css +14 -0
- package/dist/styles/tab-scaffold.css +1 -0
- package/dist/styles/token-search-field.css +4 -0
- package/dist/styles/toolbar-control-group.css +98 -16
- package/dist/styles/webawesome.css +22 -0
- package/dist/styles/workbench.css +4 -0
- package/dist/sunken-panel.d.ts +4 -3
- package/dist/sunken-panel.js +1 -1
- package/dist/surface-scaffold.d.ts +6 -5
- package/dist/surface-scaffold.js +1 -1
- package/dist/tab-bar.d.ts +6 -5
- package/dist/tab-bar.js +1 -1
- package/dist/tab-scaffold.d.ts +2 -1
- package/dist/tab-scaffold.js.map +1 -1
- package/dist/token-search-field.d.ts +5 -4
- package/dist/token-search-field.js +1 -1
- package/dist/toolbar-control-group.d.ts +10 -4
- package/dist/toolbar-control-group.js +1 -1
- package/dist/toolbar-text.js +2 -1
- package/dist/toolbar.d.ts +6 -5
- package/dist/toolbar.js +1 -1
- package/dist/value-table.d.ts +4 -2
- package/dist/value-table.js +2 -1
- package/dist/wire-nav-stack.d.ts +4 -1
- package/dist/wire-nav-stack.js +125 -0
- package/dist/wire-nav-stack.js.map +1 -1
- package/dist/wire-resizable-regions.js +1 -1
- package/dist/wire-tab-bars.d.ts +1 -0
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/workbench.d.ts +7 -4
- package/dist/workbench.js.map +1 -1
- package/docs/accessibility.md +9 -3
- package/docs/collapsible-panel.md +4 -1
- package/docs/component-contract.md +56 -8
- package/docs/component-selection.md +45 -8
- package/docs/design/templates/list/compact-dark.svg +1 -1
- package/docs/design/templates/list/compact.svg +1 -1
- package/docs/design/templates/list/stack-dark.svg +1 -1
- package/docs/design/templates/list/stack.svg +1 -1
- package/docs/design/templates/list-action-row/default-dark.svg +1 -1
- package/docs/design/templates/list-action-row/default.svg +1 -1
- package/docs/design/templates/list-action-row/selected-dark.svg +1 -1
- package/docs/design/templates/list-action-row/selected.svg +1 -1
- package/docs/design/templates/list-action-row-dark.svg +1 -1
- package/docs/design/templates/list-action-row.svg +1 -1
- package/docs/design/templates/list-dark.svg +1 -1
- package/docs/design/templates/list-item/default-dark.svg +1 -1
- package/docs/design/templates/list-item/default.svg +1 -1
- package/docs/design/templates/list-item/multiline-dark.svg +1 -1
- package/docs/design/templates/list-item/multiline.svg +1 -1
- package/docs/design/templates/list-item/selected-dark.svg +1 -1
- package/docs/design/templates/list-item/selected.svg +1 -1
- package/docs/design/templates/list-item/trailing-dark.svg +1 -1
- package/docs/design/templates/list-item/trailing.svg +1 -1
- package/docs/design/templates/list-item-dark.svg +1 -1
- package/docs/design/templates/list-item.svg +1 -1
- package/docs/design/templates/list.svg +1 -1
- package/docs/design-philosophy.md +4 -2
- package/docs/examples/component-catalog-extension-v2.json +2 -0
- package/docs/layout.md +12 -4
- package/docs/nav-stack.md +29 -8
- package/docs/recipes.md +8 -4
- package/docs/split-view.md +6 -0
- package/docs/surface-scaffold.md +8 -0
- package/docs/tab-scaffold.md +3 -1
- package/docs/type-contracts.md +39 -12
- package/docs/ui-analyzer.md +17 -3
- package/docs/ui-doctor.md +7 -0
- package/docs/ux-demo.md +10 -4
- package/docs/webawesome-theme.md +6 -0
- package/docs/workbench.md +6 -4
- package/llms.txt +46 -6
- package/package.json +5 -1
- package/ux-demo/recipes/compact-toolbar.tsx +10 -9
- package/ux-demo/recipes/composer-form.tsx +6 -3
- package/ux-demo/recipes/loading-inspector.tsx +2 -1
- package/dist/chunk-2NMQW7FX.js.map +0 -1
- package/dist/chunk-4EF2CMYS.js.map +0 -1
- package/dist/chunk-7KEUJIIC.js.map +0 -1
- package/dist/chunk-B3A3IVO5.js.map +0 -1
- package/dist/chunk-FEY65TBV.js.map +0 -1
- package/dist/chunk-GWEAPEZI.js.map +0 -1
- package/dist/chunk-HP2B2L26.js.map +0 -1
- package/dist/chunk-IJBSZ4NX.js.map +0 -1
- package/dist/chunk-J5BFYY7Q.js.map +0 -1
- package/dist/chunk-JFGXQBIP.js.map +0 -1
- package/dist/chunk-JRKSK2HX.js.map +0 -1
- package/dist/chunk-KWWR5VMS.js.map +0 -1
- package/dist/chunk-LPOMRC4C.js.map +0 -1
- package/dist/chunk-OBLTAKSX.js.map +0 -1
- package/dist/chunk-OT6RPYAP.js.map +0 -1
- package/dist/chunk-PX3YSS5C.js.map +0 -1
- package/dist/chunk-QO55FN2Y.js.map +0 -1
- package/dist/chunk-R7ZWUN64.js.map +0 -1
- package/dist/chunk-RKVQEH4J.js.map +0 -1
- package/dist/chunk-SYDMYBPG.js.map +0 -1
- package/dist/chunk-TB6DY7H5.js.map +0 -1
- package/dist/chunk-VCE4MPVE.js.map +0 -1
- package/dist/chunk-W5L2JSBY.js.map +0 -1
- package/dist/chunk-WNWD54GR.js.map +0 -1
- package/dist/chunk-X2U3QJCJ.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 452 512" width="452" height="512"><defs><clipPath id="cp0"><rect x="16" y="38" width="420" height="230"/></clipPath><clipPath id="cp1"><rect x="16" y="306" width="420" height="190"/></clipPath><clipPath id="ct2"><rect x="16" y="16" width="420" height="22"/></clipPath><clipPath id="irc3"><rect x="16" y="38" width="420" height="230" rx="0"/></clipPath><clipPath id="ct5"><rect x="16" y="284" width="420" height="22"/></clipPath><clipPath id="irc6"><rect x="16" y="306" width="420" height="190" rx="0"/></clipPath></defs><rect x="0" y="0" width="452" height="512" rx="0" fill="rgb(255,255,255)"/><text x="16" y="28" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(110,110,115)">Standard gap and four dividers</text><g clip-path="url(#cp0)"><g clip-path="url(#irc3)"><clipPath id="svgimg4vclip"><rect x="16" y="38" width="420" height="230"/></clipPath><g clip-path="url(#svgimg4vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg4cp0"><rect x="37" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="svgimg4ct1"><rect x="37" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="svgimg4ct2"><rect x="126.8" y="31.2" width="21.6" height="21.6"/></clipPath><clipPath id="svgimg4cp3"><rect x="37" y="85" width="18" height="18"/></clipPath><clipPath id="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 452 512" width="452" height="512"><defs><clipPath id="cp0"><rect x="16" y="38" width="420" height="230"/></clipPath><clipPath id="cp1"><rect x="16" y="306" width="420" height="190"/></clipPath><clipPath id="ct2"><rect x="16" y="16" width="420" height="22"/></clipPath><clipPath id="irc3"><rect x="16" y="38" width="420" height="230" rx="0"/></clipPath><clipPath id="ct5"><rect x="16" y="284" width="420" height="22"/></clipPath><clipPath id="irc6"><rect x="16" y="306" width="420" height="190" rx="0"/></clipPath></defs><rect x="0" y="0" width="452" height="512" rx="0" fill="rgb(255,255,255)"/><text x="16" y="28" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(110,110,115)">Standard gap and four dividers</text><g clip-path="url(#cp0)"><g clip-path="url(#irc3)"><clipPath id="svgimg4vclip"><rect x="16" y="38" width="420" height="230"/></clipPath><g clip-path="url(#svgimg4vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg4cp0"><rect x="37" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="svgimg4ct1"><rect x="37" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="svgimg4ct2"><rect x="126.8" y="31.2" width="21.6" height="21.6"/></clipPath><clipPath id="svgimg4cp3"><rect x="28" y="72" width="324" height="44"/></clipPath><clipPath id="svgimg4ov4"><rect x="29" y="73" width="322" height="42" rx="11"/></clipPath><clipPath id="svgimg4cp5"><rect x="37" y="85" width="18" height="18"/></clipPath><clipPath id="svgimg4cp7"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="svgimg4ov8"><rect x="63" y="85" width="272" height="18" rx="0"/></clipPath><clipPath id="svgimg4ct9"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="svgimg4cp10"><rect x="28" y="124" width="324" height="44"/></clipPath><clipPath id="svgimg4ov11"><rect x="29" y="125" width="322" height="42" rx="11"/></clipPath><clipPath id="svgimg4cp12"><rect x="37" y="137" width="18" height="18"/></clipPath><clipPath id="svgimg4cp14"><rect x="63" y="137" width="272" height="18"/></clipPath><clipPath id="svgimg4ov15"><rect x="63" y="137" width="272" height="18" rx="0"/></clipPath><clipPath id="svgimg4ct16"><rect x="63" y="137" width="272" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg4cp0)"><g clip-path="url(#svgimg4ct1)"><text x="37" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(110,110,115)">WORKSPACE</text></g></g><rect x="126.8" y="31.2" width="21.6" height="21.6" rx="10.8" fill="rgb(242,242,247)"/><text x="134.33" y="46" font-family="system-ui, "-apple-system", sans-serif" font-size="10" font-weight="700" fill="rgb(110,110,115)">2</text><g clip-path="url(#svgimg4cp3)"><rect x="28" y="72" width="324" height="44" rx="12" fill="rgb(214,236,255)"/><rect x="28.5" y="72.5" width="323" height="43" rx="11.5" fill="none" stroke="rgb(166,213,255)" stroke-width="1"/><g clip-path="url(#svgimg4ov4)"><g clip-path="url(#svgimg4cp5)"><g color="rgb(29, 29, 31)"><clipPath id="svgimg4svgic6"><rect x="37" y="85" width="18" height="18"/></clipPath><g clip-path="url(#svgimg4svgic6)"><g transform="matrix(.75 0 0 .75 37 85)"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.4-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#svgimg4cp7)"><g clip-path="url(#svgimg4ov8)"><text x="63" y="100" font-family="system-ui, "-apple-system", sans-serif" font-size="16" font-weight="650" fill="rgb(29,29,31)">Inbox</text></g></g></g></g><g clip-path="url(#svgimg4cp10)"><rect x="28.5" y="124.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg4ov11)"><g clip-path="url(#svgimg4cp12)"><g color="rgb(29, 29, 31)"><clipPath id="svgimg4svgic13"><rect x="37" y="137" width="18" height="18"/></clipPath><g clip-path="url(#svgimg4svgic13)"><g transform="matrix(.75 0 0 .75 37 137)"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.7-.9l-.8-1.2A2 2 0 0 0 7.9 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#svgimg4cp14)"><g clip-path="url(#svgimg4ov15)"><text x="63" y="152" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(29,29,31)">Projects</text></g></g></g></g></g></g></g></g><text x="16" y="296" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(110,110,115)">Compact, no gap</text><g clip-path="url(#cp1)"><g clip-path="url(#irc6)"><clipPath id="svgimg7vclip"><rect x="16" y="306" width="420" height="190"/></clipPath><g clip-path="url(#svgimg7vclip)"><g transform="translate(16 306)"><defs><clipPath id="svgimg7cp0"><rect x="28" y="20" width="324" height="44"/></clipPath><clipPath id="svgimg7ov1"><rect x="29" y="21" width="322" height="42" rx="11"/></clipPath><clipPath id="svgimg7cp2"><rect x="37" y="33" width="18" height="18"/></clipPath><clipPath id="svgimg7cp4"><rect x="63" y="33" width="272" height="18"/></clipPath><clipPath id="svgimg7ov5"><rect x="63" y="33" width="272" height="18" rx="0"/></clipPath><clipPath id="svgimg7ct6"><rect x="63" y="33" width="272" height="18"/></clipPath><clipPath id="svgimg7cp7"><rect x="28" y="64" width="324" height="44"/></clipPath><clipPath id="svgimg7ov8"><rect x="29" y="65" width="322" height="42" rx="11"/></clipPath><clipPath id="svgimg7cp9"><rect x="37" y="77" width="18" height="18"/></clipPath><clipPath id="svgimg7cp11"><rect x="63" y="77" width="272" height="18"/></clipPath><clipPath id="svgimg7ov12"><rect x="63" y="77" width="272" height="18" rx="0"/></clipPath><clipPath id="svgimg7ct13"><rect x="63" y="77" width="272" height="18"/></clipPath></defs><g clip-path="url(#svgimg7cp0)"><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg7ov1)"><g clip-path="url(#svgimg7cp2)"><g color="rgb(29, 29, 31)"><clipPath id="svgimg7svgic3"><rect x="37" y="33" width="18" height="18"/></clipPath><g clip-path="url(#svgimg7svgic3)"><g transform="matrix(.75 0 0 .75 37 33)"><path d="M11.5 2.3a.5.5 0 0 1 1 0L14.8 7a2 2 0 0 0 1.6 1l5.1.8a.5.5 0 0 1 .3.9l-3.7 3.6a2 2 0 0 0-.6 2l.9 5a.5.5 0 0 1-.8.6L13 18.6a2 2 0 0 0-2 0L6.4 21a.5.5 0 0 1-.8-.6l1-5a2 2 0 0 0-.7-2L2.2 9.8a.5.5 0 0 1 .3-1l5.1-.7A2 2 0 0 0 9.2 7Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#svgimg7cp4)"><g clip-path="url(#svgimg7ov5)"><text x="63" y="48" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(29,29,31)">Priority</text></g></g></g></g><g clip-path="url(#svgimg7cp7)"><rect x="28.5" y="64.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg7ov8)"><g clip-path="url(#svgimg7cp9)"><g color="rgb(29, 29, 31)"><clipPath id="svgimg7svgic10"><rect x="37" y="77" width="18" height="18"/></clipPath><g clip-path="url(#svgimg7svgic10)"><g transform="matrix(.75 0 0 .75 37 77)"><path d="M3 5z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 12z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 19z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 5h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 12h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 19h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#svgimg7cp11)"><g clip-path="url(#svgimg7ov12)"><text x="63" y="92" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(29,29,31)">All work</text></g></g></g></g></g></g></g></g></svg>
|
|
@@ -88,8 +88,10 @@ Reuse a component when surfaces share its purpose, anatomy, state model, and int
|
|
|
88
88
|
Color, type, spacing, radius, elevation, and motion express semantic roles. Prefer package tokens over raw values in consuming code. State is never communicated by color alone.
|
|
89
89
|
|
|
90
90
|
The default vocabulary is opinionated rather than empty: neutral, brand/info,
|
|
91
|
-
success, warning, and danger provide quiet/normal/loud fills, borders, and
|
|
92
|
-
foregrounds compatible with Hot Sheet 2 and Web Awesome.
|
|
91
|
+
pop, success, warning, and danger provide quiet/normal/loud fills, borders, and
|
|
92
|
+
foregrounds compatible with Hot Sheet 2 and Web Awesome. Pop is vibrant,
|
|
93
|
+
non-status emphasis for featured, novel, or celebratory content; never use it as
|
|
94
|
+
a success, warning, or danger substitute. Consumers may replace
|
|
93
95
|
the global palette, one semantic role, or one component instance through
|
|
94
96
|
documented custom properties without rewriting component CSS.
|
|
95
97
|
|
|
@@ -19,12 +19,14 @@
|
|
|
19
19
|
"zones": [
|
|
20
20
|
{
|
|
21
21
|
"id": "header",
|
|
22
|
+
"jsx": { "prop": "header" },
|
|
22
23
|
"accepts": ["@kerfjs/ui:toolbar"],
|
|
23
24
|
"cardinality": { "min": 1, "max": 1 },
|
|
24
25
|
"exclusiveWith": []
|
|
25
26
|
},
|
|
26
27
|
{
|
|
27
28
|
"id": "facts",
|
|
29
|
+
"jsx": { "prop": "facts" },
|
|
28
30
|
"accepts": ["@kerfjs/ui:value-table"],
|
|
29
31
|
"cardinality": { "min": 1, "max": 1 },
|
|
30
32
|
"exclusiveWith": []
|
package/docs/layout.md
CHANGED
|
@@ -50,10 +50,12 @@ Use `.kui-content-item--pill` for the 22px pill radius expressed as
|
|
|
50
50
|
changing its geometry by setting `--kui-content-item-border` and
|
|
51
51
|
`--kui-content-item-background`.
|
|
52
52
|
|
|
53
|
-
Nested
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
Nested selection and hover highlights stay concentric and match their owning
|
|
54
|
+
control's shape. Their inner radius is the outer radius minus the full inset,
|
|
55
|
+
expressed by the shared `--kui-layout-highlight-inset` token (2px by default).
|
|
56
|
+
For example, `SegmentedControl` and `ToolbarControlGroup` place each highlight
|
|
57
|
+
behind a 1px control border and 1px control padding, so a rounded control's 12px
|
|
58
|
+
outer radius produces a 10px highlight radius; a 22px pill produces 20px.
|
|
57
59
|
|
|
58
60
|
A visible parent surface does not make every child another visible card. The
|
|
59
61
|
composer recipe keeps its form as the single surface, uses a heading `Toolbar` for
|
|
@@ -110,6 +112,12 @@ The two relationships that get confused most are 8px vs 24px: 8px is _inside_ a
|
|
|
110
112
|
group, 24px is _between_ major, differing regions. 16px sits between them for
|
|
111
113
|
same-kind groups.
|
|
112
114
|
|
|
115
|
+
For `List.gap`, pass these token names directly (`gap="xs"`, `gap="m"`) or use
|
|
116
|
+
`space('xs')` from `@kerfjs/ui/css-values` when composing a value in JavaScript.
|
|
117
|
+
Use `rem`, `em`, `px`, `pct`, `lengthVar`, and `calc(plus(...))` only when a
|
|
118
|
+
named spacing relationship does not express the requirement; do not pass raw
|
|
119
|
+
CSS strings.
|
|
120
|
+
|
|
113
121
|
`--kui-space-s` (12px) and `--kui-space-xl` (32px) exist but are **off the
|
|
114
122
|
canonical rhythm** — reach for them only as a deliberate exception, never as a
|
|
115
123
|
default step. Prefer the five canonical tokens so spacing stays legible and
|
package/docs/nav-stack.md
CHANGED
|
@@ -21,7 +21,12 @@ stack as a `signal<NavStackView[]>`, `NavStack({ views })` renders it, and
|
|
|
21
21
|
|
|
22
22
|
```tsx
|
|
23
23
|
const views = signal<NavStackView[]>([
|
|
24
|
-
{
|
|
24
|
+
{
|
|
25
|
+
key: "inbox",
|
|
26
|
+
title: "Inbox",
|
|
27
|
+
content: <InboxView />,
|
|
28
|
+
bottomToolbar: <InboxStatus />,
|
|
29
|
+
},
|
|
25
30
|
]);
|
|
26
31
|
|
|
27
32
|
// render inside mount():
|
|
@@ -42,15 +47,31 @@ views.value = [
|
|
|
42
47
|
```
|
|
43
48
|
|
|
44
49
|
`NavStack` renders every entry stacked, the last one active and the rest kept
|
|
45
|
-
mounted (so their DOM state
|
|
46
|
-
`key` (stable identity), `content`, an optional `title`,
|
|
47
|
-
`toolbar` actions
|
|
48
|
-
|
|
50
|
+
mounted (so their DOM state survives) but hidden. Each entry carries a
|
|
51
|
+
`key` (stable identity), `content`, an optional `title`, optional per-view
|
|
52
|
+
`toolbar` actions, and an optional per-view `bottomToolbar`. The component-level
|
|
53
|
+
`bottomToolbar` remains a persistent fallback for views that do not provide one.
|
|
54
|
+
The back control appears automatically once the stack has more than one entry;
|
|
55
|
+
`wireNavStack`'s `onBack` is where the app pops its own signal.
|
|
56
|
+
|
|
57
|
+
Focus follows the controlled stack automatically. On push, `wireNavStack`
|
|
58
|
+
remembers the focused descendant of the departing view and moves focus into the
|
|
59
|
+
new top view. On pop it restores that exact descendant when it still exists. A
|
|
60
|
+
new view prefers a descendant marked `data-nav-focus`, then its first enabled
|
|
61
|
+
focusable descendant, and finally the view container itself. Use
|
|
62
|
+
`data-nav-focus` for a heading or primary control when DOM order is not the best
|
|
63
|
+
initial reading position; it may use `tabindex="-1"` for programmatic focus.
|
|
64
|
+
When a remembered control was removed during the controlled rerender, the same
|
|
65
|
+
fallback order applies. Disposing the helper stops future transitions and
|
|
66
|
+
cleans up any temporary fallback `tabindex` it added.
|
|
49
67
|
|
|
50
68
|
## Transitions
|
|
51
69
|
|
|
52
70
|
`wireNavStack(root, { onBack, duration? })` observes the rendered stack and
|
|
53
71
|
animates each change: a pushed view slides in from the trailing edge; a popped
|
|
54
|
-
view slides back off it over the revealed view
|
|
55
|
-
|
|
56
|
-
|
|
72
|
+
view slides back off it over the revealed view; and snapshots of the previous
|
|
73
|
+
top and bottom chrome cross-fade into the active view's chrome. Focus moves to
|
|
74
|
+
the new top view independently of animation duration. It returns a disposer.
|
|
75
|
+
The animation honors `prefers-reduced-motion` (transitions collapse to instant)
|
|
76
|
+
and `duration: 0` disables it. Applicable at every device size and inside
|
|
77
|
+
dialogs.
|
package/docs/recipes.md
CHANGED
|
@@ -81,8 +81,10 @@ Do not rebuild the dialog or reach into private shadow parts.
|
|
|
81
81
|
[Open the recipe](../ux-demo/?component=recipe-composer-form) · [TSX source](../ux-demo/recipes/composer-form.tsx)
|
|
82
82
|
|
|
83
83
|
A direct `ToolbarText` supplies the task title, with app-owned supporting copy
|
|
84
|
-
below; their ids are referenced by the form.
|
|
85
|
-
|
|
84
|
+
below; their ids are referenced by the form. `ListInsetText` gives that bare
|
|
85
|
+
supporting copy the same content-item text inset as the fields instead of
|
|
86
|
+
duplicating its geometry in recipe CSS. Production fields own labels, help, and
|
|
87
|
+
native focus. The field
|
|
86
88
|
and footer control edges sit directly on the shared 8px inline gutter rather
|
|
87
89
|
than acquiring a second content-item padding inset; major children remain 24px
|
|
88
90
|
apart and related controls use 8px gaps. The app owns
|
|
@@ -107,8 +109,10 @@ rows.
|
|
|
107
109
|
|
|
108
110
|
Use `ToolbarControlGroup` for related commands, `SegmentedControl` for a few
|
|
109
111
|
visible exclusive choices, `Select` for a longer value list, and an ordinary
|
|
110
|
-
button for an independent command.
|
|
111
|
-
|
|
112
|
+
button for an independent command. Even that independent button sits in a
|
|
113
|
+
single-control `ToolbarControlGroup`, which keeps its height, pill shape, focus,
|
|
114
|
+
and hover treatment aligned with the adjacent toolbar controls. The app owns
|
|
115
|
+
values, actions, persistence, and responsive priority.
|
|
112
116
|
|
|
113
117
|
## Navigation stack
|
|
114
118
|
|
package/docs/split-view.md
CHANGED
|
@@ -45,5 +45,11 @@ const selected = signal<string | null>(null);
|
|
|
45
45
|
app's selection). This is the portrait-tablet / handset presentation; as a
|
|
46
46
|
dialog the compact form is a full-screen or large partial-cover modal.
|
|
47
47
|
|
|
48
|
+
The catalog's **Interactive compact drill-down** example exercises this exact
|
|
49
|
+
controlled flow: a list action sets the selected message, `detailActive` pushes
|
|
50
|
+
its detail, and the wired Back action clears the selection to reveal the
|
|
51
|
+
preserved list. Use the same structure in application demos so compact examples
|
|
52
|
+
show the interaction rather than rendering a disconnected detail state.
|
|
53
|
+
|
|
48
54
|
Compose the interactive wiring from the existing helpers — `SplitView` adds no
|
|
49
55
|
wire of its own.
|
package/docs/surface-scaffold.md
CHANGED
|
@@ -10,6 +10,14 @@ Wrap one `wa-dialog` with `DialogSurface`. Choose `size` (`small`, `medium`, or
|
|
|
10
10
|
`bodyInset` / `footerInset` (`none`, `compact`, or `comfortable`). The defaults
|
|
11
11
|
match Kerf's medium modal, 8px body, and 16px footer rhythm.
|
|
12
12
|
|
|
13
|
+
Treat a dialog body as a `List` by default. When its rows or sections own their
|
|
14
|
+
standard list geometry, set `bodyInset="none"` so the dialog does not add a
|
|
15
|
+
second inset. Bare prose is still a list child: wrap it in `ListInsetText` so its
|
|
16
|
+
text edge receives the standard 8px margin + 1px transparent border + 8px
|
|
17
|
+
padding and aligns with bordered siblings. Reserve `compact` or `comfortable`
|
|
18
|
+
body insets for exceptional content that does not already have list/content-item
|
|
19
|
+
geometry.
|
|
20
|
+
|
|
13
21
|
Wrap one `wa-dropdown` with `PopupSurface`. `inset="list-zero"` removes menu
|
|
14
22
|
padding for a child that already owns row insets, `compact` uses 4px, and
|
|
15
23
|
`standard` uses the shared 8px surface inset. Keep the dropdown trigger named and
|
package/docs/tab-scaffold.md
CHANGED
|
@@ -46,5 +46,7 @@ const dispose = wireTabScaffold(root, {
|
|
|
46
46
|
|
|
47
47
|
Each `TabScaffoldTab` has an `id`, `label`, optional `icon`, and `content`. The
|
|
48
48
|
bottom bar respects the home-indicator safe area (`env(safe-area-inset-bottom)`)
|
|
49
|
-
and keeps 44px targets.
|
|
49
|
+
and keeps 44px targets. Its single-line labels preserve their full line box and
|
|
50
|
+
truncate horizontally with an ellipsis when a destination name exceeds its
|
|
51
|
+
share of the bar. On larger device classes, promote the tab set to a
|
|
50
52
|
`Workbench` rail or a persistent sidebar instead of a bottom bar.
|
package/docs/type-contracts.md
CHANGED
|
@@ -11,18 +11,37 @@ public-signature artifact.
|
|
|
11
11
|
|
|
12
12
|
## Strengthened contracts
|
|
13
13
|
|
|
14
|
-
| ID | Compile-time guarantee
|
|
15
|
-
| ---------- |
|
|
16
|
-
| `KUI-T001` | `ListHeader` is a passive heading, a fully named/icon-bearing trailing action, or a controlled disclosure with `action` + `expanded`. Props ignored by the selected mode are rejected.
|
|
17
|
-
| `KUI-T002` | `Select` has a visible `label` or an `ariaLabel`.
|
|
18
|
-
| `KUI-T003` | A literal `Select.value` belongs to its literal `choices`.
|
|
19
|
-
| `KUI-T004` | A literal `SegmentedControl.value` belongs to its literal `choices`.
|
|
20
|
-
| `KUI-T005` | `expanded`, `expandAction`, and `expandLabel` exist only on `TokenSearchField({ collapsible: true })`.
|
|
21
|
-
| `KUI-T006` | `TokenSearchEditorAttributes` accepts application `data-*` metadata but rejects component-owned identity, morph, count, and placeholder attributes.
|
|
22
|
-
| `KUI-T007` | `ToolbarText.maxLines` requires `wrap: true`; it is never silently ignored in typed code.
|
|
23
|
-
| `KUI-T008` | A literal `TabScaffold.active` id belongs to its literal `tabs`.
|
|
24
|
-
| `KUI-T009` | Adjacent-token keyboard removal requires `onRemoveToken`; disabling removal rejects the now-meaningless callback.
|
|
25
|
-
| `KUI-T010` | Finite public variants have named exported union types, including divider sides, tab activation, banner urgency, and all AppTab, TabBar, ToolbarControlGroup, and Select presentation axes; the convenience root barrel re-exports them.
|
|
14
|
+
| ID | Compile-time guarantee |
|
|
15
|
+
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
16
|
+
| `KUI-T001` | `ListHeader` is a passive heading, a fully named/icon-bearing trailing action, or a controlled disclosure with `action` + `expanded`. Props ignored by the selected mode are rejected. |
|
|
17
|
+
| `KUI-T002` | `Select` has a visible `label` or an `ariaLabel`. |
|
|
18
|
+
| `KUI-T003` | A literal `Select.value` belongs to its literal `choices`. |
|
|
19
|
+
| `KUI-T004` | A literal `SegmentedControl.value` belongs to its literal `choices`. |
|
|
20
|
+
| `KUI-T005` | `expanded`, `expandAction`, and `expandLabel` exist only on `TokenSearchField({ collapsible: true })`. |
|
|
21
|
+
| `KUI-T006` | `TokenSearchEditorAttributes` accepts application `data-*` metadata but rejects component-owned identity, morph, count, and placeholder attributes. |
|
|
22
|
+
| `KUI-T007` | `ToolbarText.maxLines` requires `wrap: true`; it is never silently ignored in typed code. |
|
|
23
|
+
| `KUI-T008` | A literal `TabScaffold.active` id belongs to its literal `tabs`. |
|
|
24
|
+
| `KUI-T009` | Adjacent-token keyboard removal requires `onRemoveToken`; disabling removal rejects the now-meaningless callback. |
|
|
25
|
+
| `KUI-T010` | Finite public variants have named exported union types, including divider sides, tab activation, banner urgency, and all AppTab, TabBar, ToolbarControlGroup, and Select presentation axes; the convenience root barrel re-exports them. |
|
|
26
|
+
| `KUI-T011` | Semantic component zones use the recursive `KerfUiContent` type: `SafeHtml`, runtime-empty booleans/nullish values, and readonly nested arrays are valid; arbitrary strings, numbers, and signals are rejected. Explicit text positions such as `ListInsetText` retain their text exception. |
|
|
27
|
+
| `KUI-T012` | `List.gap` accepts finite `UiSpaceName` shorthands or a complete branded `CssLength`; raw strings and non-standalone `CssLengthExpression` arithmetic are rejected. `calc(plus(...))` promotes a typed expression to a complete value. |
|
|
28
|
+
| `KUI-T013` | CSS-valued props preserve property grammar: `List.flex` uses `CssFlex`, `Skeleton` dimensions use `CssSize`/`CssLength`, and choice icons use `CssColor`; row declaration strings are absent. |
|
|
29
|
+
|
|
30
|
+
`KerfUiContent` lets conditionals and mapped component collections be direct
|
|
31
|
+
siblings without an otherwise-unnecessary `Fragment`:
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
<List>
|
|
35
|
+
{intro ? <ListInsetText>{intro}</ListInsetText> : null}
|
|
36
|
+
{rows.map((row) => (
|
|
37
|
+
<ListItem label={row.label} />
|
|
38
|
+
))}
|
|
39
|
+
</List>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The type is intentionally narrower than core JSX children. Wrap prose in a
|
|
43
|
+
semantic text component, and read signals into components or structural
|
|
44
|
+
conditionals rather than passing signal objects as content.
|
|
26
45
|
|
|
27
46
|
Literal identity inference is intentionally additive for dynamic applications.
|
|
28
47
|
When choices or ids arrive at runtime and the state signal is correctly typed as
|
|
@@ -95,6 +114,14 @@ move errors into casts without making the integration safer.
|
|
|
95
114
|
- Replace `Toolbar({ divider: false })` with `dividerSides: ''`; the default
|
|
96
115
|
remains a bottom divider, while canonical combinations such as `tr` and
|
|
97
116
|
`trbl` select more physical edges.
|
|
117
|
+
- Replace raw `List.gap` strings with a direct spacing shorthand (`"xs"`,
|
|
118
|
+
`"m"`) or a complete value from `@kerfjs/ui/css-values`. Replace
|
|
119
|
+
`gap="0.25rem"` with `gap={rem(0.25)}` and wrap sums with `calc(plus(...))`.
|
|
120
|
+
- Replace raw `List.flex` shorthands with `flex(grow, shrink, basis)` or a finite
|
|
121
|
+
keyword; replace raw Skeleton dimensions with `px`/`rem`/`em`/`pct` builders;
|
|
122
|
+
and replace raw choice colors with `uiColor()` or `colorVar()`.
|
|
123
|
+
- Remove `style` from `ListItem` and `ListActionRow`; use `className`, public
|
|
124
|
+
tokens, and cataloged props. These breaking cleanups land before 5.0 stable.
|
|
98
125
|
|
|
99
126
|
JavaScript runtime behavior remains defensive for previously emitted calls, but
|
|
100
127
|
new TypeScript builds report these invalid or ignored combinations.
|
package/docs/ui-analyzer.md
CHANGED
|
@@ -13,8 +13,9 @@ npx kerf-ui-analyze --root . --format sarif --output artifacts/kerf-ui.sarif
|
|
|
13
13
|
The analyzer is opt-in. Add a project script such as
|
|
14
14
|
`"check:kerf-ui-layout": "kerf-ui-analyze --root . src"`; it never executes
|
|
15
15
|
application code. It discovers `.kerf-ui-profile.json`, joins every declared
|
|
16
|
-
composition catalog by `package:id`, parses literal
|
|
17
|
-
and reports portable repository-relative
|
|
16
|
+
composition catalog by `package:id`, parses literal JavaScript/TypeScript
|
|
17
|
+
component calls, TSX/JSX, and CSS, and reports portable repository-relative
|
|
18
|
+
locations.
|
|
18
19
|
|
|
19
20
|
Analysis is scoped per source file. Each TSX/JSX file resolves package,
|
|
20
21
|
workspace, and parent-to-child directory profiles from its own location, then
|
|
@@ -49,6 +50,11 @@ policy, or analysis inputs to the containing application.
|
|
|
49
50
|
| `KUI-L010` | error | A selector reaches a private Kerf descendant from a public root. |
|
|
50
51
|
| `KUI-L011` | error | A `::part()` target is not cataloged as a public extension point. |
|
|
51
52
|
| `KUI-L012` | error | CSS assigns a Kerf token without a public configuration contract. |
|
|
53
|
+
| `KUI-L013` | error | A CSS-adjacent prop uses an unknown shorthand or raw literal. |
|
|
54
|
+
| `KUI-L014` | error | A typed helper produces the wrong property grammar. |
|
|
55
|
+
| `KUI-L015` | error | An expression-only helper is passed without a composer. |
|
|
56
|
+
| `KUI-L016` | error | A removed declaration-list escape hatch is used. |
|
|
57
|
+
| `KUI-L017` | review | A valid but exceptional off-scale shorthand needs justification. |
|
|
52
58
|
|
|
53
59
|
Errors are provable contract violations and make the command exit 1. Review
|
|
54
60
|
findings are deliberately heuristic and do not fail by default; pass
|
|
@@ -70,6 +76,13 @@ Parent-owned placement and selectors for application-owned content remain
|
|
|
70
76
|
allowed because the analyzer only reserves `.kui-*`, `--kui-*`, and cataloged
|
|
71
77
|
shadow boundaries.
|
|
72
78
|
|
|
79
|
+
Catalog entries may also publish `cssValueProps`. Each path names its grammar,
|
|
80
|
+
finite shorthands, canonical and exceptional scale steps, accepted typed
|
|
81
|
+
helpers, expression-only helpers, raw escape policy, and examples. The analyzer
|
|
82
|
+
uses that same metadata for direct component calls and JSX, including nested
|
|
83
|
+
paths such as `choices[].color`; consumer catalogs receive identical checks.
|
|
84
|
+
Dynamic values remain a type-system responsibility rather than being guessed.
|
|
85
|
+
|
|
73
86
|
The JSON report schema is exported as
|
|
74
87
|
`@kerfjs/ui/analyzer/report.schema.json`.
|
|
75
88
|
|
|
@@ -100,5 +113,6 @@ validator.
|
|
|
100
113
|
|
|
101
114
|
Review findings remain visible until explicitly suppressed. Avoid suppressing
|
|
102
115
|
`KUI-L001`, `KUI-L002`, `KUI-L003`, `KUI-L007`, `KUI-L009`, `KUI-L010`,
|
|
103
|
-
`KUI-L011`,
|
|
116
|
+
`KUI-L011`, `KUI-L012`, `KUI-L013`, `KUI-L014`, `KUI-L015`, or `KUI-L016`:
|
|
117
|
+
those indicate a
|
|
104
118
|
definite boundary or parsing failure rather than an aesthetic judgment.
|
package/docs/ui-doctor.md
CHANGED
|
@@ -17,6 +17,13 @@ The catalog stage discovers the package-default application UI profile and works
|
|
|
17
17
|
|
|
18
18
|
TypeScript uses the compiler API with `noEmit`. ESLint loads the installed `eslint-plugin-kerfjs` `recommended-ui` preset (`--eslint strict-ui` opts into advisory rules as errors). This is deliberately an isolated Kerf lint pass rather than the consumer's complete ESLint configuration. For each file, the doctor projects the applicable core ESLint rules and `linterOptions` from the consumer configuration so core-rule suppression directives retain the same used/unused semantics as the application's normal lint command. Consumer plugin rules are not executed, and inline directives for plugins such as `@typescript-eslint` therefore do not produce false "rule definition not found" diagnostics; the consumer's normal ESLint command remains authoritative for those rules. Unknown `kerfjs/*` directives still fail the doctor pass. Stable KUI identifiers come from the packaged `application-ui-diagnostic-ids-v1.json` registry; the doctor also reads installed ESLint message metadata for semantic conflict detection instead of duplicating rule definitions. The analyzer calls the public `@kerfjs/ui/analyzer` contract. None of these stages executes generated application code.
|
|
19
19
|
|
|
20
|
+
Property-specific CSS values are evaluated from each first- or third-party
|
|
21
|
+
catalog entry's `cssValueProps`. `KUI-L013`–`KUI-L016` are blocking grammar
|
|
22
|
+
violations and name a preferred shorthand/helper; `KUI-L017` keeps an
|
|
23
|
+
exceptional but valid spacing choice in the review queue. The ESLint and
|
|
24
|
+
analyzer stages share these ids, so the normalized report can be consumed as
|
|
25
|
+
one repair loop without tool-specific translations.
|
|
26
|
+
|
|
20
27
|
The browser evaluator is different: it runs the application and is disabled by default. It only runs when configuration supplies `browser.url` or the command receives `--browser-url`. Start and authorize the target application separately.
|
|
21
28
|
|
|
22
29
|
An unavailable or failed stage does not prevent independent stages from reporting. Its final exit is still a configuration failure, so a partial run cannot appear clean.
|
package/docs/ux-demo.md
CHANGED
|
@@ -8,7 +8,7 @@ deterministic state, and semantic layout owners from the [recipe guide](./recipe
|
|
|
8
8
|
|
|
9
9
|
- It imports public component subpaths, exercising their browser-selected reachable CSS rather than a catalog-only style path.
|
|
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
|
-
- The `AppTab`
|
|
11
|
+
- The `AppTab` and `TabBar` routes are focused component specimens: AppTab shows its selected, compact, segmented, icon-only, truncation, placeholder, metadata, and close-icon axes inside the required tablist context; TabBar shows its rail, segmented, inspector, allocation, placement, and accessory-zone axes without application readouts. The separate `Application tabs composition` route demonstrates controlled selection, matching panel content, overflow, adding, closing, keyboard/pointer reordering, and application-owned ordering. 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
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/<public-subpath>.tsx` from their canonical `delivery.browserImport` or opt-in `delivery.moduleImport`.
|
|
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.
|
|
@@ -19,12 +19,18 @@ deterministic state, and semantic layout owners from the [recipe guide](./recipe
|
|
|
19
19
|
- Catalog-only brand marks, preview dimensions, checkerboard tiles, and the compound display-settings control retain local geometry because they are specimen chrome or intrinsic control anatomy rather than reusable application spacing roles.
|
|
20
20
|
- The menu composition route demonstrates toolbar/content/footer anatomy, 24px major gaps, 8/1/8 child geometry, the full-width `ListHeader` count-or-badge/action split, logical-end 44px action targets with 18px visuals, and 44px row/header/toolbar targets. Its one chevron is a production 18px `DisclosureArrow` inside a controlled Tools header that actually reveals and hides content; ordinary Projects navigation has no false disclosure affordance. Browser assertions cover stable naming, expanded/content transitions, visual rotation, node identity, reduced motion, RTL alignment and containment, and wide, narrow, dark, and 200% layouts. The focused ListHeader route separately shows the shared neutral count pill for Attachments, Notes (including zero), and Duplicates plus a non-count legacy badge, full-width logical-end actions, and no disclosure without content.
|
|
21
21
|
- The `DisclosureArrow` route renders the production 18px root-scaled default without a catalog-only size override. Its two native buttons independently control the default right-to-down chevron and a recognizable right-facing replacement arrow with left-to-up custom directions; both use shortest-path rotation and their names stay stable while `aria-expanded` communicates state. Browser coverage verifies the custom clockwise path, pointer and native keyboard activation, focus, narrow and 200%-zoom stacking with contained labels, consumer sizing, and the independent `.5` Web Awesome glyph scale retained by Kerf `Select`.
|
|
22
|
-
- A detail with relationships renders one
|
|
22
|
+
- A detail with relationships renders one content-fitted `Components` footer selector: `Uses` links to direct dependencies and `Used by` links to reverse dependents. Its popup owns the standard surface inset so headings and even long component names stay clear of the menu border. Choosing either navigates to that component's demo. The relationship group is absent when both sets are empty; no duplicate summary is rendered.
|
|
23
23
|
- Demo-only CSS supplies only the catalog shell and stages; component appearance stays in package CSS. Decorative chrome and Web Awesome controls share the same semantic system palette instead of carrying a separate demo identity.
|
|
24
|
-
- Scenarios use deterministic data and cover real variants, long content, disabled state, selection, progress, feedback, overlays, media, helpers, and stateful interactions. The Web Awesome theme route remains the broad system view, while individual action, form, layout, navigation, feedback, media, and helper routes provide focused specimens; ListItem and ListHeader demonstrate typed domain metadata, protected native button/disclosure semantics, and a native popover trigger relationship without product props; the Headers composition demonstrates direct toolbar headings with an extra-large title, optional supporting copy, and grouped icon/actions; the Select route verifies that option icons survive unrelated Kerf rerenders and selected slot content follows value changes; the Animation route exposes preset, easing, duration, playback-rate, and transport controls with live lifecycle status; observer routes provide user-driven intersection, mutation, and resize events with live results; ToolbarControlGroup exposes all eight Hot Sheet 2 variants, loads the Web Awesome registrations needed by its popup specimen, and preserves the upgraded dropdown's managed light-DOM children across Kerf rerenders; the Toolbar route composes a collapsible TokenSearchField inside a group, animates between the empty iconic and complete field states, stays open while populated, and focuses the revealed editor; SegmentedControl covers toolbar, rounded-rectangle, pill, equal-width, and disabled presentations; TokenSearchField covers editable ordered chips, pointer and keyboard removal, caret-preserving controlled deletion, editing, clearing, free text, disabled state, and fixed first-line alignment while content wraps; StateBanner exposes every built-in tone with tone-tinted badges plus a scoped override;
|
|
24
|
+
- Scenarios use deterministic data and cover real variants, long content, disabled state, selection, progress, feedback, overlays, media, helpers, and stateful interactions. The Web Awesome theme route remains the broad system view, while individual action, form, layout, navigation, feedback, media, and helper routes provide focused specimens; ListItem and ListHeader demonstrate typed domain metadata, protected native button/disclosure semantics, and a native popover trigger relationship without product props; the Headers composition demonstrates direct toolbar headings with an extra-large title, optional supporting copy, and grouped icon/actions; the Select route verifies that option icons survive unrelated Kerf rerenders and selected slot content follows value changes; the Animation route exposes preset, easing, duration, playback-rate, and transport controls with live lifecycle status; observer routes provide user-driven intersection, mutation, and resize events with live results; ToolbarControlGroup exposes all eight Hot Sheet 2 variants, loads the Web Awesome registrations needed by its popup specimen, and preserves the upgraded dropdown's managed light-DOM children across Kerf rerenders; the Toolbar route composes a collapsible TokenSearchField inside a group, animates between the empty iconic and complete field states, stays open while populated, and focuses the revealed editor; SegmentedControl covers toolbar, rounded-rectangle, pill, equal-width, and disabled presentations; TokenSearchField covers editable ordered chips, pointer and keyboard removal, caret-preserving controlled deletion, editing, clearing, free text, disabled state, and fixed first-line alignment while content wraps; StateBanner exposes every built-in tone with tone-tinted badges plus a scoped override; the Application tabs composition demonstrates overflow, edge autoscroll, and controlled pointer/keyboard reordering.
|
|
25
25
|
- The ToolbarControlGroup route also demonstrates the public compact/tight,
|
|
26
26
|
mixed-content, filled-selection, nested-dropdown, and avatar/scrim contracts
|
|
27
|
-
added for consumers that previously restyled group descendants.
|
|
27
|
+
added for consumers that previously restyled group descendants. The compact
|
|
28
|
+
mixed specimen keeps its separator, trigger label, and caret inside both pill
|
|
29
|
+
and rounded group shapes. Avatar images are chrome rather than nested `img`
|
|
30
|
+
elements: a lone avatar paints the group, while a multi-button avatar group
|
|
31
|
+
paints only the pressed selection, with contain fitting in both cases. Its
|
|
32
|
+
collapsible-search specimen follows the selected group shape with a
|
|
33
|
+
concentric inner radius in both collapsed and expanded states.
|
|
28
34
|
- Recipe ownership notes are hidden by default. A page-toolbar toggle reveals them as floating warning-toned notes with a folded corner, keeping instructional copy visually distinct and removable from the specimen flow.
|
|
29
35
|
- Settings exercise light/dark, increased contrast, and reduced motion without changing component code. The theme action starts from the operating system's effective color scheme, always names the appearance it will switch to, and installs an explicit light or dark override when activated; contrast and reduced motion expose their independent preferences through `aria-pressed`.
|
|
30
36
|
- The footer action log is an `aria-live` region, making interactions visible to both people and browser tests.
|
package/docs/webawesome-theme.md
CHANGED
|
@@ -103,6 +103,12 @@ tiers:
|
|
|
103
103
|
content stays compact and the action group has a clearer boundary. These two
|
|
104
104
|
parts do not inherit the dialog's shared `--spacing` value.
|
|
105
105
|
|
|
106
|
+
Add `class="hide-actions"` to a `wa-dialog` when the dialog supplies its own
|
|
107
|
+
dismissal affordance and should omit Web Awesome's header action region. The
|
|
108
|
+
theme sets `display: none` on the directly exported `header-actions` part; it
|
|
109
|
+
does not attempt to chain `::part()` through the internal `dialog` and `header`
|
|
110
|
+
parts, which CSS shadow parts do not support.
|
|
111
|
+
|
|
106
112
|
Badge remains intentionally compact at Web Awesome's intrinsic `0.375em` block /
|
|
107
113
|
`0.625em` inline padding (4.5px / 7.5px at its default 12px text size): it is a
|
|
108
114
|
short status or count, not a content item. Breadcrumb has no bordered or filled
|
package/docs/workbench.md
CHANGED
|
@@ -115,7 +115,9 @@ attributes or descendant tags as styling contracts.
|
|
|
115
115
|
Collapsing snaps the panel's flex track to zero in a single reflow (so the work
|
|
116
116
|
area relayouts once, not per frame) while the panel's fixed-size content slides
|
|
117
117
|
out via a composited `transform` — a rail slides horizontally, the drawer
|
|
118
|
-
vertically — clipped by the shell's overflow.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
118
|
+
vertically — clipped by the shell's overflow. The drawer content is positioned
|
|
119
|
+
against the shell's stable bottom edge, so opening and closing move monotonically
|
|
120
|
+
through the transform rather than inheriting a changing normal-flow origin. It
|
|
121
|
+
honors `prefers-reduced-motion` (the slide collapses to instant). On smaller
|
|
122
|
+
device classes, present the rails' contents through a `NavStack` or overlay
|
|
123
|
+
drawers rather than shrinking the three-panel shell.
|
package/llms.txt
CHANGED
|
@@ -45,6 +45,17 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
45
45
|
child; synchronous hosts use [application-ui-profile-sync.cjs](./ai/application-ui-profile-sync.cjs).
|
|
46
46
|
See the
|
|
47
47
|
[workspace profile example](./docs/examples/application-ui-profile.json).
|
|
48
|
+
A zone's optional `jsx.prop` is its only authoritative JSX binding; never
|
|
49
|
+
infer one from the zone id. Use `children` for one homogeneous primary
|
|
50
|
+
region and explicit named content prop slots for semantic positions or
|
|
51
|
+
replacement content. These slots use the recursive `KerfUiContent` type:
|
|
52
|
+
`SafeHtml`, runtime-empty boolean/nullish values, and readonly nested arrays.
|
|
53
|
+
Put conditionals and mapped component arrays directly in them; do not add a
|
|
54
|
+
`Fragment` only to satisfy types. Arbitrary strings, numbers, and signals are
|
|
55
|
+
rejected unless a component explicitly exposes a text position such as
|
|
56
|
+
`ListInsetText`. These are typed props, not native `<slot>` elements,
|
|
57
|
+
wrapper slot components, or a generic `slots` object. Leave unresolved
|
|
58
|
+
dynamic expressions unknown.
|
|
48
59
|
4. **When authoring a component gallery**, load
|
|
49
60
|
[catalog-authoring.json](./ai/catalog-authoring.json), then follow its
|
|
50
61
|
authoritative [Catalog demo authoring contract](./docs/catalog.md#catalog-demo-authoring-contract).
|
|
@@ -52,6 +63,8 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
52
63
|
6. **Before calling an integration complete**, run
|
|
53
64
|
[`kerf-ui-doctor`](./docs/ui-doctor.md). Its portable JSON report merges
|
|
54
65
|
profile/catalog, TypeScript, Kerf ESLint, and static analyzer diagnostics;
|
|
66
|
+
CSS-adjacent component props are checked from catalog `cssValueProps`, so
|
|
67
|
+
prefer its canonical shorthand or typed helper over raw CSS strings;
|
|
55
68
|
repair source-located errors until exit 0. Use full mode for release gates;
|
|
56
69
|
generated `dist`/`coverage`, dependency, cache, evidence, and nested-worktree
|
|
57
70
|
directories are excluded consistently from every static stage.
|
|
@@ -79,9 +92,14 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
79
92
|
container padding on top of a content-item's own margin — pick one owner. Use
|
|
80
93
|
`.kui-content` for 24px major vertical rhythm.
|
|
81
94
|
- **Use `List` for vertical layout.** It supplies a stretch-aligned column plus
|
|
82
|
-
optional
|
|
95
|
+
optional typed `gap`, `flex`, vertical scrolling, and canonical
|
|
83
96
|
`dividerSides` (`t`/`r`/`b`/`l` order). It adds no list semantics; children own
|
|
84
|
-
those, and only one bounded region should own scrolling.
|
|
97
|
+
those, and only one bounded region should own scrolling. Pass a finite spacing
|
|
98
|
+
shorthand (`gap="xs"`, `gap="m"`) or a complete `CssLength` from the CSS-free
|
|
99
|
+
`@kerfjs/ui/css-values` builders; raw CSS strings are rejected. Use `flex()`
|
|
100
|
+
for List flex, typed lengths for Skeleton geometry, and
|
|
101
|
+
`uiColor()`/`colorVar()` for choice-icon colors. These brands are intentionally
|
|
102
|
+
not interchangeable; rows use classes/tokens/props rather than raw `style`.
|
|
85
103
|
- **Keep Web Awesome on the shared inset tiers.** `webawesome.css` uses
|
|
86
104
|
`--kui-wa-control-inset` (8px controls/items) and
|
|
87
105
|
`--kui-wa-surface-margin` / `--kui-wa-surface-inset` (8px around/inside
|
|
@@ -90,6 +108,9 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
90
108
|
the surface (8px) and container (16px) tiers respectively, independent of the
|
|
91
109
|
dialog's shared `--spacing`. Override the tier at the narrowest useful scope
|
|
92
110
|
instead of restyling individual shadow parts.
|
|
111
|
+
When a dialog provides another dismissal affordance, add `hide-actions` to
|
|
112
|
+
the `wa-dialog` host; the theme hides its directly exported `header-actions`
|
|
113
|
+
part without an unsupported chained `::part()` selector.
|
|
93
114
|
Checkbox and Radio Group option regions also receive the shared 8px inline
|
|
94
115
|
outer inset because those groups have no bordered field shell. The Color
|
|
95
116
|
Picker trigger receives the same inset for the same unbordered geometry.
|
|
@@ -117,7 +138,9 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
117
138
|
need a Web Awesome feature, chiefly the `slot="trigger"` button of a `wa-dropdown`
|
|
118
139
|
popup menu. A toolbar popup menu is a `single` `ToolbarControlGroup` around a
|
|
119
140
|
`wa-dropdown` (its `slot="trigger"` `wa-button` is the toolbar button, kept under
|
|
120
|
-
`data-morph-skip-children`).
|
|
141
|
+
`data-morph-skip-children`). For an avatar control, set `content="avatar"` and
|
|
142
|
+
`avatarImage` on the group instead of inserting an `img`; a lone control paints
|
|
143
|
+
the group and a multi-button group paints only its pressed highlight.
|
|
121
144
|
- **Use one direct toolbar composition for panel/dialog/page headings.** Put an
|
|
122
145
|
optional icon in a `ToolbarControlGroup`, an extra-large `ToolbarText` directly
|
|
123
146
|
in the leading zone, and actions in a trailing group. Supporting copy is
|
|
@@ -126,7 +149,13 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
126
149
|
- **Space by the five-step scale, by relationship not by eye.** `0`
|
|
127
150
|
`--kui-space-none`, `4px` `--kui-space-2xs`, `8px` `--kui-space-xs` (inside a
|
|
128
151
|
group), `16px` `--kui-space-m`, `24px` `--kui-space-l` (between major differing
|
|
129
|
-
regions). 12px/32px are off-scale exceptions.
|
|
152
|
+
regions). 12px/32px are off-scale exceptions. Prefer direct `List.gap`
|
|
153
|
+
shorthands; use `space`, `px`, `rem`, `em`, `pct`, `lengthVar`, and
|
|
154
|
+
`calc(plus(...))` for typed runtime composition. `remify()` is source-CSS only.
|
|
155
|
+
- **Keep nested highlight corners concentric.** Inset hover and selection surfaces
|
|
156
|
+
follow the owning control's pill or rounded shape; their radius is the outer
|
|
157
|
+
radius minus `--kui-layout-highlight-inset`. Do not give an inner highlight an
|
|
158
|
+
unrelated radius.
|
|
130
159
|
- **Panes share one child-owned geometry.** Sidebars, main areas, inspectors, and
|
|
131
160
|
dialogs all use an unpadded `.kui-pane` (optional `.kui-pane__toolbar`, one
|
|
132
161
|
scrolling `.kui-pane__content`, optional `.kui-pane__footer`). A visible pane owns
|
|
@@ -141,11 +170,14 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
141
170
|
navigation stacks, tab selection and order, pane sizes, and `collapsed`/`expanded`
|
|
142
171
|
disclosure flags in the app — they are data or persisted layout, and the app reads
|
|
143
172
|
them to render. The `wire…` helpers own the _ephemeral_ parts: `wireNavStack` the
|
|
144
|
-
|
|
173
|
+
content-slide, per-view top/bottom chrome cross-fade, and focus move/restore
|
|
174
|
+
(mark a preferred new-view target with `data-nav-focus`), `wireTabBars` the
|
|
175
|
+
overflow autoscroll, drag preview, and
|
|
145
176
|
replacement focus after controlled automatic tab activation,
|
|
146
177
|
`wireResizableRegions` the live drag preview; they report committed changes via
|
|
147
178
|
callbacks. Managed TokenSearchField clear also preserves open state and replacement
|
|
148
|
-
editor focus
|
|
179
|
+
editor focus before the next input task, so shortcut-letter typing stays in search.
|
|
180
|
+
Select All deletion does the same; deletion
|
|
149
181
|
restoration finishes before the next keystroke rather than on a delayed frame.
|
|
150
182
|
Persist both query and remaining tokens read from an edited field. The one richer case is `wireTokenSearchFields`, which manages the
|
|
151
183
|
collapsible field's expand/collapse/focus by default (on, per-behavior opt-out) and
|
|
@@ -168,6 +200,14 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
168
200
|
markup. Use the standalone `Skeleton` for a custom slot. Prefer it over `wa-skeleton`
|
|
169
201
|
(the pure-Kerf primitives avoid Web Awesome), and never animate it — use
|
|
170
202
|
`LoadingSpinner` for known busy activity instead.
|
|
203
|
+
- **Keep ListItem content inside the row.** The rounded `ListItem` root clips
|
|
204
|
+
overflowing label, status, and dormant trailing content. Set `multiline` when
|
|
205
|
+
the primary label should wrap; use `ListActionRow` instead when trailing content
|
|
206
|
+
must be interactive.
|
|
207
|
+
- **Dialog bodies are lists by default.** Compose rows and sections in `List`,
|
|
208
|
+
use `DialogSurface bodyInset="none"` when those children own their geometry,
|
|
209
|
+
and wrap bare prose in `ListInsetText` so it shares the standard list gutter
|
|
210
|
+
without stacking a second body inset.
|
|
171
211
|
- **Use a StateBanner badge only for compact supporting status.** Pass the
|
|
172
212
|
optional string `badge` for a terse count or status beside the title. It
|
|
173
213
|
inherits the banner tone and is announced with the banner, so keep its text
|
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.30",
|
|
4
4
|
"description": "Accessible, composable UI primitives for kerf applications.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,6 +44,10 @@
|
|
|
44
44
|
"types": "./dist/index.d.ts",
|
|
45
45
|
"import": "./dist/index.js"
|
|
46
46
|
},
|
|
47
|
+
"./css-values": {
|
|
48
|
+
"types": "./dist/css-values.d.ts",
|
|
49
|
+
"import": "./dist/css-values.js"
|
|
50
|
+
},
|
|
47
51
|
"./lucide-icon": {
|
|
48
52
|
"types": "./dist/lucide-icon.d.ts",
|
|
49
53
|
"browser": "./dist/browser/lucide-icon.js",
|