@kerfjs/ui 4.4.1 → 5.0.0-beta.10

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.
Files changed (292) hide show
  1. package/README.md +240 -10
  2. package/ai/component-catalog.json +4766 -0
  3. package/ai/component-catalog.schema.json +79 -0
  4. package/ai/public-api-signatures-v1.md +1327 -0
  5. package/ai/skill.md +73 -11
  6. package/ai/webawesome-jsx-signatures-v1.md +106 -0
  7. package/dist/app-tab.d.ts +14 -2
  8. package/dist/app-tab.js +3 -1
  9. package/dist/browser/app-tab.js +3 -2
  10. package/dist/browser/disclosure-arrow.js +4 -0
  11. package/dist/browser/empty-state.js +3 -3
  12. package/dist/browser/list-action-row.js +4 -0
  13. package/dist/browser/list-header.js +6 -0
  14. package/dist/browser/list-item.js +4 -0
  15. package/dist/browser/loading-spinner.js +2 -2
  16. package/dist/browser/lucide-icon.js +2 -2
  17. package/dist/browser/panel-header.js +7 -0
  18. package/dist/browser/resizable-region.js +2 -2
  19. package/dist/browser/segmented-control.js +3 -2
  20. package/dist/browser/select.js +4 -3
  21. package/dist/browser/skeleton.js +3 -0
  22. package/dist/browser/state-banner.js +3 -2
  23. package/dist/browser/tab-bar.js +2 -2
  24. package/dist/browser/token-search-field.js +4 -0
  25. package/dist/browser/toolbar-control-group.js +2 -2
  26. package/dist/browser/toolbar-text.js +3 -2
  27. package/dist/browser/toolbar.js +2 -2
  28. package/dist/browser/value-table.js +3 -2
  29. package/dist/catalog.d.ts +119 -0
  30. package/dist/catalog.js +143 -0
  31. package/dist/catalog.js.map +1 -0
  32. package/dist/chunk-2Z5TWHKQ.js +34 -0
  33. package/dist/chunk-2Z5TWHKQ.js.map +1 -0
  34. package/dist/chunk-37T3VNIZ.js +19 -0
  35. package/dist/chunk-37T3VNIZ.js.map +1 -0
  36. package/dist/chunk-56RJXPHG.js +43 -0
  37. package/dist/chunk-56RJXPHG.js.map +1 -0
  38. package/dist/chunk-7BR3DO2A.js +31 -0
  39. package/dist/chunk-7BR3DO2A.js.map +1 -0
  40. package/dist/chunk-7JB7VPRI.js +34 -0
  41. package/dist/chunk-7JB7VPRI.js.map +1 -0
  42. package/dist/chunk-7LDCTU7D.js +134 -0
  43. package/dist/chunk-7LDCTU7D.js.map +1 -0
  44. package/dist/{chunk-4HHCYSGT.js → chunk-AQNKJRFH.js} +2 -2
  45. package/dist/{chunk-4HHCYSGT.js.map → chunk-AQNKJRFH.js.map} +1 -1
  46. package/dist/{chunk-MBR3TYNL.js → chunk-AVZHJN6C.js} +3 -3
  47. package/dist/chunk-AVZHJN6C.js.map +1 -0
  48. package/dist/chunk-B24C4A6T.js +22 -0
  49. package/dist/chunk-B24C4A6T.js.map +1 -0
  50. package/dist/chunk-BLK3UEEI.js +23 -0
  51. package/dist/chunk-BLK3UEEI.js.map +1 -0
  52. package/dist/chunk-CVZYNJJ5.js +265 -0
  53. package/dist/chunk-CVZYNJJ5.js.map +1 -0
  54. package/dist/chunk-I7INRJO4.js +17 -0
  55. package/dist/chunk-I7INRJO4.js.map +1 -0
  56. package/dist/chunk-L4OKFDJY.js +24 -0
  57. package/dist/chunk-L4OKFDJY.js.map +1 -0
  58. package/dist/chunk-LC3YSAZC.js +39 -0
  59. package/dist/chunk-LC3YSAZC.js.map +1 -0
  60. package/dist/{chunk-3O7ZEUW2.js → chunk-M5JRI6MN.js} +3 -3
  61. package/dist/chunk-M5JRI6MN.js.map +1 -0
  62. package/dist/chunk-RUNWEPR4.js +10 -0
  63. package/dist/chunk-RUNWEPR4.js.map +1 -0
  64. package/dist/chunk-W5EQ3HYQ.js +42 -0
  65. package/dist/chunk-W5EQ3HYQ.js.map +1 -0
  66. package/dist/{chunk-MQIZAD4A.js → chunk-XXMOARTH.js} +5 -3
  67. package/dist/chunk-XXMOARTH.js.map +1 -0
  68. package/dist/chunk-Y5MRDTLC.js +20 -0
  69. package/dist/chunk-Y5MRDTLC.js.map +1 -0
  70. package/dist/{chunk-TRNBHPNW.js → chunk-YGN7OMLT.js} +11 -8
  71. package/dist/chunk-YGN7OMLT.js.map +1 -0
  72. package/dist/collapsible-panel.d.ts +66 -0
  73. package/dist/collapsible-panel.js +22 -0
  74. package/dist/collapsible-panel.js.map +1 -0
  75. package/dist/device-class.d.ts +62 -0
  76. package/dist/device-class.js +75 -0
  77. package/dist/device-class.js.map +1 -0
  78. package/dist/disclosure-arrow.d.ts +14 -0
  79. package/dist/disclosure-arrow.js +4 -0
  80. package/dist/disclosure-arrow.js.map +1 -0
  81. package/dist/index.d.ts +10 -6
  82. package/dist/index.js +21 -16
  83. package/dist/list-action-row.d.ts +52 -0
  84. package/dist/list-action-row.js +5 -0
  85. package/dist/list-action-row.js.map +1 -0
  86. package/dist/list-header.d.ts +43 -0
  87. package/dist/list-header.js +7 -0
  88. package/dist/list-header.js.map +1 -0
  89. package/dist/list-item.d.ts +33 -0
  90. package/dist/list-item.js +5 -0
  91. package/dist/list-item.js.map +1 -0
  92. package/dist/nav-stack.d.ts +38 -0
  93. package/dist/nav-stack.js +5 -0
  94. package/dist/nav-stack.js.map +1 -0
  95. package/dist/panel-header.d.ts +36 -0
  96. package/dist/panel-header.js +7 -0
  97. package/dist/panel-header.js.map +1 -0
  98. package/dist/resizable-region.d.ts +3 -1
  99. package/dist/resizable-region.js +1 -1
  100. package/dist/segmented-control.d.ts +3 -1
  101. package/dist/segmented-control.js +2 -1
  102. package/dist/select-register.d.ts +5 -1
  103. package/dist/select-register.js +3 -0
  104. package/dist/select-register.js.map +1 -1
  105. package/dist/select.d.ts +5 -2
  106. package/dist/select.js +2 -1
  107. package/dist/skeleton.d.ts +24 -0
  108. package/dist/skeleton.js +3 -0
  109. package/dist/skeleton.js.map +1 -0
  110. package/dist/split-view.d.ts +42 -0
  111. package/dist/split-view.js +21 -0
  112. package/dist/split-view.js.map +1 -0
  113. package/dist/state-banner.d.ts +3 -1
  114. package/dist/state-banner.js +2 -1
  115. package/dist/styles/app-tab.css +152 -0
  116. package/dist/styles/catalog.css +498 -0
  117. package/dist/styles/collapsible-panel.css +146 -0
  118. package/dist/styles/disclosure-arrow.css +23 -0
  119. package/dist/styles/empty-state.css +47 -0
  120. package/dist/styles/foundation.css +347 -0
  121. package/dist/styles/layout.css +73 -0
  122. package/dist/styles/list-action-row.css +160 -0
  123. package/dist/styles/list-header.css +160 -0
  124. package/dist/styles/list-item.css +123 -0
  125. package/dist/styles/loading-spinner.css +21 -0
  126. package/dist/styles/lucide-icon.css +6 -0
  127. package/dist/styles/nav-stack.css +111 -0
  128. package/dist/styles/panel-header.css +64 -0
  129. package/dist/styles/resizable-region.css +111 -0
  130. package/{src → dist/styles}/segmented-control.css +62 -31
  131. package/dist/styles/select.css +138 -0
  132. package/dist/styles/skeleton.css +31 -0
  133. package/dist/styles/split-view.css +35 -0
  134. package/dist/styles/state-banner.css +173 -0
  135. package/dist/styles/styles.css +23 -0
  136. package/dist/styles/tab-bar.css +45 -0
  137. package/dist/styles/tab-scaffold.css +84 -0
  138. package/dist/styles/token-search-field.css +289 -0
  139. package/dist/styles/toolbar-control-group.css +211 -0
  140. package/dist/styles/toolbar-text.css +40 -0
  141. package/dist/styles/toolbar.css +61 -0
  142. package/dist/styles/value-table.css +75 -0
  143. package/{src → dist/styles}/webawesome.css +119 -29
  144. package/dist/styles/workbench.css +94 -0
  145. package/dist/tab-bar.d.ts +8 -1
  146. package/dist/tab-bar.js +1 -1
  147. package/dist/tab-scaffold.d.ts +30 -0
  148. package/dist/tab-scaffold.js +16 -0
  149. package/dist/tab-scaffold.js.map +1 -0
  150. package/dist/token-search-field.d.ts +43 -0
  151. package/dist/token-search-field.js +4 -0
  152. package/dist/token-search-field.js.map +1 -0
  153. package/dist/toolbar-text.d.ts +15 -3
  154. package/dist/toolbar-text.js +2 -1
  155. package/dist/value-table.d.ts +12 -2
  156. package/dist/value-table.js +2 -1
  157. package/dist/webawesome.d.ts +100 -0
  158. package/dist/webawesome.js +3 -0
  159. package/dist/webawesome.js.map +1 -0
  160. package/dist/wire-catalog.d.ts +26 -0
  161. package/dist/wire-catalog.js +48 -0
  162. package/dist/wire-catalog.js.map +1 -0
  163. package/dist/wire-nav-stack.d.ts +15 -0
  164. package/dist/wire-nav-stack.js +88 -0
  165. package/dist/wire-nav-stack.js.map +1 -0
  166. package/dist/wire-resizable-regions.js +1 -1
  167. package/dist/wire-sidebar.d.ts +43 -0
  168. package/dist/wire-sidebar.js +117 -0
  169. package/dist/wire-sidebar.js.map +1 -0
  170. package/dist/wire-tab-bars.d.ts +15 -2
  171. package/dist/wire-tab-bars.js +1 -1
  172. package/dist/wire-tab-scaffold.d.ts +11 -0
  173. package/dist/wire-tab-scaffold.js +16 -0
  174. package/dist/wire-tab-scaffold.js.map +1 -0
  175. package/dist/wire-token-search-fields.d.ts +97 -0
  176. package/dist/wire-token-search-fields.js +5 -0
  177. package/dist/wire-token-search-fields.js.map +1 -0
  178. package/dist/workbench.d.ts +33 -0
  179. package/dist/workbench.js +17 -0
  180. package/dist/workbench.js.map +1 -0
  181. package/docs/accessibility.md +101 -3
  182. package/docs/app-layouts.md +61 -0
  183. package/docs/catalog.md +155 -0
  184. package/docs/collapsible-panel.md +102 -0
  185. package/docs/component-contract.md +169 -4
  186. package/docs/component-selection.md +185 -0
  187. package/docs/design/templates/panel-header/icon-actions-dark.svg +1 -0
  188. package/docs/design/templates/panel-header/icon-actions.svg +1 -0
  189. package/docs/design/templates/panel-header/icon-summary-actions-dark.svg +1 -0
  190. package/docs/design/templates/panel-header/icon-summary-actions.svg +1 -0
  191. package/docs/design/templates/panel-header/no-icon-dark.svg +1 -0
  192. package/docs/design/templates/panel-header/no-icon.svg +1 -0
  193. package/docs/design/templates/panel-header/page-heading-dark.svg +1 -0
  194. package/docs/design/templates/panel-header/page-heading.svg +1 -0
  195. package/docs/design/templates/panel-header/title-only-dark.svg +1 -0
  196. package/docs/design/templates/panel-header/title-only.svg +1 -0
  197. package/docs/design/templates/panel-header-dark.svg +13 -0
  198. package/docs/design/templates/panel-header.svg +13 -0
  199. package/docs/design/templates/toolbar-control-group/borderless-single-dark.svg +1 -0
  200. package/docs/design/templates/toolbar-control-group/borderless-single.svg +1 -0
  201. package/docs/design/templates/toolbar-control-group/icon-buttons-dark.svg +1 -0
  202. package/docs/design/templates/toolbar-control-group/icon-buttons.svg +1 -0
  203. package/docs/design/templates/toolbar-control-group/push-buttons-dark.svg +1 -0
  204. package/docs/design/templates/toolbar-control-group/push-buttons.svg +1 -0
  205. package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -0
  206. package/docs/design/templates/toolbar-control-group/with-text.svg +1 -0
  207. package/docs/design/templates/toolbar-control-group-dark.svg +11 -0
  208. package/docs/design/templates/toolbar-control-group.svg +11 -0
  209. package/docs/design/templates.md +83 -0
  210. package/docs/design-philosophy.md +61 -1
  211. package/docs/device-class.md +54 -0
  212. package/docs/examples/command-palette-adapter.tsx +70 -0
  213. package/docs/layout.md +131 -0
  214. package/docs/nav-stack.md +47 -0
  215. package/docs/recipes.md +167 -0
  216. package/docs/split-view.md +49 -0
  217. package/docs/tab-scaffold.md +41 -0
  218. package/docs/ux-demo.md +23 -9
  219. package/docs/webawesome-theme.md +15 -0
  220. package/docs/workbench.md +47 -0
  221. package/llms.txt +123 -14
  222. package/package.json +139 -44
  223. package/ux-demo/recipes/app-shell.tsx +32 -0
  224. package/ux-demo/recipes/collapsible-sidebar.tsx +100 -0
  225. package/ux-demo/recipes/compact-toolbar.tsx +43 -0
  226. package/ux-demo/recipes/composer-form.tsx +63 -0
  227. package/ux-demo/recipes/list-detail-dialog.tsx +45 -0
  228. package/ux-demo/recipes/list-workspace-states.tsx +26 -0
  229. package/ux-demo/recipes/loaders.ts +33 -0
  230. package/ux-demo/recipes/loading-inspector.tsx +81 -0
  231. package/ux-demo/recipes/mount-recipe.ts +43 -0
  232. package/ux-demo/recipes/navigation-sidebar.tsx +26 -0
  233. package/ux-demo/recipes/navigation-stack.tsx +76 -0
  234. package/ux-demo/recipes/recipes.css +448 -0
  235. package/ux-demo/recipes/types.ts +17 -0
  236. package/ux-demo/recipes/workspace-header.tsx +12 -0
  237. package/dist/browser/dialog-header.js +0 -3
  238. package/dist/browser/menu-header.js +0 -3
  239. package/dist/browser/menu-item.js +0 -3
  240. package/dist/browser/page-header.js +0 -3
  241. package/dist/chunk-2PES33HS.js +0 -13
  242. package/dist/chunk-2PES33HS.js.map +0 -1
  243. package/dist/chunk-3O7ZEUW2.js.map +0 -1
  244. package/dist/chunk-723YNJBH.js +0 -17
  245. package/dist/chunk-723YNJBH.js.map +0 -1
  246. package/dist/chunk-GY5WH7TO.js +0 -10
  247. package/dist/chunk-GY5WH7TO.js.map +0 -1
  248. package/dist/chunk-MBR3TYNL.js.map +0 -1
  249. package/dist/chunk-MQIZAD4A.js.map +0 -1
  250. package/dist/chunk-NHXX4JI5.js +0 -28
  251. package/dist/chunk-NHXX4JI5.js.map +0 -1
  252. package/dist/chunk-OPCJRCYO.js +0 -19
  253. package/dist/chunk-OPCJRCYO.js.map +0 -1
  254. package/dist/chunk-T5XNMVOI.js +0 -24
  255. package/dist/chunk-T5XNMVOI.js.map +0 -1
  256. package/dist/chunk-TRNBHPNW.js.map +0 -1
  257. package/dist/chunk-VHW5YNIB.js +0 -17
  258. package/dist/chunk-VHW5YNIB.js.map +0 -1
  259. package/dist/chunk-VKH2JLDZ.js +0 -10
  260. package/dist/chunk-VKH2JLDZ.js.map +0 -1
  261. package/dist/chunk-WY4CAEPG.js +0 -14
  262. package/dist/chunk-WY4CAEPG.js.map +0 -1
  263. package/dist/dialog-header.d.ts +0 -14
  264. package/dist/dialog-header.js +0 -3
  265. package/dist/dialog-header.js.map +0 -1
  266. package/dist/menu-header.d.ts +0 -15
  267. package/dist/menu-header.js +0 -3
  268. package/dist/menu-header.js.map +0 -1
  269. package/dist/menu-item.d.ts +0 -22
  270. package/dist/menu-item.js +0 -3
  271. package/dist/menu-item.js.map +0 -1
  272. package/dist/page-header.d.ts +0 -9
  273. package/dist/page-header.js +0 -3
  274. package/dist/page-header.js.map +0 -1
  275. package/src/app-tab.css +0 -20
  276. package/src/dialog-header.css +0 -9
  277. package/src/empty-state.css +0 -6
  278. package/src/foundation.css +0 -106
  279. package/src/loading-spinner.css +0 -4
  280. package/src/lucide-icon.css +0 -1
  281. package/src/menu-header.css +0 -13
  282. package/src/menu-item.css +0 -12
  283. package/src/page-header.css +0 -3
  284. package/src/resizable-region.css +0 -19
  285. package/src/select.css +0 -18
  286. package/src/state-banner.css +0 -31
  287. package/src/styles.css +0 -18
  288. package/src/tab-bar.css +0 -4
  289. package/src/toolbar-control-group.css +0 -25
  290. package/src/toolbar-text.css +0 -4
  291. package/src/toolbar.css +0 -9
  292. package/src/value-table.css +0 -5
@@ -0,0 +1,13 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="752" height="806" viewBox="0 0 752 806">
2
+ <rect width="752" height="806" fill="#ffffff"/>
3
+ <text x="16" y="30" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#6e6e73">Icon, summary, and action</text>
4
+ <svg x="16" y="38" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 136" width="720" height="136"><defs><clipPath id="v0-cp0"><rect x="28" y="28" width="550.7" height="44"/></clipPath><clipPath id="v0-ov1"><rect x="28" y="28" width="550.7" height="44" rx="0"/></clipPath><clipPath id="v0-cp2"><rect x="39" y="39" width="22" height="22"/></clipPath><clipPath id="v0-cp3"><rect x="80" y="28" width="189.8" height="44"/></clipPath><clipPath id="v0-ct4"><rect x="80" y="28" width="189.8" height="44"/></clipPath><clipPath id="v0-ct5"><rect x="586.7" y="34" width="65.3" height="32"/></clipPath><clipPath id="v0-cp6"><rect x="20" y="80" width="640" height="18"/></clipPath><clipPath id="v0-ct7"><rect x="20" y="80" width="640" height="18"/></clipPath></defs><g clip-path="url(#v0-cp0)"><g clip-path="url(#v0-ov1)"><rect x="28" y="28" width="44" height="44" rx="22" fill="rgb(235,245,255)"/><rect x="28.5" y="28.5" width="43" height="43" rx="21.5" fill="none" stroke="rgb(235,245,255)" stroke-width="1"/><g clip-path="url(#v0-cp2)"><g transform="translate(39 39)" color="rgb(30, 110, 244)"><svg data-lucide="file-text" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(30, 110, 244)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="ui-sans-serif, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif" style="overflow:hidden" width="22" height="22"><path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2 2 0 0 1 1.7.7l3.6 3.6A2 2 0 0 1 20 8v12a2 2 0 0 1-2 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(30, 110, 244)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M14 2v5a1 1 0 0 0 1 1h5" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(30, 110, 244)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M10 9H8" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(30, 110, 244)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M16 13H8" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(30, 110, 244)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M16 17H8" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(30, 110, 244)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g><g clip-path="url(#v0-cp3)"><g clip-path="url(#v0-ct4)"><text x="88" y="57" font-family="&quot;ui-sans-serif&quot;, &quot;-apple-system&quot;, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif" font-size="20" font-weight="650" fill="rgb(29,29,31)">Northstar migration</text></g></g></g></g><rect x="586.7" y="34" width="65.3" height="32" rx="16" fill="rgb(255,255,255)"/><rect x="587.5" y="34.5" width="64" height="31" rx="15.5" fill="none" stroke="rgb(209,209,214)" stroke-width="1"/><text x="599.66" y="56" font-family="&quot;ui-sans-serif&quot;, &quot;-apple-system&quot;, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif" font-size="16" fill="rgb(29,29,31)">Open</text><g clip-path="url(#v0-cp6)"><g clip-path="url(#v0-ct7)"><text x="88" y="95" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(110,110,115)">In review · updated today</text></g></g></svg>
5
+ <text x="16" y="204" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#6e6e73">Icon and action, no summary</text>
6
+ <svg x="16" y="212" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 112" width="720" height="112"><defs><clipPath id="v1-cp0"><rect x="28" y="28" width="551.7" height="44"/></clipPath><clipPath id="v1-ov1"><rect x="28" y="28" width="551.7" height="44" rx="0"/></clipPath><clipPath id="v1-cp2"><rect x="39" y="39" width="22" height="22"/></clipPath><clipPath id="v1-cp3"><rect x="80" y="28" width="154.5" height="44"/></clipPath><clipPath id="v1-ct4"><rect x="80" y="28" width="154.5" height="44"/></clipPath><clipPath id="v1-ct5"><rect x="587.7" y="34" width="64.3" height="32"/></clipPath></defs><g clip-path="url(#v1-cp0)"><g clip-path="url(#v1-ov1)"><rect x="28" y="28" width="44" height="44" rx="22" fill="rgb(235,245,255)"/><rect x="28.5" y="28.5" width="43" height="43" rx="21.5" fill="none" stroke="rgb(235,245,255)" stroke-width="1"/><g clip-path="url(#v1-cp2)"><g transform="translate(39 39)" color="rgb(30, 110, 244)"><svg data-lucide="folder" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(30, 110, 244)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="ui-sans-serif, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif" style="overflow:hidden" width="22" height="22"><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(30, 110, 244)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g><g clip-path="url(#v1-cp3)"><g clip-path="url(#v1-ct4)"><text x="88" y="57" font-family="&quot;ui-sans-serif&quot;, &quot;-apple-system&quot;, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif" font-size="20" font-weight="650" fill="rgb(29,29,31)">Package details</text></g></g></g></g><rect x="587.7" y="34" width="64.3" height="32" rx="16" fill="rgb(255,255,255)"/><rect x="588.5" y="34.5" width="63" height="31" rx="15.5" fill="none" stroke="rgb(209,209,214)" stroke-width="1"/><text x="600.69" y="56" font-family="&quot;ui-sans-serif&quot;, &quot;-apple-system&quot;, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif" font-size="16" fill="rgb(29,29,31)">Done</text></svg>
7
+ <text x="16" y="354" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#6e6e73">No icon, summary and action</text>
8
+ <svg x="16" y="362" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 136" width="720" height="136"><defs><clipPath id="v2-cp0"><rect x="28" y="28" width="557.5" height="44"/></clipPath><clipPath id="v2-ov1"><rect x="28" y="28" width="557.5" height="44" rx="0"/></clipPath><clipPath id="v2-cp2"><rect x="28" y="28" width="191.4" height="44"/></clipPath><clipPath id="v2-ct3"><rect x="28" y="28" width="191.4" height="44"/></clipPath><clipPath id="v2-ct4"><rect x="593.5" y="34" width="58.5" height="32"/></clipPath><clipPath id="v2-cp5"><rect x="20" y="80" width="640" height="18"/></clipPath><clipPath id="v2-ct6"><rect x="20" y="80" width="640" height="18"/></clipPath></defs><g clip-path="url(#v2-cp0)"><g clip-path="url(#v2-ov1)"><g clip-path="url(#v2-cp2)"><g clip-path="url(#v2-ct3)"><text x="36" y="57" font-family="&quot;ui-sans-serif&quot;, &quot;-apple-system&quot;, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif" font-size="20" font-weight="650" fill="rgb(29,29,31)">Workspace settings</text></g></g></g></g><rect x="593.5" y="34" width="58.5" height="32" rx="16" fill="rgb(255,255,255)"/><rect x="594.5" y="34.5" width="57" height="31" rx="15.5" fill="none" stroke="rgb(209,209,214)" stroke-width="1"/><text x="606.53" y="56" font-family="&quot;ui-sans-serif&quot;, &quot;-apple-system&quot;, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif" font-size="16" fill="rgb(29,29,31)">New</text><g clip-path="url(#v2-cp5)"><g clip-path="url(#v2-ct6)"><text x="36" y="95" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(110,110,115)">Manage members, billing, and integrations.</text></g></g></svg>
9
+ <text x="16" y="528" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#6e6e73">Title only</text>
10
+ <svg x="16" y="536" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 104" width="720" height="104"><defs><clipPath id="v3-cp0"><rect x="28" y="28" width="616" height="44"/></clipPath><clipPath id="v3-ov1"><rect x="28" y="28" width="616" height="44" rx="0"/></clipPath><clipPath id="v3-cp2"><rect x="28" y="28" width="146.9" height="44"/></clipPath><clipPath id="v3-ct3"><rect x="28" y="28" width="146.9" height="44"/></clipPath></defs><g clip-path="url(#v3-cp0)"><g clip-path="url(#v3-ov1)"><g clip-path="url(#v3-cp2)"><g clip-path="url(#v3-ct3)"><text x="36" y="57" font-family="&quot;ui-sans-serif&quot;, &quot;-apple-system&quot;, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif" font-size="20" font-weight="650" fill="rgb(29,29,31)">Recent activity</text></g></g></g></g></svg>
11
+ <text x="16" y="670" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#6e6e73">Page heading (h1) with action</text>
12
+ <svg x="16" y="678" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 112" width="720" height="112"><defs><clipPath id="v4-cp0"><rect x="28" y="28" width="500.7" height="44"/></clipPath><clipPath id="v4-ov1"><rect x="28" y="28" width="500.7" height="44" rx="0"/></clipPath><clipPath id="v4-cp2"><rect x="28" y="28" width="144.6" height="44"/></clipPath><clipPath id="v4-ct3"><rect x="28" y="28" width="144.6" height="44"/></clipPath><clipPath id="v4-ct4"><rect x="536.7" y="34" width="115.3" height="32"/></clipPath></defs><g clip-path="url(#v4-cp0)"><g clip-path="url(#v4-ov1)"><g clip-path="url(#v4-cp2)"><g clip-path="url(#v4-ct3)"><text x="36" y="57" font-family="&quot;ui-sans-serif&quot;, &quot;-apple-system&quot;, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif" font-size="20" font-weight="650" fill="rgb(29,29,31)">UI foundations</text></g></g></g></g><rect x="536.7" y="34" width="115.3" height="32" rx="16" fill="rgb(255,255,255)"/><rect x="537.5" y="34.5" width="114" height="31" rx="15.5" fill="none" stroke="rgb(209,209,214)" stroke-width="1"/><text x="549.7" y="56" font-family="&quot;ui-sans-serif&quot;, &quot;-apple-system&quot;, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif" font-size="16" fill="rgb(29,29,31)">New pattern</text></svg>
13
+ </svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="34" y="34" width="16" height="16"/></clipPath></defs><rect x="20.5" y="20.5" width="43" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g transform="translate(34 34)" color="rgb(174, 174, 178)"><svg data-lucide="plus" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><path d="M5 12h14" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M12 5v14" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="34" y="34" width="16" height="16"/></clipPath></defs><rect x="20.5" y="20.5" width="43" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g transform="translate(34 34)" color="rgb(110, 110, 115)"><svg data-lucide="plus" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><path d="M5 12h14" 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="M12 5v14" 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"/></svg></g></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="34" y="34" width="16" height="16"/></clipPath><clipPath id="cp1"><rect x="74" y="34" width="16" height="16"/></clipPath><clipPath id="cp2"><rect x="114" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="124" height="44" rx="22" fill="rgb(58,58,60)"/><rect x="20.5" y="20.5" width="123" height="43" rx="21.5" fill="none" stroke="rgb(72,72,74)" stroke-width="1"/><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g transform="translate(34 34)" color="rgb(174, 174, 178)"><svg data-lucide="list" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><path d="M3 5z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g><rect x="62.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp1)"><g transform="translate(74 34)" color="rgb(174, 174, 178)"><svg data-lucide="columns-3" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><rect width="18" height="18" x="3" y="3" rx="2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g><rect x="102.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp2)"><g transform="translate(114 34)" color="rgb(174, 174, 178)"><svg data-lucide="settings" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><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(174, 174, 178)" 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(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="34" y="34" width="16" height="16"/></clipPath><clipPath id="cp1"><rect x="74" y="34" width="16" height="16"/></clipPath><clipPath id="cp2"><rect x="114" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="124" height="44" rx="22" fill="rgb(229,229,234)"/><rect x="20.5" y="20.5" width="123" height="43" rx="21.5" fill="none" stroke="rgb(209,209,214)" stroke-width="1"/><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g transform="translate(34 34)" color="rgb(110, 110, 115)"><svg data-lucide="list" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><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"/></svg></g></g><rect x="62.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp1)"><g transform="translate(74 34)" color="rgb(110, 110, 115)"><svg data-lucide="columns-3" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><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"/></svg></g></g><rect x="102.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp2)"><g transform="translate(114 34)" color="rgb(110, 110, 115)"><svg data-lucide="settings" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><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"/></svg></g></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="34" y="34" width="16" height="16"/></clipPath><clipPath id="cp1"><rect x="74" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="84" height="44" rx="22" fill="rgb(58,58,60)"/><rect x="20.5" y="20.5" width="83" height="43" rx="21.5" fill="none" stroke="rgb(72,72,74)" stroke-width="1"/><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g transform="translate(34 34)" color="rgb(174, 174, 178)"><svg data-lucide="list" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><path d="M3 5z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g><rect x="62.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp1)"><g transform="translate(74 34)" color="rgb(174, 174, 178)"><svg data-lucide="columns-3" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><rect width="18" height="18" x="3" y="3" rx="2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="34" y="34" width="16" height="16"/></clipPath><clipPath id="cp1"><rect x="74" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="84" height="44" rx="22" fill="rgb(229,229,234)"/><rect x="20.5" y="20.5" width="83" height="43" rx="21.5" fill="none" stroke="rgb(209,209,214)" stroke-width="1"/><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g transform="translate(34 34)" color="rgb(110, 110, 115)"><svg data-lucide="list" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><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"/></svg></g></g><rect x="62.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp1)"><g transform="translate(74 34)" color="rgb(110, 110, 115)"><svg data-lucide="columns-3" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><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"/></svg></g></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="22" y="22" width="82.8" height="40"/></clipPath><clipPath id="ct1"><rect x="22" y="22" width="82.8" height="40"/></clipPath><clipPath id="cp2"><rect x="116.8" y="34" width="16.2" height="16"/></clipPath></defs><rect x="20.5" y="20.5" width="126" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g clip-path="url(#ct1)"><text x="30" y="46" font-family="&quot;ui-monospace&quot;, &quot;SFMono-Regular&quot;, &quot;Menlo&quot;, monospace" font-size="12" font-weight="650" fill="rgb(174,174,178)">Workspace</text></g></g><rect x="105.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp2)"><g transform="translate(116.8 34)" color="rgb(174, 174, 178)"><svg data-lucide="bell" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><path d="M10.3 21a2 2 0 0 0 3.4 0" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3.3 15.3A1 1 0 0 0 4 17h16a1 1 0 0 0 .7-1.7C19.4 14 18 12.5 18 8A6 6 0 0 0 6 8c0 4.5-1.4 6-2.7 7.3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="22" y="22" width="82.8" height="40"/></clipPath><clipPath id="ct1"><rect x="22" y="22" width="82.8" height="40"/></clipPath><clipPath id="cp2"><rect x="116.8" y="34" width="16.2" height="16"/></clipPath></defs><rect x="20.5" y="20.5" width="126" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g clip-path="url(#ct1)"><text x="30" y="46" font-family="&quot;ui-monospace&quot;, &quot;SFMono-Regular&quot;, &quot;Menlo&quot;, monospace" font-size="12" font-weight="650" fill="rgb(110,110,115)">Workspace</text></g></g><rect x="105.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp2)"><g transform="translate(116.8 34)" color="rgb(110, 110, 115)"><svg data-lucide="bell" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><path d="M10.3 21a2 2 0 0 0 3.4 0" 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.3 15.3A1 1 0 0 0 4 17h16a1 1 0 0 0 .7-1.7C19.4 14 18 12.5 18 8A6 6 0 0 0 6 8c0 4.5-1.4 6-2.7 7.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"/></svg></g></g></svg>
@@ -0,0 +1,11 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="552" height="552" viewBox="0 0 552 552">
2
+ <rect width="552" height="552" fill="#1c1c1e"/>
3
+ <text x="16" y="30" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#aeaeb2">Bordered group of icon buttons</text>
4
+ <svg x="16" y="38" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="v0-cp0"><rect x="34" y="34" width="16" height="16"/></clipPath><clipPath id="v0-cp1"><rect x="74" y="34" width="16" height="16"/></clipPath><clipPath id="v0-cp2"><rect x="114" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="124" height="44" rx="22" fill="rgb(58,58,60)"/><rect x="20.5" y="20.5" width="123" height="43" rx="21.5" fill="none" stroke="rgb(72,72,74)" stroke-width="1"/><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v0-cp0)"><g transform="translate(34 34)" color="rgb(174, 174, 178)"><svg data-lucide="list" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><path d="M3 5z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g><rect x="62.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v0-cp1)"><g transform="translate(74 34)" color="rgb(174, 174, 178)"><svg data-lucide="columns-3" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><rect width="18" height="18" x="3" y="3" rx="2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g><rect x="102.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v0-cp2)"><g transform="translate(114 34)" color="rgb(174, 174, 178)"><svg data-lucide="settings" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><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(174, 174, 178)" 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(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g></svg>
5
+ <text x="16" y="164" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#aeaeb2">Borderless single control</text>
6
+ <svg x="16" y="172" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="v1-cp0"><rect x="34" y="34" width="16" height="16"/></clipPath></defs><rect x="20.5" y="20.5" width="43" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v1-cp0)"><g transform="translate(34 34)" color="rgb(174, 174, 178)"><svg data-lucide="plus" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><path d="M5 12h14" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M12 5v14" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g></svg>
7
+ <text x="16" y="298" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#aeaeb2">Label text beside a control</text>
8
+ <svg x="16" y="306" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="v2-cp0"><rect x="22" y="22" width="82.8" height="40"/></clipPath><clipPath id="v2-ct1"><rect x="22" y="22" width="82.8" height="40"/></clipPath><clipPath id="v2-cp2"><rect x="116.8" y="34" width="16.2" height="16"/></clipPath></defs><rect x="20.5" y="20.5" width="126" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v2-cp0)"><g clip-path="url(#v2-ct1)"><text x="30" y="46" font-family="&quot;ui-monospace&quot;, &quot;SFMono-Regular&quot;, &quot;Menlo&quot;, monospace" font-size="12" font-weight="650" fill="rgb(174,174,178)">Workspace</text></g></g><rect x="105.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v2-cp2)"><g transform="translate(116.8 34)" color="rgb(174, 174, 178)"><svg data-lucide="bell" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><path d="M10.3 21a2 2 0 0 0 3.4 0" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3.3 15.3A1 1 0 0 0 4 17h16a1 1 0 0 0 .7-1.7C19.4 14 18 12.5 18 8A6 6 0 0 0 6 8c0 4.5-1.4 6-2.7 7.3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g></svg>
9
+ <text x="16" y="432" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#aeaeb2">Push-appearance buttons</text>
10
+ <svg x="16" y="440" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="v3-cp0"><rect x="34" y="34" width="16" height="16"/></clipPath><clipPath id="v3-cp1"><rect x="74" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="84" height="44" rx="22" fill="rgb(58,58,60)"/><rect x="20.5" y="20.5" width="83" height="43" rx="21.5" fill="none" stroke="rgb(72,72,74)" stroke-width="1"/><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v3-cp0)"><g transform="translate(34 34)" color="rgb(174, 174, 178)"><svg data-lucide="list" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><path d="M3 5z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g><rect x="62.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v3-cp1)"><g transform="translate(74 34)" color="rgb(174, 174, 178)"><svg data-lucide="columns-3" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><rect width="18" height="18" x="3" y="3" rx="2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" 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(174, 174, 178)" 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(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></svg></g></g></svg>
11
+ </svg>
@@ -0,0 +1,11 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="552" height="552" viewBox="0 0 552 552">
2
+ <rect width="552" height="552" fill="#ffffff"/>
3
+ <text x="16" y="30" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#6e6e73">Bordered group of icon buttons</text>
4
+ <svg x="16" y="38" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="v0-cp0"><rect x="34" y="34" width="16" height="16"/></clipPath><clipPath id="v0-cp1"><rect x="74" y="34" width="16" height="16"/></clipPath><clipPath id="v0-cp2"><rect x="114" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="124" height="44" rx="22" fill="rgb(229,229,234)"/><rect x="20.5" y="20.5" width="123" height="43" rx="21.5" fill="none" stroke="rgb(209,209,214)" stroke-width="1"/><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v0-cp0)"><g transform="translate(34 34)" color="rgb(110, 110, 115)"><svg data-lucide="list" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><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"/></svg></g></g><rect x="62.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v0-cp1)"><g transform="translate(74 34)" color="rgb(110, 110, 115)"><svg data-lucide="columns-3" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><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"/></svg></g></g><rect x="102.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v0-cp2)"><g transform="translate(114 34)" color="rgb(110, 110, 115)"><svg data-lucide="settings" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><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"/></svg></g></g></svg>
5
+ <text x="16" y="164" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#6e6e73">Borderless single control</text>
6
+ <svg x="16" y="172" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="v1-cp0"><rect x="34" y="34" width="16" height="16"/></clipPath></defs><rect x="20.5" y="20.5" width="43" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v1-cp0)"><g transform="translate(34 34)" color="rgb(110, 110, 115)"><svg data-lucide="plus" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><path d="M5 12h14" 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="M12 5v14" 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"/></svg></g></g></svg>
7
+ <text x="16" y="298" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#6e6e73">Label text beside a control</text>
8
+ <svg x="16" y="306" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="v2-cp0"><rect x="22" y="22" width="82.8" height="40"/></clipPath><clipPath id="v2-ct1"><rect x="22" y="22" width="82.8" height="40"/></clipPath><clipPath id="v2-cp2"><rect x="116.8" y="34" width="16.2" height="16"/></clipPath></defs><rect x="20.5" y="20.5" width="126" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v2-cp0)"><g clip-path="url(#v2-ct1)"><text x="30" y="46" font-family="&quot;ui-monospace&quot;, &quot;SFMono-Regular&quot;, &quot;Menlo&quot;, monospace" font-size="12" font-weight="650" fill="rgb(110,110,115)">Workspace</text></g></g><rect x="105.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v2-cp2)"><g transform="translate(116.8 34)" color="rgb(110, 110, 115)"><svg data-lucide="bell" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><path d="M10.3 21a2 2 0 0 0 3.4 0" 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.3 15.3A1 1 0 0 0 4 17h16a1 1 0 0 0 .7-1.7C19.4 14 18 12.5 18 8A6 6 0 0 0 6 8c0 4.5-1.4 6-2.7 7.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"/></svg></g></g></svg>
9
+ <text x="16" y="432" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#6e6e73">Push-appearance buttons</text>
10
+ <svg x="16" y="440" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="v3-cp0"><rect x="34" y="34" width="16" height="16"/></clipPath><clipPath id="v3-cp1"><rect x="74" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="84" height="44" rx="22" fill="rgb(229,229,234)"/><rect x="20.5" y="20.5" width="83" height="43" rx="21.5" fill="none" stroke="rgb(209,209,214)" stroke-width="1"/><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v3-cp0)"><g transform="translate(34 34)" color="rgb(110, 110, 115)"><svg data-lucide="list" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><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"/></svg></g></g><rect x="62.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#v3-cp1)"><g transform="translate(74 34)" color="rgb(110, 110, 115)"><svg data-lucide="columns-3" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" font-family="system-ui, -apple-system, sans-serif" style="overflow:hidden" width="16" height="16"><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"/></svg></g></g></svg>
11
+ </svg>
@@ -0,0 +1,83 @@
1
+ # Design templates — components as self-contained SVGs
2
+
3
+ `docs/design/templates/` holds **SVG design templates** for `@kerfjs/ui`
4
+ components: a faithful, self-contained picture of each component in its common
5
+ presentation combinations, captured from the real rendered HTML/CSS (production
6
+ tokens and styles, representative sample data). They're for design review,
7
+ documentation, figma/paste hand-off, and any surface that wants an accurate
8
+ component picture without running the app.
9
+
10
+ ## Layout
11
+
12
+ ```
13
+ docs/design/templates/
14
+ panel-header.svg ← library: every variant, inlined (light)
15
+ panel-header-dark.svg ← library: dark theme
16
+ panel-header/
17
+ icon-summary-actions.svg ← one self-contained variant (light)
18
+ icon-summary-actions-dark.svg ← the same variant, dark theme
19
+ icon-actions.svg
20
+ icon-actions-dark.svg
21
+
22
+ toolbar-control-group.svg
23
+ toolbar-control-group-dark.svg
24
+ toolbar-control-group/
25
+
26
+ ```
27
+
28
+ - Each **variant** is captured in both themes — `<variant>.svg` (light) and
29
+ `<variant>-dark.svg` (dark) — a standalone SVG that scales crisply and drops
30
+ into an `<img>` anywhere. Dark is driven by domotion's `--color-scheme`, which
31
+ foundation.css's `light-dark()` tokens respond to. Captured with
32
+ `--text-mode system-font`, so text is emitted as authored `<text>` painted by the
33
+ viewer's system fonts: real, selectable, and small (no embedded font data). The
34
+ kerf UI design font stack is system-based, so the picture matches; a viewer
35
+ without those fonts falls back to its own.
36
+ - The **library** files (`<component>.svg` light, `<component>-dark.svg` dark) lay
37
+ the variants out with captions and embed an inline **copy** of each variant as a
38
+ positioned nested `<svg>`. Each is fully self-contained and renders everywhere —
39
+ a browser, an `<img>`, GitHub, or a static rasterizer. (External
40
+ `<use href="…#id">` and `<image href="…">` references render blank in many SVG
41
+ viewers, so the library inlines copies instead. Each copy's local ids and
42
+ domotion font-family names are namespaced so the inlined variants don't collide
43
+ in the one document; the individual variant files stay individually reusable.)
44
+
45
+ ## Building
46
+
47
+ ```sh
48
+ npm run design-templates:build
49
+ ```
50
+
51
+ This renders each component's real `SafeHtml` (with its CSS subpaths + `foundation.css`
52
+ tokens and representative sample data) into a standalone page and captures it with
53
+ [`domotion-svg`](https://github.com/brianwestphal/domotion)'s `domotion capture`.
54
+ `domotion` must be reachable: it resolves `DOMOTION_BIN`, then a local
55
+ `node_modules/.bin/domotion`, then a sibling `../domotion` checkout.
56
+
57
+ **Keep the templates current as components change.** The variants live in the
58
+ `COMPONENTS` manifest in `scripts/build-design-templates.mjs` — when a component
59
+ gains or changes a presentation combination (e.g. a new `PanelHeader` slot), add
60
+ or adjust its variant there and re-run the build. Cover the common cases: if a
61
+ component can render with or without an icon, include both.
62
+
63
+ ## Templating your own components
64
+
65
+ Apps that build on `@kerfjs/ui` can produce the same design templates for their
66
+ own application-level components. Copy `scripts/build-design-templates.mjs` as a
67
+ starting point and:
68
+
69
+ 1. Import your component and render it to a `SafeHtml` string with realistic
70
+ sample data (pass icon/action slots as `SafeHtml`, e.g. `LucideIcon({ … })` or
71
+ `raw('<button …>')` — never plain strings, which kerf escapes).
72
+ 2. List the component's CSS (its `@kerfjs/ui` subpaths plus `foundation.css` for
73
+ tokens and `layout.css`), and any of your own component CSS.
74
+ 3. Enumerate the presentation combinations in the per-component manifest.
75
+ 4. Capture each variant with `domotion capture <page.html> --selector <css>
76
+ --text-mode system-font -o <variant>.svg`, once per theme with
77
+ `--color-scheme light` / `--color-scheme dark` (if your components theme with
78
+ `light-dark()`), then write a light and a dark library file that each embed an
79
+ inline copy of every variant (namespacing each copy's ids/font-family names so
80
+ they don't collide) rather than referencing them, so they render everywhere.
81
+
82
+ Maintaining these next to the components — and reviewing the captured SVGs on
83
+ every component change — keeps the design source of truth honest.
@@ -18,12 +18,65 @@ A reference image defines hierarchy, relationships, and intended feel. It does n
18
18
 
19
19
  ### Continuity is correctness
20
20
 
21
- Unrelated updates must not close controls, move focus, reset a draft, replace a selection, or jump scroll. Give every durable and transient state an explicit owner. Preserve DOM identity when meaning has not changed. Distinguish blocking foreground work from background synchronization.
21
+ Unrelated updates must not close controls, move focus, reset a draft, replace a selection, or jump scroll. Give every durable and transient state an explicit owner. The default owner is the application: domain data and persisted layout preferences — a navigation stack, a selection, a tab order, a pane size, a `collapsed`/`expanded` disclosure flag — are the app's signals, which it reads to render. A `wire…` helper owns only the *ephemeral mechanics* around that state (a push/pop animation, overflow autoscroll, a live resize preview) and reports committed changes through callbacks. A helper takes over a piece of transient state itself only when hand-rolling that behavior is substantial and error-prone enough to cause real, inconsistent variation across apps — `wireTokenSearchFields`'s collapsible reveal/focus/Escape/blur-collapse is the bar; a one-line boolean toggle is not. Preserve DOM identity when meaning has not changed. Distinguish blocking foreground work from background synchronization.
22
22
 
23
23
  ### Hierarchy precedes decoration
24
24
 
25
25
  Establish one reading order and one dominant action per decision point. Group first with alignment, spacing, typography, and shared surfaces. A border, fill, badge, or nested card must communicate a real distinction.
26
26
 
27
+ ### Reach for the primitive, not for CSS
28
+
29
+ The package is designed to look right *unstyled*. A screen built from the
30
+ primitives, their props, and the semantic tokens should already read well, so
31
+ custom CSS is the exception. Before adding any `padding`, `margin`, `width`,
32
+ `height`, `border`, `background`, wrapper card, or decoration, check whether the
33
+ component, the pane, or the content-item already owns it — it almost always does,
34
+ and adding more usually **double-insets** or fights the component (the most common
35
+ mistake). Trust component defaults: render a control at its natural size and color
36
+ and fix the surrounding layout rather than overriding the control. Legitimate
37
+ custom CSS is limited to genuinely new structure, and even then may only join a
38
+ component's documented `publicClasses` or override documented `--kui-*` tokens at a
39
+ real composition boundary — never size, space, or re-skin a primitive by hand, and
40
+ never build a heading, toolbar, card, or pane geometry that a primitive provides.
41
+
42
+ ### Panes share one child-owned geometry
43
+
44
+ Sidebars, main areas, inspectors, and dialogs use the same unpadded pane. Their
45
+ children own margin, border, background, padding, and radius, so a transparent
46
+ surface occupies exactly the same geometry as a visible one. Major content
47
+ groups use 24px vertical separation; the inside of an item and the gap between
48
+ toolbar groups use 8px. Rows and actions keep 44px targets.
49
+
50
+ Use the package composition so the geometry has one owner:
51
+
52
+ ```tsx
53
+ <aside class="kui-pane">
54
+ <nav class="kui-pane__content kui-content">
55
+ <section>
56
+ <ListHeader label="Workspace" />
57
+ <ListItem action="open" label="Inbox" icon={inboxIcon} />
58
+ <ListItem action="open" label="Drafts" />
59
+ </section>
60
+ <div class="kui-content-item">Panel contents</div>
61
+ </nav>
62
+ </aside>
63
+ ```
64
+
65
+ Do not pad the pane and then pad every wrapper. That duplicates the geometry
66
+ and makes transparent borders behave differently from visible ones:
67
+
68
+ ```tsx
69
+ <aside class="pane padded">
70
+ <section class="padded">
71
+ <ListHeader label="Workspace" />
72
+ <div class="panel padded-again">Panel contents</div>
73
+ </section>
74
+ </aside>
75
+ ```
76
+
77
+ Change the shared item tokens at a real composition boundary when a product
78
+ needs different geometry; do not compensate with one-off negative margins.
79
+
27
80
  ### Prefer directness
28
81
 
29
82
  Use the shortest understandable, recoverable interaction. Avoid modes, dialogs, confirmations, and explicit saves when direct manipulation can safely express the same result. Low ceremony still requires a discoverable affordance, visible focus, and honest feedback.
@@ -42,6 +95,13 @@ foregrounds compatible with Hot Sheet 2 and Web Awesome. Consumers may replace
42
95
  the global palette, one semantic role, or one component instance through
43
96
  documented custom properties without rewriting component CSS.
44
97
 
98
+ Spacing is likewise a finite, semantic scale, not a free measurement. Five
99
+ canonical steps — 0, 4, 8, 16, and 24px, each a `--kui-space-*` token — map to a
100
+ single relationship apiece, chosen by how connected two elements are: no
101
+ separation, very minor air, standard within a group, between homogeneous groups,
102
+ and major between heterogeneous groups. Off-scale values (12px, 32px) are
103
+ deliberate exceptions. See [`layout.md`](layout.md) "Spacing scale".
104
+
45
105
  ### Responsive design reprioritizes
46
106
 
47
107
  Protect primary content, readable type, recognizable icons, and usable targets. Relocate secondary information before compressing it below a usable scale. Keep one clear scroll owner per region and test narrow, wide, zoomed, and intermediate layouts.
@@ -0,0 +1,54 @@
1
+ # Device class
2
+
3
+ `@kerfjs/ui/device-class` reports the current viewport as a reactive **device
4
+ class** — a size bucket × orientation × viewport-segment count — so a layout can
5
+ pick its presentation from one signal instead of hand-wiring `matchMedia`. It is
6
+ the foundation the app/dialog layouts build on (see
7
+ [`../../docs/23-app-layouts.md`](../../docs/23-app-layouts.md)).
8
+
9
+ ```ts
10
+ import { deviceClass } from '@kerfjs/ui/device-class';
11
+
12
+ const device = deviceClass(); // ReadonlySignal<DeviceClass>
13
+
14
+ effect(() => {
15
+ if (device.value.compact) showStack();
16
+ else showSplit();
17
+ });
18
+ ```
19
+
20
+ ## `DeviceClass`
21
+
22
+ | Field | Meaning |
23
+ | --- | --- |
24
+ | `size` | `xs-mobile` \| `mobile` \| `tablet` \| `desktop` \| `xl-desktop` |
25
+ | `orientation` | `portrait` \| `landscape` |
26
+ | `segments` / `verticalSegments` | viewport segment counts (foldables / dual-screen); `1` on ordinary devices |
27
+ | `handset` | `xs-mobile` or `mobile` |
28
+ | `compact` | "one pane at a time" — a handset or a portrait tablet |
29
+ | `atLeast(size)` | true when the current size is `size` or larger |
30
+
31
+ Reading `device.value` inside an `effect`/`computed` re-runs when the viewport
32
+ crosses a breakpoint, rotates, or changes its segment count. One shared viewport
33
+ source backs every reader.
34
+
35
+ ## Breakpoints
36
+
37
+ Default minimum widths (px): `mobile` 360, `tablet` 720, `desktop` 1024,
38
+ `xl-desktop` 1440. Override per reader:
39
+
40
+ ```ts
41
+ const device = deviceClass({ breakpoints: { tablet: 900 } });
42
+ ```
43
+
44
+ The same numbers are mirrored as CSS custom properties in the foundation
45
+ (`--kui-bp-mobile`, `--kui-bp-tablet`, `--kui-bp-desktop`, `--kui-bp-xl-desktop`)
46
+ so CSS media queries and the JS signal read one source. `classifyViewport(width,
47
+ orientation, segments?, verticalSegments?, breakpoints?)` is exported as the
48
+ pure, DOM-free bucketing core.
49
+
50
+ ## Server rendering
51
+
52
+ Without a DOM, `deviceClass()` resolves to an SSR default (1024×768, landscape,
53
+ one segment) and hydrates to the real class on the client. Override the assumed
54
+ viewport with `deviceClass({ ssr: { width, height } })`.
@@ -0,0 +1,70 @@
1
+ import '@kerfjs/ui/layout.css';
2
+
3
+ import { delegate, mount, signal } from 'kerfjs';
4
+ import { delegateActions } from 'kerfjs/actions';
5
+
6
+ export interface AppCommand {
7
+ id: string;
8
+ label: string;
9
+ keywords?: string[];
10
+ }
11
+
12
+ export interface CommandPaletteCallbacks {
13
+ onClose(): void;
14
+ onRun(command: AppCommand): void;
15
+ }
16
+
17
+ /**
18
+ * Application-local example, not an @kerfjs/ui export. The application owns
19
+ * ranking, history, shortcuts, focus policy, command availability, and copy.
20
+ */
21
+ export function mountCommandPaletteAdapter(
22
+ root: HTMLElement,
23
+ commands: AppCommand[],
24
+ { onClose, onRun }: CommandPaletteCallbacks,
25
+ ): () => void {
26
+ const query = signal('');
27
+ const render = () => {
28
+ const needle = query.value.trim().toLocaleLowerCase();
29
+ const matches = commands.filter((command) => !needle ||
30
+ [command.label, ...(command.keywords ?? [])].some((value) => value.toLocaleLowerCase().includes(needle)));
31
+ return <section class="app-command-palette kui-content" aria-label="Command palette">
32
+ <div class="kui-content-item"><label for="app-command-query">Search commands</label><input id="app-command-query" type="search" value={query.value} autocomplete="off" data-command-query /></div>
33
+ <p class="kui-content-item" aria-live="polite">{matches.length} matching commands</p>
34
+ <ul class="kui-content-item" aria-label="Matching commands">{matches.map((command) => <li><button type="button" data-action="run-command" data-command-id={command.id}>{command.label}</button></li>)}</ul>
35
+ <footer class="kui-control-cluster kui-content-item" aria-label="Command palette actions">
36
+ <button type="button" data-action="clear-query">Clear search</button>
37
+ <button type="button" data-action="close-palette">Close</button>
38
+ </footer>
39
+ </section>;
40
+ };
41
+
42
+ const stopMount = mount(root, render);
43
+ const stopActions = delegateActions(root, 'click', {
44
+ 'run-command': (_event, element) => {
45
+ const id = (element as HTMLElement).dataset.commandId;
46
+ const command = commands.find((candidate) => candidate.id === id);
47
+ if (command) onRun(command);
48
+ },
49
+ 'clear-query': () => {
50
+ query.value = '';
51
+ root.querySelector<HTMLInputElement>('[data-command-query]')?.focus();
52
+ },
53
+ 'close-palette': onClose,
54
+ });
55
+ const stopInput = delegate<HTMLInputElement>(root, 'input', '[data-command-query]', (_event, input) => {
56
+ query.value = input.value;
57
+ });
58
+ const stopEscape = delegate(root, 'keydown', '[data-command-query]', (event) => {
59
+ if ((event as KeyboardEvent).key === 'Escape') onClose();
60
+ });
61
+ let disposed = false;
62
+ return () => {
63
+ if (disposed) return;
64
+ disposed = true;
65
+ stopEscape();
66
+ stopInput();
67
+ stopActions();
68
+ stopMount();
69
+ };
70
+ }