@tcn/ui 0.0.4 → 0.2.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 (198) hide show
  1. package/README.md +38 -3
  2. package/dist/actions/button/base_button/base_button.d.ts.map +1 -1
  3. package/dist/actions/button/base_button/base_button.js +17 -12
  4. package/dist/actions/button/base_button/base_button.js.map +1 -1
  5. package/dist/actions/button/button/button.d.ts.map +1 -1
  6. package/dist/actions/button/button/button.js +7 -7
  7. package/dist/actions/button/button/button.js.map +1 -1
  8. package/dist/actions/button/slim_button/slim_button.js +2 -2
  9. package/dist/actions/button/slim_button/slim_button.js.map +1 -1
  10. package/dist/button.css +1 -1
  11. package/dist/draggable.css +1 -0
  12. package/dist/feedback/progress/progress_bar.js +1 -1
  13. package/dist/footer.css +1 -1
  14. package/dist/form/field/common/field_description.js +1 -1
  15. package/dist/form/field/common/field_error.js +4 -3
  16. package/dist/form/field/common/field_error.js.map +1 -1
  17. package/dist/form/field/common/field_label.js +1 -1
  18. package/dist/inputs/date_picker/date_picker_date.js +1 -1
  19. package/dist/inputs/date_picker/date_picker_day.js +1 -1
  20. package/dist/inputs/date_picker/date_picker_time_selector.js +1 -1
  21. package/dist/inputs/date_picker/date_picker_year_selector.js +1 -1
  22. package/dist/inputs/input/input.d.ts +2 -2
  23. package/dist/inputs/input/input.d.ts.map +1 -1
  24. package/dist/inputs/input/input.js.map +1 -1
  25. package/dist/inputs/options/option.d.ts +1 -0
  26. package/dist/inputs/options/option.d.ts.map +1 -1
  27. package/dist/inputs/options/option.js.map +1 -1
  28. package/dist/inputs/phone_number_input/phone_number_input.d.ts +8 -1
  29. package/dist/inputs/phone_number_input/phone_number_input.d.ts.map +1 -1
  30. package/dist/inputs/phone_number_input/phone_number_input.js +187 -137
  31. package/dist/inputs/phone_number_input/phone_number_input.js.map +1 -1
  32. package/dist/inputs/suggestions/suggestion_item.d.ts +1 -1
  33. package/dist/inputs/suggestions/suggestion_item.d.ts.map +1 -1
  34. package/dist/inputs/suggestions/suggestion_item.js +23 -18
  35. package/dist/inputs/suggestions/suggestion_item.js.map +1 -1
  36. package/dist/inputs/suggestions/suggestion_list.d.ts +1 -1
  37. package/dist/inputs/suggestions/suggestion_list.d.ts.map +1 -1
  38. package/dist/inputs/suggestions/suggestion_list.js +106 -96
  39. package/dist/inputs/suggestions/suggestion_list.js.map +1 -1
  40. package/dist/inputs/textarea/textarea.d.ts +2 -2
  41. package/dist/inputs/textarea/textarea.d.ts.map +1 -1
  42. package/dist/inputs/textarea/textarea.js.map +1 -1
  43. package/dist/layouts/footer/footer.js +5 -5
  44. package/dist/layouts/footer/footer.js.map +1 -1
  45. package/dist/layouts/header/header.d.ts.map +1 -1
  46. package/dist/layouts/header/header.js.map +1 -1
  47. package/dist/layouts/index.d.ts +3 -2
  48. package/dist/layouts/index.d.ts.map +1 -1
  49. package/dist/layouts/index.js +26 -24
  50. package/dist/layouts/index.js.map +1 -1
  51. package/dist/layouts/list/item.d.ts +1 -0
  52. package/dist/layouts/list/item.d.ts.map +1 -1
  53. package/dist/layouts/list/item.js +17 -6
  54. package/dist/layouts/list/item.js.map +1 -1
  55. package/dist/layouts/list/list.js +10 -10
  56. package/dist/layouts/list/list.js.map +1 -1
  57. package/dist/overlay/context_menu/context_menu.js +4 -4
  58. package/dist/overlay/frame/frame.d.ts +11 -0
  59. package/dist/overlay/frame/frame.d.ts.map +1 -0
  60. package/dist/overlay/frame/frame.js +18 -0
  61. package/dist/overlay/frame/frame.js.map +1 -0
  62. package/dist/overlay/index.d.ts +1 -0
  63. package/dist/overlay/index.d.ts.map +1 -1
  64. package/dist/overlay/index.js +5 -3
  65. package/dist/overlay/index.js.map +1 -1
  66. package/dist/overlay/popper/popper.js +12 -12
  67. package/dist/{portal-qqIp4SIl.js → overlay/portal/portal.js} +3 -3
  68. package/dist/overlay/portal/portal.js.map +1 -0
  69. package/dist/overlay/portal/portal_platform.js +3 -4
  70. package/dist/overlay/portal/portal_platform.js.map +1 -1
  71. package/dist/phone_number_input.css +1 -1
  72. package/dist/slim_button.css +1 -1
  73. package/dist/stacks/box/box.d.ts +1 -1
  74. package/dist/stacks/box/box.d.ts.map +1 -1
  75. package/dist/stacks/box/box.js.map +1 -1
  76. package/dist/surfaces/card/card.d.ts.map +1 -1
  77. package/dist/surfaces/card/card.js +7 -16
  78. package/dist/surfaces/card/card.js.map +1 -1
  79. package/dist/surfaces/confirm/confirm.js +4 -4
  80. package/dist/surfaces/index.d.ts +2 -2
  81. package/dist/surfaces/index.d.ts.map +1 -1
  82. package/dist/surfaces/index.js +22 -22
  83. package/dist/surfaces/modal/modal.d.ts +3 -2
  84. package/dist/surfaces/modal/modal.d.ts.map +1 -1
  85. package/dist/surfaces/modal/modal.js +14 -13
  86. package/dist/surfaces/modal/modal.js.map +1 -1
  87. package/dist/surfaces/window/window.d.ts +3 -2
  88. package/dist/surfaces/window/window.d.ts.map +1 -1
  89. package/dist/surfaces/window/window.js +17 -7
  90. package/dist/surfaces/window/window.js.map +1 -1
  91. package/dist/themes/index.js +6 -141
  92. package/dist/themes/index.js.map +1 -1
  93. package/dist/themes/stylesheets/reset.js +140 -0
  94. package/dist/themes/stylesheets/reset.js.map +1 -0
  95. package/dist/themes/themes/ergo/ergo_theme.js +664 -0
  96. package/dist/themes/themes/ergo/ergo_theme.js.map +1 -0
  97. package/dist/tokens/bubble/bubble.js +17 -16
  98. package/dist/tokens/bubble/bubble.js.map +1 -1
  99. package/dist/tokens/chip/chip.js +9 -8
  100. package/dist/tokens/chip/chip.js.map +1 -1
  101. package/dist/typography/title/title.d.ts +2 -1
  102. package/dist/typography/title/title.d.ts.map +1 -1
  103. package/dist/typography/title/title.js +24 -23
  104. package/dist/typography/title/title.js.map +1 -1
  105. package/dist/utils/dnd/context.d.ts +4 -0
  106. package/dist/utils/dnd/context.d.ts.map +1 -0
  107. package/dist/utils/dnd/context.js +20 -0
  108. package/dist/utils/dnd/context.js.map +1 -0
  109. package/dist/utils/dnd/draggable/draggable.d.ts +7 -0
  110. package/dist/utils/dnd/draggable/draggable.d.ts.map +1 -0
  111. package/dist/utils/dnd/draggable/draggable.js +27 -0
  112. package/dist/utils/dnd/draggable/draggable.js.map +1 -0
  113. package/dist/utils/dnd/handle.d.ts +6 -0
  114. package/dist/utils/dnd/handle.d.ts.map +1 -0
  115. package/dist/utils/dnd/handle.js +22 -0
  116. package/dist/utils/dnd/handle.js.map +1 -0
  117. package/dist/utils/dnd/hooks/use_drag_container.d.ts +7 -0
  118. package/dist/utils/dnd/hooks/use_drag_container.d.ts.map +1 -0
  119. package/dist/utils/dnd/hooks/use_drag_container.js +30 -0
  120. package/dist/utils/dnd/hooks/use_drag_container.js.map +1 -0
  121. package/dist/utils/{hooks → dnd/hooks}/use_draggable.d.ts +3 -3
  122. package/dist/utils/dnd/hooks/use_draggable.d.ts.map +1 -0
  123. package/dist/utils/dnd/hooks/use_draggable.js +41 -0
  124. package/dist/utils/dnd/hooks/use_draggable.js.map +1 -0
  125. package/dist/utils/dnd/types.d.ts +10 -0
  126. package/dist/utils/dnd/types.d.ts.map +1 -0
  127. package/dist/utils/dnd/types.js +2 -0
  128. package/dist/utils/dnd/types.js.map +1 -0
  129. package/dist/utils/index.d.ts +1 -1
  130. package/dist/utils/index.d.ts.map +1 -1
  131. package/dist/utils/index.js +1 -1
  132. package/package.json +9 -3
  133. package/src/actions/button/base_button/base_button.tsx +7 -2
  134. package/src/actions/button/button/button.module.css +0 -78
  135. package/src/actions/button/button/button.tsx +2 -4
  136. package/src/actions/button/slim_button/slim_button.module.css +0 -26
  137. package/src/actions/button/slim_button/slim_button.tsx +1 -1
  138. package/src/inputs/input/input.tsx +3 -2
  139. package/src/inputs/options/option.tsx +1 -0
  140. package/src/inputs/phone_number_input/phone_number_input.module.css +12 -0
  141. package/src/inputs/phone_number_input/phone_number_input.stories.tsx +8 -0
  142. package/src/inputs/phone_number_input/phone_number_input.tsx +107 -21
  143. package/src/inputs/suggestions/suggestion_item.tsx +12 -2
  144. package/src/inputs/suggestions/suggestion_list.tsx +22 -3
  145. package/src/inputs/textarea/textarea.tsx +2 -2
  146. package/src/layouts/footer/footer.module.css +0 -1
  147. package/src/layouts/footer/footer.tsx +1 -1
  148. package/src/layouts/header/header.tsx +0 -1
  149. package/src/layouts/index.ts +3 -2
  150. package/src/layouts/list/item.tsx +10 -2
  151. package/src/layouts/list/list.tsx +2 -2
  152. package/src/overlay/frame/frame.stories.tsx +40 -0
  153. package/src/overlay/frame/frame.tsx +34 -0
  154. package/src/overlay/frame/frame_stories.module.css +14 -0
  155. package/src/overlay/index.ts +1 -0
  156. package/src/stacks/box/box.tsx +8 -2
  157. package/src/surfaces/card/card.tsx +2 -8
  158. package/src/surfaces/index.ts +2 -2
  159. package/src/surfaces/modal/__stories__/modal.stories.tsx +19 -27
  160. package/src/surfaces/modal/modal.tsx +13 -10
  161. package/src/surfaces/panel/__stories__/panel.stories.tsx +13 -12
  162. package/src/surfaces/window/window.stories.tsx +37 -4
  163. package/src/surfaces/window/window.tsx +14 -6
  164. package/src/themes/themes/ergo/__stories__/components/material_picker/sb_inverted_materials.module.css +34 -0
  165. package/src/themes/themes/ergo/__stories__/components/material_picker/sb_material_picker.tsx +52 -0
  166. package/src/themes/themes/ergo/__stories__/components/tone_picker/sb_card.module.css +5 -0
  167. package/src/themes/themes/ergo/__stories__/components/tone_picker/sb_tone_card.tsx +40 -0
  168. package/src/themes/themes/ergo/__stories__/components/tone_picker/sb_tone_picker.tsx +83 -0
  169. package/src/themes/themes/ergo/__stories__/components/tone_picker/types.ts +7 -0
  170. package/src/themes/themes/ergo/__stories__/material.stories.tsx +154 -0
  171. package/src/themes/themes/ergo/__stories__/sb_materials.module.css +110 -0
  172. package/src/themes/themes/ergo/__stories__/utils.ts +92 -0
  173. package/src/themes/themes/ergo/ergo_theme.css +358 -26
  174. package/src/typography/title/title.tsx +23 -19
  175. package/src/utils/dnd/__stories__/draggable.stories.tsx +48 -0
  176. package/src/utils/dnd/__stories__/draggable_stories.module.css +21 -0
  177. package/src/utils/{__stories__ → dnd/__stories__}/use_draggable.stories.tsx +15 -10
  178. package/src/utils/dnd/context.ts +24 -0
  179. package/src/utils/dnd/draggable/draggable.module.css +8 -0
  180. package/src/utils/dnd/draggable/draggable.tsx +42 -0
  181. package/src/utils/dnd/handle.tsx +32 -0
  182. package/src/utils/dnd/hooks/use_drag_container.ts +42 -0
  183. package/src/utils/{hooks → dnd/hooks}/use_draggable.ts +23 -17
  184. package/src/utils/dnd/types.ts +6 -0
  185. package/src/utils/index.ts +1 -1
  186. package/tsconfig.json +0 -3
  187. package/dist/card.css +0 -1
  188. package/dist/portal-qqIp4SIl.js.map +0 -1
  189. package/dist/themes/stylesheets/reset.css +0 -1
  190. package/dist/themes/themes/ergo/ergo_theme.css +0 -1
  191. package/dist/themes/themes/windows_98/windows_98.css +0 -1
  192. package/dist/title.module-B16de2jd.js +0 -5
  193. package/dist/title.module-B16de2jd.js.map +0 -1
  194. package/dist/utils/hooks/use_draggable.d.ts.map +0 -1
  195. package/dist/utils/hooks/use_draggable.js +0 -30
  196. package/dist/utils/hooks/use_draggable.js.map +0 -1
  197. package/src/surfaces/card/card.module.css +0 -5
  198. /package/dist/{overlay/portal/portal.css → portal_platform.css} +0 -0
@@ -146,7 +146,8 @@ legend {
146
146
 
147
147
  --status-color-disabled: #7f7f7f;
148
148
  --status-color-info: #008cff;
149
- --status-color-warning: #ff0000;
149
+ --status-color-warning: #ffff00;
150
+ --status-color-positive: #00ff00;
150
151
  --status-color-error: #ff0000;
151
152
 
152
153
  --async-color-initial: #c0c0c0;
@@ -184,24 +185,290 @@ legend {
184
185
  --foreground-color-tertiary: #222222;
185
186
  --foreground-color-quaternary: #222222;
186
187
 
187
- --accent-color: #008cff;
188
+ --material-disabled: #d3d3d3;
189
+ --material-secondary-dark: 197 29.1% 40.4%;
190
+ --material-tan: 33, 22%, 84%;
188
191
 
189
192
  --shape-radius-small: 2px;
190
193
  --shape-radius-medium: 4px;
191
194
  --shape-radius-large: 8px;
195
+
196
+ --accent-color: #cd6b2c;
197
+
198
+ --action: 23, 65%, 49%;
199
+ --on-action: 0, 0%, 100%;
200
+ --material: 0, 0%, 100%;
201
+ --on-material: 213, 35.6%, 34.7%;
192
202
  }
193
203
 
194
204
  * {
195
205
  position: relative;
196
206
  box-sizing: border-box;
197
207
  }
208
+ /* ===== Actions ===== */
209
+
210
+ .tcn-interactive {
211
+ cursor: pointer;
212
+ user-select: none;
213
+ transition:
214
+ transform 0.1s,
215
+ background 0.1s,
216
+ color 0.1s;
217
+
218
+ --act: hsl(var(--action));
219
+ --on-act: hsl(var(--on-action));
220
+ /* Could use hsl here if we made three color variables for each of the hsl values */
221
+ --act-down: color-mix(in srgb, var(--act), black 8%);
222
+ --act-raised: color-mix(in srgb, var(--act), white 8%);
223
+ --act-faint: hsla(var(--action), 0.2);
224
+ --on-mat: hsl(var(--on-material));
225
+ --on-mat-faint: hsla(var(--on-material), 0.2);
226
+ --mat: hsl(var(--material));
227
+ --mat-down: color-mix(in srgb, var(--mat), black 8%);
228
+ --mat-raised: color-mix(in srgb, var(--mat), white 8%);
229
+ }
230
+
231
+ .tcn-interactive[data-is-disabled="true"] {
232
+ pointer-events: none;
233
+ cursor: not-allowed;
234
+ }
235
+
236
+ .tcn-interactive[data-hierarchy="primary"] {
237
+ background: var(--act);
238
+ color: var(--on-act);
239
+ border: 1px solid var(--act);
240
+ }
241
+
242
+ .tcn-interactive[data-hierarchy="primary"]:focus-visible {
243
+ outline: 2px dashed var(--act);
244
+ }
245
+
246
+ .tcn-interactive[data-hierarchy="primary"][data-is-disabled="true"] {
247
+ background: var(--material-disabled);
248
+ color: white;
249
+ border: 1px solid var(--material-disabled);
250
+ }
251
+
252
+ .tcn-interactive[data-hierarchy="primary"]:hover {
253
+ background: var(--act-raised);
254
+ }
255
+
256
+ .tcn-interactive[data-hierarchy="primary"]:active {
257
+ background: var(--act-down);
258
+ }
259
+
260
+ .tcn-interactive[data-hierarchy="secondary"] {
261
+ background: transparent;
262
+ color: var(--on-mat);
263
+ border: 1px solid var(--on-mat);
264
+ }
265
+
266
+ .tcn-interactive[data-hierarchy="secondary"]:focus-visible {
267
+ outline: 2px dashed var(--on-mat);
268
+ }
269
+
270
+ .tcn-interactive[data-hierarchy="secondary"][data-is-disabled="true"] {
271
+ color: var(--material-disabled);
272
+ border: 1px solid var(--material-disabled);
273
+ }
274
+
275
+ .tcn-interactive[data-hierarchy="secondary"]:hover {
276
+ background: var(--on-mat-faint);
277
+ }
278
+
279
+ .tcn-interactive[data-hierarchy="secondary"]:active {
280
+ background: var(--mat-down);
281
+ }
282
+
283
+ .tcn-interactive[data-hierarchy="tertiary"] {
284
+ background: transparent;
285
+ color: var(--on-mat);
286
+ border: 1px solid transparent;
287
+ }
288
+
289
+ .tcn-interactive[data-hierarchy="tertiary"]:focus-visible {
290
+ outline: 2px dashed var(--on-mat);
291
+ }
292
+
293
+ .tcn-interactive[data-hierarchy="tertiary"][data-is-disabled="true"] {
294
+ color: var(--material-disabled);
295
+ }
296
+
297
+ .tcn-interactive[data-hierarchy="tertiary"]:hover {
298
+ text-decoration: underline;
299
+ text-decoration-color: var(--on-mat);
300
+ text-decoration-thickness: 1px;
301
+ text-underline-offset: 4px;
302
+ color: var(--on-mat);
303
+ background: var(--on-mat-faint);
304
+ }
305
+
306
+ .tcn-interactive[data-hierarchy="tertiary"]:active {
307
+ background: var(--mat-down);
308
+ }
309
+
310
+ /* Button */
311
+ .tcn-button {
312
+ border-radius: 4px;
313
+ }
314
+
315
+ .tcn-button[data-size="sm"] {
316
+ padding: 0px 8px;
317
+ min-height: 22px;
318
+ }
319
+
320
+ .tcn-button[data-size="md"] {
321
+ padding: 0px 12px;
322
+ min-height: 26px;
323
+ }
324
+
325
+ .tcn-button[data-size="lg"] {
326
+ padding: 0px 16px;
327
+ min-height: 32px;
328
+ }
329
+
330
+ .tcn-button:hover {
331
+ transform: translateY(-1px);
332
+ box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.1);
333
+ }
334
+
335
+ .tcn-button:active {
336
+ transform: translateY(1px);
337
+ box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.1);
338
+ }
339
+
340
+ .tcn-slim-button {
341
+ height: auto;
342
+ width: auto;
343
+ padding: 0;
344
+ }
345
+
346
+ .tcn-slim-button[data-size="sm"] {
347
+ min-height: 12px;
348
+ min-width: 12px;
349
+ padding: 0;
350
+ .tcn-icon {
351
+ min-height: 10px;
352
+ min-width: 10px;
353
+ }
354
+ }
355
+
356
+ .tcn-slim-button[data-size="md"] {
357
+ min-height: 18px;
358
+ min-width: 18px;
359
+ padding: 0;
360
+ .tcn-icon {
361
+ min-height: 14px;
362
+ min-width: 14px;
363
+ }
364
+ }
365
+
366
+ .tcn-slim-button[data-size="lg"] {
367
+ min-height: 24px;
368
+ min-width: 24px;
369
+ padding: 0;
370
+ .tcn-icon {
371
+ min-height: 20px;
372
+ min-width: 20px;
373
+ }
374
+ }
375
+
376
+ /* ===== Materials ===== */
377
+
378
+ /* White on Gray */
379
+ .material-status-disabled {
380
+ --action: 0, 0%, 100%;
381
+ --on-action: 0, 0%, 49.8%;
382
+ --material: 0, 0%, 49.8%;
383
+ --on-material: 0, 0%, 100%;
384
+ }
385
+
386
+ /* White on Vivid Blue */
387
+ .material-status-info {
388
+ --action: 0, 0%, 100%;
389
+ --on-action: 207, 100%, 50%;
390
+ --material: 207, 100%, 50%;
391
+ --on-material: 0, 0%, 100%;
392
+ }
393
+
394
+ /* Navy on Yellow */
395
+ .material-status-warning {
396
+ --action: 213, 35.6%, 34.7%;
397
+ --on-action: 60, 100%, 50%;
398
+ --material: 60, 100%, 50%;
399
+ --on-material: 213, 35.6%, 34.7%;
400
+ }
401
+
402
+ /* White on Red */
403
+ .material-status-error {
404
+ --action: 0, 0%, 100%;
405
+ --on-action: 0, 100%, 50%;
406
+ --material: 0, 100%, 50%;
407
+ --on-material: 0, 0%, 100%;
408
+ }
409
+
410
+ /* Navy on Light Grey */
411
+ .material-async-initial {
412
+ --action: 213, 35.6%, 34.7%;
413
+ --on-action: 0, 0%, 75.3%;
414
+ --material: 0, 0%, 75.3%;
415
+ --on-material: 213, 35.6%, 34.7%;
416
+ }
417
+
418
+ /* White on Loading Blue */
419
+ .material-async-pending {
420
+ --action: 0, 0%, 100%;
421
+ --on-action: 207, 100%, 50%;
422
+ --material: 207, 100%, 50%;
423
+ --on-material: 0, 0%, 100%;
424
+ }
425
+
426
+ /* White on Vivid Green */
427
+ .material-async-success {
428
+ --action: 0, 0%, 100%;
429
+ --on-action: 120, 100%, 50%;
430
+ --material: 120, 100%, 50%;
431
+ --on-material: 0, 0%, 100%;
432
+ }
433
+
434
+ /* White on Red */
435
+ .material-async-failed {
436
+ --action: 0, 0%, 100%;
437
+ --on-action: 0, 100%, 50%;
438
+ --material: 0, 100%, 50%;
439
+ --on-material: 0, 0%, 100%;
440
+ }
441
+
442
+ .material {
443
+ background-color: hsl(var(--material));
444
+ color: hsl(var(--on-material));
445
+ }
198
446
 
199
447
  /* ===== SURFACES ===== */
448
+ .tcn-draggable[data-is-draggable="true"] {
449
+ .tcn-drag-handle {
450
+ cursor: move;
451
+ }
452
+ }
453
+
454
+ .tcn-frame[data-is-veil="true"] {
455
+ background-color: rgba(0, 0, 0, 0.5);
456
+ }
457
+
458
+ .tcn-list {
459
+ gap: var(--gap-medium);
460
+ .tcn-item {
461
+ height: 24px;
462
+ padding: 0px var(--padding-medium);
463
+ border-radius: var(--shape-radius-medium);
464
+ }
465
+ }
200
466
 
201
467
  .tcn-veil {
202
468
  background-color: rgba(0, 0, 0, 0.5);
203
469
  }
204
470
 
471
+ /* TODO: FIX Borders on modal header and footer -- when there are multiple header/footers */
205
472
  /* MODAL: */
206
473
  .tcn-modal {
207
474
  --v-inset: var(--padding-large);
@@ -210,28 +477,80 @@ legend {
210
477
  /* TODO: This should be a variable */
211
478
  border: 1px solid rgba(170, 170, 170, 1);
212
479
  overflow: hidden;
480
+
481
+ :where(.tcn-typography) {
482
+ color: inherit;
483
+ }
484
+
213
485
  :where(.tcn-header) {
486
+ --material: var(--material-secondary-dark);
487
+ --on-material: 0, 0%, 100%;
488
+ --action: var(--material-tan);
489
+ --on-action: 0, 0%, 100%;
490
+ background-color: hsl(var(--material));
491
+ color: hsl(var(--on-material));
214
492
  min-height: 40px;
215
- /* TODO: This should be a variable */
216
- background-color: rgb(73, 116, 133);
217
- color: white;
218
493
  padding: 0 var(--v-inset);
219
494
  gap: var(--gap-medium);
220
495
 
221
- :where(.tcn-title) {
222
- color: white;
496
+ :where(.tcn-divider) {
497
+ padding: 4px 0;
498
+ :where(.tcn-divider-line) {
499
+ width: 1.5px;
500
+ min-height: 18px;
501
+ height: auto;
502
+ }
223
503
  }
504
+ }
505
+
506
+ :where(.tcn-utility-bar) {
507
+ min-height: 32px;
508
+ border-bottom: 1px solid var(--foreground-color-primary);
509
+ padding: 0 var(--v-inset);
224
510
 
225
511
  :where(.tcn-button) {
226
512
  padding: 0;
227
513
  min-width: 18px;
228
514
  min-height: 18px;
229
- color: white;
230
515
  }
516
+ }
231
517
 
232
- :where(.tcn-button)[data-hierarchy="tertiary"] {
233
- color: white;
234
- }
518
+ :where(.tcn-body) {
519
+ padding: 0 var(--v-inset);
520
+ gap: var(--gap-medium);
521
+ }
522
+
523
+ :where(.tcn-footer) {
524
+ gap: var(--gap-medium);
525
+ min-height: 40px;
526
+ border-top: 1px solid var(--foreground-color-primary);
527
+ padding: 0 var(--v-inset);
528
+ }
529
+ }
530
+
531
+ /* WINDOW: */
532
+ .tcn-window {
533
+ --v-inset: var(--padding-large);
534
+ background-color: var(--background-color-primary);
535
+ border-radius: var(--shape-radius-medium);
536
+ /* TODO: This should be a variable */
537
+ border: 1px solid rgba(170, 170, 170, 1);
538
+ overflow: hidden;
539
+
540
+ :where(.tcn-typography) {
541
+ color: inherit;
542
+ }
543
+
544
+ :where(.tcn-header) {
545
+ --material: var(--material-secondary-dark);
546
+ --on-material: 0, 0%, 100%;
547
+ --action: var(--material-tan);
548
+ --on-action: 0, 0%, 100%;
549
+ background-color: hsl(var(--material));
550
+ color: hsl(var(--on-material));
551
+ min-height: 40px;
552
+ padding: 0 var(--v-inset);
553
+ gap: var(--gap-medium);
235
554
 
236
555
  :where(.tcn-divider) {
237
556
  padding: 4px 0;
@@ -273,10 +592,10 @@ legend {
273
592
  --v-inset: var(--padding-large);
274
593
  background-color: var(--background-color-primary);
275
594
  border-radius: var(--shape-radius-medium);
595
+ overflow: hidden;
276
596
 
277
597
  :where(.tcn-header) {
278
598
  min-height: 40px;
279
- border-bottom: 1px solid var(--foreground-color-primary);
280
599
  padding: 0 var(--v-inset);
281
600
  gap: var(--gap-medium);
282
601
 
@@ -284,12 +603,6 @@ legend {
284
603
  font-weight: 700;
285
604
  }
286
605
 
287
- :where(.tcn-button) {
288
- padding: 0;
289
- min-width: 18px;
290
- min-height: 18px;
291
- }
292
-
293
606
  :where(.tcn-divider) {
294
607
  padding: 4px 0;
295
608
  :where(.tcn-divider-line) {
@@ -300,16 +613,20 @@ legend {
300
613
  }
301
614
  }
302
615
 
616
+ /* Border appears on body only when it follows header or utility-bar */
617
+ :where(.tcn-header) + :where(.tcn-body),
618
+ :where(.tcn-utility-bar) + :where(.tcn-body) {
619
+ border-top: 1px solid var(--foreground-color-primary);
620
+ }
621
+
622
+ /* Border appears on footer only when it follows body */
623
+ :where(.tcn-body) + :where(.tcn-footer) {
624
+ border-top: 1px solid var(--foreground-color-primary);
625
+ }
626
+
303
627
  :where(.tcn-utility-bar) {
304
628
  min-height: 32px;
305
- border-bottom: 1px solid var(--foreground-color-primary);
306
629
  padding: 0 var(--v-inset);
307
-
308
- :where(.tcn-button) {
309
- padding: 0;
310
- min-width: 18px;
311
- min-height: 18px;
312
- }
313
630
  }
314
631
 
315
632
  :where(.tcn-body) {
@@ -320,7 +637,22 @@ legend {
320
637
  :where(.tcn-footer) {
321
638
  gap: var(--gap-medium);
322
639
  min-height: 40px;
323
- border-top: 1px solid var(--foreground-color-primary);
324
640
  padding: 0 var(--v-inset);
325
641
  }
326
642
  }
643
+
644
+ /* Card */
645
+ .tcn-card {
646
+ padding: 0;
647
+ gap: 0px;
648
+ border: 1px solid var(--foreground-color-primary);
649
+ border-radius: var(--shape-radius-medium);
650
+ overflow: hidden;
651
+ :where(.tcn-header) {
652
+ /* TODO: Color header */
653
+ min-height: 32px;
654
+ }
655
+ :where(.tcn-body) {
656
+ padding: var(--padding-medium) var(--v-inset);
657
+ }
658
+ }
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { forwardRef } from 'react';
2
2
  import { clsx } from 'clsx';
3
3
  import type { WithDetailedHTMLProps } from '../../stacks/types/as.js';
4
4
  import type { Emphasis, Hierarchy, Size } from '../../utils/index.js';
@@ -21,22 +21,25 @@ export interface TitleOwnProps {
21
21
 
22
22
  export type TitleProps = WithDetailedHTMLProps<TitleOwnProps, 'h1' | 'h2' | 'h3'>;
23
23
 
24
- export function Title({
25
- size = 'md',
26
- emphasis = 'normal',
27
- hierarchy = 'primary',
28
- color,
29
- children,
30
- className,
31
- style = {},
32
- padStart,
33
- padEnd,
34
- padBottom,
35
- padTop,
36
- pad,
37
- selectable = true,
38
- as,
39
- }: TitleProps) {
24
+ export const Title = forwardRef<HTMLHeadingElement, TitleProps>(function Title(
25
+ {
26
+ size = 'md',
27
+ emphasis = 'normal',
28
+ hierarchy = 'primary',
29
+ color,
30
+ children,
31
+ className,
32
+ style = {},
33
+ padStart,
34
+ padEnd,
35
+ padBottom,
36
+ padTop,
37
+ pad,
38
+ selectable = true,
39
+ as,
40
+ },
41
+ ref
42
+ ) {
40
43
  let As: React.ElementType = as as React.ElementType;
41
44
 
42
45
  if (as == null) {
@@ -75,14 +78,15 @@ export function Title({
75
78
 
76
79
  return (
77
80
  <As
81
+ ref={ref}
78
82
  data-hierarchy={hierarchy}
79
83
  data-emphasis={emphasis}
80
84
  data-selectable={selectable}
81
- className={clsx(styles['title'], 'title', 'tcn-title', className)}
85
+ className={clsx(styles['title'], 'title', 'tcn-typography', 'tcn-title', className)}
82
86
  style={style}
83
87
  data-size={size}
84
88
  >
85
89
  {children}
86
90
  </As>
87
91
  );
88
- }
92
+ });
@@ -0,0 +1,48 @@
1
+ import { Draggable } from '../draggable/draggable.js';
2
+ import { VStack } from '../../../stacks/v_stack.js';
3
+ import { DragHandle } from '../handle.js';
4
+ import { Box } from '../../../stacks/box/box.js';
5
+ import { BodyText } from '../../../typography/index.js';
6
+ import styles from './draggable_stories.module.css';
7
+
8
+ export default {
9
+ title: 'Utils/Draggable',
10
+ component: Draggable,
11
+ tags: ['autodocs'],
12
+ };
13
+
14
+ export const DraggableStory = () => {
15
+ return (
16
+ <VStack minHeight="600px" height="100%" width="100%">
17
+ <Draggable>
18
+ <Box width="400px" height="300px" className={styles['handle-container']}>
19
+ <DragHandle>
20
+ <Box
21
+ className={styles.handle}
22
+ width="100px"
23
+ style={{
24
+ top: 50,
25
+ left: 100,
26
+ }}
27
+ >
28
+ <BodyText>Drag Handle</BodyText>
29
+ </Box>
30
+ </DragHandle>
31
+
32
+ <DragHandle>
33
+ <Box
34
+ className={styles.handle}
35
+ width="150px"
36
+ style={{
37
+ top: 200,
38
+ left: 50,
39
+ }}
40
+ >
41
+ <BodyText>Another Drag Handle</BodyText>
42
+ </Box>
43
+ </DragHandle>
44
+ </Box>
45
+ </Draggable>
46
+ </VStack>
47
+ );
48
+ };
@@ -0,0 +1,21 @@
1
+ .handle {
2
+ position: relative;
3
+ background: var(--accent-color);
4
+ color: white;
5
+ font-weight: bold;
6
+ border: 2px solid black;
7
+ padding: var(--padding-medium);
8
+ border-radius: var(--shape-radius-medium);
9
+ }
10
+
11
+ .handle-container {
12
+ background: #f7e9fe;
13
+ padding: var(--padding-medium);
14
+ border-radius: var(--shape-radius-large);
15
+ }
16
+
17
+ .handle-container[data-is-dragging="true"] {
18
+ box-shadow:
19
+ 0 4px 16px 0 rgba(25, 118, 210, 0.2),
20
+ 0 1.5px 4px 0 rgba(21, 101, 192, 0.15);
21
+ }
@@ -1,9 +1,9 @@
1
1
  import React, { useState, useRef } from 'react';
2
2
  import { useDraggable } from '../hooks/use_draggable';
3
- import { Box } from '../../stacks/box/box.js';
3
+ import { Box } from '../../../stacks/box/box.js';
4
4
 
5
5
  export default {
6
- title: 'Hooks/useDraggable',
6
+ title: 'Utils/useDraggable',
7
7
  component: <></>,
8
8
  args: {
9
9
  startX: 200,
@@ -16,8 +16,9 @@ export const BasicDraggable = {
16
16
  const [position, setPosition] = useState({ x: args.startX, y: args.startY });
17
17
  const [isDragging, setIsDragging] = useState(false);
18
18
  const elementStartPosition = useRef({ x: args.startX, y: args.startY });
19
-
20
- const dragRef = useDraggable({
19
+ const dragRef = useRef<HTMLDivElement>(null);
20
+ useDraggable({
21
+ handles: dragRef,
21
22
  startDragCallback: () => {
22
23
  setIsDragging(true);
23
24
  elementStartPosition.current = { x: position.x, y: position.y };
@@ -76,8 +77,10 @@ export const MultipleDraggables = {
76
77
 
77
78
  const createDragHandlers = (
78
79
  id: number,
79
- elementStartPosition: React.RefObject<{ x: number; y: number }>
80
+ elementStartPosition: React.RefObject<{ x: number; y: number }>,
81
+ handleRef: React.RefObject<HTMLDivElement>
80
82
  ) => ({
83
+ handles: handleRef,
81
84
  startDragCallback: () => {
82
85
  const box = boxes.find(b => b.id === id);
83
86
  if (box && elementStartPosition.current) {
@@ -120,11 +123,12 @@ export const MultipleDraggables = {
120
123
  </p>
121
124
  {boxes.map(box => {
122
125
  const elementStartPosition = useRef({ x: box.x, y: box.y });
123
- const dragRef = useDraggable(createDragHandlers(box.id, elementStartPosition));
126
+ const handleRef = useRef<HTMLDivElement>(null);
127
+ useDraggable(createDragHandlers(box.id, elementStartPosition, handleRef));
124
128
  return (
125
129
  <Box
126
130
  key={box.id}
127
- ref={dragRef as React.RefObject<HTMLDivElement>}
131
+ ref={handleRef}
128
132
  style={{
129
133
  width: '90px',
130
134
  height: '100px',
@@ -155,8 +159,9 @@ export const CustomDragHandle = {
155
159
  const [position, setPosition] = useState({ x: args.startX, y: args.startY });
156
160
  const [isDragging, setIsDragging] = useState(false);
157
161
  const elementStartPosition = useRef({ x: args.startX, y: args.startY });
158
-
159
- const dragRef = useDraggable({
162
+ const handleRef = useRef<HTMLDivElement>(null);
163
+ useDraggable({
164
+ handles: handleRef,
160
165
  startDragCallback: () => {
161
166
  setIsDragging(true);
162
167
  elementStartPosition.current = { x: position.x, y: position.y };
@@ -189,7 +194,7 @@ export const CustomDragHandle = {
189
194
  }}
190
195
  >
191
196
  <Box
192
- ref={dragRef as React.RefObject<HTMLDivElement>}
197
+ ref={handleRef}
193
198
  style={{
194
199
  height: '30px',
195
200
  backgroundColor: '#2196F3',
@@ -0,0 +1,24 @@
1
+ import { createContext, useContext } from 'react';
2
+ import type { DragContainer } from './types.js';
3
+
4
+ const defaultValue: DragContainer = {
5
+ registerHandle: () => {},
6
+ unregisterHandle: () => {},
7
+ isDragging: false,
8
+ position: { x: 0, y: 0 },
9
+ };
10
+
11
+ export const DragContainerContext = createContext<DragContainer>(defaultValue);
12
+
13
+ export function useDragContainer(): DragContainer {
14
+ const context = useContext(DragContainerContext);
15
+
16
+ if (context === defaultValue) {
17
+ // biome-ignore lint/suspicious/noConsole: Let devs know if they're not using the context correctly
18
+ console.warn(
19
+ 'useDragContainer: No DragContainerContext found. Handles may will not register or trigger drag events.'
20
+ );
21
+ }
22
+
23
+ return context;
24
+ }
@@ -0,0 +1,8 @@
1
+ .draggable {
2
+ position: relative;
3
+ }
4
+
5
+ .draggable[data-is-draggable="true"] {
6
+ left: var(--position-x);
7
+ top: var(--position-y);
8
+ }