@keyfunc/keybricks-ds 1.0.4 → 2.3.1

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 (381) hide show
  1. package/DEPLOY.md +14 -5
  2. package/DESIGN.md +245 -59
  3. package/INTEGRATION.md +243 -49
  4. package/SKILL.md +13 -11
  5. package/_adherence.oxlintrc.json +183 -70
  6. package/_scripts/build-index.mjs +24 -4
  7. package/_scripts/build-tokens.mjs +5 -2
  8. package/assets/icons/icon-index.js +1 -1
  9. package/assets/icons/icon-index.json +1 -1
  10. package/components/_cards/accordion.card.html +2 -2
  11. package/components/_cards/action-chip.card.html +11 -9
  12. package/components/_cards/activity.card.html +3 -3
  13. package/components/_cards/alert.card.html +3 -3
  14. package/components/_cards/app-chrome.card.html +4 -4
  15. package/components/_cards/banner.card.html +1 -1
  16. package/components/_cards/breadcrumb.card.html +5 -5
  17. package/components/_cards/button-1-base.card.html +23 -26
  18. package/components/_cards/button-2-states.card.html +27 -25
  19. package/components/_cards/button-3-sizes-icons.card.html +20 -19
  20. package/components/_cards/button-4-group.card.html +14 -31
  21. package/components/_cards/canvas-zoom-controls.card.html +1 -1
  22. package/components/_cards/cards-indicators.card.html +2 -2
  23. package/components/_cards/charts-1-sparkline.card.html +5 -5
  24. package/components/_cards/charts-10-gauge.card.html +5 -5
  25. package/components/_cards/charts-11-funnel.card.html +3 -3
  26. package/components/_cards/charts-12-treemap.card.html +3 -3
  27. package/components/_cards/charts-14-radar.card.html +3 -3
  28. package/components/_cards/charts-15-distribution.card.html +2 -2
  29. package/components/_cards/charts-16-pareto.card.html +3 -3
  30. package/components/_cards/charts-17-candlestick.card.html +3 -3
  31. package/components/_cards/charts-18-sankey.card.html +3 -3
  32. package/components/_cards/charts-19-chord.card.html +3 -3
  33. package/components/_cards/charts-2-line.card.html +4 -4
  34. package/components/_cards/charts-20-sunburst.card.html +3 -3
  35. package/components/_cards/charts-21-worldmap.card.html +4 -4
  36. package/components/_cards/charts-22-gantt.card.html +3 -3
  37. package/components/_cards/charts-23-bar3d.card.html +3 -3
  38. package/components/_cards/charts-24-pie3d.card.html +3 -3
  39. package/components/_cards/charts-25-surface3d.card.html +3 -3
  40. package/components/_cards/charts-26-scatter3d.card.html +3 -3
  41. package/components/_cards/charts-27-ribbon3d.card.html +3 -3
  42. package/components/_cards/charts-3-bar.card.html +7 -7
  43. package/components/_cards/charts-4-barlist.card.html +3 -3
  44. package/components/_cards/charts-5-donut.card.html +4 -4
  45. package/components/_cards/charts-6-scatter.card.html +3 -3
  46. package/components/_cards/charts-7-heatmap.card.html +3 -3
  47. package/components/_cards/charts-8-waterfall.card.html +3 -3
  48. package/components/_cards/charts-9-bullet.card.html +3 -3
  49. package/components/_cards/charts-99-fullpage.card.html +5 -5
  50. package/components/_cards/checkbox.card.html +9 -6
  51. package/components/_cards/codeblock.card.html +2 -2
  52. package/components/_cards/combobox.card.html +6 -3
  53. package/components/_cards/context-menu.card.html +6 -3
  54. package/components/_cards/date-picker.card.html +10 -4
  55. package/components/_cards/diffvalue.card.html +3 -3
  56. package/components/_cards/divider.card.html +4 -4
  57. package/components/_cards/drawer.card.html +4 -4
  58. package/components/_cards/dropdown-menu.card.html +7 -7
  59. package/components/_cards/dropzone.card.html +5 -3
  60. package/components/_cards/empty-state.card.html +6 -6
  61. package/components/_cards/filter-bar.card.html +5 -5
  62. package/components/_cards/icon-button.card.html +14 -14
  63. package/components/_cards/icons-1-core.card.html +4 -4
  64. package/components/_cards/icons-2-feather.card.html +4 -4
  65. package/components/_cards/icons-3-unicons.card.html +4 -4
  66. package/components/_cards/input.card.html +5 -2
  67. package/components/_cards/kbd.card.html +2 -2
  68. package/components/_cards/keyvalue.card.html +2 -2
  69. package/components/_cards/listrow.card.html +2 -2
  70. package/components/_cards/loading.card.html +3 -3
  71. package/components/_cards/log-viewer.card.html +3 -3
  72. package/components/_cards/modal.card.html +9 -9
  73. package/components/_cards/multi-select.card.html +6 -3
  74. package/components/_cards/number-stepper.card.html +9 -5
  75. package/components/_cards/pagination.card.html +6 -3
  76. package/components/_cards/people.card.html +4 -4
  77. package/components/_cards/pipeline-node.card.html +8 -8
  78. package/components/_cards/pipeline-palette.card.html +5 -5
  79. package/components/_cards/radio.card.html +12 -7
  80. package/components/_cards/search.card.html +6 -3
  81. package/components/_cards/segmented-control.card.html +11 -10
  82. package/components/_cards/select.card.html +8 -4
  83. package/components/_cards/slider.card.html +2 -2
  84. package/components/_cards/smart-table.card.html +3 -3
  85. package/components/_cards/spreadsheet.card.html +3 -3
  86. package/components/_cards/stepper.card.html +3 -3
  87. package/components/_cards/table.card.html +165 -0
  88. package/components/_cards/tabs.card.html +6 -3
  89. package/components/_cards/tag.card.html +6 -3
  90. package/components/_cards/textarea.card.html +2 -2
  91. package/components/_cards/timeline.card.html +3 -3
  92. package/components/_cards/toast.card.html +10 -8
  93. package/components/_cards/toggles.card.html +15 -10
  94. package/components/_cards/tooltip.card.html +7 -7
  95. package/components/_cards/tree.card.html +3 -3
  96. package/components/_shared/card-kit.css +25 -0
  97. package/components/_shared/card-kit.js +50 -0
  98. package/components/_shared/src-buttons.js +1 -1
  99. package/components/_shared/src-charts.js +1 -1
  100. package/components/_shared/src-data.js +1 -1
  101. package/components/_shared/src-display.js +1 -1
  102. package/components/_shared/src-feedback.js +1 -1
  103. package/components/_shared/src-forms.js +1 -1
  104. package/components/_shared/src-icons.js +1 -1
  105. package/components/_shared/src-navigation.js +1 -1
  106. package/components/_shared/src-pipeline.js +1 -1
  107. package/components/_shared/src-tabs.js +1 -1
  108. package/components/_shared/view-source.js +3 -3
  109. package/components/_vue/index.mjs +16 -5
  110. package/components/buttons/ActionChip.d.ts +3 -1
  111. package/components/buttons/ActionChip.jsx +4 -4
  112. package/components/buttons/ActionChip.vue +4 -4
  113. package/components/buttons/Button.d.ts +5 -2
  114. package/components/buttons/Button.jsx +15 -18
  115. package/components/buttons/Button.vue +17 -18
  116. package/components/buttons/ButtonGroup.vue +1 -1
  117. package/components/buttons/IconButton.d.ts +2 -1
  118. package/components/buttons/IconButton.jsx +13 -9
  119. package/components/buttons/IconButton.vue +12 -9
  120. package/components/buttons/buttons.prompt.md +6 -5
  121. package/components/charts/Bar3D.jsx +2 -2
  122. package/components/charts/Bar3D.vue +3 -3
  123. package/components/charts/BarChart.jsx +4 -4
  124. package/components/charts/BarChart.vue +6 -6
  125. package/components/charts/BarList.jsx +4 -4
  126. package/components/charts/BarList.vue +4 -4
  127. package/components/charts/BoxPlot.jsx +1 -1
  128. package/components/charts/BoxPlot.vue +3 -3
  129. package/components/charts/BulletChart.jsx +6 -6
  130. package/components/charts/BulletChart.vue +6 -6
  131. package/components/charts/CandlestickChart.jsx +2 -2
  132. package/components/charts/CandlestickChart.vue +5 -5
  133. package/components/charts/ChartKit.jsx +8 -7
  134. package/components/charts/ChartLegend.vue +16 -0
  135. package/components/charts/ChartTooltip.vue +16 -0
  136. package/components/charts/ChordChart.jsx +2 -2
  137. package/components/charts/ChordChart.vue +3 -3
  138. package/components/charts/DonutChart.jsx +1 -1
  139. package/components/charts/DonutChart.vue +2 -2
  140. package/components/charts/FunnelChart.jsx +3 -3
  141. package/components/charts/FunnelChart.vue +4 -4
  142. package/components/charts/GanttChart.jsx +2 -2
  143. package/components/charts/GanttChart.vue +3 -3
  144. package/components/charts/GaugeChart.jsx +2 -2
  145. package/components/charts/GaugeChart.vue +2 -2
  146. package/components/charts/HeatmapChart.jsx +2 -2
  147. package/components/charts/HeatmapChart.vue +2 -2
  148. package/components/charts/Histogram.jsx +2 -2
  149. package/components/charts/Histogram.vue +4 -4
  150. package/components/charts/LineChart.jsx +1 -1
  151. package/components/charts/LineChart.vue +4 -4
  152. package/components/charts/ParetoChart.jsx +3 -3
  153. package/components/charts/ParetoChart.vue +5 -5
  154. package/components/charts/Pie3D.jsx +1 -1
  155. package/components/charts/Pie3D.vue +2 -2
  156. package/components/charts/PlotGrid.vue +18 -0
  157. package/components/charts/RadarChart.jsx +1 -1
  158. package/components/charts/RadarChart.vue +2 -2
  159. package/components/charts/Ribbon3D.jsx +2 -2
  160. package/components/charts/Ribbon3D.vue +3 -3
  161. package/components/charts/SankeyChart.jsx +2 -2
  162. package/components/charts/SankeyChart.vue +3 -3
  163. package/components/charts/Scatter3D.jsx +1 -1
  164. package/components/charts/Scatter3D.vue +2 -2
  165. package/components/charts/ScatterChart.jsx +3 -3
  166. package/components/charts/ScatterChart.vue +5 -5
  167. package/components/charts/Sparkline.jsx +1 -1
  168. package/components/charts/Sparkline.vue +1 -1
  169. package/components/charts/SunburstChart.jsx +1 -1
  170. package/components/charts/SunburstChart.vue +2 -2
  171. package/components/charts/Surface3D.jsx +2 -2
  172. package/components/charts/Surface3D.vue +3 -3
  173. package/components/charts/TreemapChart.jsx +2 -2
  174. package/components/charts/TreemapChart.vue +3 -3
  175. package/components/charts/WaterfallChart.jsx +2 -2
  176. package/components/charts/WaterfallChart.vue +6 -5
  177. package/components/charts/WorldMap.jsx +4 -4
  178. package/components/charts/WorldMap.vue +5 -5
  179. package/components/charts/XLabels.vue +11 -0
  180. package/components/data/CodeBlock.jsx +1 -1
  181. package/components/data/CodeBlock.vue +1 -1
  182. package/components/data/DiffValue.d.ts +1 -0
  183. package/components/data/DiffValue.jsx +1 -1
  184. package/components/data/DiffValue.vue +1 -1
  185. package/components/data/FilterBar.d.ts +2 -0
  186. package/components/data/FilterBar.jsx +10 -9
  187. package/components/data/FilterBar.vue +9 -8
  188. package/components/data/KeyValue.d.ts +1 -1
  189. package/components/data/KeyValue.jsx +4 -4
  190. package/components/data/KeyValue.vue +4 -4
  191. package/components/data/ListRow.jsx +2 -2
  192. package/components/data/ListRow.vue +2 -2
  193. package/components/data/Pagination.d.ts +5 -1
  194. package/components/data/Pagination.jsx +16 -12
  195. package/components/data/Pagination.vue +14 -9
  196. package/components/data/SmartTable.d.ts +4 -1
  197. package/components/data/SmartTable.jsx +16 -14
  198. package/components/data/SmartTable.vue +26 -23
  199. package/components/data/Spreadsheet.d.ts +2 -0
  200. package/components/data/Spreadsheet.jsx +16 -15
  201. package/components/data/Spreadsheet.vue +19 -18
  202. package/components/data/Table.d.ts +101 -0
  203. package/components/data/Table.jsx +223 -0
  204. package/components/data/Table.vue +153 -0
  205. package/components/data/data.prompt.md +3 -3
  206. package/components/display/Avatar.jsx +2 -2
  207. package/components/display/Avatar.vue +3 -2
  208. package/components/display/AvatarGroup.vue +3 -2
  209. package/components/display/Badge.d.ts +4 -1
  210. package/components/display/Badge.jsx +10 -5
  211. package/components/display/Badge.vue +1 -1
  212. package/components/display/Divider.vue +3 -3
  213. package/components/display/Donut.vue +3 -2
  214. package/components/display/IconTile.vue +10 -4
  215. package/components/display/Kbd.d.ts +1 -1
  216. package/components/display/Kbd.jsx +1 -1
  217. package/components/display/Kbd.vue +2 -2
  218. package/components/display/ProgressBar.jsx +1 -1
  219. package/components/display/ProgressBar.vue +1 -1
  220. package/components/display/StatCard.vue +1 -1
  221. package/components/display/Tag.d.ts +3 -1
  222. package/components/display/Tag.jsx +4 -4
  223. package/components/display/Tag.vue +4 -4
  224. package/components/feedback/Accordion.jsx +2 -2
  225. package/components/feedback/Accordion.vue +2 -2
  226. package/components/feedback/ActivityItem.d.ts +3 -1
  227. package/components/feedback/ActivityItem.jsx +6 -6
  228. package/components/feedback/ActivityItem.vue +5 -4
  229. package/components/feedback/Alert.jsx +4 -4
  230. package/components/feedback/Alert.vue +3 -3
  231. package/components/feedback/Banner.jsx +5 -5
  232. package/components/feedback/Banner.vue +5 -5
  233. package/components/feedback/ContextMenu.d.ts +3 -1
  234. package/components/feedback/ContextMenu.jsx +5 -5
  235. package/components/feedback/ContextMenu.vue +5 -5
  236. package/components/feedback/DotActivity.vue +3 -3
  237. package/components/feedback/Drawer.d.ts +2 -0
  238. package/components/feedback/Drawer.jsx +6 -6
  239. package/components/feedback/Drawer.vue +22 -15
  240. package/components/feedback/EmptyState.vue +2 -2
  241. package/components/feedback/LogViewer.vue +1 -1
  242. package/components/feedback/Modal.d.ts +2 -0
  243. package/components/feedback/Modal.jsx +12 -11
  244. package/components/feedback/Modal.vue +10 -8
  245. package/components/feedback/Skeleton.vue +2 -1
  246. package/components/feedback/Spinner.vue +2 -1
  247. package/components/feedback/Stepper.vue +1 -1
  248. package/components/feedback/Timeline.jsx +1 -1
  249. package/components/feedback/Timeline.vue +3 -3
  250. package/components/feedback/Toast.vue +4 -4
  251. package/components/feedback/ToastStack.vue +11 -0
  252. package/components/feedback/Tooltip.vue +19 -0
  253. package/components/feedback/feedback.prompt.md +4 -4
  254. package/components/forms/Checkbox.d.ts +3 -2
  255. package/components/forms/Checkbox.jsx +7 -7
  256. package/components/forms/Checkbox.vue +8 -8
  257. package/components/forms/Combobox.d.ts +2 -0
  258. package/components/forms/Combobox.jsx +12 -10
  259. package/components/forms/Combobox.vue +11 -10
  260. package/components/forms/DatePicker.d.ts +4 -0
  261. package/components/forms/DatePicker.jsx +16 -12
  262. package/components/forms/DatePicker.vue +15 -11
  263. package/components/forms/Dropzone.jsx +2 -2
  264. package/components/forms/Dropzone.vue +5 -5
  265. package/components/forms/Field.d.ts +5 -1
  266. package/components/forms/Field.jsx +4 -4
  267. package/components/forms/Field.vue +4 -4
  268. package/components/forms/Input.d.ts +5 -1
  269. package/components/forms/Input.jsx +8 -8
  270. package/components/forms/Input.vue +3 -3
  271. package/components/forms/MultiSelect.d.ts +2 -0
  272. package/components/forms/MultiSelect.jsx +13 -11
  273. package/components/forms/MultiSelect.vue +12 -11
  274. package/components/forms/NumberStepper.d.ts +3 -1
  275. package/components/forms/NumberStepper.jsx +7 -7
  276. package/components/forms/NumberStepper.vue +8 -7
  277. package/components/forms/Radio.d.ts +5 -3
  278. package/components/forms/Radio.jsx +13 -15
  279. package/components/forms/Radio.vue +9 -10
  280. package/components/forms/RadioGroup.vue +5 -5
  281. package/components/forms/SearchInput.d.ts +3 -1
  282. package/components/forms/SearchInput.jsx +6 -6
  283. package/components/forms/SearchInput.vue +7 -6
  284. package/components/forms/Select.d.ts +3 -2
  285. package/components/forms/Select.jsx +6 -7
  286. package/components/forms/Select.vue +6 -6
  287. package/components/forms/Slider.jsx +3 -3
  288. package/components/forms/Slider.vue +3 -3
  289. package/components/forms/Switch.d.ts +2 -2
  290. package/components/forms/Switch.jsx +20 -22
  291. package/components/forms/Switch.vue +22 -18
  292. package/components/forms/Textarea.vue +5 -5
  293. package/components/forms/forms.prompt.md +1 -1
  294. package/components/forms/input-base.js +2 -1
  295. package/components/icons/Icon.jsx +17 -1
  296. package/components/icons/Icon.prompt.md +2 -0
  297. package/components/icons/Icon.vue +1 -1
  298. package/components/icons/icon-paths.js +15 -0
  299. package/components/index.d.ts +1 -2
  300. package/components/index.js +4 -5
  301. package/components/navigation/Breadcrumb.jsx +6 -10
  302. package/components/navigation/Breadcrumb.vue +6 -12
  303. package/components/navigation/DocTree.jsx +3 -3
  304. package/components/navigation/DocTree.vue +3 -3
  305. package/components/navigation/PageHeading.vue +1 -1
  306. package/components/navigation/PageToolbar.vue +7 -6
  307. package/components/navigation/Sidebar.jsx +4 -23
  308. package/components/navigation/Sidebar.vue +5 -10
  309. package/components/navigation/ThemeToggle.vue +2 -1
  310. package/components/navigation/TopBar.d.ts +3 -1
  311. package/components/navigation/TopBar.jsx +6 -6
  312. package/components/navigation/Tree.jsx +5 -5
  313. package/components/navigation/Tree.vue +13 -8
  314. package/components/navigation/nav-model.js +23 -0
  315. package/components/navigation/theme-store.js +9 -0
  316. package/components/pipeline/ConfigPanel.d.ts +2 -0
  317. package/components/pipeline/ConfigPanel.jsx +9 -9
  318. package/components/pipeline/ConfigPanel.vue +9 -9
  319. package/components/pipeline/DataPreview.d.ts +3 -1
  320. package/components/pipeline/DataPreview.jsx +7 -7
  321. package/components/pipeline/DataPreview.vue +7 -7
  322. package/components/pipeline/NodeCard.jsx +3 -3
  323. package/components/pipeline/NodeCard.vue +3 -3
  324. package/components/pipeline/PaletteItem.vue +2 -2
  325. package/components/pipeline/PaletteListItem.vue +1 -1
  326. package/components/pipeline/PalettePanel.jsx +2 -2
  327. package/components/pipeline/PalettePanel.vue +1 -1
  328. package/components/pipeline/Port.vue +15 -0
  329. package/components/pipeline/PortLabel.vue +15 -0
  330. package/components/pipeline/ZoomControls.vue +1 -1
  331. package/components/pipeline/port-skin.js +13 -0
  332. package/components/px.js +4 -0
  333. package/components/tabs/PanelTabs.vue +5 -4
  334. package/components/tabs/PillTabs.vue +5 -4
  335. package/components/tabs/SegmentedControl.d.ts +2 -2
  336. package/components/tabs/SegmentedControl.jsx +7 -7
  337. package/components/tabs/SegmentedControl.vue +7 -7
  338. package/components/tabs/Tabs.d.ts +5 -3
  339. package/components/tabs/Tabs.jsx +15 -15
  340. package/components/tabs/Tabs.vue +5 -5
  341. package/components/tabs/ViewToggle.d.ts +3 -1
  342. package/components/tabs/ViewToggle.jsx +5 -5
  343. package/components/tabs/ViewToggle.vue +5 -5
  344. package/components/tabs/tabs.prompt.md +1 -1
  345. package/keybricks.css +4 -0
  346. package/package.json +6 -3
  347. package/readme.md +91 -122
  348. package/readme.zh-CN.md +121 -0
  349. package/tokens/alpha.css +3 -1
  350. package/tokens/charts.css +20 -17
  351. package/tokens/colors.css +3 -3
  352. package/tokens/dark.css +3 -3
  353. package/tokens/hover.css +32 -0
  354. package/tokens/interaction.css +3 -1
  355. package/tokens/layout.css +31 -7
  356. package/tokens/tokens.d.ts +58 -0
  357. package/tokens/tokens.js +179 -92
  358. package/tokens/tokens.json +327 -114
  359. package/tokens/typography.css +45 -15
  360. package/components/_cards/brand-visual.card.html +0 -43
  361. package/components/_cards/datatable.card.html +0 -48
  362. package/components/_shared/src-brand.js +0 -1
  363. package/components/brand/BrandVisual.d.ts +0 -17
  364. package/components/brand/BrandVisual.jsx +0 -29
  365. package/components/brand/BrandVisual.vue +0 -34
  366. package/components/brand/_dir.card.html +0 -13
  367. package/components/brand/brandMotifs.js +0 -210
  368. package/components/buttons/_dir.card.html +0 -13
  369. package/components/charts/ChartKit.vue +0 -47
  370. package/components/charts/_dir.card.html +0 -7
  371. package/components/data/DataTable.d.ts +0 -28
  372. package/components/data/DataTable.jsx +0 -32
  373. package/components/data/DataTable.vue +0 -25
  374. package/components/data/_dir.card.html +0 -13
  375. package/components/display/_dir.card.html +0 -13
  376. package/components/feedback/_dir.card.html +0 -13
  377. package/components/forms/_dir.card.html +0 -13
  378. package/components/icons/_dir.card.html +0 -13
  379. package/components/navigation/_dir.card.html +0 -13
  380. package/components/pipeline/_dir.card.html +0 -13
  381. package/components/tabs/_dir.card.html +0 -13
@@ -0,0 +1,165 @@
1
+ <!-- @dsCard group="Components" viewport="700x6150" name="Table" subtitle="Anatomy · densities · column types · two-line name · sorting · selection · frames · column resize · states · composition" -->
2
+ <!DOCTYPE html>
3
+ <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
+ <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
5
+ <script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
6
+ <script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
7
+ <script src="../../_ds_bundle.js"></script>
8
+ <script src="../_shared/view-source.js"></script>
9
+ <script src="../_shared/card-kit.js"></script>
10
+ <style>body{margin:0;background:var(--bg-surface);padding:20px 24px;font-family:var(--font-sans);box-sizing:border-box}.sec{font-size:var(--text-xs);font-weight:600;color:var(--text-muted);padding:20px 0 4px;border-top:1px solid var(--border-subtle);margin-top:18px}.sec:first-child{border-top:none;margin-top:0;padding-top:0}.case{padding:10px 0 4px}.k{font-size:var(--text-xs);color:var(--text-secondary);font-family:var(--font-sans);display:block;padding-bottom:8px}.note{font-size:var(--text-xs);line-height:17px;color:var(--text-secondary);max-width:64ch;padding:6px 0 0}.note code{font-family:var(--font-mono);font-size:var(--text-xs);color:var(--text-heading)}.grey{background:var(--bg-app);padding:16px;border-radius:var(--radius-lg)}a{color:var(--link)}a:hover{color:var(--link-hover)}.kb-h-gap{margin:28px 0 12px}.kb-h-gap:first-child{margin-top:0}</style></head>
11
+ <body><div id="root"></div>
12
+ <script type="text/babel">
13
+ const { Table, Select, Badge, Pagination, EmptyState, Skeleton, IconButton } = window.KeybricksDesignSystem_71231a;
14
+ const { KBLive: Live } = window;
15
+ const { KBTiers: Tiers } = window;
16
+ const Case = ({ k, children }) => <div className="case"><span className="k">{k}</span>{children}</div>;
17
+ const CFG = [{ key: "module", label: "Module", width: 150 }, { key: "code", label: "Code", code: true, width: 200 }, { key: "cur", label: "Current Value" }, { key: "next", label: "New Value" }];
18
+ const CFG_ROWS = [
19
+ { module: "Financial Settings", code: "FIN_CURRENCY_DEFAULT", cur: "USD", next: "EUR" },
20
+ { module: "Financial Settings", code: "FIN_DECIMAL_PLACES", cur: "2", next: "2" },
21
+ { module: "User Management", code: "USER_SESSION_TIMEOUT", cur: "30", next: "60" },
22
+ ];
23
+ const RUNS = [{ key: "id", label: "Run ID", mono: true, width: 110 }, { key: "doc", label: "Document" }, { key: "status", label: "Status", width: 120, render: v => <Badge tone={{ Completed: "success", Failed: "danger", Partial: "warning" }[v]}>{v}</Badge> }, { key: "rows", label: "Rows", mono: true, align: "right", width: 90 }, { key: "fin", label: "Finished", width: 100 }];
24
+ const RUN_ROWS = [
25
+ { id: "RUN-1892", doc: "August Close — Journal Import", status: "Completed", rows: "12,401", fin: "09:41" },
26
+ { id: "RUN-1891", doc: "Vendor Master Sync", status: "Failed", rows: "–", fin: "08:12" },
27
+ { id: "RUN-1890", doc: "FX Rates Refresh", status: "Completed", rows: "312", fin: "06:00" },
28
+ ];
29
+ const SORT_COLS = [...RUNS.filter(c => c.key !== "fin").map(c => ({ ...c, sortable: true })), { key: "act", label: "", width: 44, align: "right", render: () => <IconButton icon="ellipsis" size="sm" muted label="Row actions" /> }];
30
+ const SORT_ROWS = [...RUN_ROWS, { id: "RUN-1889", doc: "Intercompany Matching", status: "Partial", rows: "2,048", fin: "05:30" }, { id: "RUN-1888", doc: "Bank Statement Import", status: "Completed", rows: "964", fin: "04:15" }];
31
+ const DENSE = [{ key: "id", label: "ID", mono: true }, { key: "entity", label: "Entity", mono: true }, { key: "customer", label: "Customer", mono: true }, { key: "batch", label: "Batch Code", mono: true }, { key: "qty", label: "Qty", mono: true, align: "right" }];
32
+ const DENSE_ROWS = [
33
+ { id: "528563", entity: "HK", customer: "A", batch: "HYSTK-1", qty: "4100" },
34
+ { id: "528564", entity: "SG", customer: "B", batch: "HYSTK-4", qty: "1610" },
35
+ { id: "528565", entity: "HK", customer: "C", batch: "HYSTK-5", qty: "3200" },
36
+ ];
37
+ const DOCS = [{ key: "name", label: "Name", width: 270, minWidth: 200, twoLine: true, sortable: true }, { key: "details", label: "Details", width: 110, sortable: true }, { key: "at", label: "Changed at", mono: true, sortable: true }];
38
+ const DOC_ROWS = [
39
+ { name: "2026 Budget", description: "Budget cycle FY2026", icon: "folder", hue: "neutral", details: "1 folder · 3 docs" },
40
+ { name: "Consolidation", description: "Group consolidation model", icon: "folder", hue: "neutral", details: "2 docs" },
41
+ { name: "FX Rates Model", description: "Average and closing rates", icon: "box", hue: "merge", mark: "favorite", details: "Model Sheet", by: "Luo Lisi", at: "2026-09-17 06:35" },
42
+ { name: "Opening Balance Sheet — FY26 Group Entities", description: "FY26 opening balances", icon: "table", hue: "join", details: "Detail Sheet", by: "Felix Wang", at: "2026-09-12 09:10" },
43
+ { name: "Cash Flow Forecast", description: "13-week rolling forecast", icon: "table", hue: "source", details: "Spreadsheet", by: "Guo Kaige", at: "2026-10-16 08:30" },
44
+ ];
45
+ const TREE_ROWS = [
46
+ { id: "budget", name: "2026 Budget", description: "Budget cycle FY2026", icon: "folder", hue: "neutral", details: "1 folder · 2 docs", children: [
47
+ { id: "q1", name: "Q1 Forecast", description: "Quarterly re-forecast", icon: "folder", hue: "neutral", details: "1 doc", children: [
48
+ { id: "q1-opex", name: "Opex by Department", description: "Detail sheet", icon: "table", hue: "join", details: "Detail Sheet", at: "2026-10-02 14:20" },
49
+ ] },
50
+ { id: "headcount", name: "Headcount Plan", description: "Hiring by cost centre", icon: "table", hue: "source", details: "Spreadsheet", at: "2026-09-28 10:05" },
51
+ { id: "capex", name: "Capex Model", description: "Asset additions and depreciation", icon: "box", hue: "merge", details: "Model Sheet", at: "2026-09-21 16:40" },
52
+ ] },
53
+ { id: "consol", name: "Consolidation", description: "Group consolidation model", icon: "folder", hue: "neutral", details: "2 docs", children: [
54
+ { id: "elim", name: "Intercompany Eliminations", description: "Matched pairs by entity", icon: "table", hue: "join", details: "Detail Sheet", at: "2026-10-12 09:30" },
55
+ { id: "fx", name: "FX Rates Model", description: "Average and closing rates", icon: "box", hue: "merge", mark: "favorite", details: "Model Sheet", at: "2026-09-17 06:35" },
56
+ ] },
57
+ { id: "cash", name: "Cash Flow Forecast", description: "13-week rolling forecast", icon: "table", hue: "source", details: "Spreadsheet", at: "2026-10-16 08:30" },
58
+ ];
59
+ const ZH_LABELS = { sortAsc: "升序排列", sortDesc: "降序排列", sortClear: "取消排序", more: "更多操作", expand: "展开", collapse: "收起" };
60
+ const DOC_ROWS_ZH = [
61
+ { name: "2026 预算", description: "FY2026 预算周期", icon: "folder", hue: "neutral", details: "3 个文档" },
62
+ { name: "汇率模型", description: "月平均与期末汇率", icon: "box", hue: "merge", mark: "favorite", details: "模型表", by: "罗丽思", at: "2026-09-17 06:35" },
63
+ ];
64
+
65
+ function Sheet() {
66
+ const [sel, setSel] = React.useState([0]);
67
+ const toggle = (w, v) => { if (w === "all") setSel(v ? [0, 1, 2] : []); else setSel(v ? [...sel, w] : sel.filter(i => i !== w)); };
68
+ const [widths, setWidths] = React.useState({ module: 150, code: 200 });
69
+ const [page, setPage] = React.useState(1);
70
+ const [dsel, setDsel] = React.useState([]);
71
+ const dtoggle = (w, v) => { if (w === "all") setDsel(v ? DOC_ROWS.map((_, i) => i) : []); else setDsel(v ? [...dsel, w] : dsel.filter(i => i !== w)); };
72
+ const [moreOn, setMoreOn] = React.useState(null);
73
+ const [srt, setSrt] = React.useState(null);
74
+ const [exp, setExp] = React.useState(["budget"]);
75
+ const [opened, setOpened] = React.useState(null);
76
+ return <div>
77
+ <div className="kb-h kb-h-gap">Anatomy</div>
78
+ <Case k="md — 40px rows · 14px cells · header in weight 600, sentence case · hairline rules">
79
+ <Table bordered columns={RUNS} rows={RUN_ROWS} />
80
+ <div className="note">One rule weight throughout (<code>--border-subtle</code>). The header is set apart by its <code>--bg-table-header</code> tint — never by a heavier line. Config-code columns (<code>code</code>) show a code chip — Menlo 12px on the inset fill; amount and ID columns (<code>mono</code>) keep the UI font with tabular figures; <code>align: "right"</code> for quantities.</div>
81
+ </Case>
82
+
83
+ <div className="kb-h kb-h-gap">Densities</div>
84
+ <Case k="md · 40px rows (the default)"><Table bordered columns={CFG} rows={CFG_ROWS.slice(0, 2)} /></Case>
85
+ <Case k="sm · 36px rows, 12px text — dense grids and the data-preview drawer"><Table size="sm" bordered columns={DENSE} rows={DENSE_ROWS} /></Case>
86
+ <Case k="sm · CJK — 13px text, regular weight (lang=&quot;zh-CN&quot; on the region)"><div lang="zh-CN"><Table size="sm" bordered columns={[{ key: "code", label: "科目代码", mono: true }, { key: "name", label: "科目名称" }, { key: "dept", label: "成本中心" }, { key: "amt", label: "期末余额", mono: true }]} rows={[{ code: "1001", name: "库存现金", dept: "總部財務", amt: "12,480.00" }, { code: "1002", name: "银行存款", dept: "上海分公司", amt: "3,215,906.12" }, { code: "2202", name: "应付账款", dept: "東京支社", amt: "486,300.00" }]} /></div></Case>
87
+
88
+ <div className="kb-h kb-h-gap">Column types</div>
89
+ <Case k="text · mono · align right · render (Badge) · render (Select)">
90
+ <Table bordered columns={[{ ...CFG[1], width: 220 }, { key: "cur", label: "Current Value", align: "right", width: 130 }, { key: "status", label: "Status", width: 120, render: (_, r, i) => <Badge tone={["success", "neutral", "warning"][i]}>{["Match", "Identical", "Conflict"][i]}</Badge> }, { key: "action", label: "Action", width: 160, render: () => <Live init="New">{(v, set) => <Select options={["New", "Overwrite", "Skip"]} value={v} onChange={(e)=>set(e && e.target ? e.target.value : e)} style={{ width: 128 }} />}</Live> }]} rows={CFG_ROWS} />
91
+ </Case>
92
+
93
+ <div className="kb-h kb-h-gap">Two-line name</div>
94
+ <Case k="twoLine column — md · 58px rows · header stays 40px · resizable + sortable: the sort button and the ⋯ share the column's right edge">
95
+ <Table bordered resizable selectable selected={dsel} onToggle={dtoggle} columns={DOCS} rows={DOC_ROWS} onRowMore={(r) => setMoreOn(r.name)} />
96
+ <div className="note">Icon tile (<code>IconTile kind="row"</code>, 32px r8, tinted by <code>hue</code>; <code>neutral</code> is the grey folder tile) · 12px · title 14px <code>--text-heading</code> over description 12px <code>--text-secondary</code>, 2px apart, each one line and truncated · sm ⋯ button on the right. <code>mark: "favorite"</code> adds a filled 14px star in <code>--warning</code>. Other cells stay vertically centred and unchanged. Last ⋯ clicked: <code>{moreOn || "none"}</code></div>
97
+ </Case>
98
+ <Case k="tree — rows nest through children · 24px per level · arrow to expand · onRowOpen on the tile and title">
99
+ <Table bordered tree columns={DOCS} rows={TREE_ROWS} expandedKeys={exp} onExpandChange={(r, open, keys) => setExp(keys)} onRowOpen={(r) => setOpened(r.name)} />
100
+ <div className="note">Each level indents 24px; the 20px arrow slot plus 4px puts a child's arrow under its parent's tile. Rows without children keep the slot, so tiles line up. Click a tile or a title to open the row (hand cursor; Enter or Space on the title). Sorting reorders siblings only. Opened: <code>{opened || "none"}</code> · <code>expandedKeys</code>: <code>{JSON.stringify(exp)}</code></div>
101
+ </Case>
102
+ <Case k="sm · 50px rows — 28px tile, 8px to the text, 12px title, 8px padding"><Table size="sm" bordered columns={DOCS} rows={DOC_ROWS.slice(2, 4)} /></Case>
103
+ <Case k="lg · 68px rows — 40px tile r10, 20px icon, 4px between lines, 14px padding"><Table size="lg" bordered columns={DOCS} rows={DOC_ROWS.slice(2, 4)} /></Case>
104
+ <Case k="md · CJK — description 13/18, row 60px (lang=&quot;zh-CN&quot;) · labels: the sort and ⋯ tooltips in Chinese"><div lang="zh-CN"><Table bordered labels={ZH_LABELS} columns={[{ ...DOCS[0], label: "名称" }, { ...DOCS[1], label: "详情" }, { ...DOCS[2], label: "修改时间" }]} rows={DOC_ROWS_ZH} /></div></Case>
105
+
106
+ <div className="kb-h kb-h-gap">Sorting</div>
107
+ <Case k="sortable — hover a header for the sort button · ascending → descending → none · one column at a time">
108
+ <Table bordered columns={SORT_COLS} rows={SORT_ROWS} sort={srt} onSortChange={setSrt} />
109
+ <div className="note">A muted sm <code>IconButton</code> sits at the header cell's right end — in line with a two-line row's ⋯: shown on hover (<code>arrow-up</code>, “Sort ascending”), then kept while the column is sorted (<code>arrow-up</code> / <code>arrow-down</code>) and the label turns <code>--text-heading</code>. A new column always starts ascending. The action column is not <code>sortable</code>, so it has no button. <code>sort</code>: <code>{srt ? srt.key + " · " + srt.direction : "null"}</code></div>
110
+ </Case>
111
+ <Case k="with resizable — the button sits left of the divider; a long label truncates, the button stays · defaultSort: Rows descending">
112
+ <Table bordered resizable defaultSort={{ key: "rows", direction: "desc" }} columns={[{ key: "id", label: "Run ID", mono: true, width: 110, sortable: true }, { key: "doc", label: "Document", width: 220, sortable: true }, { key: "rows", label: "Rows", mono: true, align: "right", width: 100, sortable: true }, { key: "fin", label: "Finished at (local time)", width: 110, sortable: true }]} rows={SORT_ROWS} />
113
+ </Case>
114
+ <Case k="sm — same button at 28px in a 36px header · defaultSort: Document ascending, so its button shows without hover"><Table size="sm" bordered columns={SORT_COLS.slice(0, 4)} rows={SORT_ROWS.slice(0, 3)} defaultSort={{ key: "doc", direction: "asc" }} /></Case>
115
+
116
+ <div className="kb-h kb-h-gap">Selection</div>
117
+ <Case k="selectable · selected · onToggle — header checkbox is indeterminate on partial">
118
+ <Table bordered selectable selected={sel} onToggle={toggle} columns={CFG} rows={CFG_ROWS} />
119
+ </Case>
120
+
121
+ <div className="kb-h kb-h-gap">Frames</div>
122
+ <Case k="bordered — table draws its own card frame; use on grey pages">
123
+ <div className="grey"><Table bordered columns={RUNS.slice(0, 3)} rows={RUN_ROWS.slice(0, 2)} /></div>
124
+ </Case>
125
+ <Case k="framed — flush inside a Card pad={false}, with a footer">
126
+ <div style={{ background: "var(--bg-surface)", border: "1px solid var(--border-card)", borderRadius: "var(--radius-lg)", overflow: "hidden" }}>
127
+ <Table framed columns={RUNS.slice(0, 3)} rows={RUN_ROWS.slice(0, 2)} />
128
+ <div style={{ padding: "10px 16px", borderTop: "1px solid var(--border-subtle)" }}><Pagination page={page} pageCount={12} total={224} pageSize={20} onChange={setPage} /></div>
129
+ </div>
130
+ <div className="note">Never wrap a bare table in your own bordered div — its header rule doubles against the frame. <code>bordered</code> when the table is the card; <code>framed</code> when the card also holds a toolbar or pagination.</div>
131
+ </Case>
132
+
133
+ <div className="kb-h kb-h-gap">Column resize</div>
134
+ <Case k="resizable — short divider between header cells; hover turns it blue, drag sets the width">
135
+ <Table bordered resizable columns={CFG} rows={CFG_ROWS.slice(0, 2)} />
136
+ </Case>
137
+ <Case k="minWidth — per column lower bound (default 48)">
138
+ <Table bordered resizable columns={[{ key: "module", label: "Module", width: 150, minWidth: 140 }, { key: "code", label: "Code", code: true, width: 200, minWidth: 120 }, { key: "cur", label: "Current Value" }, { key: "next", label: "New Value", align: "right" }]} rows={CFG_ROWS.slice(0, 2)} />
139
+ </Case>
140
+ <Case k="sm — same handle">
141
+ <Table size="sm" bordered resizable columns={DENSE} rows={DENSE_ROWS.slice(0, 2)} />
142
+ </Case>
143
+ <Case k="controlled — columnWidths + onColumnResize">
144
+ <Table bordered resizable columns={CFG} rows={CFG_ROWS.slice(0, 2)} columnWidths={widths} onColumnResize={(k, w) => setWidths(s => ({ ...s, [k]: w }))} />
145
+ <div className="note">Uncontrolled (above) keeps widths inside the component — they reset on remount. Controlled hands them to you: module <code>{widths.module ?? "auto"}</code> · code <code>{widths.code ?? "auto"}</code> — persist these to keep a user's layout across sessions.</div>
146
+ </Case>
147
+
148
+ <div className="kb-h kb-h-gap">States</div>
149
+ <Case k="empty — content renders inside the table">
150
+ <Table bordered columns={CFG.slice(0, 3)} rows={[]} empty={<EmptyState icon="table" title="No rows to display" hint="Run a sync to populate this table." style={{ padding: "28px 0" }} />} />
151
+ </Case>
152
+ <Case k="loading — Skeleton rows in place of data">
153
+ <Table bordered columns={CFG.slice(0, 3)} rows={[0, 1, 2].map(() => ({ module: <Skeleton width="60%" height={10} />, code: <Skeleton width="80%" height={10} />, cur: <Skeleton width="30%" height={10} /> }))} />
154
+ </Case>
155
+
156
+ <div className="kb-h kb-h-gap">Composition</div>
157
+ <Case k="row actions — trailing IconButton column, align right">
158
+ <Table bordered columns={[...RUNS.slice(0, 3), { key: "act", label: "", width: 44, align: "right", render: () => <IconButton icon="ellipsis" muted label="Row actions" /> }]} rows={RUN_ROWS} />
159
+ <div className="note">See <b>Filter Bar (List Report)</b> for the full list-report pattern: filters above, <code>framed</code> table, pagination below. See <b>Smart Table</b> and <b>Spreadsheet</b> for editable grids.</div>
160
+ </Case>
161
+ </div>;
162
+ }
163
+ ReactDOM.createRoot(document.getElementById("root")).render(<Sheet/>);
164
+ if (window.KBViewSource) setTimeout(function(){ KBViewSource.mount("#root", [{"name":"Table.jsx","path":"../data/Table.jsx"},{"name":"Badge.jsx (IconTile)","path":"../display/Badge.jsx","vue":"../display/IconTile.vue","vueName":"IconTile.vue"},{"name":"Pagination.jsx","path":"../data/Pagination.jsx"},{"name":"Alert.jsx (EmptyState · Skeleton)","path":"../feedback/Alert.jsx","vue":"../feedback/EmptyState.vue","vueName":"EmptyState.vue"}]); }, 0);
165
+ </script></body></html>
@@ -1,15 +1,17 @@
1
- <!-- @dsCard group="Components" viewport="700x230" name="Tabs" subtitle="Underline tabs · panel tabs · pill filter tabs" -->
1
+ <!-- @dsCard group="Components" viewport="700x550" name="Tabs" subtitle="Underline tabs · panel tabs · pill filter tabs" -->
2
2
  <!DOCTYPE html>
3
- <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css">
3
+ <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
5
5
  <script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
6
6
  <script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
7
7
  <script src="../../_ds_bundle.js"></script>
8
8
  <script src="../_shared/view-source.js"></script>
9
- <style>body{margin:0;background:var(--bg-surface);padding:16px;font-family:var(--font-sans);box-sizing:border-box}.lbl{font-size:10px;letter-spacing:.5px;text-transform:uppercase;color:var(--text-muted);display:block;padding-bottom:8px}</style></head>
9
+ <script src="../_shared/card-kit.js"></script>
10
+ <style>body{margin:0;background:var(--bg-surface);padding:16px;font-family:var(--font-sans);box-sizing:border-box}.lbl{font-size:var(--text-xs);color:var(--text-muted);display:block;padding-bottom:8px}</style></head>
10
11
  <body><div id="root"></div>
11
12
  <script type="text/babel">
12
13
  const { Tabs, PanelTabs, PillTabs } = window.KeybricksDesignSystem_71231a;
14
+ const { KBTiers: Tiers } = window;
13
15
  function Sheet(){
14
16
  const [a,setA]=React.useState("Import");
15
17
  const [b,setB]=React.useState("Node Info");
@@ -18,6 +20,7 @@ function Sheet(){
18
20
  <div><span className="lbl">Tabs — underline, page level</span><Tabs tabs={["Import","Export"]} active={a} onChange={setA}/></div>
19
21
  <div><span className="lbl">PanelTabs — inside a detail panel</span><PanelTabs tabs={["Node Info","Calc Rules","Output Fields","SQL Preview"]} active={b} onChange={setB}/></div>
20
22
  <div><span className="lbl">PillTabs — filter/status tabs</span><PillTabs tabs={["For Review","To be Submitted","For Approval"]} active={c} onChange={setC}/></div>
23
+ <div style={{gridColumn:"1 / -1",display:"flex",flexDirection:"column",gap:8}}><span className="lbl">Size tiers — data-size on the region, the control inherits it</span><Tiers align="flex-start" heads={{sm:"sm · bar 36 · pill 28",md:"md · bar 40 · pill 32",lg:"lg · bar 48 · pill 40"}} init={(l)=>({tab:l==="en"?"Import":"导入",pill:l==="en"?"Review":"待审核"})} render={(t,l,v,set)=><div style={{display:"flex",flexDirection:"column",gap:8}}><Tabs tabs={l==="en"?["Import","Export"]:["导入","导出"]} active={v.tab} onChange={(x)=>set({...v,tab:x})}/><PillTabs tabs={l==="en"?["Review","Done"]:["待审核","已完成"]} active={v.pill} onChange={(x)=>set({...v,pill:x})}/></div>}/></div>
21
24
  </div>;
22
25
  }
23
26
  ReactDOM.createRoot(document.getElementById("root")).render(<Sheet/>);
@@ -1,15 +1,17 @@
1
- <!-- @dsCard group="Components" viewport="700x150" name="Tag" subtitle="Removable filter tags — distinct from Badge/ActionChip" -->
1
+ <!-- @dsCard group="Components" viewport="700x300" name="Tag" subtitle="Removable filter tags — distinct from Badge/ActionChip" -->
2
2
  <!DOCTYPE html>
3
- <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css">
3
+ <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
5
5
  <script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
6
6
  <script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
7
7
  <script src="../../_ds_bundle.js"></script>
8
8
  <script src="../_shared/view-source.js"></script>
9
- <style>body{margin:0;background:var(--bg-surface);padding:16px;font-family:var(--font-sans);box-sizing:border-box}.lbl{font-size:10px;letter-spacing:.5px;text-transform:uppercase;color:var(--text-muted);display:block;padding-bottom:8px}</style></head>
9
+ <script src="../_shared/card-kit.js"></script>
10
+ <style>body{margin:0;background:var(--bg-surface);padding:16px;font-family:var(--font-sans);box-sizing:border-box}.lbl{font-size:var(--text-xs);color:var(--text-muted);display:block;padding-bottom:8px}</style></head>
10
11
  <body><div id="root"></div>
11
12
  <script type="text/babel">
12
13
  const { Tag } = window.KeybricksDesignSystem_71231a;
14
+ const { KBTiers: Tiers } = window;
13
15
  function Sheet(){
14
16
  const [tags,setTags]=React.useState(["Financial Settings","User Management","2026"]);
15
17
  return <div style={{display:"flex",flexDirection:"column",gap:14}}>
@@ -19,6 +21,7 @@ function Sheet(){
19
21
  <div><span className="lbl">Static, neutral & info tone</span>
20
22
  <div style={{display:"flex",gap:6}}><Tag>Draft</Tag><Tag tone="info">Auto-tagged</Tag></div>
21
23
  </div>
24
+ <div style={{gridColumn:"1 / -1",display:"flex",flexDirection:"column",gap:8}}><span className="lbl">Size tiers — data-size on the region, the control inherits it</span><Tiers heads={{sm:"sm · 20",md:"md · 24",lg:"lg · 28"}} init={true} render={(t,l,v,set)=>v?<Tag onRemove={()=>set(false)}>{l==="en"?"Financial Settings":"财务设置"}</Tag>:<button type="button" onClick={()=>set(true)} style={{border:"none",background:"none",padding:0,cursor:"pointer",font:"inherit",fontSize:"var(--control-text)",color:"var(--link)"}}>{l==="en"?"Undo":"撤销"}</button>}/></div>
22
25
  </div>;
23
26
  }
24
27
  ReactDOM.createRoot(document.getElementById("root")).render(<Sheet/>);
@@ -1,6 +1,6 @@
1
- <!-- @dsCard group="Components" viewport="924x509" name="Textarea" subtitle="Default · character count · over the limit · disabled" -->
1
+ <!-- @dsCard group="Components" viewport="924x520" name="Textarea" subtitle="Default · character count · over the limit · disabled" -->
2
2
  <!DOCTYPE html>
3
- <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css">
3
+ <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
5
5
  <script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
6
6
  <script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
@@ -1,12 +1,12 @@
1
- <!-- @dsCard group="Components" viewport="700x440" name="Timeline" subtitle="Vertical activity timeline — toned icon nodes on a hairline spine" -->
1
+ <!-- @dsCard group="Components" viewport="700x350" name="Timeline" subtitle="Vertical activity timeline — toned icon nodes on a hairline spine" -->
2
2
  <!DOCTYPE html>
3
- <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css">
3
+ <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
5
5
  <script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
6
6
  <script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
7
7
  <script src="../../_ds_bundle.js"></script>
8
8
  <script src="../_shared/view-source.js"></script>
9
- <style>body{margin:0;background:var(--bg-surface);padding:16px;font-family:var(--font-sans);box-sizing:border-box}.g{display:grid;grid-template-columns:1fr 1fr;gap:24px}.lbl{font-size:10px;letter-spacing:.5px;text-transform:uppercase;color:var(--text-muted);display:block;padding-bottom:10px}</style></head>
9
+ <style>body{margin:0;background:var(--bg-surface);padding:16px;font-family:var(--font-sans);box-sizing:border-box}.g{display:grid;grid-template-columns:1fr 1fr;gap:24px}.lbl{font-size:var(--text-xs);color:var(--text-muted);display:block;padding-bottom:10px}</style></head>
10
10
  <body><div id="root"></div>
11
11
  <script type="text/babel">
12
12
  const { Timeline, Tag } = window.KeybricksDesignSystem_71231a;
@@ -1,29 +1,31 @@
1
- <!-- @dsCard group="Components" viewport="700x420" name="Toast" subtitle="Tones · with/without meta · live ToastStack demo" -->
1
+ <!-- @dsCard group="Components" viewport="700x450" name="Toast" subtitle="Tones · with/without meta · live ToastStack demo" -->
2
2
  <!DOCTYPE html>
3
- <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css">
3
+ <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
5
5
  <script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
6
6
  <script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
7
7
  <script src="../../_ds_bundle.js"></script>
8
8
  <script src="../_shared/view-source.js"></script>
9
+ <script src="../_shared/card-kit.js"></script>
9
10
  <style>body{margin:0;background:var(--bg-surface);padding:16px;font-family:var(--font-sans);box-sizing:border-box}.col{display:flex;flex-direction:column;gap:10px;max-width:380px}</style></head>
10
11
  <body><div id="root"></div>
11
12
  <script type="text/babel">
12
13
  const { Toast, ToastStack, Button } = window.KeybricksDesignSystem_71231a;
14
+ const { KBLive: Live } = window;
13
15
  function Sheet(){
14
16
  const [toasts,setToasts]=React.useState([]);
15
17
  const notify=(tone,title,meta)=>{const id=Date.now()+Math.random();setToasts(s=>[...s,{id,tone,title,meta}]);setTimeout(()=>setToasts(s=>s.filter(t=>t.id!==id)),3200);};
16
18
  return <div>
17
19
  <div className="col">
18
- <Toast tone="success" title="Import completed" meta="3 configurations applied" onClose={()=>{}}/>
19
- <Toast tone="danger" title="Report generation failed" meta="Q1 Summary • retry available" onClose={()=>{}}/>
20
- <Toast tone="warning" title="4 configurations differ" meta="Review before continuing" onClose={()=>{}}/>
21
- <Toast tone="info" title="Sync started" onClose={()=>{}}/>
20
+ <Live init={true}>{(v,set)=>v?<Toast tone="success" title="Import completed" meta="3 configurations applied" onClose={()=>set(false)}/>:<button type="button" onClick={()=>set(true)} style={{alignSelf:"flex-start",border:"none",background:"none",padding:0,cursor:"pointer",font:"inherit",fontSize:"var(--text-xs)",color:"var(--link)"}}>Show again</button>}</Live>
21
+ <Live init={true}>{(v,set)=>v?<Toast tone="danger" title="Report generation failed" meta="Q1 Summary • retry available" onClose={()=>set(false)}/>:<button type="button" onClick={()=>set(true)} style={{alignSelf:"flex-start",border:"none",background:"none",padding:0,cursor:"pointer",font:"inherit",fontSize:"var(--text-xs)",color:"var(--link)"}}>Show again</button>}</Live>
22
+ <Live init={true}>{(v,set)=>v?<Toast tone="warning" title="4 configurations differ" meta="Review before continuing" onClose={()=>set(false)}/>:<button type="button" onClick={()=>set(true)} style={{alignSelf:"flex-start",border:"none",background:"none",padding:0,cursor:"pointer",font:"inherit",fontSize:"var(--text-xs)",color:"var(--link)"}}>Show again</button>}</Live>
23
+ <Live init={true}>{(v,set)=>v?<Toast tone="info" title="Sync started" onClose={()=>set(false)}/>:<button type="button" onClick={()=>set(true)} style={{alignSelf:"flex-start",border:"none",background:"none",padding:0,cursor:"pointer",font:"inherit",fontSize:"var(--text-xs)",color:"var(--link)"}}>Show again</button>}</Live>
22
24
  <Toast tone="success" title="Saved" />
23
25
  </div>
24
26
  <div style={{display:"flex",gap:8,paddingTop:16}}>
25
- <Button size="sm" onClick={()=>notify("success","Import completed","3 configurations applied")}>Trigger success</Button>
26
- <Button size="sm" variant="outline" onClick={()=>notify("danger","Task failed","Retry available")}>Trigger danger</Button>
27
+ <Button onClick={()=>notify("success","Import completed","3 configurations applied")}>Trigger success</Button>
28
+ <Button variant="outline" onClick={()=>notify("danger","Task failed","Retry available")}>Trigger danger</Button>
27
29
  </div>
28
30
  <ToastStack toasts={toasts} onDismiss={(id)=>setToasts(s=>s.filter(t=>t.id!==id))}/>
29
31
  </div>;
@@ -1,50 +1,55 @@
1
- <!-- @dsCard group="Components" viewport="700x1060" name="Toggle Switch" subtitle="Binary settings pill — sizes · semantic red→green · glyph knobs · inline text · captions · async loading" -->
1
+ <!-- @dsCard group="Components" viewport="700x1670" name="Toggle Switch" subtitle="Binary settings pill — sizes · semantic red→green · glyph knobs · inline text · captions · async loading" -->
2
2
  <!DOCTYPE html>
3
- <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css">
3
+ <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
5
5
  <script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
6
6
  <script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
7
7
  <script src="../../_ds_bundle.js"></script>
8
8
  <script src="../_shared/view-source.js"></script>
9
- <style>body{margin:0;padding:20px 24px;font-family:var(--font-sans);background:var(--bg-surface)}.sec{font-size:var(--text-2xs);font-weight:600;letter-spacing:.7px;text-transform:uppercase;color:var(--text-muted);padding:18px 0 6px;border-top:1px solid var(--border-subtle);margin-top:14px}.sec:first-child{border-top:none;margin-top:0;padding-top:0}.case{display:grid;grid-template-columns:230px 1fr;align-items:center;gap:20px;min-height:36px;padding:5px 0}.k{font-size:var(--text-xs);color:var(--text-secondary);font-family:var(--font-mono)}.v{display:flex;align-items:center;gap:16px;flex-wrap:wrap}.cap{font-size:var(--text-xs);color:var(--text-muted)}a{color:var(--link)}a:hover{color:var(--link-hover)}</style>
9
+ <script src="../_shared/card-kit.js"></script>
10
+ <style>body{margin:0;padding:20px 24px;font-family:var(--font-sans);background:var(--bg-surface)}.sec{font-size:var(--text-xs);font-weight:600;color:var(--text-muted);padding:18px 0 6px;border-top:1px solid var(--border-subtle);margin-top:14px}.sec:first-child{border-top:none;margin-top:0;padding-top:0}.case{display:grid;grid-template-columns:230px 1fr;align-items:center;gap:20px;min-height:36px;padding:5px 0}.k{font-size:var(--text-xs);color:var(--text-secondary);font-family:var(--font-sans)}.v{display:flex;align-items:center;gap:16px;flex-wrap:wrap}.cap{font-size:var(--text-xs);color:var(--text-muted)}a{color:var(--link)}a:hover{color:var(--link-hover)}.kb-h-gap{margin:28px 0 12px}.kb-h-gap:first-child{margin-top:0}</style>
10
11
  </head><body><div id="root"></div>
11
12
  <script type="text/babel">
12
13
  const { Switch } = window.KeybricksDesignSystem_71231a;
14
+ const { KBTiers: Tiers } = window;
13
15
  const wait = (ms, ok = true) => new Promise(r => setTimeout(() => r(ok), ms));
14
16
  const Case = ({ k, children }) => <div className="case"><span className="k">{k}</span><div className="v">{children}</div></div>;
15
17
  function Sheet() {
16
18
  const [v, set] = React.useState({});
17
19
  const b = (k, d = false) => ({ checked: v[k] ?? d, onChange: n => set(s => ({ ...s, [k]: n })) });
18
20
  return <div>
19
- <div className="sec">Sizes &amp; states — sm · md · lg</div>
21
+ <div className="kb-h kb-h-gap">Sizes &amp; states — sm · md · lg</div>
20
22
  <Case k="on"><Switch size="sm" {...b("s1", true)} /><Switch {...b("s2", true)} /><Switch size="lg" {...b("s3", true)} /></Case>
21
23
  <Case k="off"><Switch size="sm" {...b("s4")} /><Switch {...b("s5")} /><Switch size="lg" {...b("s6")} /></Case>
22
24
  <Case k="disabled"><Switch size="sm" checked disabled /><Switch checked disabled /><Switch size="lg" checked disabled /></Case>
23
25
  <Case k="label (settings row)"><Switch size="sm" label="Compact rows" {...b("s7", true)} /><Switch label="Debug Mode" {...b("s8", true)} /><Switch size="lg" label="Auto-run" {...b("s9", true)} /></Case>
24
26
 
25
- <div className="sec">Semantic tone — danger off → success on</div>
27
+ <div className="kb-h kb-h-gap">Size tiers — Latin and CJK labels</div>
28
+ <Tiers init={true} render={(t,l,v,set)=><Switch label={l==="en"?"Compact rows":"紧凑行高"} checked={v} onChange={set}/>}/>
29
+
30
+ <div className="kb-h kb-h-gap">Semantic tone — danger off → success on</div>
26
31
  <Case k='tone="semantic" · on'><Switch size="sm" tone="semantic" {...b("t1", true)} /><Switch tone="semantic" {...b("t2", true)} /><Switch size="lg" tone="semantic" {...b("t3", true)} /></Case>
27
32
  <Case k="off"><Switch size="sm" tone="semantic" {...b("t4")} /><Switch tone="semantic" {...b("t5")} /><Switch size="lg" tone="semantic" {...b("t6")} /></Case>
28
33
 
29
- <div className="sec">Glyph in the knob — md · lg only (sm knob is 12px, too small for a glyph)</div>
34
+ <div className="kb-h kb-h-gap">Glyph in the knob — md · lg only (sm knob is 12px, too small for a glyph)</div>
30
35
  <Case k="knobIcon check"><Switch knobIcon="check" {...b("g1", true)} /><Switch size="lg" knobIcon="check" {...b("g2", true)} /></Case>
31
36
  <Case k="knobIcon {check, x}"><Switch knobIcon={{ on: "check", off: "x" }} {...b("g3")} /><Switch size="lg" knobIcon={{ on: "check", off: "x" }} {...b("g4")} /></Case>
32
37
  <Case k="knobIcon {sun, moon}"><Switch knobIcon={{ on: "sun", off: "moon" }} {...b("g5", true)} /><Switch size="lg" knobIcon={{ on: "sun", off: "moon" }} {...b("g6", true)} /></Case>
33
38
  <Case k="knobText {Y, N}"><Switch knobText={{ on: "Y", off: "N" }} {...b("g7", true)} /><Switch size="lg" knobText={{ on: "Y", off: "N" }} {...b("g8", true)} /></Case>
34
- <Case k="knobText {开, 关}"><Switch knobText={{ on: "开", off: "关" }} {...b("g9")} /><Switch size="lg" knobText={{ on: "开", off: "关" }} {...b("g10")} /></Case>
39
+ <Case k="knobText — one CJK character {开, 关}"><Switch knobText={{ on: "开", off: "关" }} {...b("g9")} /><Switch size="lg" knobText={{ on: "开", off: "关" }} {...b("g10")} /></Case>
35
40
  <Case k="semantic + knobIcon"><Switch tone="semantic" knobIcon={{ on: "check", off: "x" }} {...b("g11", true)} /><Switch size="lg" tone="semantic" knobIcon={{ on: "check", off: "x" }} {...b("g12", true)} /></Case>
36
41
 
37
- <div className="sec">Text inside the pill — md · lg only</div>
42
+ <div className="kb-h kb-h-gap">Text inside the pill — md · lg only</div>
38
43
  <Case k="ON / OFF"><Switch insideOn="ON" insideOff="OFF" {...b("i1", true)} /><Switch size="lg" insideOn="ON" insideOff="OFF" {...b("i2", true)} /></Case>
39
44
  <Case k="开 / 关"><Switch insideOn="开" insideOff="关" {...b("i3")} /><Switch size="lg" insideOn="开" insideOff="关" {...b("i4")} /></Case>
40
45
  <Case k="semantic · Y / N"><Switch tone="semantic" insideOn="Y" insideOff="N" {...b("i5", true)} /><Switch size="lg" tone="semantic" insideOn="Y" insideOff="N" {...b("i6", true)} /></Case>
41
46
 
42
- <div className="sec">Captions beside — sm · md · lg (active side reads heading)</div>
47
+ <div className="kb-h kb-h-gap">Captions beside — sm · md · lg (active side reads heading)</div>
43
48
  <Case k="labelOn"><Switch size="sm" labelOn="Enabled" {...b("l1", true)} /><Switch labelOn="Enabled" {...b("l2", true)} /><Switch size="lg" labelOn="Enabled" {...b("l3", true)} /></Case>
44
49
  <Case k="labelOff + labelOn"><Switch size="sm" labelOff="Monthly" labelOn="Annual" {...b("l4")} /><Switch labelOff="Monthly" labelOn="Annual" {...b("l5")} /><Switch size="lg" labelOff="Monthly" labelOn="Annual" {...b("l6")} /></Case>
45
50
  <Case k="semantic · Off / On"><Switch size="sm" tone="semantic" labelOff="Off" labelOn="On" {...b("l7", true)} /><Switch tone="semantic" labelOff="Off" labelOn="On" {...b("l8", true)} /><Switch size="lg" tone="semantic" labelOff="Off" labelOn="On" {...b("l9", true)} /></Case>
46
51
 
47
- <div className="sec">Loading — sm · md · lg</div>
52
+ <div className="kb-h kb-h-gap">Loading — sm · md · lg</div>
48
53
  <Case k="loading · on"><Switch size="sm" checked loading /><Switch checked loading /><Switch size="lg" checked loading /></Case>
49
54
  <Case k="loading · off"><Switch size="sm" loading /><Switch loading /><Switch size="lg" loading /></Case>
50
55
  <Case k="semantic · loading"><Switch size="sm" tone="semantic" checked loading /><Switch tone="semantic" checked loading /><Switch size="lg" tone="semantic" checked loading /></Case>
@@ -1,20 +1,20 @@
1
- <!-- @dsCard group="Components" viewport="700x260" name="Tooltip" subtitle="Placements — top · bottom · left · right, on icon and text triggers" -->
1
+ <!-- @dsCard group="Components" viewport="700x360" name="Tooltip" subtitle="Placements — top · bottom · left · right, on icon and text triggers" -->
2
2
  <!DOCTYPE html>
3
- <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css">
3
+ <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
5
5
  <script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
6
6
  <script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
7
7
  <script src="../../_ds_bundle.js"></script>
8
8
  <script src="../_shared/view-source.js"></script>
9
- <style>body{margin:0;background:var(--bg-surface);padding:16px 16px 60px;font-family:var(--font-sans);box-sizing:border-box}.row{display:flex;gap:24px;align-items:center;margin-bottom:20px}.lbl{width:64px;flex-shrink:0;font-size:10px;letter-spacing:.5px;text-transform:uppercase;color:var(--text-muted)}</style></head>
10
- <body><div id="root"></div>
9
+ <style>body{margin:0;background:var(--bg-surface);padding:16px 16px 60px;font-family:var(--font-sans);box-sizing:border-box}.row{display:flex;gap:24px;align-items:center;margin-bottom:20px}.lbl{width:64px;flex-shrink:0;font-size:var(--text-xs);color:var(--text-muted)}</style></head>
10
+ <body data-pad="tall"><div id="root"></div>
11
11
  <script type="text/babel">
12
12
  const { Tooltip, Button, IconButton } = window.KeybricksDesignSystem_71231a;
13
13
  function Sheet(){return <div>
14
14
  <div className="row"><span className="lbl">top</span><Tooltip label="Run a test execution" placement="top"><Button variant="ghost" icon="play">Run Test</Button></Tooltip></div>
15
- <div className="row"><span className="lbl">bottom</span><Tooltip label="Notifications" placement="bottom"><IconButton icon="bell" size="lg"/></Tooltip></div>
16
- <div className="row"><span className="lbl">left</span><Tooltip label="Collapse sidebar" placement="left"><IconButton icon="panel-left" size="md"/></Tooltip></div>
17
- <div className="row"><span className="lbl">right</span><Tooltip label="More actions" placement="right"><IconButton icon="ellipsis" size="md"/></Tooltip></div>
15
+ <div className="row"><span className="lbl">bottom</span><Tooltip label="Notifications" placement="bottom"><IconButton icon="bell"/></Tooltip></div>
16
+ <div className="row"><span className="lbl">left</span><Tooltip label="Collapse sidebar" placement="left"><IconButton icon="panel-left"/></Tooltip></div>
17
+ <div className="row"><span className="lbl">right</span><Tooltip label="More actions" placement="right"><IconButton icon="ellipsis"/></Tooltip></div>
18
18
  <div className="row"><span className="lbl">on text</span><Tooltip label="This value is derived from the node's input schema"><span style={{fontSize:13,color:"var(--text-secondary)",borderBottom:"1px dotted var(--text-muted)",cursor:"help"}}>Output Field</span></Tooltip></div>
19
19
  </div>;}
20
20
  ReactDOM.createRoot(document.getElementById("root")).render(<Sheet/>);
@@ -1,12 +1,12 @@
1
- <!-- @dsCard group="Components" viewport="700x1340" name="Tree" subtitle="Cascading checkboxes · disabled nodes · lines · async load · search · drag · keyboard" -->
1
+ <!-- @dsCard group="Components" viewport="700x2110" name="Tree" subtitle="Cascading checkboxes · disabled nodes · lines · async load · search · drag · keyboard" -->
2
2
  <!DOCTYPE html>
3
- <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css">
3
+ <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
5
5
  <script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
6
6
  <script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
7
7
  <script src="../../_ds_bundle.js"></script>
8
8
  <script src="../_shared/view-source.js"></script>
9
- <style>body{margin:0;background:var(--bg-surface);padding:16px;font-family:var(--font-sans);box-sizing:border-box}.g{display:grid;grid-template-columns:1fr 1fr;gap:24px 28px}.lbl{font-size:10px;letter-spacing:.5px;text-transform:uppercase;color:var(--text-muted);display:block;padding-bottom:8px}.hint{font-size:var(--text-xs);line-height:16px;color:var(--text-secondary);padding-top:7px}.hint code{font-family:var(--font-mono);font-size:11px;color:var(--text-body)}.note{grid-column:1/-1;border-top:1px solid var(--border-subtle);padding-top:12px;font-size:var(--text-xs);line-height:17px;color:var(--text-secondary)}.note code{font-family:var(--font-mono);font-size:11px;color:var(--text-body)}.note strong{color:var(--text-heading);font-weight:var(--weight-medium)}</style></head>
9
+ <style>body{margin:0;background:var(--bg-surface);padding:16px;font-family:var(--font-sans);box-sizing:border-box}.g{display:grid;grid-template-columns:1fr 1fr;gap:24px 28px}.lbl{font-size:var(--text-xs);color:var(--text-muted);display:block;padding-bottom:8px}.hint{font-size:var(--text-xs);line-height:16px;color:var(--text-secondary);padding-top:7px}.hint code{font-family:var(--font-mono);font-size:var(--text-xs);color:var(--text-body)}.note{grid-column:1/-1;border-top:1px solid var(--border-subtle);padding-top:12px;font-size:var(--text-xs);line-height:17px;color:var(--text-secondary)}.note code{font-family:var(--font-mono);font-size:var(--text-xs);color:var(--text-body)}.note strong{color:var(--text-heading);font-weight:var(--weight-medium)}</style></head>
10
10
  <body><div id="root"></div>
11
11
  <script type="text/babel">
12
12
  const { Tree, SearchInput, IconButton, Icon } = window.KeybricksDesignSystem_71231a;
@@ -0,0 +1,25 @@
1
+ /* Specimen layout for component cards — one grid for every card, so labels, rows and tier demos line up.
2
+ Not a token file and not part of the package: cards link it next to styles.css. */
3
+ body{margin:0;background:var(--bg-surface);padding:24px;font-family:var(--font-sans);color:var(--text-body);box-sizing:border-box}
4
+ .kb-sheet{display:flex;flex-direction:column;gap:28px}
5
+ .kb-sec{display:flex;flex-direction:column;gap:12px}
6
+ .kb-h{margin:0;font-size:var(--text-xs);line-height:var(--leading-xs);font-weight:600;color:var(--text-muted);padding-bottom:8px;border-bottom:1px solid var(--border-subtle)}
7
+ .kb-row{display:grid;grid-template-columns:120px minmax(0,1fr);column-gap:16px;align-items:center;min-height:32px}
8
+ .kb-k{font-size:var(--text-xs);line-height:var(--leading-xs);color:var(--text-secondary);font-family:var(--font-sans);font-variant-numeric:tabular-nums}
9
+ .kb-v{display:flex;flex-wrap:wrap;gap:12px;align-items:center;min-width:0}
10
+ .kb-note{margin:0;font-size:var(--text-xs);line-height:18px;color:var(--text-secondary);text-wrap:pretty}
11
+ .kb-note code,.kb-code{font-family:var(--font-mono);font-size:var(--text-xs);color:var(--text-body)}
12
+ .kb-tiers{display:grid;grid-template-columns:120px repeat(3,max-content);gap:12px 24px;align-items:center}
13
+ .kb-th{font-size:var(--text-xs);line-height:var(--leading-xs);color:var(--text-muted);font-family:var(--font-sans);font-variant-numeric:tabular-nums}
14
+ .kb-grid{display:grid;gap:12px 20px;align-items:center}
15
+ /* ── Legacy card markup, normalized to the same rhythm (outranks each card's own one-class rules) ── */
16
+ html body{padding:24px}
17
+ html body[data-pad="tall"]{padding-bottom:60px} /* room for popovers that open below the last row */
18
+ body .sh{margin:0 0 12px;font-size:var(--text-xs);line-height:var(--leading-xs);font-weight:600;color:var(--text-muted);padding-bottom:8px;border-bottom:1px solid var(--border-subtle)}
19
+ body .lbl{font-size:var(--text-xs);line-height:var(--leading-xs);color:var(--text-secondary)}
20
+ body :not(.row)>.lbl{padding-bottom:8px}
21
+ body .hint,body .note{font-size:var(--text-xs);line-height:18px;color:var(--text-secondary)}
22
+ body .g{gap:20px 24px}
23
+ body .sec{padding-bottom:28px}
24
+ body .sec:last-child{padding-bottom:0}
25
+ body .case .k{font-size:var(--text-xs);line-height:var(--leading-xs);color:var(--text-secondary);font-family:var(--font-sans)}
@@ -0,0 +1,50 @@
1
+ // Specimen helpers for component cards (plain JS, no JSX). Load after React.
2
+ // <KBSec title="…" note="…">rows</KBSec> a section with a hairline heading
3
+ // <KBRow k="primary">controls</KBRow> a label column + a wrapping control row
4
+ // <KBTiers render={(tier, lang) => …}/> sm · md · lg across, a Latin row and a CJK row
5
+ // <KBTiers stack …/> wide controls: one row per tier, Latin and CJK side by side
6
+ // <KBTiers init={(lang) => v} render={(tier, lang, value, setValue) => …}/>
7
+ // every cell keeps its own state, so each demo is live on its own
8
+ // The CJK row sets lang="zh-CN" on each cell, so the 13px sm text and the regular sm weight apply.
9
+ (function () {
10
+ var h = function () { return window.React.createElement.apply(null, arguments); };
11
+ var HEADS = { sm: "sm · 28", md: "md · 32", lg: "lg · 40" };
12
+ function KBSec(p) {
13
+ return h("section", { className: "kb-sec", style: p.style },
14
+ p.title ? h("h3", { className: "kb-h" }, p.title) : null, p.children,
15
+ p.note ? h("p", { className: "kb-note" }, p.note) : null);
16
+ }
17
+ function KBRow(p) {
18
+ return h("div", { className: "kb-row" }, h("span", { className: "kb-k" }, p.k), h("div", { className: "kb-v", style: p.style }, p.children));
19
+ }
20
+ function TierCell(p) {
21
+ var st = window.React.useState(function () { return typeof p.init === "function" ? p.init(p.lang) : p.init; });
22
+ return h("div", { "data-size": p.tier, lang: p.l, style: { display: "flex", alignItems: p.align || "center", gap: 8, minWidth: 0 } }, p.render(p.tier, p.lang, st[0], st[1]));
23
+ }
24
+ function KBTiers(p) {
25
+ var heads = Object.assign({}, HEADS, p.heads || {});
26
+ var rows = p.cjk === false ? [["Latin", "en"]] : [["Latin", "en"], ["CJK · 中文", "zh-CN"]];
27
+ var cell = function (t, l, k) { return h(TierCell, { key: k, tier: t, l: l, lang: l === "en" ? "en" : "zh", init: p.init, render: p.render, align: p.align }); };
28
+ if (p.stack) {
29
+ var sc = [h("span", { key: "h0" })];
30
+ rows.forEach(function (r) { sc.push(h("span", { key: "h" + r[1], className: "kb-th" }, r[0])); });
31
+ ["sm", "md", "lg"].forEach(function (t) {
32
+ sc.push(h("span", { key: "r" + t, className: "kb-th" }, heads[t]));
33
+ rows.forEach(function (r) { sc.push(cell(t, r[1], t + r[1])); });
34
+ });
35
+ return h("div", { className: "kb-tiers", style: Object.assign({ gridTemplateColumns: "120px repeat(" + rows.length + ",max-content)" }, p.style) }, sc);
36
+ }
37
+ var cells = [h("span", { key: "h0" })];
38
+ ["sm", "md", "lg"].forEach(function (t) { cells.push(h("span", { key: "h" + t, className: "kb-th" }, heads[t])); });
39
+ rows.forEach(function (r) {
40
+ cells.push(h("span", { key: r[1], className: "kb-k" }, r[0]));
41
+ ["sm", "md", "lg"].forEach(function (t) {
42
+ cells.push(cell(t, r[1], r[1] + t));
43
+ });
44
+ });
45
+ return h("div", { className: "kb-tiers", style: p.style }, cells);
46
+ }
47
+ // <KBLive init={v}>{(value, setValue) => …}</KBLive> — local state for a single live demo
48
+ function KBLive(p) { var st = window.React.useState(p.init); return p.children(st[0], st[1]); }
49
+ window.KBSec = KBSec; window.KBRow = KBRow; window.KBTiers = KBTiers; window.KBLive = KBLive;
50
+ })();