@tcn/ui 0.16.0 → 0.18.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 (437) hide show
  1. package/dist/actions/index.d.ts +0 -1
  2. package/dist/actions/index.d.ts.map +1 -1
  3. package/dist/actions/index.js +6 -8
  4. package/dist/actions/index.js.map +1 -1
  5. package/dist/card.css +1 -0
  6. package/dist/column.css +1 -1
  7. package/dist/containers.css +1 -1
  8. package/dist/containers.module-BmICKsOK.js +5 -0
  9. package/dist/containers.module-BmICKsOK.js.map +1 -0
  10. package/dist/draggable.css +1 -1
  11. package/dist/draggable.module-DFYR5n3n.js +5 -0
  12. package/dist/draggable.module-DFYR5n3n.js.map +1 -0
  13. package/dist/field_set.css +1 -1
  14. package/dist/field_set.module-BpJTFCi4.js +5 -0
  15. package/dist/field_set.module-BpJTFCi4.js.map +1 -0
  16. package/dist/form/field/field.js +17 -13
  17. package/dist/form/field/field.js.map +1 -1
  18. package/dist/form/field_set/field_set.d.ts +6 -10
  19. package/dist/form/field_set/field_set.d.ts.map +1 -1
  20. package/dist/form/field_set/field_set.js +33 -61
  21. package/dist/form/field_set/field_set.js.map +1 -1
  22. package/dist/form/field_set/legend.d.ts +20 -0
  23. package/dist/form/field_set/legend.d.ts.map +1 -0
  24. package/dist/form/field_set/legend.js +28 -0
  25. package/dist/form/field_set/legend.js.map +1 -0
  26. package/dist/form/index.d.ts +2 -1
  27. package/dist/form/index.d.ts.map +1 -1
  28. package/dist/form/index.js +24 -22
  29. package/dist/form/index.js.map +1 -1
  30. package/dist/inputs/color_input/color_input.js +2 -3
  31. package/dist/inputs/color_input/color_input.js.map +1 -1
  32. package/dist/inputs/color_input/color_picker.js +11 -7
  33. package/dist/inputs/color_input/color_picker.js.map +1 -1
  34. package/dist/inputs/combo_box/combo_box.js +24 -20
  35. package/dist/inputs/combo_box/combo_box.js.map +1 -1
  36. package/dist/inputs/date_picker/date_picker.js +19 -15
  37. package/dist/inputs/date_picker/date_picker.js.map +1 -1
  38. package/dist/inputs/date_picker/date_picker_header.d.ts.map +1 -1
  39. package/dist/inputs/date_picker/date_picker_header.js +15 -14
  40. package/dist/inputs/date_picker/date_picker_header.js.map +1 -1
  41. package/dist/inputs/date_picker/date_picker_input.js +26 -23
  42. package/dist/inputs/date_picker/date_picker_input.js.map +1 -1
  43. package/dist/inputs/date_picker/date_picker_time_selector.js +2 -3
  44. package/dist/inputs/date_picker/date_picker_time_selector.js.map +1 -1
  45. package/dist/inputs/date_picker/date_picker_year_input.js +2 -3
  46. package/dist/inputs/date_picker/date_picker_year_input.js.map +1 -1
  47. package/dist/inputs/date_picker/date_picker_year_selector.js +24 -21
  48. package/dist/inputs/date_picker/date_picker_year_selector.js.map +1 -1
  49. package/dist/inputs/mask_input/key_capture_input.js +35 -31
  50. package/dist/inputs/mask_input/key_capture_input.js.map +1 -1
  51. package/dist/inputs/mask_input/mask_input.js +18 -14
  52. package/dist/inputs/mask_input/mask_input.js.map +1 -1
  53. package/dist/inputs/multiselect/multiselect.js +28 -24
  54. package/dist/inputs/multiselect/multiselect.js.map +1 -1
  55. package/dist/inputs/multiselect/multiselect_inline_values.d.ts.map +1 -1
  56. package/dist/inputs/multiselect/multiselect_inline_values.js +15 -15
  57. package/dist/inputs/multiselect/multiselect_inline_values.js.map +1 -1
  58. package/dist/inputs/multiselect/multiselect_values.js +16 -17
  59. package/dist/inputs/multiselect/multiselect_values.js.map +1 -1
  60. package/dist/inputs/phone_number_input/phone_number_context.js +13 -9
  61. package/dist/inputs/phone_number_input/phone_number_context.js.map +1 -1
  62. package/dist/inputs/phone_number_input/phone_number_input_adapter.js +2 -3
  63. package/dist/inputs/phone_number_input/phone_number_input_adapter.js.map +1 -1
  64. package/dist/inputs/phone_number_input/sip_input.js +8 -9
  65. package/dist/inputs/phone_number_input/sip_input.js.map +1 -1
  66. package/dist/inputs/select/select.js +11 -8
  67. package/dist/inputs/select/select.js.map +1 -1
  68. package/dist/inputs/slider/slider.js +28 -24
  69. package/dist/inputs/slider/slider.js.map +1 -1
  70. package/dist/inputs/suggestions/suggestion_list.js +11 -8
  71. package/dist/inputs/suggestions/suggestion_list.js.map +1 -1
  72. package/dist/inputs/switch/switch.js +29 -25
  73. package/dist/inputs/switch/switch.js.map +1 -1
  74. package/dist/inputs/unit_input/unit_input.js +21 -17
  75. package/dist/inputs/unit_input/unit_input.js.map +1 -1
  76. package/dist/layouts/containers/columns/columns.d.ts +6 -1
  77. package/dist/layouts/containers/columns/columns.d.ts.map +1 -1
  78. package/dist/layouts/containers/columns/columns.js +30 -7
  79. package/dist/layouts/containers/columns/columns.js.map +1 -1
  80. package/dist/layouts/containers/rail.d.ts +2 -5
  81. package/dist/layouts/containers/rail.d.ts.map +1 -1
  82. package/dist/layouts/containers/rail.js +17 -55
  83. package/dist/layouts/containers/rail.js.map +1 -1
  84. package/dist/layouts/containers/rows/index.d.ts +3 -0
  85. package/dist/layouts/containers/rows/index.d.ts.map +1 -0
  86. package/dist/layouts/containers/rows/index.js +7 -0
  87. package/dist/layouts/containers/rows/index.js.map +1 -0
  88. package/dist/layouts/containers/rows/row.d.ts +6 -0
  89. package/dist/layouts/containers/rows/row.d.ts.map +1 -0
  90. package/dist/layouts/containers/rows/row.js +20 -0
  91. package/dist/layouts/containers/rows/row.js.map +1 -0
  92. package/dist/layouts/containers/rows/rows.d.ts +11 -0
  93. package/dist/layouts/containers/rows/rows.d.ts.map +1 -0
  94. package/dist/layouts/containers/rows/rows.js +34 -0
  95. package/dist/layouts/containers/rows/rows.js.map +1 -0
  96. package/dist/layouts/containers/scaffold.d.ts +2 -5
  97. package/dist/layouts/containers/scaffold.d.ts.map +1 -1
  98. package/dist/layouts/containers/scaffold.js +17 -55
  99. package/dist/layouts/containers/scaffold.js.map +1 -1
  100. package/dist/layouts/index.d.ts +2 -0
  101. package/dist/layouts/index.d.ts.map +1 -1
  102. package/dist/layouts/index.js +26 -22
  103. package/dist/layouts/index.js.map +1 -1
  104. package/dist/mobile/inputs/date_picker/mobile_date_picker_header.js +11 -7
  105. package/dist/mobile/inputs/date_picker/mobile_date_picker_header.js.map +1 -1
  106. package/dist/mobile/inputs/date_picker/mobile_date_picker_input.js +11 -7
  107. package/dist/mobile/inputs/date_picker/mobile_date_picker_input.js.map +1 -1
  108. package/dist/mobile/inputs/date_picker/mobile_date_picker_year_selector.js +14 -10
  109. package/dist/mobile/inputs/date_picker/mobile_date_picker_year_selector.js.map +1 -1
  110. package/dist/multiselect_values.css +1 -1
  111. package/dist/navigation/tabs/state/link/tab_link.js +15 -11
  112. package/dist/navigation/tabs/state/link/tab_link.js.map +1 -1
  113. package/dist/overlay/frame/frame.d.ts.map +1 -1
  114. package/dist/overlay/frame/frame.js +117 -76
  115. package/dist/overlay/frame/frame.js.map +1 -1
  116. package/dist/overlay/menu/menu.js +21 -17
  117. package/dist/overlay/menu/menu.js.map +1 -1
  118. package/dist/overlay/popper/base/dismissal_decorator.js +3 -3
  119. package/dist/overlay/popper/base/dismissal_decorator.js.map +1 -1
  120. package/dist/overlay/popper/context_popper.js +14 -10
  121. package/dist/overlay/popper/context_popper.js.map +1 -1
  122. package/dist/overlay/popper/element_popper.js +15 -11
  123. package/dist/overlay/popper/element_popper.js.map +1 -1
  124. package/dist/overlay/popper/legacy/popper.js +32 -28
  125. package/dist/overlay/popper/legacy/popper.js.map +1 -1
  126. package/dist/overlay/popper/preview_popper.js +16 -12
  127. package/dist/overlay/popper/preview_popper.js.map +1 -1
  128. package/dist/overlay/tethered/tethered.js +17 -13
  129. package/dist/overlay/tethered/tethered.js.map +1 -1
  130. package/dist/resizable.css +1 -0
  131. package/dist/resizable.module-ur5FBfxo.js +5 -0
  132. package/dist/resizable.module-ur5FBfxo.js.map +1 -0
  133. package/dist/resize_handle.css +1 -0
  134. package/dist/row.css +1 -0
  135. package/dist/stacks/box/box.d.ts +14 -0
  136. package/dist/stacks/box/box.d.ts.map +1 -1
  137. package/dist/stacks/box/box.js +104 -102
  138. package/dist/stacks/box/box.js.map +1 -1
  139. package/dist/stacks/box/detect_resize_bounds.d.ts +1 -0
  140. package/dist/stacks/box/detect_resize_bounds.d.ts.map +1 -1
  141. package/dist/stacks/box/detect_resize_bounds.js +22 -20
  142. package/dist/stacks/box/detect_resize_bounds.js.map +1 -1
  143. package/dist/stacks/box/end_resize_handle.js +5 -5
  144. package/dist/stacks/box/end_resize_handle.js.map +1 -1
  145. package/dist/stacks/box/resize_handlers.d.ts.map +1 -1
  146. package/dist/stacks/box/resize_handlers.js +12 -12
  147. package/dist/stacks/box/resize_handlers.js.map +1 -1
  148. package/dist/stacks/box/start_resize_handle.js +7 -7
  149. package/dist/stacks/box/start_resize_handle.js.map +1 -1
  150. package/dist/stacks/box/types.d.ts +3 -2
  151. package/dist/stacks/box/types.d.ts.map +1 -1
  152. package/dist/stacks/h_collapsible_box.js +24 -20
  153. package/dist/stacks/h_collapsible_box.js.map +1 -1
  154. package/dist/stacks/v_collapsible_box.js +26 -22
  155. package/dist/stacks/v_collapsible_box.js.map +1 -1
  156. package/dist/surfaces/alert/alert.js +7 -8
  157. package/dist/surfaces/alert/alert.js.map +1 -1
  158. package/dist/surfaces/card/card.d.ts.map +1 -1
  159. package/dist/surfaces/card/card.js +14 -6
  160. package/dist/surfaces/card/card.js.map +1 -1
  161. package/dist/surfaces/pop_confirm/pop_confirm.js +4 -2
  162. package/dist/surfaces/pop_confirm/pop_confirm.js.map +1 -1
  163. package/dist/test-setup.d.ts +2 -0
  164. package/dist/test-setup.d.ts.map +1 -0
  165. package/dist/test-setup.js +10 -0
  166. package/dist/test-setup.js.map +1 -0
  167. package/dist/themes/stories/button_showcase.d.ts.map +1 -1
  168. package/dist/themes/stories/controls_fieldset.d.ts.map +1 -1
  169. package/dist/themes/stories/menu_showcase.d.ts.map +1 -1
  170. package/dist/themes/theme.d.ts.map +1 -1
  171. package/dist/themes/theme.js +17 -22
  172. package/dist/themes/theme.js.map +1 -1
  173. package/dist/themes/themes/ergo/ergo_theme.css +1 -1
  174. package/dist/themes/themes/ergo/ergo_theme.d.ts.map +1 -1
  175. package/dist/themes/themes/ergo/ergo_theme.js +653 -431
  176. package/dist/themes/themes/ergo/ergo_theme.js.map +1 -1
  177. package/dist/themes/themes/ergo/parts/actions.css +1 -0
  178. package/dist/themes/themes/ergo/parts/base.css +1 -0
  179. package/dist/themes/themes/ergo/parts/form.css +1 -0
  180. package/dist/themes/themes/ergo/parts/inputs.css +1 -0
  181. package/dist/themes/themes/ergo/parts/navigation.css +1 -0
  182. package/dist/themes/themes/windows_98/windows_98.css +1 -1
  183. package/dist/themes/themes/windows_98/windows_98_theme.js +32 -43
  184. package/dist/themes/themes/windows_98/windows_98_theme.js.map +1 -1
  185. package/dist/utils/decorators/clone_with_decorator.d.ts +21 -0
  186. package/dist/utils/decorators/clone_with_decorator.d.ts.map +1 -0
  187. package/dist/utils/decorators/clone_with_decorator.js +16 -0
  188. package/dist/utils/decorators/clone_with_decorator.js.map +1 -0
  189. package/dist/utils/decorators/draggable/context.d.ts.map +1 -0
  190. package/dist/utils/decorators/draggable/context.js.map +1 -0
  191. package/dist/utils/{dnd/handle.d.ts → decorators/draggable/drag_handle.d.ts} +1 -1
  192. package/dist/utils/decorators/draggable/drag_handle.d.ts.map +1 -0
  193. package/dist/utils/{dnd/handle.js → decorators/draggable/drag_handle.js} +2 -2
  194. package/dist/utils/decorators/draggable/drag_handle.js.map +1 -0
  195. package/dist/utils/decorators/draggable/draggable.d.ts.map +1 -0
  196. package/dist/utils/{dnd → decorators}/draggable/draggable.js +3 -3
  197. package/dist/utils/decorators/draggable/draggable.js.map +1 -0
  198. package/dist/utils/decorators/draggable/index.d.ts +11 -0
  199. package/dist/utils/decorators/draggable/index.d.ts.map +1 -0
  200. package/dist/utils/decorators/draggable/index.js +14 -0
  201. package/dist/utils/decorators/draggable/index.js.map +1 -0
  202. package/dist/utils/{dnd → decorators/draggable}/types.d.ts +1 -1
  203. package/dist/utils/decorators/draggable/types.d.ts.map +1 -0
  204. package/dist/utils/{dnd/hooks → decorators/draggable}/use_drag_container.d.ts +2 -2
  205. package/dist/utils/decorators/draggable/use_drag_container.d.ts.map +1 -0
  206. package/dist/utils/decorators/draggable/use_drag_container.js.map +1 -0
  207. package/dist/utils/decorators/draggable/use_draggable.d.ts.map +1 -0
  208. package/dist/utils/decorators/draggable/use_draggable.js.map +1 -0
  209. package/dist/utils/decorators/index.d.ts +3 -0
  210. package/dist/utils/decorators/index.d.ts.map +1 -0
  211. package/dist/utils/decorators/index.js +27 -0
  212. package/dist/utils/decorators/index.js.map +1 -0
  213. package/dist/utils/decorators/resizable/context.d.ts +4 -0
  214. package/dist/utils/decorators/resizable/context.d.ts.map +1 -0
  215. package/dist/utils/decorators/resizable/context.js +10 -0
  216. package/dist/utils/decorators/resizable/context.js.map +1 -0
  217. package/dist/utils/decorators/resizable/handle_config.d.ts +32 -0
  218. package/dist/utils/decorators/resizable/handle_config.d.ts.map +1 -0
  219. package/dist/utils/decorators/resizable/handle_config.js +62 -0
  220. package/dist/utils/decorators/resizable/handle_config.js.map +1 -0
  221. package/dist/utils/decorators/resizable/index.d.ts +10 -0
  222. package/dist/utils/decorators/resizable/index.d.ts.map +1 -0
  223. package/dist/utils/decorators/resizable/index.js +16 -0
  224. package/dist/utils/decorators/resizable/index.js.map +1 -0
  225. package/dist/utils/decorators/resizable/resizable.d.ts +11 -0
  226. package/dist/utils/decorators/resizable/resizable.d.ts.map +1 -0
  227. package/dist/utils/decorators/resizable/resizable.js +52 -0
  228. package/dist/utils/decorators/resizable/resizable.js.map +1 -0
  229. package/dist/utils/decorators/resizable/resize_handle.d.ts +7 -0
  230. package/dist/utils/decorators/resizable/resize_handle.d.ts.map +1 -0
  231. package/dist/utils/decorators/resizable/resize_handle.js +100 -0
  232. package/dist/utils/decorators/resizable/resize_handle.js.map +1 -0
  233. package/dist/utils/decorators/resizable/resize_strategy.d.ts +47 -0
  234. package/dist/utils/decorators/resizable/resize_strategy.d.ts.map +1 -0
  235. package/dist/utils/decorators/resizable/resize_strategy.js +108 -0
  236. package/dist/utils/decorators/resizable/resize_strategy.js.map +1 -0
  237. package/dist/utils/decorators/resizable/types.d.ts +28 -0
  238. package/dist/utils/decorators/resizable/types.d.ts.map +1 -0
  239. package/dist/utils/decorators/resizable/types.js +2 -0
  240. package/dist/utils/decorators/resizable/types.js.map +1 -0
  241. package/dist/utils/hooks/labelled_by_context.d.ts +21 -0
  242. package/dist/utils/hooks/labelled_by_context.d.ts.map +1 -0
  243. package/dist/utils/hooks/labelled_by_context.js +12 -0
  244. package/dist/utils/hooks/labelled_by_context.js.map +1 -0
  245. package/dist/utils/index.d.ts +8 -7
  246. package/dist/utils/index.d.ts.map +1 -1
  247. package/dist/utils/index.js +45 -28
  248. package/dist/utils/index.js.map +1 -1
  249. package/dist/utils/listeners/click_away_listener.d.ts.map +1 -0
  250. package/dist/utils/{click_away_listener.js → listeners/click_away_listener.js} +1 -1
  251. package/dist/utils/listeners/click_away_listener.js.map +1 -0
  252. package/dist/utils/listeners/focus_redirect.d.ts.map +1 -0
  253. package/dist/utils/listeners/focus_redirect.js.map +1 -0
  254. package/dist/utils/listeners/index.d.ts +4 -0
  255. package/dist/utils/listeners/index.d.ts.map +1 -0
  256. package/dist/utils/listeners/index.js +10 -0
  257. package/dist/utils/listeners/index.js.map +1 -0
  258. package/dist/utils/listeners/mouse_leave_region.d.ts.map +1 -0
  259. package/dist/utils/listeners/mouse_leave_region.js.map +1 -0
  260. package/dist/utils/listeners/scroll_away_listener.d.ts.map +1 -0
  261. package/dist/utils/{scroll_away_listener.js → listeners/scroll_away_listener.js} +1 -1
  262. package/dist/utils/listeners/scroll_away_listener.js.map +1 -0
  263. package/dist/utils/system/index.d.ts +2 -0
  264. package/dist/utils/system/index.d.ts.map +1 -0
  265. package/dist/utils/system/index.js +2 -0
  266. package/dist/utils/system/index.js.map +1 -0
  267. package/dist/utils/system/variations.d.ts.map +1 -0
  268. package/dist/utils/system/variations.js +2 -0
  269. package/dist/utils/system/variations.js.map +1 -0
  270. package/dist/utils/types/sides.d.ts +3 -0
  271. package/dist/utils/types/sides.d.ts.map +1 -0
  272. package/package.json +3 -9
  273. package/src/actions/button/__stories__/button_group.stories.tsx +23 -24
  274. package/src/actions/index.ts +0 -1
  275. package/src/form/field/field.stories.tsx +2 -2
  276. package/src/form/field/h_field/h_field.stories.tsx +1 -1
  277. package/src/form/field/v_field/v_field.stories.tsx +1 -1
  278. package/src/form/field_set/field_set.module.css +0 -14
  279. package/src/form/field_set/field_set.stories.tsx +101 -1
  280. package/src/form/field_set/field_set.tsx +43 -57
  281. package/src/form/field_set/legend.tsx +44 -0
  282. package/src/form/index.ts +6 -1
  283. package/src/inputs/date_picker/date_picker_header.tsx +7 -5
  284. package/src/inputs/date_picker/date_picker_year_selector.tsx +5 -5
  285. package/src/inputs/multiselect/multiselect_inline_values.tsx +4 -3
  286. package/src/inputs/multiselect/multiselect_values.module.css +1 -0
  287. package/src/inputs/multiselect/multiselect_values.tsx +4 -4
  288. package/src/layouts/__stories__/columns.stories.tsx +31 -0
  289. package/src/layouts/__stories__/composed.stories.tsx +77 -8
  290. package/src/layouts/__stories__/rows.stories.tsx +77 -0
  291. package/src/layouts/__stories__/utils.tsx +2 -84
  292. package/src/layouts/containers/columns/column.module.css +3 -2
  293. package/src/layouts/containers/columns/columns.tsx +29 -3
  294. package/src/layouts/containers/containers.module.css +27 -29
  295. package/src/layouts/containers/rail.tsx +9 -51
  296. package/src/layouts/containers/rows/index.ts +2 -0
  297. package/src/layouts/containers/rows/row.module.css +15 -0
  298. package/src/layouts/containers/rows/row.tsx +22 -0
  299. package/src/layouts/containers/rows/rows.tsx +42 -0
  300. package/src/layouts/containers/scaffold.tsx +9 -49
  301. package/src/layouts/index.ts +2 -0
  302. package/src/overlay/frame/frame.stories.tsx +2 -1
  303. package/src/overlay/frame/frame.tsx +68 -20
  304. package/src/overlay/popper/base/dismissal_decorator.tsx +3 -3
  305. package/src/overlay/slide/slide.stories.tsx +1 -1
  306. package/src/stacks/box/box.tsx +29 -4
  307. package/src/stacks/box/detect_resize_bounds.ts +5 -1
  308. package/src/stacks/box/end_resize_handle.tsx +1 -1
  309. package/src/stacks/box/resize_handlers.ts +1 -1
  310. package/src/stacks/box/start_resize_handle.tsx +1 -1
  311. package/src/stacks/box/types.ts +3 -2
  312. package/src/stacks/collapsible_box.stories.tsx +5 -5
  313. package/src/stacks/demo.stories.tsx +7 -7
  314. package/src/surfaces/card/card.module.css +5 -0
  315. package/src/surfaces/card/card.stories.tsx +66 -8
  316. package/src/surfaces/card/card.tsx +6 -2
  317. package/src/surfaces/page/page.stories.tsx +84 -4
  318. package/src/surfaces/panel/__stories__/panel.stories.tsx +84 -9
  319. package/src/surfaces/window/window.stories.tsx +1 -1
  320. package/src/test-setup.ts +11 -0
  321. package/src/themes/stories/button_showcase.tsx +3 -1
  322. package/src/themes/stories/controls_fieldset.tsx +3 -1
  323. package/src/themes/stories/menu_showcase.tsx +3 -1
  324. package/src/themes/theme.tsx +6 -16
  325. package/src/themes/themes/ergo/INTERACTIVE.md +89 -0
  326. package/src/themes/themes/ergo/ROADMAP.md +116 -0
  327. package/src/themes/themes/ergo/ergo_theme.css +219 -734
  328. package/src/themes/themes/ergo/ergo_theme.ts +15 -1
  329. package/src/themes/themes/ergo/parts/actions.css +287 -0
  330. package/src/themes/themes/ergo/parts/base.css +62 -0
  331. package/src/themes/themes/ergo/parts/form.css +23 -0
  332. package/src/themes/themes/ergo/parts/inputs.css +252 -0
  333. package/src/themes/themes/ergo/parts/navigation.css +104 -0
  334. package/src/themes/themes/windows_98/windows_98.css +32 -43
  335. package/src/tokens/chip/chip.stories.tsx +5 -5
  336. package/src/utils/decorators/DECORATOR_PATTERN.md +86 -0
  337. package/src/utils/decorators/clone_with_decorator.ts +47 -0
  338. package/src/utils/{dnd → decorators/draggable}/__stories__/draggable.stories.tsx +7 -7
  339. package/src/utils/{dnd → decorators/draggable}/__stories__/use_draggable.stories.tsx +2 -2
  340. package/src/utils/{dnd/handle.tsx → decorators/draggable/drag_handle.tsx} +1 -1
  341. package/src/utils/{dnd → decorators}/draggable/draggable.tsx +2 -2
  342. package/src/utils/decorators/draggable/index.ts +15 -0
  343. package/src/utils/{dnd → decorators/draggable}/types.ts +1 -1
  344. package/src/utils/{dnd/hooks → decorators/draggable}/use_drag_container.ts +2 -2
  345. package/src/utils/decorators/index.ts +2 -0
  346. package/src/utils/decorators/resizable/__stories__/resizable.stories.tsx +214 -0
  347. package/src/utils/decorators/resizable/__stories__/resizable_stories.module.css +47 -0
  348. package/src/utils/decorators/resizable/__tests__/handle_config.test.ts +191 -0
  349. package/src/utils/decorators/resizable/__tests__/resize_strategy.test.ts +163 -0
  350. package/src/utils/decorators/resizable/context.ts +9 -0
  351. package/src/utils/decorators/resizable/handle_config.ts +118 -0
  352. package/src/utils/decorators/resizable/index.ts +37 -0
  353. package/src/utils/decorators/resizable/resizable.module.css +5 -0
  354. package/src/utils/decorators/resizable/resizable.tsx +97 -0
  355. package/src/utils/decorators/resizable/resize_handle.module.css +106 -0
  356. package/src/utils/decorators/resizable/resize_handle.tsx +165 -0
  357. package/src/utils/decorators/resizable/resize_strategy.ts +190 -0
  358. package/src/utils/decorators/resizable/types.ts +58 -0
  359. package/src/utils/hooks/labelled_by_context.ts +27 -0
  360. package/src/utils/index.ts +9 -7
  361. package/src/utils/{click_away_listener.tsx → listeners/click_away_listener.tsx} +1 -1
  362. package/src/utils/listeners/index.ts +3 -0
  363. package/src/utils/{scroll_away_listener.tsx → listeners/scroll_away_listener.tsx} +1 -1
  364. package/src/utils/system/index.ts +1 -0
  365. package/src/utils/types/sides.ts +2 -0
  366. package/dist/actions/button/slim_button/slim_button.d.ts +0 -9
  367. package/dist/actions/button/slim_button/slim_button.d.ts.map +0 -1
  368. package/dist/actions/button/slim_button/slim_button.js +0 -18
  369. package/dist/actions/button/slim_button/slim_button.js.map +0 -1
  370. package/dist/containers.module-DlGySre0.js +0 -5
  371. package/dist/containers.module-DlGySre0.js.map +0 -1
  372. package/dist/draggable.module-BgelQsuJ.js +0 -5
  373. package/dist/draggable.module-BgelQsuJ.js.map +0 -1
  374. package/dist/frame.css +0 -1
  375. package/dist/left_resize_handle.css +0 -1
  376. package/dist/right_resize_handle.css +0 -1
  377. package/dist/slim_button.css +0 -1
  378. package/dist/stacks/box/left_resize_handle.d.ts +0 -4
  379. package/dist/stacks/box/left_resize_handle.d.ts.map +0 -1
  380. package/dist/stacks/box/left_resize_handle.js +0 -36
  381. package/dist/stacks/box/left_resize_handle.js.map +0 -1
  382. package/dist/stacks/box/right_resize_handle.d.ts +0 -4
  383. package/dist/stacks/box/right_resize_handle.d.ts.map +0 -1
  384. package/dist/stacks/box/right_resize_handle.js +0 -36
  385. package/dist/stacks/box/right_resize_handle.js.map +0 -1
  386. package/dist/utils/click_away_listener.d.ts.map +0 -1
  387. package/dist/utils/click_away_listener.js.map +0 -1
  388. package/dist/utils/dnd/context.d.ts.map +0 -1
  389. package/dist/utils/dnd/context.js.map +0 -1
  390. package/dist/utils/dnd/draggable/draggable.d.ts.map +0 -1
  391. package/dist/utils/dnd/draggable/draggable.js.map +0 -1
  392. package/dist/utils/dnd/handle.d.ts.map +0 -1
  393. package/dist/utils/dnd/handle.js.map +0 -1
  394. package/dist/utils/dnd/hooks/use_drag_container.d.ts.map +0 -1
  395. package/dist/utils/dnd/hooks/use_drag_container.js.map +0 -1
  396. package/dist/utils/dnd/hooks/use_draggable.d.ts.map +0 -1
  397. package/dist/utils/dnd/hooks/use_draggable.js.map +0 -1
  398. package/dist/utils/dnd/types.d.ts.map +0 -1
  399. package/dist/utils/focus_redirect.d.ts.map +0 -1
  400. package/dist/utils/focus_redirect.js.map +0 -1
  401. package/dist/utils/mouse_leave_region.d.ts.map +0 -1
  402. package/dist/utils/mouse_leave_region.js.map +0 -1
  403. package/dist/utils/scroll_away_listener.d.ts.map +0 -1
  404. package/dist/utils/scroll_away_listener.js.map +0 -1
  405. package/dist/utils/types/variations.d.ts.map +0 -1
  406. package/src/actions/button/__stories__/slim_button.stories.tsx +0 -274
  407. package/src/actions/button/slim_button/slim_button.module.css +0 -9
  408. package/src/actions/button/slim_button/slim_button.tsx +0 -26
  409. package/src/overlay/frame/frame.module.css +0 -5
  410. package/src/stacks/box/left_resize_handle.module.css +0 -12
  411. package/src/stacks/box/left_resize_handle.tsx +0 -39
  412. package/src/stacks/box/right_resize_handle.module.css +0 -12
  413. package/src/stacks/box/right_resize_handle.tsx +0 -38
  414. /package/dist/utils/{dnd → decorators/draggable}/context.d.ts +0 -0
  415. /package/dist/utils/{dnd → decorators/draggable}/context.js +0 -0
  416. /package/dist/utils/{dnd → decorators}/draggable/draggable.d.ts +0 -0
  417. /package/dist/utils/{dnd → decorators/draggable}/types.js +0 -0
  418. /package/dist/utils/{dnd → decorators/draggable}/types.js.map +0 -0
  419. /package/dist/utils/{dnd/hooks → decorators/draggable}/use_drag_container.js +0 -0
  420. /package/dist/utils/{dnd/hooks → decorators/draggable}/use_draggable.d.ts +0 -0
  421. /package/dist/utils/{dnd/hooks → decorators/draggable}/use_draggable.js +0 -0
  422. /package/dist/utils/{click_away_listener.d.ts → listeners/click_away_listener.d.ts} +0 -0
  423. /package/dist/utils/{focus_redirect.d.ts → listeners/focus_redirect.d.ts} +0 -0
  424. /package/dist/utils/{focus_redirect.js → listeners/focus_redirect.js} +0 -0
  425. /package/dist/utils/{mouse_leave_region.d.ts → listeners/mouse_leave_region.d.ts} +0 -0
  426. /package/dist/utils/{mouse_leave_region.js → listeners/mouse_leave_region.js} +0 -0
  427. /package/dist/utils/{scroll_away_listener.d.ts → listeners/scroll_away_listener.d.ts} +0 -0
  428. /package/dist/utils/{types → system}/variations.d.ts +0 -0
  429. /package/src/utils/{dnd → decorators/draggable}/__stories__/draggable_stories.module.css +0 -0
  430. /package/src/utils/{dnd → decorators/draggable}/context.ts +0 -0
  431. /package/src/utils/{dnd → decorators}/draggable/draggable.module.css +0 -0
  432. /package/src/utils/{dnd/hooks → decorators/draggable}/use_draggable.ts +0 -0
  433. /package/src/utils/{click_away_listener.stories.tsx → listeners/click_away_listener.stories.tsx} +0 -0
  434. /package/src/utils/{focus_redirect.tsx → listeners/focus_redirect.tsx} +0 -0
  435. /package/src/utils/{mouse_leave_region.tsx → listeners/mouse_leave_region.tsx} +0 -0
  436. /package/src/utils/{scroll_away_listener.stories.tsx → listeners/scroll_away_listener.stories.tsx} +0 -0
  437. /package/src/utils/{types → system}/variations.ts +0 -0
@@ -6,7 +6,10 @@ import { Box, Spacer } from '../../stacks/index.js';
6
6
  import { Title } from '../../typography/title/title.js';
7
7
  import { Button } from '../../actions/index.js';
8
8
  import { Card } from './card.js';
9
- import { Scaffold } from '../../layouts/index.js';
9
+ import { Detail, Row, Rows, Scaffold } from '../../layouts/index.js';
10
+ import { Key } from '../../tokens/key/key.js';
11
+ import { Term } from '../../tokens/term/term.js';
12
+ import { Value } from '../../tokens/value/value.js';
10
13
 
11
14
  // Styles
12
15
  import styles from './card_stories.module.css';
@@ -52,13 +55,68 @@ export const Default = () => {
52
55
  <Box className={styles['content-box']} />
53
56
  <Box className={styles['content-box']} />
54
57
  </Scaffold>
55
- {/* Cards typically do not have a footer */}
56
- {/* <Footer>
57
- <Title>Footer</Title>
58
- <Spacer />
59
- <Button hierarchy="secondary">Secondary</Button>
60
- <Button hierarchy="primary">Primary</Button>
61
- </Footer> */}
58
+ </Card>
59
+ </div>
60
+ );
61
+ };
62
+
63
+ /**
64
+ * Rows inside a Card body. Fixed-height rows stack vertically with a
65
+ * fill row consuming remaining space — mirrors the Login Information
66
+ * card pattern from the app.
67
+ */
68
+ export const CardWithRows = () => {
69
+ return (
70
+ <div className={styles['stories-container']}>
71
+ <Card maxHeight="500px" maxWidth="400px">
72
+ <Header>
73
+ <Title>Login Information</Title>
74
+ </Header>
75
+ <Scaffold>
76
+ <Rows>
77
+ <Row>
78
+ <Detail>
79
+ <Term>
80
+ <Key>Username:</Key>
81
+ <Value>1026223MinhtestCreateAgent1</Value>
82
+ </Term>
83
+ <Term>
84
+ <Key>Email:</Key>
85
+ <Value severity="encouraged">jsmith@example.com</Value>
86
+ </Term>
87
+ </Detail>
88
+ </Row>
89
+
90
+ <Row>
91
+ <Detail>
92
+ <Term>
93
+ <Key>Force Password Reset:</Key>
94
+ <Value>No</Value>
95
+ </Term>
96
+ <Term>
97
+ <Key>Two-Factor Status:</Key>
98
+ <Value severity="encouraged">Enabled</Value>
99
+ </Term>
100
+ <Term>
101
+ <Key>Two-Factor Type:</Key>
102
+ <Value>Email</Value>
103
+ </Term>
104
+ </Detail>
105
+ </Row>
106
+ <Row>
107
+ <Detail>
108
+ <Term>
109
+ <Key>Access Token:</Key>
110
+ <Value>••••••••••••</Value>
111
+ </Term>
112
+ <Term>
113
+ <Key>Expiration Date:</Key>
114
+ <Value>02/27/2024</Value>
115
+ </Term>
116
+ </Detail>
117
+ </Row>
118
+ </Rows>
119
+ </Scaffold>
62
120
  </Card>
63
121
  </div>
64
122
  );
@@ -1,7 +1,7 @@
1
1
  import { clsx } from 'clsx';
2
2
  import React from 'react';
3
3
  import { Scaffold, type ScaffoldProps } from '../../layouts/containers/scaffold.js';
4
-
4
+ import styles from './card.module.css';
5
5
  export interface CardProps extends Omit<ScaffoldProps, 'as' | 'children'> {
6
6
  children?: React.ReactNode;
7
7
  }
@@ -11,7 +11,11 @@ export const Card = React.forwardRef<HTMLElement, CardProps>(function Card(
11
11
  ref
12
12
  ) {
13
13
  return (
14
- <Scaffold ref={ref} className={clsx(className, 'tcn-surface', 'tcn-card')} {...props}>
14
+ <Scaffold
15
+ ref={ref}
16
+ className={clsx(className, styles.card, 'tcn-surface', 'tcn-card')}
17
+ {...props}
18
+ >
15
19
  {children}
16
20
  </Scaffold>
17
21
  );
@@ -1,3 +1,4 @@
1
+ import { useState } from 'react';
1
2
  import { Header } from '../../layouts/header/header.js';
2
3
  import { Detail, Footer, Scaffold } from '../../layouts/index.js';
3
4
  import { Column } from '../../layouts/containers/columns/column.js';
@@ -7,6 +8,10 @@ import { Title } from '../../typography/title/title.js';
7
8
  import { Page } from './page.js';
8
9
  import { ZStack } from '../../stacks/z_stack.js';
9
10
  import { Panel } from '../panel/panel.js';
11
+ import { Card } from '../card/card.js';
12
+ import { SBContent } from '../../layouts/__stories__/utils.js';
13
+ import { Resizable } from '../../utils/decorators/resizable/resizable.js';
14
+ import { ResizeHandle } from '../../utils/decorators/resizable/resize_handle.js';
10
15
 
11
16
  export default {
12
17
  title: 'Surfaces/Page',
@@ -40,14 +45,38 @@ export const WithColumns = () => {
40
45
  <ZStack height="100%" width="100%" minHeight="600px" minWidth="600px">
41
46
  <Page>
42
47
  <Columns>
48
+ <Column minWidth="400px">
49
+ <Scaffold>
50
+ <Header>
51
+ <Title>Tooling Header</Title>
52
+ </Header>
53
+ <Scaffold>
54
+ <Detail>
55
+ <Card>
56
+ <Header>Tooling 1</Header>
57
+ <Scaffold>
58
+ <SBContent />
59
+ </Scaffold>
60
+ </Card>
61
+
62
+ <Card>
63
+ <Header>Tooling 2</Header>
64
+ <Scaffold>
65
+ <SBContent />
66
+ </Scaffold>
67
+ </Card>
68
+ </Detail>
69
+ </Scaffold>
70
+ </Scaffold>
71
+ </Column>
43
72
  <Column minWidth="400px" width="fill">
44
73
  <Panel>
45
74
  <Header>
46
- <Title>Left Panel</Title>
75
+ <Title>Primary</Title>
47
76
  </Header>
48
77
  <Scaffold>
49
78
  <Detail>
50
- <BodyText>Left panel content</BodyText>
79
+ <BodyText>Content</BodyText>
51
80
  </Detail>
52
81
  </Scaffold>
53
82
  </Panel>
@@ -55,15 +84,66 @@ export const WithColumns = () => {
55
84
  <Column minWidth="400px">
56
85
  <Panel>
57
86
  <Header>
58
- <Title>Right Panel</Title>
87
+ <Title>Secondary</Title>
88
+ </Header>
89
+ <Scaffold>
90
+ <Detail>
91
+ <BodyText>Content</BodyText>
92
+ </Detail>
93
+ </Scaffold>
94
+ </Panel>
95
+ </Column>
96
+ </Columns>
97
+ </Page>
98
+ </ZStack>
99
+ );
100
+ };
101
+
102
+ /** WIP: Testing Resizable + ResizeHandle with a two-column layout */
103
+ export const ResizableSecondaryColumn = () => {
104
+ const MIN_WIDTH = 200;
105
+ const MAX_WIDTH = 600;
106
+ const [secondaryWidth, setSecondaryWidth] = useState(350);
107
+
108
+ const atMin = secondaryWidth <= MIN_WIDTH;
109
+ const atMax = secondaryWidth >= MAX_WIDTH;
110
+ const constraint = atMin ? ' (At Min)' : atMax ? ' (At Max)' : '';
111
+
112
+ return (
113
+ <ZStack height="100%" width="100%" minHeight="600px" minWidth="600px">
114
+ <Page>
115
+ <Columns>
116
+ <Column width="fill">
117
+ <Panel>
118
+ <Header>
119
+ <Title>Primary</Title>
59
120
  </Header>
60
121
  <Scaffold>
61
122
  <Detail>
62
- <BodyText>Right panel content</BodyText>
123
+ <BodyText>Primary content fills remaining space.</BodyText>
63
124
  </Detail>
64
125
  </Scaffold>
65
126
  </Panel>
66
127
  </Column>
128
+ <Resizable onWidthResize={({ width }) => setSecondaryWidth(Math.round(width))}>
129
+ <Column
130
+ width={`${secondaryWidth}px`}
131
+ minWidth={`${MIN_WIDTH}px`}
132
+ maxWidth={`${MAX_WIDTH}px`}
133
+ >
134
+ <Panel>
135
+ <Header>
136
+ <Title>{`Secondary (${secondaryWidth}px)${constraint}`}</Title>
137
+ </Header>
138
+ <Scaffold>
139
+ <Detail>
140
+ <BodyText>Drag the start edge to resize this column.</BodyText>
141
+ </Detail>
142
+ </Scaffold>
143
+ </Panel>
144
+ </Column>
145
+ <ResizeHandle position="start" />
146
+ </Resizable>
67
147
  </Columns>
68
148
  </Page>
69
149
  </ZStack>
@@ -4,7 +4,7 @@ import { Footer } from '../../../layouts/footer/footer.js';
4
4
  import { Header } from '../../../layouts/header/header.js';
5
5
  import { Column } from '../../../layouts/containers/columns/column.js';
6
6
  import { Columns } from '../../../layouts/containers/columns/columns.js';
7
- import { Detail, Heading, Scaffold, Section } from '../../../layouts/index.js';
7
+ import { Detail, Heading, Row, Rows, Scaffold, Section } from '../../../layouts/index.js';
8
8
  import { UtilityBar } from '../../../layouts/utility_bar/utility_bar.js';
9
9
  import { Box, HStack, Spacer } from '../../../stacks/index.js';
10
10
  import { Title } from '../../../typography/title/title.js';
@@ -345,21 +345,19 @@ export const WithColumns = () => {
345
345
  <Heading>General</Heading>
346
346
  <Detail>
347
347
  <Term>
348
- <Key>Agent</Key>
349
- <Value>John Doe</Value>
348
+ <Key>Email</Key>
349
+ <Value>john.doe@example.com</Value>
350
350
  </Term>
351
351
  <Term>
352
- <Key>Queue</Key>
353
- <Value>Support</Value>
352
+ <Key>Phone</Key>
353
+ <Value>+1 555 000 1234</Value>
354
354
  </Term>
355
355
  <Term>
356
- <Key>Status</Key>
357
- <Value>Active</Value>
356
+ <Key>Start Date</Key>
357
+ <Value>05/27/2023</Value>
358
358
  </Term>
359
359
  </Detail>
360
360
  </Section>
361
- </Column>
362
- <Column minWidth="300px">
363
361
  <Section>
364
362
  <Heading>Contact</Heading>
365
363
  <Detail>
@@ -378,6 +376,83 @@ export const WithColumns = () => {
378
376
  </Detail>
379
377
  </Section>
380
378
  </Column>
379
+ <Column minWidth="300px">
380
+ <Rows>
381
+ <Row>
382
+ <Detail>
383
+ <Term>
384
+ <Key>Email</Key>
385
+ <Value>john.doe@example.com</Value>
386
+ </Term>
387
+ <Term>
388
+ <Key>Phone</Key>
389
+ <Value>+1 555 000 1234</Value>
390
+ </Term>
391
+ <Term>
392
+ <Key>Start Date</Key>
393
+ <Value>05/27/2023</Value>
394
+ </Term>
395
+ </Detail>
396
+ </Row>
397
+ <Row>
398
+ <Detail>
399
+ <Term>
400
+ <Key>Email</Key>
401
+ <Value>john.doe@example.com</Value>
402
+ </Term>
403
+ <Term>
404
+ <Key>Phone</Key>
405
+ <Value>+1 555 000 1234</Value>
406
+ </Term>
407
+ <Term>
408
+ <Key>Start Date</Key>
409
+ <Value>05/27/2023</Value>
410
+ </Term>
411
+ </Detail>
412
+ </Row>
413
+ </Rows>
414
+ </Column>
415
+ <Column minWidth="300px">
416
+ <Card>
417
+ <Header>General</Header>
418
+ <Scaffold>
419
+ <Detail>
420
+ <Term>
421
+ <Key>Email</Key>
422
+ <Value>john.doe@example.com</Value>
423
+ </Term>
424
+ <Term>
425
+ <Key>Phone</Key>
426
+ <Value>+1 555 000 1234</Value>
427
+ </Term>
428
+ <Term>
429
+ <Key>Start Date</Key>
430
+ <Value>05/27/2023</Value>
431
+ </Term>
432
+ </Detail>
433
+ </Scaffold>
434
+ </Card>
435
+
436
+ <Card>
437
+ <Header>Contact</Header>
438
+ <Scaffold>
439
+ <Detail>
440
+ <Term>
441
+ <Key>Email</Key>
442
+ <Value>john.doe@example.com</Value>
443
+ </Term>
444
+ <Term>
445
+ <Key>Phone</Key>
446
+ <Value>+1 555 000 1234</Value>
447
+ </Term>
448
+ <Term>
449
+ <Key>Start Date</Key>
450
+ <Value>05/27/2023</Value>
451
+ </Term>
452
+ </Detail>
453
+ </Scaffold>
454
+ </Card>
455
+ </Column>
381
456
  </Columns>
382
457
  </Scaffold>
383
458
  <Footer>
@@ -6,7 +6,7 @@ import { Spacer } from '../../stacks/spacer.js';
6
6
  import { Button } from '../../actions/index.js';
7
7
  import { CrossIcon } from '@tcn/icons/cross_icon.js';
8
8
  import { ZStack } from '../../stacks/z_stack.js';
9
- import { DragHandle } from '../../utils/dnd/handle.js';
9
+ import { DragHandle } from '../../utils/decorators/draggable/drag_handle.js';
10
10
  import { BugIcon } from '@tcn/icons/bug_icon.js';
11
11
 
12
12
  export default {
@@ -0,0 +1,11 @@
1
+ // ResizeObserver is not available in vitest's jsdom environment.
2
+ // `use_resize_observer.ts` instantiates a registry singleton at module load
3
+ // time, so this stub must be in place before any imports run.
4
+ globalThis.ResizeObserver = class ResizeObserver {
5
+ observe() {}
6
+ unobserve() {}
7
+ disconnect() {}
8
+ };
9
+
10
+ // Required for React's act() to work correctly in jsdom tests.
11
+ globalThis.IS_REACT_ACT_ENVIRONMENT = true;
@@ -7,11 +7,13 @@ import { VStack } from '../../stacks/v_stack.js';
7
7
  import { Spacer } from '../../stacks/spacer.js';
8
8
  import { Field } from '../../form/field/field.js';
9
9
  import { FieldSet } from '../../form/field_set/field_set.js';
10
+ import { Legend } from '../../form/field_set/legend.js';
10
11
  import { BodyText } from '../../typography/index.js';
11
12
 
12
13
  export function ButtonShowcase() {
13
14
  return (
14
- <FieldSet legend="Button Showcase">
15
+ <FieldSet>
16
+ <Legend>Button Showcase</Legend>
15
17
  {/* Basic Buttons */}
16
18
  <Field label="Basic Buttons">
17
19
  <HStack width="400px" gap="8px">
@@ -21,6 +21,7 @@ import { HStack } from '../../stacks/h_stack.js';
21
21
  import { Spacer } from '../../stacks/spacer.js';
22
22
  import { Field } from '../../form/field/field.js';
23
23
  import { FieldSet } from '../../form/field_set/field_set.js';
24
+ import { Legend } from '../../form/field_set/legend.js';
24
25
 
25
26
  export function ControlsFieldSet() {
26
27
  const [disabled, setDisabled] = useState<boolean>(false);
@@ -49,7 +50,8 @@ export function ControlsFieldSet() {
49
50
  <Switch checked={disabled} onChange={setDisabled} />
50
51
  </Field>
51
52
  <Spacer height="8px" />
52
- <FieldSet legend="Inputs">
53
+ <FieldSet>
54
+ <Legend>Inputs</Legend>
53
55
  <Field label="Input">
54
56
  <Input disabled={disabled} />
55
57
  </Field>
@@ -18,6 +18,7 @@ import { Spacer } from '../../stacks/spacer.js';
18
18
  import { ZStack } from '../../stacks/z_stack.js';
19
19
  import { Field } from '../../form/field/field.js';
20
20
  import { FieldSet } from '../../form/field_set/field_set.js';
21
+ import { Legend } from '../../form/field_set/legend.js';
21
22
  import { BodyText } from '../../typography/index.js';
22
23
  import { Checkbox } from '../../inputs/index.js';
23
24
  import { Divider } from '../../layouts/divider/divider.js';
@@ -117,7 +118,8 @@ export function MenuShowcase() {
117
118
  };
118
119
 
119
120
  return (
120
- <FieldSet legend="Menu Showcase">
121
+ <FieldSet>
122
+ <Legend>Menu Showcase</Legend>
121
123
  {/* Basic Dropdown Menus */}
122
124
  <Field label="Basic Dropdown Menus">
123
125
  <VStack gap="8px" hAlign="end">
@@ -5,7 +5,6 @@ import { clsx } from 'clsx';
5
5
  // Styles
6
6
  import './stylesheets/reset.css';
7
7
  import styles from './theme_provider.module.css';
8
- import layers from '../css/layers.css?raw';
9
8
 
10
9
  export interface ThemeProps extends BoxProps {
11
10
  styleSheets: CSSStyleSheet[];
@@ -14,27 +13,18 @@ export interface ThemeProps extends BoxProps {
14
13
  }
15
14
 
16
15
  export function Theme({ styleSheets, children, className, ...boxProps }: ThemeProps) {
17
- useLayoutEffect(() => {
18
- document.adoptedStyleSheets = styleSheets;
19
- }, [styleSheets]);
16
+ const ref = React.useRef<HTMLElement>(null);
20
17
 
21
- // I used this approach instead to guarantee the order of the stylesheets
22
18
  useLayoutEffect(() => {
23
- if (document.getElementById('critical-css')) return;
24
-
25
- const style = document.createElement('style');
26
- style.id = 'critical-css';
27
- style.textContent = layers;
19
+ const root = ref.current?.getRootNode();
20
+ if (!root || !('adoptedStyleSheets' in root)) return;
28
21
 
29
- document.head.prepend(style);
30
-
31
- return () => {
32
- document.getElementById('critical-css')?.remove();
33
- };
34
- }, []);
22
+ (root as Document | ShadowRoot).adoptedStyleSheets = styleSheets;
23
+ }, [styleSheets]);
35
24
 
36
25
  return (
37
26
  <Box
27
+ ref={ref}
38
28
  className={clsx('tcn-theme-root', styles['tcn-theme-provider'], className)}
39
29
  {...boxProps}
40
30
  >
@@ -0,0 +1,89 @@
1
+ # `.tcn-interactive` — The Interaction State Primitive
2
+
3
+ ## What it is
4
+
5
+ `.tcn-interactive` is a CSS class that provides the foundational interaction state system for all clickable/tappable elements. It is an atomic theme concept — alongside material, surface, and elevation — that doesn't define what something looks like, but how something responds to user interaction.
6
+
7
+ ## What it provides
8
+
9
+ ### CSS custom properties (state vocabulary)
10
+
11
+ These variables form the "interaction vocabulary" that all interactive components share:
12
+
13
+ | Variable | Purpose |
14
+ |----------|---------|
15
+ | `--ink` | Text/foreground color (defaults to `--on-material`) |
16
+ | `--act` | Action accent color (defaults to `--action`) |
17
+ | `--mat` | Background/material color (defaults to `--material`) |
18
+ | `--act-down` | Active/pressed state — darkened material (`black 12%` mix) |
19
+ | `--act-raised` | Hover state — action tinted into material (`--act 12%` mix) |
20
+ | `--act-focus` | Focus state — stronger action tint (`--act 16%` mix) |
21
+ | `--act-drag` | Drag state — strongest action tint (`--act 24%` mix) |
22
+
23
+ ### Presentational defaults
24
+
25
+ | Property | Value | Why |
26
+ |----------|-------|-----|
27
+ | `cursor` | `pointer` | Signals clickability |
28
+ | `user-select` | `none` | Prevents accidental text selection during interaction |
29
+ | `background` | `var(--mat)` | Material background |
30
+ | `color` | `var(--ink)` | Foreground color |
31
+ | `transition` | `background 0.1s, color 0.1s` | Smooth state changes |
32
+
33
+ ### Pseudo-state mapping
34
+
35
+ | State | Selector | Background |
36
+ |-------|----------|------------|
37
+ | Focus | `:focus-visible`, `[data-focus-visible]` | `--act-focus` + 2px outline |
38
+ | Hover | `:hover`, `[data-hover]` | `--act-raised` |
39
+ | Active | `:active`, `[data-active]` | `--act-down` |
40
+ | Disabled | `[data-is-disabled="true"]` | `pointer-events: none` |
41
+
42
+ The `data-*` attribute selectors exist alongside pseudo-classes so that components can programmatically force states (e.g., showing a hover state in Storybook without actual mouse interaction).
43
+
44
+ ## Why we have it
45
+
46
+ Without `.tcn-interactive`, every clickable component would need to independently implement:
47
+ - Its own hover/focus/active/disabled background logic
48
+ - Its own color-mixing math for state changes
49
+ - Its own transition timing
50
+
51
+ By centralizing this in a single class, components opt into a consistent interaction model. A button, a toggle, a tab item, and a list item all respond to hover/focus/active in the same way — the only difference is what `--act`, `--mat`, and `--ink` resolve to in context.
52
+
53
+ This is what makes the "material system" work: a button inside a modal header automatically picks up the header's `--material` and `--on-material`, and the interactive states remix those colors correctly. No component needs to know what surface it's sitting on.
54
+
55
+ ## Which components apply it
56
+
57
+ | Component | File | Additional classes |
58
+ |-----------|------|--------------------|
59
+ | `BaseButton` | `actions/button/base_button/base_button.tsx` | `.tcn-base-button` |
60
+ | `TabItem` | `navigation/tabs/primitives/tabs_list.tsx` | `.tcn-tab-item` |
61
+ | `Item` (list) | `layouts/list/item.tsx` | `.tcn-item` |
62
+
63
+ All button variants (`Button`, `Toggle`, `MobileButton`) inherit `.tcn-interactive` through `BaseButton`. This means the class is active on every button, toggle, tab, and list item in the system.
64
+
65
+ ## How components customize it
66
+
67
+ Components override the vocabulary variables rather than the properties:
68
+
69
+ ```css
70
+ /* Button sets --mat and --ink based on hierarchy */
71
+ .tcn-button[data-hierarchy="primary"] {
72
+ --mat: var(--tcn-button-color, var(--btn-primary));
73
+ --ink: var(--tcn-button-text-color, var(--btn-on-primary));
74
+ }
75
+
76
+ /* Toggle overrides for selected state */
77
+ .tcn-toggle[data-is-selected="true"] {
78
+ --mat: var(--tcn-button-color, var(--tgl-true));
79
+ --ink: var(--tcn-button-text-color, var(--ergo-white));
80
+ }
81
+
82
+ /* Tab item overrides for selected state */
83
+ .tcn-tab-item[data-is-selected="true"] {
84
+ --mat: var(--tcn-button-color, var(--material));
85
+ --ink: var(--tcn-button-text-color, var(--ergo-primary));
86
+ }
87
+ ```
88
+
89
+ Because the state backgrounds (`--act-raised`, `--act-down`, `--act-focus`) are computed from `--mat` and `--act` via `color-mix()`, changing the input variables automatically produces correct state colors for any context.