@kerfjs/ui 5.0.0-beta.50 → 5.0.0-beta.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -5
- package/ai/compile-time-contracts-v1.json +5 -2
- package/ai/component-catalog-v2.d.ts +19 -1
- package/ai/component-catalog-v2.json +842 -127
- package/ai/component-catalog-v2.schema.json +33 -1
- package/ai/component-catalog.json +603 -126
- package/ai/component-catalog.schema.json +21 -1
- package/ai/public-api-signatures-v1.md +201 -29
- package/ai/skill.md +12 -9
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/analyzer/index.mjs +105 -35
- package/dist/app-tab.js +1 -1
- package/dist/catalog-resources.d.ts +1 -1
- package/dist/catalog.d.ts +28 -5
- package/dist/catalog.js +66 -25
- package/dist/catalog.js.map +1 -1
- package/dist/{chunk-COUPLRZG.js → chunk-5FZZMIMD.js} +3 -3
- package/dist/{chunk-COUPLRZG.js.map → chunk-5FZZMIMD.js.map} +1 -1
- package/dist/{chunk-DARTMI5Z.js → chunk-5PMGQDG7.js} +2 -2
- package/dist/{chunk-DARTMI5Z.js.map → chunk-5PMGQDG7.js.map} +1 -1
- package/dist/{chunk-V6RZWDII.js → chunk-7GUQYHKA.js} +19 -2
- package/dist/chunk-7GUQYHKA.js.map +1 -0
- package/dist/{chunk-ZNZ2JDBW.js → chunk-7IUSV4XG.js} +1 -1
- package/dist/chunk-7IUSV4XG.js.map +1 -0
- package/dist/{chunk-ELRMBQEC.js → chunk-AEPXGCNF.js} +17 -2
- package/dist/chunk-AEPXGCNF.js.map +1 -0
- package/dist/{chunk-5CE64WGC.js → chunk-D547PH4L.js} +3 -3
- package/dist/{chunk-5CE64WGC.js.map → chunk-D547PH4L.js.map} +1 -1
- package/dist/{chunk-S6ZTTTV7.js → chunk-DVZCMMB3.js} +3 -3
- package/dist/{chunk-S6ZTTTV7.js.map → chunk-DVZCMMB3.js.map} +1 -1
- package/dist/chunk-EKYZCRCX.js +256 -0
- package/dist/chunk-EKYZCRCX.js.map +1 -0
- package/dist/{chunk-3V75EQIP.js → chunk-JM53SMVF.js} +3 -3
- package/dist/{chunk-3V75EQIP.js.map → chunk-JM53SMVF.js.map} +1 -1
- package/dist/{chunk-2WMSE4MK.js → chunk-JMGKM7RK.js} +2 -2
- package/dist/{chunk-2WMSE4MK.js.map → chunk-JMGKM7RK.js.map} +1 -1
- package/dist/{chunk-2YOUUEWR.js → chunk-KX7DP2GO.js} +4 -4
- package/dist/{chunk-2YOUUEWR.js.map → chunk-KX7DP2GO.js.map} +1 -1
- package/dist/{chunk-OL4TC3U2.js → chunk-MO56ZZLG.js} +6 -2
- package/dist/chunk-MO56ZZLG.js.map +1 -0
- package/dist/{chunk-OQI7RCRP.js → chunk-MTM43SJO.js} +7 -1
- package/dist/chunk-MTM43SJO.js.map +1 -0
- package/dist/{chunk-ZSYLBVWG.js → chunk-NMGTHYW3.js} +3 -3
- package/dist/{chunk-ZSYLBVWG.js.map → chunk-NMGTHYW3.js.map} +1 -1
- package/dist/{chunk-AQSKJ6U6.js → chunk-NZXWU4R5.js} +21 -2
- package/dist/chunk-NZXWU4R5.js.map +1 -0
- package/dist/{chunk-DJKWFYAA.js → chunk-O3RCCSQJ.js} +3 -3
- package/dist/{chunk-DJKWFYAA.js.map → chunk-O3RCCSQJ.js.map} +1 -1
- package/dist/{chunk-UMGY5JSP.js → chunk-S4QRSBFI.js} +22 -2
- package/dist/chunk-S4QRSBFI.js.map +1 -0
- package/dist/{chunk-KKNK3JUT.js → chunk-UBH743HV.js} +5 -5
- package/dist/chunk-UBH743HV.js.map +1 -0
- package/dist/{chunk-54HM36IQ.js → chunk-ULCDZTWL.js} +2 -2
- package/dist/{chunk-54HM36IQ.js.map → chunk-ULCDZTWL.js.map} +1 -1
- package/dist/{chunk-SIU2AC5W.js → chunk-UPZ6EEJN.js} +3 -3
- package/dist/{chunk-SIU2AC5W.js.map → chunk-UPZ6EEJN.js.map} +1 -1
- package/dist/collapsible-panel.d.ts +1 -1
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/css-values.d.ts +39 -3
- package/dist/css-values.js +1 -1
- package/dist/grid.d.ts +15 -1
- package/dist/grid.js +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +19 -19
- package/dist/list-action-row.js +1 -1
- package/dist/list-header.js +1 -1
- package/dist/list-item.js +1 -1
- package/dist/list.d.ts +21 -2
- package/dist/list.js +2 -1
- package/dist/nav-stack.js +1 -1
- package/dist/pane.d.ts +17 -2
- package/dist/pane.js +1 -1
- package/dist/row.d.ts +19 -1
- package/dist/row.js +2 -1
- package/dist/segmented-control.js +1 -1
- package/dist/select.d.ts +13 -3
- package/dist/select.js +1 -1
- package/dist/skeleton.js +1 -1
- package/dist/spacer.js +1 -1
- package/dist/split-view.js +1 -1
- package/dist/state-banner.js +1 -1
- package/dist/styles/catalog/components/catalog-example-stack.css +4 -1
- package/dist/styles/catalog/components/catalog-example.css +145 -0
- package/dist/styles/collapsible-panel.css +132 -4
- package/dist/styles/document.css +23 -0
- package/dist/styles/foundation.css +21 -7
- package/dist/styles/grid.css +10 -0
- package/dist/styles/list-header.css +45 -0
- package/dist/styles/list-inset-control.css +8 -1
- package/dist/styles/list-item.css +6 -0
- package/dist/styles/list.css +11 -0
- package/dist/styles/nav-stack.css +89 -2
- package/dist/styles/pane.css +86 -1
- package/dist/styles/resizable-region.css +93 -5
- package/dist/styles/row.css +10 -0
- package/dist/styles/select.css +39 -4
- package/dist/styles/split-view.css +107 -1
- package/dist/styles/tab-scaffold.css +64 -1
- package/dist/styles/text.css +6 -0
- package/dist/styles/toolbar-control-group.css +90 -11
- package/dist/styles/toolbar-text.css +4 -1
- package/dist/styles/toolbar.css +130 -38
- package/dist/styles/webawesome.css +48 -2
- package/dist/styles/workbench.css +136 -4
- package/dist/text.d.ts +4 -3
- package/dist/text.js +1 -1
- package/dist/toolbar-text.js +1 -1
- package/dist/toolbar.d.ts +24 -3
- package/dist/toolbar.js +1 -1
- package/dist/{types-CzgSrFXP.d.ts → types-CEsieBZi.d.ts} +6 -1
- package/dist/value-table.js +1 -1
- package/dist/wire-resizable-regions.js +1 -1
- package/dist/wire-sidebar.d.ts +18 -3
- package/dist/wire-sidebar.js +95 -14
- package/dist/wire-sidebar.js.map +1 -1
- package/docs/accessibility.md +45 -8
- package/docs/app-layouts.md +73 -0
- package/docs/catalog.md +23 -2
- package/docs/collapsible-panel.md +81 -8
- package/docs/component-contract.md +28 -9
- package/docs/component-integration.md +9 -4
- package/docs/component-selection.md +25 -6
- package/docs/design/templates/list/stack-dark.svg +1 -1
- package/docs/design/templates/list/stack.svg +1 -1
- package/docs/design/templates/list-dark.svg +1 -1
- package/docs/design/templates/list-header/action-dark.svg +1 -1
- package/docs/design/templates/list-header/action.svg +1 -1
- package/docs/design/templates/list-header/count-dark.svg +1 -1
- package/docs/design/templates/list-header/count.svg +1 -1
- package/docs/design/templates/list-header/inline-action-dark.svg +1 -1
- package/docs/design/templates/list-header/inline-action.svg +1 -1
- package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -1
- package/docs/design/templates/list-header/toggle-expanded.svg +1 -1
- package/docs/design/templates/list-header-dark.svg +1 -1
- package/docs/design/templates/list-header.svg +1 -1
- package/docs/design/templates/list.svg +1 -1
- package/docs/design/templates/state-banner/info-badge-dark.svg +1 -1
- package/docs/design/templates/state-banner/info-badge.svg +1 -1
- package/docs/design/templates/state-banner-dark.svg +1 -1
- package/docs/design/templates/state-banner.svg +1 -1
- package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -1
- package/docs/design/templates/toolbar/title-and-actions.svg +1 -1
- package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -1
- package/docs/design/templates/toolbar-control-group/with-text.svg +1 -1
- package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
- package/docs/design/templates/toolbar-control-group.svg +1 -1
- package/docs/design/templates/toolbar-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/default-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/default.svg +1 -1
- package/docs/design/templates/toolbar-text/large-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/large.svg +1 -1
- package/docs/design/templates/toolbar-text/small-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/small.svg +1 -1
- package/docs/design/templates/toolbar-text-dark.svg +1 -1
- package/docs/design/templates/toolbar-text.svg +1 -1
- package/docs/design/templates/toolbar.svg +1 -1
- package/docs/document-baseline.md +31 -0
- package/docs/layout.md +86 -21
- package/docs/nav-stack.md +8 -0
- package/docs/recipes.md +78 -43
- package/docs/split-view.md +8 -0
- package/docs/tab-scaffold.md +4 -2
- package/docs/type-contracts.md +21 -17
- package/docs/ui-analyzer.md +19 -0
- package/docs/ui-evaluator.md +17 -0
- package/docs/ux-demo.md +4 -4
- package/docs/webawesome-theme.md +20 -2
- package/docs/workbench.md +20 -1
- package/evaluator/index.mjs +73 -8
- package/llms.txt +32 -14
- package/package.json +4 -2
- package/ux-demo/recipes/app-shell.tsx +209 -178
- package/ux-demo/recipes/collapsible-sidebar.tsx +188 -159
- package/ux-demo/recipes/compact-toolbar.tsx +48 -35
- package/ux-demo/recipes/composer-form.tsx +85 -79
- package/ux-demo/recipes/list-detail-dialog.tsx +124 -142
- package/ux-demo/recipes/list-workspace-states.tsx +83 -83
- package/ux-demo/recipes/loaders.ts +5 -2
- package/ux-demo/recipes/loading-inspector.tsx +157 -160
- package/ux-demo/recipes/navigation-sidebar.tsx +111 -109
- package/ux-demo/recipes/navigation-stack.tsx +50 -49
- package/ux-demo/recipes/types.ts +14 -0
- package/ux-demo/recipes/workspace-header.tsx +73 -56
- package/dist/chunk-AQSKJ6U6.js.map +0 -1
- package/dist/chunk-ELRMBQEC.js.map +0 -1
- package/dist/chunk-J3EE6XWD.js +0 -115
- package/dist/chunk-J3EE6XWD.js.map +0 -1
- package/dist/chunk-KKNK3JUT.js.map +0 -1
- package/dist/chunk-OL4TC3U2.js.map +0 -1
- package/dist/chunk-OQI7RCRP.js.map +0 -1
- package/dist/chunk-UMGY5JSP.js.map +0 -1
- package/dist/chunk-V6RZWDII.js.map +0 -1
- package/dist/chunk-ZNZ2JDBW.js.map +0 -1
- package/ux-demo/recipes/app-shell.css +0 -87
- package/ux-demo/recipes/collapsible-sidebar.css +0 -83
- package/ux-demo/recipes/compact-toolbar.css +0 -35
- package/ux-demo/recipes/composer-form.css +0 -19
- package/ux-demo/recipes/list-detail-dialog.css +0 -42
- package/ux-demo/recipes/list-workspace-states.css +0 -30
- package/ux-demo/recipes/loading-inspector.css +0 -7
- package/ux-demo/recipes/navigation-sidebar.css +0 -12
- package/ux-demo/recipes/navigation-stack.css +0 -12
- package/ux-demo/recipes/recipe-root.css +0 -67
- package/ux-demo/recipes/recipe-root.tsx +0 -87
- package/ux-demo/recipes/workspace-header.css +0 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 392 358" width="392" height="358"><defs><clipPath id="cp0"><rect x="16" y="38" width="360" height="80"/></clipPath><clipPath id="cp1"><rect x="16" y="156" width="360" height="76"/></clipPath><clipPath id="cp2"><rect x="16" y="270" width="360" height="72"/></clipPath><clipPath id="ct3"><rect x="16" y="16" width="360" height="22"/></clipPath><clipPath id="irc4"><rect x="16" y="38" width="360" height="80" rx="0"/></clipPath><clipPath id="ct6"><rect x="16" y="134" width="360" height="22"/></clipPath><clipPath id="irc7"><rect x="16" y="156" width="360" height="76" rx="0"/></clipPath><clipPath id="ct9"><rect x="16" y="248" width="360" height="22"/></clipPath><clipPath id="irc10"><rect x="16" y="270" width="360" height="72" rx="0"/></clipPath></defs><rect x="0" y="0" width="392" height="358" rx="0" fill="rgb(28,28,30)"/><text x="16" y="28" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">Large (title)</text><g clip-path="url(#cp0)"><g clip-path="url(#irc4)"><clipPath id="svgimg5vclip"><rect x="16" y="38" width="360" height="80"/></clipPath><g clip-path="url(#svgimg5vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg5cp0"><rect x="20" y="20" width="163" height="40"/></clipPath><clipPath id="svgimg5ov1"><rect x="20" y="20" width="163" height="40" rx="0"/></clipPath><clipPath id="svgimg5cp2"><rect x="28" y="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 392 358" width="392" height="358"><defs><clipPath id="cp0"><rect x="16" y="38" width="360" height="80"/></clipPath><clipPath id="cp1"><rect x="16" y="156" width="360" height="76"/></clipPath><clipPath id="cp2"><rect x="16" y="270" width="360" height="72"/></clipPath><clipPath id="ct3"><rect x="16" y="16" width="360" height="22"/></clipPath><clipPath id="irc4"><rect x="16" y="38" width="360" height="80" rx="0"/></clipPath><clipPath id="ct6"><rect x="16" y="134" width="360" height="22"/></clipPath><clipPath id="irc7"><rect x="16" y="156" width="360" height="76" rx="0"/></clipPath><clipPath id="ct9"><rect x="16" y="248" width="360" height="22"/></clipPath><clipPath id="irc10"><rect x="16" y="270" width="360" height="72" rx="0"/></clipPath></defs><rect x="0" y="0" width="392" height="358" rx="0" fill="rgb(28,28,30)"/><text x="16" y="28" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">Large (title)</text><g clip-path="url(#cp0)"><g clip-path="url(#irc4)"><clipPath id="svgimg5vclip"><rect x="16" y="38" width="360" height="80"/></clipPath><g clip-path="url(#svgimg5vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg5cp0"><rect x="20" y="20" width="163" height="40"/></clipPath><clipPath id="svgimg5ov1"><rect x="20" y="20" width="163" height="40" rx="0"/></clipPath><clipPath id="svgimg5cp2"><rect x="28" y="30.4" width="147" height="19.2"/></clipPath><clipPath id="svgimg5ct3"><rect x="28" y="30.4" width="147" height="19.2"/></clipPath></defs><g clip-path="url(#svgimg5cp0)"><g clip-path="url(#svgimg5ov1)"><g clip-path="url(#svgimg5cp2)"><g clip-path="url(#svgimg5ct3)"><text x="28" y="45.41" font-family="system-ui, "-apple-system", sans-serif" font-size="16" font-weight="650" fill="rgb(174,174,178)">Northstar migration</text></g></g></g></g></g></g></g></g><text x="16" y="146" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">Default</text><g clip-path="url(#cp1)"><g clip-path="url(#irc7)"><clipPath id="svgimg8vclip"><rect x="16" y="156" width="360" height="76"/></clipPath><g clip-path="url(#svgimg8vclip)"><g transform="translate(16 156)"><defs><clipPath id="svgimg8cp0"><rect x="20" y="20" width="151.2" height="40"/></clipPath><clipPath id="svgimg8ov1"><rect x="20" y="20" width="151.2" height="40" rx="0"/></clipPath><clipPath id="svgimg8cp2"><rect x="28" y="31.6" width="135.2" height="16.8"/></clipPath><clipPath id="svgimg8ct3"><rect x="28" y="31.6" width="135.2" height="16.8"/></clipPath></defs><g clip-path="url(#svgimg8cp0)"><g clip-path="url(#svgimg8ov1)"><g clip-path="url(#svgimg8cp2)"><g clip-path="url(#svgimg8ct3)"><text x="28" y="44.59" font-family="system-ui, "-apple-system", sans-serif" font-size="14" font-weight="650" fill="rgb(174,174,178)">Workspace settings</text></g></g></g></g></g></g></g></g><text x="16" y="260" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">Small (label)</text><g clip-path="url(#cp2)"><g clip-path="url(#irc10)"><clipPath id="svgimg11vclip"><rect x="16" y="270" width="360" height="72"/></clipPath><g clip-path="url(#svgimg11vclip)"><g transform="translate(16 270)"><defs><clipPath id="svgimg11cp0"><rect x="20" y="20" width="53.6" height="40"/></clipPath><clipPath id="svgimg11ov1"><rect x="20" y="20" width="53.6" height="40" rx="0"/></clipPath><clipPath id="svgimg11cp2"><rect x="28" y="32.8" width="37.6" height="14.4"/></clipPath><clipPath id="svgimg11ct3"><rect x="28" y="32.8" width="37.6" height="14.4"/></clipPath></defs><g clip-path="url(#svgimg11cp0)"><g clip-path="url(#svgimg11ov1)"><g clip-path="url(#svgimg11cp2)"><g clip-path="url(#svgimg11ct3)"><text x="28" y="43.8" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(174,174,178)">Filters</text></g></g></g></g></g></g></g></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 392 358" width="392" height="358"><defs><clipPath id="cp0"><rect x="16" y="38" width="360" height="80"/></clipPath><clipPath id="cp1"><rect x="16" y="156" width="360" height="76"/></clipPath><clipPath id="cp2"><rect x="16" y="270" width="360" height="72"/></clipPath><clipPath id="ct3"><rect x="16" y="16" width="360" height="22"/></clipPath><clipPath id="irc4"><rect x="16" y="38" width="360" height="80" rx="0"/></clipPath><clipPath id="ct6"><rect x="16" y="134" width="360" height="22"/></clipPath><clipPath id="irc7"><rect x="16" y="156" width="360" height="76" rx="0"/></clipPath><clipPath id="ct9"><rect x="16" y="248" width="360" height="22"/></clipPath><clipPath id="irc10"><rect x="16" y="270" width="360" height="72" rx="0"/></clipPath></defs><rect x="0" y="0" width="392" height="358" 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)">Large (title)</text><g clip-path="url(#cp0)"><g clip-path="url(#irc4)"><clipPath id="svgimg5vclip"><rect x="16" y="38" width="360" height="80"/></clipPath><g clip-path="url(#svgimg5vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg5cp0"><rect x="20" y="20" width="163" height="40"/></clipPath><clipPath id="svgimg5ov1"><rect x="20" y="20" width="163" height="40" rx="0"/></clipPath><clipPath id="svgimg5cp2"><rect x="28" y="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 392 358" width="392" height="358"><defs><clipPath id="cp0"><rect x="16" y="38" width="360" height="80"/></clipPath><clipPath id="cp1"><rect x="16" y="156" width="360" height="76"/></clipPath><clipPath id="cp2"><rect x="16" y="270" width="360" height="72"/></clipPath><clipPath id="ct3"><rect x="16" y="16" width="360" height="22"/></clipPath><clipPath id="irc4"><rect x="16" y="38" width="360" height="80" rx="0"/></clipPath><clipPath id="ct6"><rect x="16" y="134" width="360" height="22"/></clipPath><clipPath id="irc7"><rect x="16" y="156" width="360" height="76" rx="0"/></clipPath><clipPath id="ct9"><rect x="16" y="248" width="360" height="22"/></clipPath><clipPath id="irc10"><rect x="16" y="270" width="360" height="72" rx="0"/></clipPath></defs><rect x="0" y="0" width="392" height="358" 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)">Large (title)</text><g clip-path="url(#cp0)"><g clip-path="url(#irc4)"><clipPath id="svgimg5vclip"><rect x="16" y="38" width="360" height="80"/></clipPath><g clip-path="url(#svgimg5vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg5cp0"><rect x="20" y="20" width="163" height="40"/></clipPath><clipPath id="svgimg5ov1"><rect x="20" y="20" width="163" height="40" rx="0"/></clipPath><clipPath id="svgimg5cp2"><rect x="28" y="30.4" width="147" height="19.2"/></clipPath><clipPath id="svgimg5ct3"><rect x="28" y="30.4" width="147" height="19.2"/></clipPath></defs><g clip-path="url(#svgimg5cp0)"><g clip-path="url(#svgimg5ov1)"><g clip-path="url(#svgimg5cp2)"><g clip-path="url(#svgimg5ct3)"><text x="28" y="45.41" font-family="system-ui, "-apple-system", sans-serif" font-size="16" font-weight="650" fill="rgb(110,110,115)">Northstar migration</text></g></g></g></g></g></g></g></g><text x="16" y="146" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(110,110,115)">Default</text><g clip-path="url(#cp1)"><g clip-path="url(#irc7)"><clipPath id="svgimg8vclip"><rect x="16" y="156" width="360" height="76"/></clipPath><g clip-path="url(#svgimg8vclip)"><g transform="translate(16 156)"><defs><clipPath id="svgimg8cp0"><rect x="20" y="20" width="151.2" height="40"/></clipPath><clipPath id="svgimg8ov1"><rect x="20" y="20" width="151.2" height="40" rx="0"/></clipPath><clipPath id="svgimg8cp2"><rect x="28" y="31.6" width="135.2" height="16.8"/></clipPath><clipPath id="svgimg8ct3"><rect x="28" y="31.6" width="135.2" height="16.8"/></clipPath></defs><g clip-path="url(#svgimg8cp0)"><g clip-path="url(#svgimg8ov1)"><g clip-path="url(#svgimg8cp2)"><g clip-path="url(#svgimg8ct3)"><text x="28" y="44.59" font-family="system-ui, "-apple-system", sans-serif" font-size="14" font-weight="650" fill="rgb(110,110,115)">Workspace settings</text></g></g></g></g></g></g></g></g><text x="16" y="260" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(110,110,115)">Small (label)</text><g clip-path="url(#cp2)"><g clip-path="url(#irc10)"><clipPath id="svgimg11vclip"><rect x="16" y="270" width="360" height="72"/></clipPath><g clip-path="url(#svgimg11vclip)"><g transform="translate(16 270)"><defs><clipPath id="svgimg11cp0"><rect x="20" y="20" width="53.6" height="40"/></clipPath><clipPath id="svgimg11ov1"><rect x="20" y="20" width="53.6" height="40" rx="0"/></clipPath><clipPath id="svgimg11cp2"><rect x="28" y="32.8" width="37.6" height="14.4"/></clipPath><clipPath id="svgimg11ct3"><rect x="28" y="32.8" width="37.6" height="14.4"/></clipPath></defs><g clip-path="url(#svgimg11cp0)"><g clip-path="url(#svgimg11ov1)"><g clip-path="url(#svgimg11cp2)"><g clip-path="url(#svgimg11ct3)"><text x="28" y="43.8" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(110,110,115)">Filters</text></g></g></g></g></g></g></g></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 672 158" width="672" height="158"><defs><clipPath id="cp0"><rect x="16" y="38" width="640" height="104"/></clipPath><clipPath id="ct1"><rect x="16" y="16" width="640" height="22"/></clipPath><clipPath id="irc2"><rect x="16" y="38" width="640" height="104" rx="0"/></clipPath></defs><rect x="0" y="0" width="672" height="158" 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)">Title with a trailing group</text><g clip-path="url(#cp0)"><g clip-path="url(#irc2)"><clipPath id="svgimg3vclip"><rect x="16" y="38" width="640" height="104"/></clipPath><g clip-path="url(#svgimg3vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg3cp0"><rect x="28" y="28" width="452" height="44"/></clipPath><clipPath id="svgimg3ov1"><rect x="28" y="28" width="452" height="44" rx="0"/></clipPath><clipPath id="svgimg3cp2"><rect x="30" y="30" width="88.1" height="40"/></clipPath><clipPath id="svgimg3ov3"><rect x="30" y="30" width="88.1" height="40" rx="0"/></clipPath><clipPath id="svgimg3cp4"><rect x="38" y="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 672 158" width="672" height="158"><defs><clipPath id="cp0"><rect x="16" y="38" width="640" height="104"/></clipPath><clipPath id="ct1"><rect x="16" y="16" width="640" height="22"/></clipPath><clipPath id="irc2"><rect x="16" y="38" width="640" height="104" rx="0"/></clipPath></defs><rect x="0" y="0" width="672" height="158" 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)">Title with a trailing group</text><g clip-path="url(#cp0)"><g clip-path="url(#irc2)"><clipPath id="svgimg3vclip"><rect x="16" y="38" width="640" height="104"/></clipPath><g clip-path="url(#svgimg3vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg3cp0"><rect x="28" y="28" width="452" height="44"/></clipPath><clipPath id="svgimg3ov1"><rect x="28" y="28" width="452" height="44" rx="0"/></clipPath><clipPath id="svgimg3cp2"><rect x="30" y="30" width="88.1" height="40"/></clipPath><clipPath id="svgimg3ov3"><rect x="30" y="30" width="88.1" height="40" rx="0"/></clipPath><clipPath id="svgimg3cp4"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="svgimg3ct5"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="svgimg3cp6"><rect x="502" y="42" width="16" height="16"/></clipPath><clipPath id="svgimg3cp8"><rect x="542" y="42" width="16" height="16"/></clipPath><clipPath id="svgimg3cp10"><rect x="582" y="42" width="16" height="16"/></clipPath></defs><g clip-path="url(#svgimg3cp0)"><g clip-path="url(#svgimg3ov1)"><rect x="28.5" y="28.5" width="91" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg3cp2)"><g clip-path="url(#svgimg3ov3)"><g clip-path="url(#svgimg3cp4)"><g clip-path="url(#svgimg3ct5)"><text x="38" y="55.41" font-family=""ui-sans-serif", "-apple-system", "system-ui", "Segoe UI", sans-serif" font-size="16" font-weight="650" fill="rgb(110,110,115)">Northstar</text></g></g></g></g></g></g><rect x="488" y="28" width="124" height="44" rx="22" fill="rgb(229,229,234)"/><rect x="488.5" y="28.5" width="123" height="43" rx="21.5" fill="none" stroke="rgb(209,209,214)" stroke-width="1"/><rect x="490.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg3cp6)"><g color="rgb(110, 110, 115)"><clipPath id="svgimg3svgic7"><rect x="502" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgimg3svgic7)"><g transform="translate(502 42)scale(.66667)"><path d="M3 5z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" 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(110, 110, 115)" 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(110, 110, 115)" 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(110, 110, 115)" 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(110, 110, 115)" 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(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><rect x="530.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg3cp8)"><g color="rgb(110, 110, 115)"><clipPath id="svgimg3svgic9"><rect x="542" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgimg3svgic9)"><g transform="translate(542 42)scale(.66667)"><rect width="18" height="18" x="3" y="3" rx="2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M9 3v18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M15 3v18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><rect x="570.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg3cp10)"><g color="rgb(110, 110, 115)"><clipPath id="svgimg3svgic11"><rect x="582" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgimg3svgic11)"><g transform="translate(582 42)scale(.66667)"><path d="M9.7 4.1a2.3 2.3 0 0 1 4.6 0 2.3 2.3 0 0 0 3.3 2 2.3 2.3 0 0 1 2.4 4 2.3 2.3 0 0 0 0 3.8 2.3 2.3 0 0 1-2.4 4 2.3 2.3 0 0 0-3.3 2 2.3 2.3 0 0 1-4.6 0 2.3 2.3 0 0 0-3.3-2A2.3 2.3 0 0 1 4 14a2.3 2.3 0 0 0 0-3.8 2.3 2.3 0 0 1 2.3-4 2.3 2.3 0 0 0 3.4-2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="12" cy="12" r="3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" 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></g></g></g></svg>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Document baseline
|
|
2
|
+
|
|
3
|
+
Import `@kerfjs/ui/document.css` when an application wants Kerf UI to own its
|
|
4
|
+
document-level defaults:
|
|
5
|
+
|
|
6
|
+
```ts
|
|
7
|
+
import "@kerfjs/ui/document.css";
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```html
|
|
11
|
+
<body>
|
|
12
|
+
<div id="app" class="kui-app-root"></div>
|
|
13
|
+
</body>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The opt-in stylesheet applies `border-box` sizing to every element and
|
|
17
|
+
pseudo-element, removes the body margin, and gives the body the foundation
|
|
18
|
+
font, foreground, lowered surface, and `1.45` line height. Plain links use the
|
|
19
|
+
semantic `--kui-color-text-link` token with zero selector specificity.
|
|
20
|
+
|
|
21
|
+
`html`, `body`, and `.kui-app-root` form a definite `height: 100%` chain. Add
|
|
22
|
+
`.kui-app-root` to the one direct mount container of a full-height application
|
|
23
|
+
whose child is a `Workbench`, `SplitView`, `NavStack`, or another percentage-
|
|
24
|
+
height shell. Ordinary document-flow pages can import the baseline without the
|
|
25
|
+
class. Do not put `.kui-app-root` on several sibling containers: each requests
|
|
26
|
+
the full available document height.
|
|
27
|
+
|
|
28
|
+
The stylesheet is intentionally absent from `@kerfjs/ui/styles.css` and every
|
|
29
|
+
component browser import because its global selectors would otherwise change
|
|
30
|
+
consumer documents implicitly. Import it once and load application overrides
|
|
31
|
+
after it.
|
package/docs/layout.md
CHANGED
|
@@ -35,6 +35,14 @@ each enabled side uses `--kui-pane-separator-width` (1px) and
|
|
|
35
35
|
`--kui-pane-separator-color` (`--kui-color-border`). Logical sides keep pane
|
|
36
36
|
boundaries correct in both left-to-right and right-to-left layouts.
|
|
37
37
|
|
|
38
|
+
A pane is safe-area aware. Its background and separators paint through a
|
|
39
|
+
device's unsafe areas while its header, content, and footer pad for each side
|
|
40
|
+
the pane still reaches; the content's block insets are scroll padding, so its
|
|
41
|
+
first and last items can always be scrolled clear. Layouts clear the sides a
|
|
42
|
+
pane does not reach. In an app-owned arrangement, pass `safeAreaEdges` (the
|
|
43
|
+
same logical sides as `separators`; all four by default, `[]` to opt out). See
|
|
44
|
+
[Choosing an app layout › Safe areas](app-layouts.md#safe-areas).
|
|
45
|
+
|
|
38
46
|
`.kui-content` is a vertical stack with a 24px gap between major children.
|
|
39
47
|
Sections may contain adjacent `ListItem` rows without adding another major gap.
|
|
40
48
|
Ordinary surface-like children use `.kui-content-item` and own their complete
|
|
@@ -66,17 +74,18 @@ semantic status.
|
|
|
66
74
|
|
|
67
75
|
## Public roles and tokens
|
|
68
76
|
|
|
69
|
-
| Need | Class | Token / default
|
|
70
|
-
| ---------------------------------------- | ------------------------- |
|
|
71
|
-
| Unpadded header/content/footer structure | `Pane`, `.kui-pane` | —
|
|
72
|
-
| Scrolling pane content | `.kui-pane__content` | —
|
|
73
|
-
| Optional logical-edge separators | `Pane.separators` | `--kui-pane-separator-width: 1px`
|
|
74
|
-
|
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
|
|
|
77
|
+
| Need | Class | Token / default |
|
|
78
|
+
| ---------------------------------------- | ------------------------- | --------------------------------------------------------------------------- |
|
|
79
|
+
| Unpadded header/content/footer structure | `Pane`, `.kui-pane` | — |
|
|
80
|
+
| Scrolling pane content | `.kui-pane__content` | — |
|
|
81
|
+
| Optional logical-edge separators | `Pane.separators` | `--kui-pane-separator-width: 1px` |
|
|
82
|
+
| Safe-area sides a pane may pad | `Pane.safeAreaEdges` | `--kui-safe-area-*: env(safe-area-inset-*)`, routed as `--kui-edge-inset-*` |
|
|
83
|
+
| Major vertical rhythm | `.kui-content` | `--kui-layout-content-gap: 24px` |
|
|
84
|
+
| Self-contained child geometry | `.kui-content-item` | 8px margin + 1px border + 8px padding |
|
|
85
|
+
| Pill child | `.kui-content-item--pill` | `--kui-layout-pill-radius: 22px` |
|
|
86
|
+
| Related controls | `.kui-control-cluster` | `--kui-layout-control-gap: 8px` |
|
|
87
|
+
| Inline metadata | `.kui-inline-metadata` | `--kui-layout-metadata-gap: 4px` |
|
|
88
|
+
| Explicit scroll owner outside a pane | `.kui-scroll-owner` | `overflow: auto` |
|
|
80
89
|
|
|
81
90
|
The component layer applies the same contract to `Toolbar`, `ListHeader`,
|
|
82
91
|
`ListItem`, `Toolbar`, `StateBanner`, `ValueTable`,
|
|
@@ -87,6 +96,12 @@ also keeps 8px of root-scaled block padding independently of its semantic inline
|
|
|
87
96
|
inset. Most interactive rows and toolbar groups are 44px tall.
|
|
88
97
|
Toolbar groups reserve a real 1px outer border around a 42px inner area, even
|
|
89
98
|
when their border and background are transparent.
|
|
99
|
+
Trailing icon actions share one axis: a toolbar control centers its glyph in
|
|
100
|
+
that 44px slot at the 8px inline margin, and a `ListHeader` action centers its
|
|
101
|
+
fitted 36px square in a slot of the same size (a transparent hit layer extends
|
|
102
|
+
its pointer target to fill that 44px slot), so a Pane header's trailing toolbar
|
|
103
|
+
action and the `ListHeader` action beneath it line up (30px from the pane edge
|
|
104
|
+
at the default scale).
|
|
90
105
|
Panel, dialog, and page headings are plain `Toolbar` compositions. The leading
|
|
91
106
|
zone holds an optional icon `ToolbarControlGroup` and a direct extra-large
|
|
92
107
|
`ToolbarText`; actions belong in a trailing group. Omit empty groups. Supporting
|
|
@@ -120,18 +135,30 @@ CSS strings.
|
|
|
120
135
|
|
|
121
136
|
## Text
|
|
122
137
|
|
|
123
|
-
Use `Text` from `@kerfjs/ui/text` for ordinary semantic headings
|
|
124
|
-
|
|
125
|
-
the document outline calls for a heading
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
138
|
+
Use `Text` from `@kerfjs/ui/text` for ordinary semantic headings, paragraphs,
|
|
139
|
+
and inline secondary text. It renders a native `p` by default; set `variant` to
|
|
140
|
+
`h1`–`h6` when the document outline calls for a heading, or `span` for inline
|
|
141
|
+
copy inside a row, label, or table cell. Ordinary global, `data-*`, and `aria-*`
|
|
142
|
+
attributes pass through. Block variants reset their native margin, own a 1px
|
|
143
|
+
transparent border, and supply the standard 8px item padding. The `span`
|
|
144
|
+
variant owns no margin, border, or padding. Choose heading levels from the
|
|
145
|
+
document outline, not for visual size. Toolbar identity and page-heading
|
|
146
|
+
compositions continue to use `ToolbarText`.
|
|
147
|
+
|
|
148
|
+
`Text` is also the answer for a normal-color subsection title. `ToolbarText`
|
|
149
|
+
below `xlarge` (`large`, `default`, `small`) is deliberately quiet: it labels a
|
|
150
|
+
toolbar's identity — a pane name or a status — and must not compete with the
|
|
151
|
+
content and controls around it, so it has no tone option. A subsection title is
|
|
152
|
+
document content, not toolbar identity: use `Text` with the `h2`–`h6` variant
|
|
153
|
+
the outline calls for (inside a `List` with `controlInsets`, its text lines up
|
|
154
|
+
with content items). Use `ListHeader` when the section is a list or menu group
|
|
155
|
+
that needs a count, badge, action, or disclosure, and keep extra-large
|
|
156
|
+
`ToolbarText` for the panel, dialog, or page title.
|
|
131
157
|
|
|
132
158
|
Presentation is independent of the native element: use `tone="quiet"` for
|
|
133
159
|
supporting copy, `tone="danger"` for error or validation copy, `size="compact"`
|
|
134
|
-
for compact metadata, and `font="monospace"` for code or identifiers
|
|
160
|
+
for compact metadata, and `font="monospace"` for code or identifiers (the
|
|
161
|
+
`--kui-font-mono` stack, which Kerf owns even with Web Awesome loaded). These
|
|
135
162
|
finite props compose with each other and with every semantic `variant`; omit
|
|
136
163
|
them to inherit the surrounding color, size, and font.
|
|
137
164
|
|
|
@@ -139,8 +166,10 @@ them to inherit the surrounding color, size, and font.
|
|
|
139
166
|
import { Text } from "@kerfjs/ui/text";
|
|
140
167
|
|
|
141
168
|
<Text variant="h2" id="details-title">Details</Text>;
|
|
169
|
+
<Text variant="h3">Notifications</Text>; // normal-color subsection title
|
|
142
170
|
<Text aria-describedby="details-title">Supporting copy</Text>;
|
|
143
171
|
<Text tone="quiet" size="compact">Updated yesterday</Text>;
|
|
172
|
+
<strong>Inbox<Text variant="span" tone="quiet" size="compact"> · 3 msg</Text></strong>;
|
|
144
173
|
<Text tone="danger" font="monospace">ERR_INVALID_ID</Text>;
|
|
145
174
|
```
|
|
146
175
|
|
|
@@ -221,6 +250,35 @@ for the CSS initial value, pass `true` for `1 1 auto`, select the finite
|
|
|
221
250
|
shorthand. A `CssLength` is not a flex shorthand, and arbitrary strings are
|
|
222
251
|
rejected by the type contract.
|
|
223
252
|
|
|
253
|
+
### Filling a fixed-height parent
|
|
254
|
+
|
|
255
|
+
`flex` sizes a Row, List, or Grid inside a flex layout. When one of them is the
|
|
256
|
+
layout **root** of a parent with a definite height (an app mount container
|
|
257
|
+
with the `.kui-app-root` height chain, a dialog body, or a fixed-height catalog
|
|
258
|
+
frame), pass `fill` instead: the root takes the parent's full height
|
|
259
|
+
(`height: 100%`), so its `flex` children can grow into it. Use `fill` only on
|
|
260
|
+
that sole layout root; a sibling inside a flex layout keeps using `flex`.
|
|
261
|
+
|
|
262
|
+
Put route, test, or recipe metadata on the same root with `rootAttributes`,
|
|
263
|
+
which accepts safe `data-*` pairs and keeps each component's structural
|
|
264
|
+
attributes (`data-component`, `data-flex`, `data-fill`, alignment, inset, and
|
|
265
|
+
column markers) protected:
|
|
266
|
+
|
|
267
|
+
```tsx
|
|
268
|
+
<Row gap="none" fill rootAttributes={{ "data-recipe": "sidebar" }}>
|
|
269
|
+
<CollapsiblePanel id="rail" side="left" collapsed={railCollapsed.value}>
|
|
270
|
+
…
|
|
271
|
+
</CollapsiblePanel>
|
|
272
|
+
<List flex>…</List>
|
|
273
|
+
</Row>
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Do not wrap a layout in a frame `Pane` just to get a definite height or a root
|
|
277
|
+
attribute: the pane's content slot becomes a scroll owner that never scrolls,
|
|
278
|
+
and its safe-area padding keeps an edge-docked rail or drawer from painting
|
|
279
|
+
through the unsafe area. A `Pane` is for a real column with a header, one
|
|
280
|
+
scrolling content region, or a footer.
|
|
281
|
+
|
|
224
282
|
Both components also accept `textInsets` and `controlInsets` using the shared
|
|
225
283
|
physical `Sides` union. Values follow canonical top/right/bottom/left order
|
|
226
284
|
(`t`, `rb`, `tbl`, `trbl`, and so on). A selected control side adds 8px of
|
|
@@ -229,11 +287,18 @@ padding. A selected text side adds the complete content-item alignment inset —
|
|
|
229
287
|
container padding. When both props select the same side, the text inset wins.
|
|
230
288
|
Each nested `Row` or `List` resolves its own four inset sides; unselected sides
|
|
231
289
|
reset to zero instead of inheriting a same-type parent's inset selection.
|
|
290
|
+
The same holds for `gap` and `flex` on a nested `List`, `Row`, or `Grid`: an
|
|
291
|
+
omitted prop falls back to that component's own default (no gap for `List`,
|
|
292
|
+
`xs` for `Row` and `Grid`; the CSS initial `flex`) rather than the enclosing
|
|
293
|
+
instance's value.
|
|
232
294
|
|
|
233
295
|
`ListInsetText` and `ListInsetControl` use the same `sides` vocabulary and
|
|
234
296
|
default to `trbl`. The text wrapper applies its complete 8/1/8 geometry only on
|
|
235
297
|
selected sides; the control wrapper applies its 8px outer margin only on
|
|
236
|
-
selected sides. `
|
|
298
|
+
selected sides. Every direct child of `ListInsetControl` grows to fill the row
|
|
299
|
+
(a `Select`, a `wa-input`, or a `wa-button` spans the full inset width), and
|
|
300
|
+
several children share the row with an 8px gap; stack controls vertically with
|
|
301
|
+
a `List` using `controlInsets` instead. `ListInsetText.horizontalOnly` remains a deprecated alias for
|
|
237
302
|
`sides="rl"`; an explicit `sides` value takes precedence.
|
|
238
303
|
|
|
239
304
|
`--kui-space-s` (12px) and `--kui-space-xl` (32px) exist but are **off the
|
package/docs/nav-stack.md
CHANGED
|
@@ -65,6 +65,14 @@ When a remembered control was removed during the controlled rerender, the same
|
|
|
65
65
|
fallback order applies. Disposing the helper stops future transitions and
|
|
66
66
|
cleans up any temporary fallback `tabindex` it added.
|
|
67
67
|
|
|
68
|
+
## Safe areas
|
|
69
|
+
|
|
70
|
+
The stack paints through a device's unsafe areas. Its chrome pads for the top
|
|
71
|
+
and side insets, its bottom toolbar for the bottom and side insets, and each
|
|
72
|
+
view pads the remaining edges inside its scroller, so content scrolls under the
|
|
73
|
+
unsafe area but can always be scrolled clear. A view whose only child is a
|
|
74
|
+
`Pane` or layout lets that child own the insets. See [Choosing an app layout › Safe areas](app-layouts.md#safe-areas).
|
|
75
|
+
|
|
68
76
|
## Transitions
|
|
69
77
|
|
|
70
78
|
`wireNavStack(root, { onBack, duration? })` observes the rendered stack and
|
package/docs/recipes.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Production composition recipes
|
|
2
2
|
|
|
3
|
-
These
|
|
4
|
-
code. Open each stable UX-catalog route to run it, then copy the linked TSX
|
|
5
|
-
|
|
6
|
-
and keep state in a per-instance application adapter. They
|
|
7
|
-
monolithic components.
|
|
3
|
+
These ten reference compositions sit between individual primitives and product
|
|
4
|
+
code. Open each stable UX-catalog route to run it, then copy the linked TSX. The
|
|
5
|
+
examples import public package subpaths, compose components through their
|
|
6
|
+
props and tokens, and keep state in a per-instance application adapter. They
|
|
7
|
+
ship no stylesheet of their own and are not new monolithic components.
|
|
8
8
|
|
|
9
9
|
Copy the recipe source together with the catalog-independent
|
|
10
10
|
[`mount-recipe.ts`](../ux-demo/recipes/mount-recipe.ts) adapter. It mounts the
|
|
@@ -28,11 +28,22 @@ specific dispatch; either way, wire once at a stable root and retain disposal.
|
|
|
28
28
|
|
|
29
29
|
## Desktop application shell
|
|
30
30
|
|
|
31
|
-
[Open the recipe](../ux-demo/?component=recipe-app-shell) · [TSX source](../ux-demo/recipes/app-shell.tsx)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
[Open the recipe](../ux-demo/?component=recipe-app-shell) · [TSX source](../ux-demo/recipes/app-shell.tsx)
|
|
32
|
+
|
|
33
|
+
A filling `List` (`fill`, with the recipe's `data-*` markers through
|
|
34
|
+
`rootAttributes`) stacks the app-bar `Toolbar` above a `Row` that places
|
|
35
|
+
controlled `ResizableRegion` navigation and inspector panes around a content
|
|
36
|
+
`Pane` that a one-column `Grid` grows to fill. Each region's lone `Pane` fills
|
|
37
|
+
the region's full height, so it reaches the bottom edge the separator does.
|
|
38
|
+
Only those three real panes own a
|
|
39
|
+
`.kui-pane__content` scroll owner; no frame `Pane` wraps the layout in a scroll
|
|
40
|
+
owner that never scrolls. Each pane lists the screen edges it reaches in
|
|
41
|
+
`safeAreaEdges` (the bottom plus its outer side, or both sides when it is the
|
|
42
|
+
only pane shown), and the app-bar `Toolbar` claims the top edge and both sides
|
|
43
|
+
with its own `safeAreaEdges`, so it clears the status area. Below desktop sizes the app reads `deviceClass()` and shows one
|
|
44
|
+
pane at a time, switched by a pressed-state `ToolbarControlGroup`. The recipe
|
|
45
|
+
owns the shell topology; the app owns routing, responsive pane visibility,
|
|
46
|
+
sizes, persistence, and data.
|
|
36
47
|
Keep each visible pane's collapse action in its own toolbar. Once hidden, put
|
|
37
48
|
its restore action in the adjacent main toolbar on the same logical edge:
|
|
38
49
|
leading for an inline-start sidebar and trailing for an inline-end inspector.
|
|
@@ -64,17 +75,19 @@ controls relocate without changing focus order.
|
|
|
64
75
|
|
|
65
76
|
[Open the recipe](../ux-demo/?component=recipe-list-detail-dialog) · [TSX source](../ux-demo/recipes/list-detail-dialog.tsx)
|
|
66
77
|
|
|
67
|
-
The production Web Awesome dialog owns modal focus
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
record actions.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
the
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
The production Web Awesome dialog owns modal focus, Escape, its labeled header,
|
|
79
|
+
and its close control; the thin recipe adapter restores the invoking control
|
|
80
|
+
after the hide event. `DialogSurface` chooses the large modal with no body
|
|
81
|
+
inset, because `SplitView` and its rows own list geometry, and a comfortable
|
|
82
|
+
footer inset for the record actions. On roomy devices `SplitView` shows the
|
|
83
|
+
project list beside its detail; each pane opens with a `ListHeader` on one
|
|
84
|
+
shared line, and the dialog title, both headers, and the list text share the
|
|
85
|
+
17px text edge while the `ValueTable` keeps the 8px outer margin. On compact
|
|
86
|
+
devices the dialog becomes a full-screen sheet and `SplitView` becomes a
|
|
87
|
+
`NavStack` drill-down whose back control the application pops. The
|
|
88
|
+
application owns open state, selection, the pushed detail, dismissal policy,
|
|
89
|
+
and record actions. Do not rebuild the dialog or reach into private shadow
|
|
90
|
+
parts.
|
|
78
91
|
|
|
79
92
|
## Composer form
|
|
80
93
|
|
|
@@ -82,12 +95,13 @@ Do not rebuild the dialog or reach into private shadow parts.
|
|
|
82
95
|
|
|
83
96
|
A direct `ToolbarText` supplies the task title, with app-owned supporting copy
|
|
84
97
|
below; their ids are referenced by the form. `ListInsetText` gives that bare
|
|
85
|
-
supporting copy the same content-item text inset as the fields
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
98
|
+
supporting copy the same content-item text inset as the fields. The title and
|
|
99
|
+
supporting line share a nested heading `List` with `gap="none"`, so the heading
|
|
100
|
+
unit stays together instead of taking the form's 24px section gap. Production
|
|
101
|
+
fields own labels, help, and native focus. One `List` owns the 24px major
|
|
102
|
+
rhythm; the field `List` and the action `Row` use `controlInsets` to sit on the
|
|
103
|
+
shared 8px inline gutter with 8px gaps between related controls, rather than
|
|
104
|
+
acquiring a second content-item padding inset. The app owns
|
|
91
105
|
validation, drafts, permissions, and transport. Persistent error or success
|
|
92
106
|
feedback is the only nested semantic surface and uses `StateBanner`, not a toast.
|
|
93
107
|
Because upgraded Web Awesome fields retain live value properties, controlled
|
|
@@ -111,8 +125,10 @@ Use `ToolbarControlGroup` for related commands, `SegmentedControl` for a few
|
|
|
111
125
|
visible exclusive choices, `Select` for a longer value list, and an ordinary
|
|
112
126
|
button for an independent command. Even that independent button sits in a
|
|
113
127
|
single-control `ToolbarControlGroup`, which keeps its height, pill shape, focus,
|
|
114
|
-
and hover treatment aligned with the adjacent toolbar controls.
|
|
115
|
-
|
|
128
|
+
and hover treatment aligned with the adjacent toolbar controls. At compact
|
|
129
|
+
widths the toolbar stacks its zones and wraps whole trailing groups onto another
|
|
130
|
+
row, so the last action is never clipped. The app owns values, actions,
|
|
131
|
+
persistence, and responsive priority.
|
|
116
132
|
|
|
117
133
|
## Navigation stack
|
|
118
134
|
|
|
@@ -121,8 +137,8 @@ values, actions, persistence, and responsive priority.
|
|
|
121
137
|
Drill from a library list into a detail and back with `NavStack`
|
|
122
138
|
(`@kerfjs/ui/nav-stack`): the app owns the stack as a signal of views and
|
|
123
139
|
pushes/pops it, `NavStack` renders it, and `wireNavStack` slides the content and
|
|
124
|
-
settles the chrome (reduced motion collapses the slide to instant).
|
|
125
|
-
|
|
140
|
+
settles the chrome (reduced motion collapses the slide to instant). See the
|
|
141
|
+
layout guide
|
|
126
142
|
[`app-layouts.md`](app-layouts.md) for choosing among `NavStack`, `SplitView`,
|
|
127
143
|
`Workbench`, and `TabScaffold`.
|
|
128
144
|
|
|
@@ -135,7 +151,9 @@ value-bearing component (`ToolbarText`, `ValueTable`/`ValueTableRow`, `Select`,
|
|
|
135
151
|
`SegmentedControl`, `ListItem`, `StateBanner`) takes its `placeholder` from one
|
|
136
152
|
loading flag, so the same real chrome renders a faithful loading state and then
|
|
137
153
|
the populated record — no separate skeleton markup. The composition is the point;
|
|
138
|
-
`Skeleton` is the primitive it builds on.
|
|
154
|
+
`Skeleton` is the primitive it builds on. Its heading `Toolbar` uses
|
|
155
|
+
`responsive="wrap"`, so on a narrow inspector the toggle moves below a whole
|
|
156
|
+
record title instead of truncating it. The app owns the loading lifecycle and
|
|
139
157
|
which values are still unknown.
|
|
140
158
|
|
|
141
159
|
## Collapsible sidebar
|
|
@@ -145,14 +163,24 @@ which values are still unknown.
|
|
|
145
163
|
A mini app frame whose left navigation rail and bottom activity drawer are
|
|
146
164
|
standalone `CollapsiblePanel`s (`@kerfjs/ui/collapsible-panel`) driven by
|
|
147
165
|
`wireSidebar` (`@kerfjs/ui/wire-sidebar`). `CollapsiblePanelToggle` supplies the
|
|
148
|
-
standard per-side glyph: a collapse toggle lives inside each panel and
|
|
149
|
-
|
|
166
|
+
standard per-side glyph: a collapse toggle lives inside each panel, and the
|
|
167
|
+
always-visible main header shows that panel's expand toggle only while it is
|
|
168
|
+
collapsed, so exactly one control owns each action and a collapsed panel is still
|
|
150
169
|
reachable. `wireSidebar` owns the toggle delegation, moves focus into a panel on
|
|
151
|
-
open
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
170
|
+
open, restores it on close (to the trigger, or to the panel's expand toggle when
|
|
171
|
+
the trigger sits inside the collapsed panel), and — when a `deviceClass()` reports
|
|
172
|
+
`compact` — presents the panels as a dismissable **overlay** (backdrop, Escape
|
|
173
|
+
and backdrop-click collapse, and a trapped Tab ring, the ARIA dialog pattern).
|
|
174
|
+
The overlay starts closed and opens only from a toggle; the rail's signal is
|
|
175
|
+
seeded from the device class with `inlineCollapsed: false`, so the first compact
|
|
176
|
+
render has no overlay and a wide crossing restores the open inline rail. It
|
|
177
|
+
also persists each panel's inline collapsed state through a supplied storage hook. A
|
|
178
|
+
filling `Row` (`fill` plus `rootAttributes`) is the root: it takes the frame's
|
|
179
|
+
definite height and places the rail beside a `List` column, and a one-column
|
|
180
|
+
`Grid` grows the main pane above the drawer. Because the panels sit at the real
|
|
181
|
+
frame edges, each grows through its edge's safe area and hands that edge back to
|
|
182
|
+
its siblings when it collapses; the drawer's activity log is a `ValueTable`. The app owns each
|
|
183
|
+
`collapsed` signal, the panel sizes, and the content; the wire owns the
|
|
156
184
|
ephemeral interaction. For a full three-pane shell use `Workbench` instead — see
|
|
157
185
|
[`app-layouts.md`](app-layouts.md). This recipe is covered end-to-end across
|
|
158
186
|
Chromium, Firefox, and WebKit by `tests/browser/collapsible-sidebar-recipe.spec.ts`.
|
|
@@ -164,9 +192,16 @@ Chromium, Firefox, and WebKit by `tests/browser/collapsible-sidebar-recipe.spec.
|
|
|
164
192
|
- For direct `wa-*` JSX, import types from `@kerfjs/ui/webawesome`. Import only
|
|
165
193
|
individual Web Awesome registration modules and theme them with
|
|
166
194
|
`@kerfjs/ui/webawesome.css`.
|
|
167
|
-
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
195
|
+
- Compose, don't style. A recipe ships no stylesheet, sets no inline style, and
|
|
196
|
+
names no class outside the published layout vocabulary (`.kui-content`,
|
|
197
|
+
`.kui-content-item`, …) and themed Web Awesome classes; it configures
|
|
198
|
+
components through props, `rootAttributes`, and tokens. When a recipe needs a
|
|
199
|
+
capability no component offers, record it as a component gap rather than
|
|
200
|
+
papering over it with CSS. `npm run check:recipes` enforces these rules on
|
|
201
|
+
every file in `ux-demo/recipes/`.
|
|
202
|
+
- Each recipe also exports a catalog-only `presentation`: the `CatalogExample`
|
|
203
|
+
viewport that frames it in the UX catalog and its ownership note. An
|
|
204
|
+
application that copies the recipe ignores that export and mounts the
|
|
205
|
+
controller into its own container.
|
|
171
206
|
- Start from the copyable mount adapter, or reproduce its complete boundary:
|
|
172
207
|
wire stable `data-action` hooks once and retain every disposer.
|
package/docs/split-view.md
CHANGED
|
@@ -13,6 +13,14 @@ import "@kerfjs/ui/split-view.css";
|
|
|
13
13
|
// wireResizableRegions / wireNavStack for the interactive behavior.
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
+
## Safe areas
|
|
17
|
+
|
|
18
|
+
The list pane grows by the inline-start unsafe inset and pads for the edges it
|
|
19
|
+
touches; the detail pads for its own outer edges. Neither is inset on the
|
|
20
|
+
shared interior edge. A pane whose only child is a `Pane` lets that child own
|
|
21
|
+
the insets, and the compact form hands them to its `NavStack`. See
|
|
22
|
+
[Choosing an app layout › Safe areas](app-layouts.md#safe-areas).
|
|
23
|
+
|
|
16
24
|
## Responsive by device class
|
|
17
25
|
|
|
18
26
|
`SplitView` is declarative; the app derives `compact` from the device class and
|
package/docs/tab-scaffold.md
CHANGED
|
@@ -45,8 +45,10 @@ const dispose = wireTabScaffold(root, {
|
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
Each `TabScaffoldTab` has an `id`, `label`, optional `icon`, and `content`. The
|
|
48
|
-
bottom bar
|
|
49
|
-
|
|
48
|
+
bottom bar paints through the home-indicator safe area and pads for it and for
|
|
49
|
+
the side insets, while each scene pads for the top and side insets (a scene
|
|
50
|
+
whose only child is a `NavStack` or `Pane` lets that child own them; see
|
|
51
|
+
[Choosing an app layout › Safe areas](app-layouts.md#safe-areas)). The bar keeps 44px targets. Its single-line labels preserve their full line box and
|
|
50
52
|
truncate horizontally with an ellipsis when a destination name exceeds its
|
|
51
53
|
share of the bar. On larger device classes, promote the tab set to a
|
|
52
54
|
`Workbench` rail or a persistent sidebar instead of a bottom bar.
|