@teseor/css 1.14.2 → 1.15.0

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 (300) hide show
  1. package/package.json +1 -1
  2. package/src/base/root.docs.html +20 -0
  3. package/src/base/typography/typography.docs.html +161 -0
  4. package/src/components/actions/button/button.docs.html +76 -0
  5. package/src/components/actions/button/button.visual.spec.ts +7 -3
  6. package/src/components/actions/button-group/button-group.docs.html +47 -0
  7. package/src/components/actions/button-group/button-group.visual.spec.ts +7 -3
  8. package/src/components/actions/close-button/close-button.docs.html +77 -0
  9. package/src/components/actions/close-button/close-button.visual.spec.ts +7 -3
  10. package/src/components/content/divider/divider.docs.html +27 -0
  11. package/src/components/content/divider/divider.visual.spec.ts +7 -3
  12. package/src/components/content/scroll-area/scroll-area-visual.png +0 -0
  13. package/src/components/content/scroll-area/scroll-area.docs.html +130 -0
  14. package/src/components/content/scroll-area/scroll-area.visual.spec.ts +7 -3
  15. package/src/components/content/spacer/spacer.docs.html +23 -0
  16. package/src/components/content/spacer/spacer.visual.spec.ts +3 -3
  17. package/src/components/data-display/avatar/avatar.docs.html +67 -0
  18. package/src/components/data-display/avatar/avatar.visual.spec.ts +7 -3
  19. package/src/components/data-display/badge/badge.docs.html +39 -0
  20. package/src/components/data-display/badge/badge.visual.spec.ts +7 -3
  21. package/src/components/data-display/card/card-visual.png +0 -0
  22. package/src/components/data-display/card/card.docs.html +36 -0
  23. package/src/components/data-display/card/card.visual.spec.ts +7 -3
  24. package/src/components/data-display/data-list/data-list-visual.png +0 -0
  25. package/src/components/data-display/data-list/data-list.docs.html +97 -0
  26. package/src/components/data-display/data-list/data-list.visual.spec.ts +7 -3
  27. package/src/components/data-display/icon/icon.docs.html +72 -0
  28. package/src/components/data-display/icon/icon.visual.spec.ts +7 -3
  29. package/src/components/data-display/image/image-visual.png +0 -0
  30. package/src/components/data-display/image/image.docs.html +67 -0
  31. package/src/components/data-display/image/image.visual.spec.ts +7 -3
  32. package/src/components/data-display/stat/stat.docs.html +35 -0
  33. package/src/components/data-display/stat/stat.visual.spec.ts +7 -3
  34. package/src/components/data-display/status/status.docs.html +67 -0
  35. package/src/components/data-display/status/status.visual.spec.ts +7 -3
  36. package/src/components/data-display/table/table.docs.html +73 -0
  37. package/src/components/data-display/table/table.visual.spec.ts +7 -3
  38. package/src/components/data-display/tag/tag.docs.html +42 -0
  39. package/src/components/data-display/tag/tag.visual.spec.ts +7 -3
  40. package/src/components/disclosure/accordion/accordion.docs.html +83 -0
  41. package/src/components/disclosure/accordion/accordion.visual.spec.ts +7 -3
  42. package/src/components/disclosure/disclosure/disclosure.docs.html +51 -0
  43. package/src/components/disclosure/disclosure/disclosure.visual.spec.ts +7 -3
  44. package/src/components/feedback/alert/alert.docs.html +90 -0
  45. package/src/components/feedback/alert/alert.visual.spec.ts +7 -3
  46. package/src/components/feedback/progress/progress.docs.html +65 -0
  47. package/src/components/feedback/progress/progress.visual.spec.ts +7 -3
  48. package/src/components/feedback/progress-circle/progress-circle.docs.html +65 -0
  49. package/src/components/feedback/progress-circle/progress-circle.visual.spec.ts +7 -3
  50. package/src/components/feedback/skeleton/skeleton.docs.html +40 -0
  51. package/src/components/feedback/skeleton/skeleton.visual.spec.ts +7 -3
  52. package/src/components/feedback/spinner/spinner.docs.html +28 -0
  53. package/src/components/feedback/spinner/spinner.visual.spec.ts +7 -3
  54. package/src/components/feedback/toast/toast-visual.png +0 -0
  55. package/src/components/feedback/toast/toast.docs.html +109 -0
  56. package/src/components/feedback/toast/toast.visual.spec.ts +7 -3
  57. package/src/components/forms/checkbox/checkbox.docs.html +33 -0
  58. package/src/components/forms/checkbox/checkbox.visual.spec.ts +7 -3
  59. package/src/components/forms/checkbox-group/checkbox-group.docs.html +104 -0
  60. package/src/components/forms/checkbox-group/checkbox-group.visual.spec.ts +7 -3
  61. package/src/components/forms/field/field.docs.html +63 -0
  62. package/src/components/forms/field/field.visual.spec.ts +7 -3
  63. package/src/components/forms/fieldset/fieldset.docs.html +122 -0
  64. package/src/components/forms/fieldset/fieldset.visual.spec.ts +7 -3
  65. package/src/components/forms/form/form.docs.html +132 -0
  66. package/src/components/forms/form/form.visual.spec.ts +7 -3
  67. package/src/components/forms/form-error/form-error.docs.html +18 -0
  68. package/src/components/forms/form-error/form-error.visual.spec.ts +7 -3
  69. package/src/components/forms/form-helper/form-helper.docs.html +42 -0
  70. package/src/components/forms/form-helper/form-helper.visual.spec.ts +7 -3
  71. package/src/components/forms/input/input-visual.png +0 -0
  72. package/src/components/forms/input/input.docs.html +69 -0
  73. package/src/components/forms/input/input.visual.spec.ts +7 -3
  74. package/src/components/forms/label/label-visual.png +0 -0
  75. package/src/components/forms/label/label.docs.html +29 -0
  76. package/src/components/forms/label/label.visual.spec.ts +7 -3
  77. package/src/components/forms/number-input/number-input-visual.png +0 -0
  78. package/src/components/forms/number-input/number-input.docs.html +100 -0
  79. package/src/components/forms/number-input/number-input.visual.spec.ts +7 -3
  80. package/src/components/forms/password-input/password-input-visual.png +0 -0
  81. package/src/components/forms/password-input/password-input.docs.html +88 -0
  82. package/src/components/forms/password-input/password-input.visual.spec.ts +7 -3
  83. package/src/components/forms/radio/radio.docs.html +52 -0
  84. package/src/components/forms/radio/radio.visual.spec.ts +7 -3
  85. package/src/components/forms/radio-group/radio-group.docs.html +100 -0
  86. package/src/components/forms/radio-group/radio-group.visual.spec.ts +7 -3
  87. package/src/components/forms/search-input/search-input-visual.png +0 -0
  88. package/src/components/forms/search-input/search-input.docs.html +87 -0
  89. package/src/components/forms/search-input/search-input.visual.spec.ts +7 -3
  90. package/src/components/forms/select/select-visual.png +0 -0
  91. package/src/components/forms/select/select.docs.html +70 -0
  92. package/src/components/forms/select/select.visual.spec.ts +7 -3
  93. package/src/components/forms/slider/slider-visual.png +0 -0
  94. package/src/components/forms/slider/slider.docs.html +25 -0
  95. package/src/components/forms/slider/slider.visual.spec.ts +7 -3
  96. package/src/components/forms/textarea/textarea-visual.png +0 -0
  97. package/src/components/forms/textarea/textarea.docs.html +39 -0
  98. package/src/components/forms/textarea/textarea.visual.spec.ts +7 -3
  99. package/src/components/forms/toggle/toggle.docs.html +64 -0
  100. package/src/components/forms/toggle/toggle.visual.spec.ts +7 -3
  101. package/src/components/navigation/breadcrumb/breadcrumb.docs.html +60 -0
  102. package/src/components/navigation/breadcrumb/breadcrumb.visual.spec.ts +7 -3
  103. package/src/components/navigation/dropdown-menu/dropdown-menu-visual.png +0 -0
  104. package/src/components/navigation/dropdown-menu/dropdown-menu.docs.html +106 -0
  105. package/src/components/navigation/dropdown-menu/dropdown-menu.visual.spec.ts +7 -3
  106. package/src/components/navigation/menu/menu.docs.html +122 -0
  107. package/src/components/navigation/menu/menu.visual.spec.ts +7 -3
  108. package/src/components/navigation/nav/nav.docs.html +74 -0
  109. package/src/components/navigation/nav/nav.visual.spec.ts +7 -3
  110. package/src/components/navigation/pagination/pagination-visual.png +0 -0
  111. package/src/components/navigation/pagination/pagination.docs.html +116 -0
  112. package/src/components/navigation/pagination/pagination.visual.spec.ts +7 -3
  113. package/src/components/navigation/tabs/tabs.docs.html +66 -0
  114. package/src/components/navigation/tabs/tabs.visual.spec.ts +7 -3
  115. package/src/components/overlays/dialog/dialog.docs.html +61 -0
  116. package/src/components/overlays/dialog/dialog.visual.spec.ts +7 -3
  117. package/src/components/overlays/drawer/drawer-visual.png +0 -0
  118. package/src/components/overlays/drawer/drawer.docs.html +90 -0
  119. package/src/components/overlays/drawer/drawer.visual.spec.ts +7 -3
  120. package/src/components/overlays/modal/modal.docs.html +69 -0
  121. package/src/components/overlays/modal/modal.visual.spec.ts +7 -3
  122. package/src/components/overlays/overlay/overlay.docs.html +30 -0
  123. package/src/components/overlays/overlay/overlay.visual.spec.ts +7 -3
  124. package/src/components/overlays/popover/popover.docs.html +41 -0
  125. package/src/components/overlays/popover/popover.visual.spec.ts +7 -3
  126. package/src/components/overlays/tooltip/tooltip.docs.html +33 -0
  127. package/src/components/overlays/tooltip/tooltip.visual.spec.ts +7 -3
  128. package/src/components/typography/blockquote/blockquote.docs.html +24 -0
  129. package/src/components/typography/blockquote/blockquote.visual.spec.ts +7 -3
  130. package/src/components/typography/code/code-visual.png +0 -0
  131. package/src/components/typography/code/code.docs.html +23 -0
  132. package/src/components/typography/code/code.visual.spec.ts +7 -3
  133. package/src/components/typography/code-block/code-block-visual.png +0 -0
  134. package/src/components/typography/code-block/code-block.docs.html +87 -0
  135. package/src/components/typography/code-block/code-block.visual.spec.ts +7 -3
  136. package/src/components/typography/heading/heading-visual.png +0 -0
  137. package/src/components/typography/heading/heading.docs.html +26 -0
  138. package/src/components/typography/heading/heading.visual.spec.ts +7 -3
  139. package/src/components/typography/kbd/kbd.docs.html +16 -0
  140. package/src/components/typography/kbd/kbd.visual.spec.ts +7 -3
  141. package/src/components/typography/link/link.docs.html +33 -0
  142. package/src/components/typography/link/link.visual.spec.ts +7 -3
  143. package/src/components/typography/list/list.docs.html +79 -0
  144. package/src/components/typography/list/list.visual.spec.ts +7 -3
  145. package/src/components/typography/mark/mark.docs.html +12 -0
  146. package/src/components/typography/mark/mark.visual.spec.ts +7 -3
  147. package/src/config/guides/accessibility.docs.html +108 -0
  148. package/src/config/guides/getting-started.docs.html +47 -0
  149. package/src/config/guides/theming.docs.html +71 -0
  150. package/src/config/tokens/colors/colors.docs.html +75 -0
  151. package/src/config/tokens/design-tokens.docs.html +116 -0
  152. package/src/config/tokens/grid/grid.docs.html +12 -0
  153. package/src/config/tokens/spacing/spacing.docs.html +33 -0
  154. package/src/debug/debug.docs.html +29 -0
  155. package/src/debug/index.scss +81 -1
  156. package/src/layout/app-shell/app-shell-visual.png +0 -0
  157. package/src/layout/app-shell/app-shell.docs.html +102 -0
  158. package/src/layout/app-shell/app-shell.visual.spec.ts +3 -3
  159. package/src/layout/aspect-ratio/aspect-ratio.docs.html +41 -0
  160. package/src/layout/aspect-ratio/aspect-ratio.visual.spec.ts +3 -3
  161. package/src/layout/box/box-visual.png +0 -0
  162. package/src/layout/box/box.docs.html +27 -0
  163. package/src/layout/box/box.visual.spec.ts +3 -3
  164. package/src/layout/center/center.docs.html +26 -0
  165. package/src/layout/center/center.visual.spec.ts +3 -3
  166. package/src/layout/column/column.docs.html +32 -0
  167. package/src/layout/column/column.visual.spec.ts +3 -3
  168. package/src/layout/container/container.docs.html +37 -0
  169. package/src/layout/content/content-visual.png +0 -0
  170. package/src/layout/content/content.docs.html +38 -0
  171. package/src/layout/content/content.visual.spec.ts +7 -3
  172. package/src/layout/footer/footer-visual.png +0 -0
  173. package/src/layout/footer/footer.docs.html +73 -0
  174. package/src/layout/footer/footer.visual.spec.ts +7 -3
  175. package/src/layout/grid/grid.docs.html +87 -0
  176. package/src/layout/grid/grid.visual.spec.ts +3 -3
  177. package/src/layout/main/main.docs.html +31 -0
  178. package/src/layout/nav-rail/nav-rail-visual.png +0 -0
  179. package/src/layout/nav-rail/nav-rail.docs.html +42 -0
  180. package/src/layout/nav-rail/nav-rail.visual.spec.ts +7 -3
  181. package/src/layout/page-header/page-header.docs.html +52 -0
  182. package/src/layout/page-header/page-header.visual.spec.ts +7 -3
  183. package/src/layout/row/row.docs.html +47 -0
  184. package/src/layout/row/row.visual.spec.ts +3 -3
  185. package/src/layout/sidebar/sidebar-visual.png +0 -0
  186. package/src/layout/sidebar/sidebar.docs.html +30 -0
  187. package/src/layout/sidebar/sidebar.visual.spec.ts +7 -3
  188. package/src/layout/sidebar-nav/sidebar-nav.docs.html +235 -0
  189. package/src/layout/sidebar-nav/sidebar-nav.visual.spec.ts +7 -3
  190. package/src/layout/topbar/topbar-visual.png +0 -0
  191. package/src/layout/topbar/topbar.docs.html +64 -0
  192. package/src/layout/topbar/topbar.visual.spec.ts +7 -3
  193. package/src/utilities/container/container.docs.html +34 -0
  194. package/src/utilities/display/display.docs.html +30 -0
  195. package/src/utilities/scroll-animation/scroll-animation.docs.html +32 -0
  196. package/src/utilities/scroll-snap/scroll-snap.docs.html +80 -0
  197. package/src/utilities/spacing/spacing.docs.html +29 -0
  198. package/src/utilities/text/text.docs.html +66 -0
  199. package/src/utilities/view-transition/view-transition.docs.html +52 -0
  200. package/src/utilities/visually-hidden/visually-hidden.docs.html +18 -0
  201. package/src/base/typography/typography.docs.json +0 -328
  202. package/src/components/actions/button/button.docs.json +0 -264
  203. package/src/components/actions/button-group/button-group.docs.json +0 -151
  204. package/src/components/actions/close-button/close-button.docs.json +0 -265
  205. package/src/components/content/divider/divider.docs.json +0 -113
  206. package/src/components/content/scroll-area/scroll-area.docs.json +0 -273
  207. package/src/components/content/spacer/spacer.docs.json +0 -102
  208. package/src/components/data-display/avatar/avatar.docs.json +0 -245
  209. package/src/components/data-display/badge/badge.docs.json +0 -114
  210. package/src/components/data-display/card/card.docs.json +0 -229
  211. package/src/components/data-display/data-list/data-list.docs.json +0 -259
  212. package/src/components/data-display/icon/icon.docs.json +0 -307
  213. package/src/components/data-display/image/image.docs.json +0 -337
  214. package/src/components/data-display/stat/stat.docs.json +0 -114
  215. package/src/components/data-display/status/status.docs.json +0 -147
  216. package/src/components/data-display/table/table.docs.json +0 -184
  217. package/src/components/data-display/tag/tag.docs.json +0 -146
  218. package/src/components/disclosure/accordion/accordion.docs.json +0 -206
  219. package/src/components/disclosure/disclosure/disclosure.docs.json +0 -154
  220. package/src/components/feedback/alert/alert.docs.json +0 -325
  221. package/src/components/feedback/progress/progress.docs.json +0 -315
  222. package/src/components/feedback/progress-circle/progress-circle.docs.json +0 -378
  223. package/src/components/feedback/skeleton/skeleton.docs.json +0 -142
  224. package/src/components/feedback/spinner/spinner.docs.json +0 -121
  225. package/src/components/feedback/toast/toast.docs.json +0 -418
  226. package/src/components/forms/checkbox/checkbox.docs.json +0 -166
  227. package/src/components/forms/checkbox-group/checkbox-group.docs.json +0 -339
  228. package/src/components/forms/field/field.docs.json +0 -276
  229. package/src/components/forms/fieldset/fieldset.docs.json +0 -520
  230. package/src/components/forms/form/form.docs.json +0 -482
  231. package/src/components/forms/form-error/form-error.docs.json +0 -61
  232. package/src/components/forms/form-helper/form-helper.docs.json +0 -151
  233. package/src/components/forms/input/input.docs.json +0 -306
  234. package/src/components/forms/label/label.docs.json +0 -110
  235. package/src/components/forms/number-input/number-input.docs.json +0 -311
  236. package/src/components/forms/password-input/password-input.docs.json +0 -316
  237. package/src/components/forms/radio/radio.docs.json +0 -236
  238. package/src/components/forms/radio-group/radio-group.docs.json +0 -351
  239. package/src/components/forms/search-input/search-input.docs.json +0 -293
  240. package/src/components/forms/select/select.docs.json +0 -231
  241. package/src/components/forms/slider/slider.docs.json +0 -144
  242. package/src/components/forms/textarea/textarea.docs.json +0 -229
  243. package/src/components/forms/toggle/toggle.docs.json +0 -229
  244. package/src/components/navigation/breadcrumb/breadcrumb.docs.json +0 -240
  245. package/src/components/navigation/dropdown-menu/dropdown-menu.docs.json +0 -290
  246. package/src/components/navigation/menu/menu.docs.json +0 -326
  247. package/src/components/navigation/nav/nav.docs.json +0 -304
  248. package/src/components/navigation/pagination/pagination.docs.json +0 -483
  249. package/src/components/navigation/tabs/tabs.docs.json +0 -243
  250. package/src/components/overlays/dialog/dialog.docs.json +0 -200
  251. package/src/components/overlays/drawer/drawer.docs.json +0 -307
  252. package/src/components/overlays/modal/modal.docs.json +0 -252
  253. package/src/components/overlays/overlay/overlay.docs.json +0 -138
  254. package/src/components/overlays/popover/popover.docs.json +0 -154
  255. package/src/components/overlays/tooltip/tooltip.docs.json +0 -133
  256. package/src/components/typography/blockquote/blockquote.docs.json +0 -89
  257. package/src/components/typography/code/code.docs.json +0 -104
  258. package/src/components/typography/code-block/code-block.docs.json +0 -308
  259. package/src/components/typography/heading/heading.docs.json +0 -120
  260. package/src/components/typography/kbd/kbd.docs.json +0 -61
  261. package/src/components/typography/link/link.docs.json +0 -149
  262. package/src/components/typography/list/list.docs.json +0 -296
  263. package/src/components/typography/mark/mark.docs.json +0 -60
  264. package/src/config/tokens/accessibility.docs.json +0 -125
  265. package/src/config/tokens/colors/colors.docs.json +0 -316
  266. package/src/config/tokens/grid/grid.docs.json +0 -54
  267. package/src/config/tokens/spacing/spacing.docs.json +0 -114
  268. package/src/config/tokens/theming.docs.json +0 -288
  269. package/src/debug/grid-overlay.scss +0 -81
  270. package/src/layout/app-shell/app-shell.docs.json +0 -155
  271. package/src/layout/aspect-ratio/aspect-ratio.docs.json +0 -193
  272. package/src/layout/box/box.docs.json +0 -93
  273. package/src/layout/center/center.docs.json +0 -63
  274. package/src/layout/column/column.docs.json +0 -157
  275. package/src/layout/container/container.docs.json +0 -85
  276. package/src/layout/content/content.docs.json +0 -82
  277. package/src/layout/footer/footer.docs.json +0 -119
  278. package/src/layout/grid/grid.docs.json +0 -493
  279. package/src/layout/main/main.docs.json +0 -87
  280. package/src/layout/nav-rail/nav-rail.docs.json +0 -76
  281. package/src/layout/page-header/page-header.docs.json +0 -124
  282. package/src/layout/row/row.docs.json +0 -237
  283. package/src/layout/sidebar/sidebar.docs.json +0 -63
  284. package/src/layout/sidebar-nav/sidebar-nav.docs.json +0 -833
  285. package/src/layout/topbar/topbar.docs.json +0 -110
  286. package/src/testing/api-types.ts +0 -20
  287. package/src/testing/grid-alignment.spec.ts +0 -38
  288. package/src/testing/html-generator.ts +0 -151
  289. package/src/testing/index.ts +0 -15
  290. package/src/testing/page-setup.ts +0 -149
  291. package/src/testing/rhythm.ts +0 -146
  292. package/src/testing/scaffold.ts +0 -50
  293. package/src/utilities/container/container.docs.json +0 -121
  294. package/src/utilities/display/display.docs.json +0 -83
  295. package/src/utilities/scroll-animation/scroll-animation.docs.json +0 -100
  296. package/src/utilities/scroll-snap/scroll-snap.docs.json +0 -333
  297. package/src/utilities/spacing/spacing.docs.json +0 -133
  298. package/src/utilities/text/text.docs.json +0 -191
  299. package/src/utilities/view-transition/view-transition.docs.json +0 -63
  300. package/src/utilities/visually-hidden/visually-hidden.docs.json +0 -44
@@ -1,110 +0,0 @@
1
- {
2
- "id": "topbar",
3
- "type": "primitive",
4
- "title": "Topbar",
5
- "description": "Fixed or sticky header bar for app layouts with start, center, and end sections.",
6
- "api": "./topbar.api.json",
7
- "sections": [
8
- {
9
- "title": "Default",
10
- "description": "Basic topbar with three sections: start (brand), center (search/nav), and end (actions).",
11
- "examples": [
12
- {
13
- "items": [
14
- {
15
- "tag": "header",
16
- "class": "ui-topbar ui-topbar--bordered",
17
- "children": [
18
- {
19
- "tag": "div",
20
- "class": "ui-topbar__start",
21
- "children": [{ "tag": "strong", "text": "Brand" }]
22
- },
23
- {
24
- "tag": "div",
25
- "class": "ui-topbar__center",
26
- "children": [{ "tag": "span", "text": "Center content" }]
27
- },
28
- {
29
- "tag": "div",
30
- "class": "ui-topbar__end",
31
- "children": [{ "tag": "span", "text": "Actions" }]
32
- }
33
- ]
34
- }
35
- ]
36
- }
37
- ]
38
- },
39
- {
40
- "title": "Sticky",
41
- "description": "Stays at the top of the viewport on scroll.",
42
- "examples": [
43
- {
44
- "code": "<header class=\"ui-topbar ui-topbar--sticky ui-topbar--bordered\">\n <div class=\"ui-topbar__start\"><strong>Brand</strong></div>\n <div class=\"ui-topbar__center\">Nav</div>\n <div class=\"ui-topbar__end\">Actions</div>\n</header>"
45
- }
46
- ]
47
- },
48
- {
49
- "title": "Bordered",
50
- "description": "Bottom border via inset box-shadow to preserve grid rhythm.",
51
- "examples": [
52
- {
53
- "items": [
54
- {
55
- "tag": "header",
56
- "class": "ui-topbar ui-topbar--bordered",
57
- "children": [
58
- {
59
- "tag": "div",
60
- "class": "ui-topbar__start",
61
- "children": [{ "tag": "strong", "text": "Bordered" }]
62
- },
63
- {
64
- "tag": "div",
65
- "class": "ui-topbar__end",
66
- "children": [{ "tag": "span", "text": "Actions" }]
67
- }
68
- ]
69
- }
70
- ]
71
- }
72
- ]
73
- },
74
- {
75
- "title": "Raised",
76
- "description": "Subtle drop shadow below the topbar.",
77
- "examples": [
78
- {
79
- "items": [
80
- {
81
- "tag": "header",
82
- "class": "ui-topbar ui-topbar--raised",
83
- "children": [
84
- {
85
- "tag": "div",
86
- "class": "ui-topbar__start",
87
- "children": [{ "tag": "strong", "text": "Raised" }]
88
- },
89
- {
90
- "tag": "div",
91
- "class": "ui-topbar__end",
92
- "children": [{ "tag": "span", "text": "Actions" }]
93
- }
94
- ]
95
- }
96
- ]
97
- }
98
- ]
99
- },
100
- {
101
- "title": "Integration with Sidebar",
102
- "description": "Set --topbar-height on .app-shell so sidebar and main offset correctly. The topbar itself uses --fixed, and sidebar/main read --topbar-height.",
103
- "examples": [
104
- {
105
- "code": "<body class=\"ui-app-shell\" style=\"--topbar-height: var(--ui-row-3)\">\n <header class=\"ui-topbar ui-topbar--fixed ui-topbar--bordered\">\n <div class=\"ui-topbar__start\"><strong>App</strong></div>\n <div class=\"ui-topbar__end\">User</div>\n </header>\n <aside class=\"ui-sidebar\">Sidebar</aside>\n <main class=\"ui-main\">\n <div class=\"ui-container\">Content</div>\n </main>\n</body>"
106
- }
107
- ]
108
- }
109
- ]
110
- }
@@ -1,20 +0,0 @@
1
- export interface ComponentAPI {
2
- name: string;
3
- baseClass?: string;
4
- element: string;
5
- description: string;
6
- modifiers: Record<
7
- string,
8
- {
9
- values?: string[];
10
- type?: string;
11
- default?: string | null;
12
- description: string;
13
- }
14
- >;
15
- states?: string[];
16
- combinations?: Array<{
17
- modifiers: string[];
18
- disabled?: boolean;
19
- }>;
20
- }
@@ -1,38 +0,0 @@
1
- import { readdirSync, statSync } from 'node:fs';
2
- import { basename, join, resolve } from 'node:path';
3
- import { test } from '@playwright/test';
4
- import { generateHtmlFromDocs, loadDocsJson, setupVisualTest, validateGridRhythm } from '.';
5
-
6
- const COMPONENTS_DIR = resolve(__dirname, '../components');
7
-
8
- // Known grid rhythm issues tracked in separate issues
9
- const SKIP_COMPONENTS = [
10
- 'data-list', // 1px borders cause off-grid heights (#179)
11
- 'spinner', // CSS var resolution issue (#154)
12
- 'spacer', // no intrinsic height by design
13
- ];
14
-
15
- function findDocsFiles(dir: string): Array<{ name: string; path: string }> {
16
- const results: Array<{ name: string; path: string }> = [];
17
- for (const entry of readdirSync(dir)) {
18
- const full = join(dir, entry);
19
- if (statSync(full).isDirectory()) {
20
- results.push(...findDocsFiles(full));
21
- } else if (entry.endsWith('.docs.json')) {
22
- results.push({ name: basename(entry, '.docs.json'), path: full });
23
- }
24
- }
25
- return results;
26
- }
27
-
28
- const docsFiles = findDocsFiles(COMPONENTS_DIR);
29
-
30
- for (const { name, path } of docsFiles) {
31
- test(`${name} aligns to vertical grid`, async ({ page }) => {
32
- test.skip(SKIP_COMPONENTS.includes(name), `${name} has known grid issues`);
33
- const docs = loadDocsJson(path);
34
- const html = generateHtmlFromDocs(docs);
35
- await setupVisualTest(page, { html });
36
- await validateGridRhythm(page, name);
37
- });
38
- }
@@ -1,151 +0,0 @@
1
- import type { ComponentAPI } from './api-types';
2
-
3
- const PREFIX = 'ui-';
4
-
5
- function generateCombinations(
6
- api: ComponentAPI,
7
- ): Array<{ modifiers: string[]; disabled?: boolean }> {
8
- if (api.combinations) return api.combinations;
9
-
10
- const enumModifiers = Object.entries(api.modifiers)
11
- .filter(([, def]) => def.values)
12
- .map(([, def]) => def.values!);
13
-
14
- if (enumModifiers.length < 2) return [];
15
-
16
- const [first, second] = enumModifiers;
17
- const combos: Array<{ modifiers: string[] }> = [];
18
-
19
- for (const a of first) {
20
- for (const b of second) {
21
- combos.push({ modifiers: [a, b] });
22
- }
23
- }
24
-
25
- return combos;
26
- }
27
-
28
- function capitalize(s: string): string {
29
- return s.charAt(0).toUpperCase() + s.slice(1);
30
- }
31
-
32
- export function generateVariationsHtml(api: ComponentAPI): string {
33
- const baseClass = `${PREFIX}${api.baseClass ?? api.name}`;
34
- const element = api.element;
35
- const title = capitalize(api.name);
36
-
37
- const sections: string[] = [];
38
-
39
- // Default section
40
- sections.push(`
41
- <div class="test-section">
42
- <div class="test-section-title">Default</div>
43
- <div class="test-row">
44
- <${element} class="${baseClass}">Default</${element}>
45
- </div>
46
- </div>
47
- `);
48
-
49
- // Generate sections for each modifier
50
- for (const [modName, modDef] of Object.entries(api.modifiers)) {
51
- const sectionTitle = capitalize(modName);
52
-
53
- if (modDef.values) {
54
- const buttons: string[] = [];
55
-
56
- if (modName === 'size') {
57
- buttons.push(`<${element} class="${baseClass}">Default</${element}>`);
58
- }
59
- if (modName === 'variant') {
60
- buttons.push(`<${element} class="${baseClass}">Primary</${element}>`);
61
- }
62
-
63
- for (const value of modDef.values) {
64
- const modClass = `${baseClass}--${value}`;
65
- const label = capitalize(value);
66
- buttons.push(`<${element} class="${baseClass} ${modClass}">${label}</${element}>`);
67
- }
68
-
69
- sections.push(`
70
- <div class="test-section">
71
- <div class="test-section-title">${sectionTitle}</div>
72
- <div class="test-row">
73
- ${buttons.join('\n ')}
74
- </div>
75
- </div>
76
- `);
77
- } else if (modDef.type === 'boolean') {
78
- const modClass = `${baseClass}--${modName}`;
79
- const content = modName === 'icon' ? '+' : 'Full Width';
80
- const blockClass = modName === 'block' ? ' test-element--block' : '';
81
-
82
- sections.push(`
83
- <div class="test-section">
84
- <div class="test-section-title">${sectionTitle}</div>
85
- <div class="test-row">
86
- <div class="${blockClass.trim()}">
87
- <${element} class="${baseClass} ${modClass}">${content}</${element}>
88
- </div>
89
- </div>
90
- </div>
91
- `);
92
- }
93
- }
94
-
95
- // States section
96
- if (api.states && api.states.length > 0) {
97
- const stateButtons: string[] = [];
98
- stateButtons.push(`<${element} class="${baseClass}">Normal</${element}>`);
99
-
100
- if (api.states.includes('hover')) {
101
- stateButtons.push(`<${element} class="${baseClass} ${baseClass}--hover">Hover</${element}>`);
102
- }
103
- if (api.states.includes('focus')) {
104
- stateButtons.push(`<${element} class="${baseClass} ${baseClass}--focus">Focus</${element}>`);
105
- }
106
- if (api.states.includes('active')) {
107
- stateButtons.push(
108
- `<${element} class="${baseClass} ${baseClass}--active">Active</${element}>`,
109
- );
110
- }
111
- if (api.states.includes('disabled')) {
112
- stateButtons.push(`<${element} class="${baseClass}" disabled>Disabled</${element}>`);
113
- }
114
-
115
- sections.push(`
116
- <div class="test-section">
117
- <div class="test-section-title">States</div>
118
- <div class="test-row">
119
- ${stateButtons.join('\n ')}
120
- </div>
121
- </div>
122
- `);
123
- }
124
-
125
- // Combinations section
126
- const combos = generateCombinations(api);
127
- if (combos.length > 0) {
128
- const comboButtons = combos.map((combo) => {
129
- const classes = combo.modifiers.map((m) => `${baseClass}--${m}`).join(' ');
130
- const label = combo.modifiers.map((m) => capitalize(m)).join(' ');
131
- const disabled = combo.disabled ? ' disabled' : '';
132
- return `<${element} class="${baseClass} ${classes}"${disabled}>${label}</${element}>`;
133
- });
134
-
135
- sections.push(`
136
- <div class="test-section">
137
- <div class="test-section-title">Combinations</div>
138
- <div class="test-grid">
139
- ${comboButtons.join('\n ')}
140
- </div>
141
- </div>
142
- `);
143
- }
144
-
145
- return `
146
- <div class="test-container">
147
- <h1 class="test-title">${title}</h1>
148
- ${sections.join('')}
149
- </div>
150
- `;
151
- }
@@ -1,15 +0,0 @@
1
- export type { ComponentAPI } from './api-types';
2
- export type { RhythmViolation } from './rhythm';
3
- export { scaffoldCss } from './scaffold';
4
- export { generateVariationsHtml } from './html-generator';
5
- export { validateGridRhythm } from './rhythm';
6
- export {
7
- loadCss,
8
- loadComponentApi,
9
- loadDocsJson,
10
- generateHtmlFromDocs,
11
- setupVisualTest,
12
- setupVisualTestFromApi,
13
- setupVisualTestFromDocs,
14
- saveForLostPixel,
15
- } from './page-setup';
@@ -1,149 +0,0 @@
1
- import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
- import { resolve } from 'node:path';
3
- import type { Page } from '@playwright/test';
4
-
5
- const LOSTPIXEL_DIR = resolve(__dirname, '../../.lostpixel');
6
- import type { ComponentAPI } from './api-types';
7
- import { generateVariationsHtml } from './html-generator';
8
- import { scaffoldCss } from './scaffold';
9
-
10
- interface DocsItem {
11
- tag?: string;
12
- class?: string;
13
- text?: string;
14
- attrs?: Record<string, string>;
15
- style?: Record<string, string>;
16
- children?: DocsItem[];
17
- }
18
-
19
- interface DocsExample {
20
- html?: string;
21
- items?: DocsItem[];
22
- layout?: string;
23
- title?: string;
24
- }
25
-
26
- interface DocsSection {
27
- title: string;
28
- examples: DocsExample[];
29
- }
30
-
31
- interface DocsJson {
32
- sections: DocsSection[];
33
- }
34
-
35
- const DIST_PATH = resolve(__dirname, '../../dist');
36
-
37
- export function loadCss(filename = 'index.css'): string {
38
- return readFileSync(resolve(DIST_PATH, filename), 'utf-8');
39
- }
40
-
41
- export function loadComponentApi(apiPath: string): ComponentAPI {
42
- return JSON.parse(readFileSync(apiPath, 'utf-8'));
43
- }
44
-
45
- function renderItem(item: DocsItem): string {
46
- if (!item.tag) return item.text ?? '';
47
-
48
- const parts: string[] = [];
49
-
50
- if (item.class) parts.push(`class="${item.class}"`);
51
-
52
- if (item.style) {
53
- const css = Object.entries(item.style)
54
- .map(([k, v]) => `${k}: ${v}`)
55
- .join('; ');
56
- parts.push(`style="${css}"`);
57
- }
58
-
59
- if (item.attrs) {
60
- for (const [k, v] of Object.entries(item.attrs)) {
61
- parts.push(v === '' ? k : `${k}="${v}"`);
62
- }
63
- }
64
-
65
- const attrStr = parts.length ? ` ${parts.join(' ')}` : '';
66
- const content = item.children ? item.children.map(renderItem).join('\n') : (item.text ?? '');
67
-
68
- return `<${item.tag}${attrStr}>${content}</${item.tag}>`;
69
- }
70
-
71
- export function loadDocsJson(docsPath: string): DocsJson {
72
- return JSON.parse(readFileSync(docsPath, 'utf-8'));
73
- }
74
-
75
- export function generateHtmlFromDocs(docs: DocsJson): string {
76
- const sections: string[] = [];
77
-
78
- for (const section of docs.sections) {
79
- const examples: string[] = [];
80
-
81
- for (const example of section.examples) {
82
- let html = '';
83
-
84
- if (example.html) {
85
- html = example.html;
86
- } else if (example.items) {
87
- const items = example.items.map(renderItem).join('\n');
88
- html = example.layout === 'row' ? `<div class="ui-row">${items}</div>` : items;
89
- }
90
-
91
- if (html) {
92
- examples.push(`<div class="test-example">${html}</div>`);
93
- }
94
- }
95
-
96
- sections.push(`
97
- <div class="test-section">
98
- <div class="test-section-title">${section.title}</div>
99
- ${examples.join('\n')}
100
- </div>
101
- `);
102
- }
103
-
104
- return `<div class="test-container">${sections.join('')}</div>`;
105
- }
106
-
107
- export async function setupVisualTest(
108
- page: Page,
109
- options: {
110
- html: string;
111
- css?: string;
112
- includeTokens?: boolean;
113
- },
114
- ): Promise<void> {
115
- const { html, css, includeTokens = true } = options;
116
- const componentCss = includeTokens ? loadCss() : css || '';
117
-
118
- const fullHtml = `
119
- <!DOCTYPE html>
120
- <html>
121
- <head>
122
- <meta charset="utf-8">
123
- <style>${scaffoldCss}</style>
124
- <style>${componentCss}</style>
125
- </head>
126
- <body>${html}</body>
127
- </html>
128
- `;
129
-
130
- await page.setContent(fullHtml);
131
- }
132
-
133
- export async function setupVisualTestFromApi(page: Page, apiPath: string): Promise<void> {
134
- const api = loadComponentApi(apiPath);
135
- const html = generateVariationsHtml(api);
136
- await setupVisualTest(page, { html });
137
- }
138
-
139
- export async function setupVisualTestFromDocs(page: Page, docsPath: string): Promise<void> {
140
- const docs = loadDocsJson(docsPath);
141
- const html = generateHtmlFromDocs(docs);
142
- await setupVisualTest(page, { html });
143
- }
144
-
145
- export async function saveForLostPixel(page: Page, name: string): Promise<void> {
146
- mkdirSync(LOSTPIXEL_DIR, { recursive: true });
147
- const screenshot = await page.screenshot({ fullPage: true });
148
- writeFileSync(resolve(LOSTPIXEL_DIR, `${name}.png`), screenshot);
149
- }
@@ -1,146 +0,0 @@
1
- import type { Page } from '@playwright/test';
2
-
3
- // Elements that are fluid containers (viewport-dependent)
4
- const SKIP_SELECTORS = [
5
- 'html',
6
- 'body',
7
- 'main',
8
- 'aside',
9
- '.ui-sidebar',
10
- '.ui-main',
11
- '.ui-app-shell',
12
- '.ui-drawer', // Fluid panel - adapts to container/viewport
13
- ];
14
-
15
- // Inline elements that don't follow grid
16
- const INLINE_TAGS = [
17
- 'STRONG',
18
- 'B',
19
- 'EM',
20
- 'I',
21
- 'SMALL',
22
- 'SPAN',
23
- 'A',
24
- 'CODE',
25
- 'ABBR',
26
- 'CITE',
27
- 'Q',
28
- 'SUB',
29
- 'SUP',
30
- 'MARK',
31
- 'BR',
32
- 'WBR',
33
- ];
34
-
35
- export interface RhythmViolation {
36
- selector: string;
37
- height: number;
38
- expected: number;
39
- offBy: number;
40
- }
41
-
42
- /**
43
- * Validates that all elements in a component follow the 8px grid rhythm
44
- * Throws an error if violations are found
45
- */
46
- export async function validateGridRhythm(
47
- page: Page,
48
- componentName: string,
49
- ): Promise<RhythmViolation[]> {
50
- const violations = await page.evaluate(
51
- ({ skipSelectors, inlineTags, component }) => {
52
- // Get unit from CSS custom property (default 8px)
53
- // Note: PostCSS prefixes --unit to --ui-unit in compiled CSS
54
- const temp = document.createElement('div');
55
- temp.style.cssText = 'position:absolute;visibility:hidden;width:var(--ui-unit, 8px)';
56
- document.body.appendChild(temp);
57
- const unit = temp.getBoundingClientRect().width || 8;
58
- document.body.removeChild(temp);
59
-
60
- const results: Array<{ selector: string; height: number; expected: number; offBy: number }> =
61
- [];
62
-
63
- // Target component elements
64
- const selector = `.ui-${component}, .ui-${component} *`;
65
- const elements = document.querySelectorAll(selector);
66
-
67
- for (const el of elements) {
68
- const tagName = el.tagName;
69
-
70
- // Skip script, style, SVG internals, etc.
71
- const upperTag = tagName.toUpperCase();
72
- if (
73
- [
74
- 'SCRIPT',
75
- 'STYLE',
76
- 'LINK',
77
- 'META',
78
- 'TITLE',
79
- 'HEAD',
80
- 'SVG',
81
- 'PATH',
82
- 'CIRCLE',
83
- 'RECT',
84
- 'LINE',
85
- 'POLYGON',
86
- 'POLYLINE',
87
- 'ELLIPSE',
88
- 'G',
89
- 'DEFS',
90
- 'USE',
91
- 'SYMBOL',
92
- 'CLIPPATH',
93
- 'MASK',
94
- 'PATTERN',
95
- 'IMAGE',
96
- 'TEXT',
97
- 'TSPAN',
98
- 'TEXTPATH',
99
- 'FOREIGNOBJECT',
100
- ].includes(upperTag)
101
- )
102
- continue;
103
-
104
- // Skip inline elements
105
- if (inlineTags.includes(tagName)) continue;
106
-
107
- // Skip BEM element children (__element) - only check blocks and modifiers
108
- const classes = el.className?.toString?.() || '';
109
- if (classes.includes('__')) continue;
110
-
111
- // Skip fluid containers
112
- if (skipSelectors.some((sel) => el.matches(sel))) continue;
113
-
114
- const height = el.getBoundingClientRect().height;
115
- // Skip zero-height and decorative lines (borders, dividers < half unit)
116
- if (height === 0 || height < unit / 2) continue;
117
-
118
- const remainder = height % unit;
119
- const isAligned = remainder < 0.5 || remainder > unit - 0.5;
120
-
121
- if (!isAligned) {
122
- const firstClass = classes.split(' ')[0];
123
- results.push({
124
- selector: `${tagName.toLowerCase()}${firstClass ? `.${firstClass}` : ''}`,
125
- height: Math.round(height * 10) / 10,
126
- expected: Math.round(height / unit) * unit,
127
- offBy: Math.round(remainder * 10) / 10,
128
- });
129
- }
130
- }
131
-
132
- return results;
133
- },
134
- { skipSelectors: SKIP_SELECTORS, inlineTags: INLINE_TAGS, component: componentName },
135
- );
136
-
137
- if (violations.length > 0) {
138
- console.log(`Grid rhythm violations in ${componentName}:`);
139
- console.table(violations);
140
- throw new Error(
141
- `Grid rhythm violations in ${componentName}:\n${JSON.stringify(violations, null, 2)}`,
142
- );
143
- }
144
-
145
- return violations;
146
- }
@@ -1,50 +0,0 @@
1
- export const scaffoldCss = `
2
- html {
3
- font-size: 16px;
4
- }
5
- body {
6
- background-image:
7
- linear-gradient(45deg, #f0f0f0 25%, transparent 25%),
8
- linear-gradient(-45deg, #f0f0f0 25%, transparent 25%),
9
- linear-gradient(45deg, transparent 75%, #f0f0f0 75%),
10
- linear-gradient(-45deg, transparent 75%, #f0f0f0 75%);
11
- background-size: 12px 12px;
12
- background-position: 0 0, 0 6px, 6px -6px, -6px 0px;
13
- background-color: #fafafa;
14
- }
15
- .test-container {
16
- padding: 1.5rem;
17
- }
18
- .test-title {
19
- font-family: var(--ui-font-sans, system-ui, sans-serif);
20
- font-size: 1.5rem;
21
- font-weight: 600;
22
- margin-block-end: 1.5rem;
23
- }
24
- .test-section {
25
- margin-block-end: 1.5rem;
26
- }
27
- .test-section-title {
28
- font-family: var(--ui-font-sans, system-ui, sans-serif);
29
- font-size: 0.75rem;
30
- color: #666;
31
- text-transform: uppercase;
32
- letter-spacing: 0.05em;
33
- margin-block-end: 0.5rem;
34
- }
35
- .test-row {
36
- display: flex;
37
- gap: 1rem;
38
- align-items: center;
39
- flex-wrap: wrap;
40
- }
41
- .test-grid {
42
- display: grid;
43
- grid-template-columns: repeat(auto-fill, minmax(100px, max-content));
44
- gap: 1rem;
45
- align-items: start;
46
- }
47
- .test-element--block {
48
- width: 200px;
49
- }
50
- `;