@wtfalch/design 0.5.0 → 0.7.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 (49) hide show
  1. package/dist/components/Button.d.ts +19 -27
  2. package/dist/components/Button.js +61 -1
  3. package/dist/components/Callout.d.ts +0 -21
  4. package/dist/components/Callout.js +7 -0
  5. package/dist/components/Card.js +7 -0
  6. package/dist/components/Checkbox.d.ts +12 -23
  7. package/dist/components/Checkbox.js +25 -2
  8. package/dist/components/Command.js +10 -2
  9. package/dist/components/DangerZone.js +7 -0
  10. package/dist/components/Dialog.d.ts +0 -21
  11. package/dist/components/Dialog.js +7 -0
  12. package/dist/components/Field.d.ts +13 -31
  13. package/dist/components/Field.js +10 -1
  14. package/dist/components/Identity.d.ts +0 -25
  15. package/dist/components/Identity.js +7 -0
  16. package/dist/components/Input.js +7 -0
  17. package/dist/components/Kbd.d.ts +7 -0
  18. package/dist/components/Kbd.js +34 -0
  19. package/dist/components/Markdown.js +7 -0
  20. package/dist/components/Menu.js +10 -2
  21. package/dist/components/Modal.d.ts +0 -33
  22. package/dist/components/Modal.js +7 -0
  23. package/dist/components/Pagination.d.ts +0 -33
  24. package/dist/components/Pagination.js +7 -0
  25. package/dist/components/Popover.js +7 -0
  26. package/dist/components/Rows.js +7 -0
  27. package/dist/components/ScrollArea.js +7 -0
  28. package/dist/components/Select.d.ts +6 -1
  29. package/dist/components/Select.js +9 -2
  30. package/dist/components/SizeGrid.js +7 -0
  31. package/dist/components/Slider.js +7 -0
  32. package/dist/components/SplitPane.js +7 -0
  33. package/dist/components/Stat.d.ts +45 -0
  34. package/dist/components/Stat.js +31 -0
  35. package/dist/components/Tabs.d.ts +21 -0
  36. package/dist/components/Tabs.js +8 -1
  37. package/dist/components/Toast.d.ts +24 -18
  38. package/dist/components/Toast.js +44 -3
  39. package/dist/components/Toggle.d.ts +0 -30
  40. package/dist/components/Toggle.js +7 -0
  41. package/dist/components/Tooltip.js +7 -0
  42. package/dist/components/Tour.d.ts +0 -23
  43. package/dist/components/Tour.js +7 -0
  44. package/dist/index.d.ts +13 -2
  45. package/dist/index.js +9 -1
  46. package/dist/styles/index.css +117 -13
  47. package/dist/tf.css +117 -13
  48. package/dist/valet.css +117 -13
  49. package/package.json +2 -1
package/dist/valet.css CHANGED
@@ -367,7 +367,28 @@ body::before {
367
367
  where the flat grey reads as recessed rather than as something to use. It is
368
368
  derived rather than declared -- a new token would have to be added to every
369
369
  theme in `themes.ts`, and a theme that missed it would lose its controls. */
370
+ /* An anchor drawn as a button. Three things the element brings that a
371
+ `<button>` does not, and all three have to go: the underline, the link
372
+ colour, and the text alignment a block anchor inherits. `cursor: pointer`
373
+ it already has. Disabled is `aria-disabled` here -- an anchor ignores the
374
+ native attribute -- so every `:disabled` rule above has an
375
+ `[aria-disabled='true']` twin rather than a rewrite, which leaves each
376
+ `button` selector at the specificity it had and every committed baseline
377
+ untouched. */
378
+ a.btn {
379
+ text-decoration: none;
380
+ color: var(--text);
381
+ text-align: center;
382
+ }
383
+
384
+ a.btn[aria-disabled='true'] {
385
+ /* A disabled anchor still takes the pointer, so say so. The click itself is
386
+ blocked in the capture phase by the component. */
387
+ cursor: not-allowed;
388
+ }
389
+
370
390
  button,
391
+ a.btn,
371
392
  input,
372
393
  textarea,
373
394
  select {
@@ -391,7 +412,8 @@ select {
391
412
  the icon; the button simply had no opinion about how to arrange two things.
392
413
  `inline-flex` and a gap gives it one, and the gap replaces the space
393
414
  character people were putting between an icon and its label. */
394
- button {
415
+ button,
416
+ a.btn {
395
417
  display: inline-flex;
396
418
  align-items: center;
397
419
  justify-content: center;
@@ -417,7 +439,8 @@ button[aria-pressed='true']:hover:not(:disabled) { border-color: var(--accent);
417
439
 
418
440
  /* The glyph never shrinks: in a narrow row flexbox would take it from the icon
419
441
  before the text, and half an icon is not a smaller icon. */
420
- button > svg { flex: none; }
442
+ button > svg,
443
+ a.btn > svg { flex: none; }
421
444
 
422
445
  .size-sm { font-size: var(--text-xs); padding: var(--space-1) var(--space-2); }
423
446
 
@@ -443,6 +466,7 @@ input, textarea, select { width: 100%; }
443
466
  textarea { resize: none; }
444
467
 
445
468
  button:hover:not(:disabled),
469
+ a.btn:hover:not([aria-disabled='true']),
446
470
  input:hover:not(:disabled),
447
471
  textarea:hover:not(:disabled),
448
472
  select:hover:not(:disabled) { border-color: var(--accent); }
@@ -451,6 +475,7 @@ select:hover:not(:disabled) { border-color: var(--accent); }
451
475
  `:focus` on the fields because a focused field is a place you are typing and
452
476
  should say so however you got there. */
453
477
  button:focus-visible,
478
+ a.btn:focus-visible,
454
479
  input:focus,
455
480
  textarea:focus,
456
481
  select:focus { outline: none; border-color: var(--accent); }
@@ -544,11 +569,13 @@ input[type='checkbox']:disabled,
544
569
  input[type='radio']:disabled { cursor: not-allowed; background: var(--panel-2); }
545
570
 
546
571
  button:disabled,
572
+ a.btn[aria-disabled='true'],
547
573
  input:disabled,
548
574
  textarea:disabled,
549
575
  select:disabled { opacity: 0.45; cursor: not-allowed; }
550
576
 
551
- button.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
577
+ button.primary,
578
+ a.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
552
579
 
553
580
  /* A disabled primary is not a faded primary.
554
581
  `opacity: .45` was the whole of it, and a coloured fill at 45% is still a
@@ -556,7 +583,8 @@ button.primary { background: var(--accent); border-color: var(--accent); color:
556
583
  thing on the panel. That got worse when onboarding started holding people at
557
584
  a disabled Next. So it gives up the fill entirely and becomes the shape of a
558
585
  disabled control -- the opacity then has nothing left to do. */
559
- button.primary:disabled {
586
+ button.primary:disabled,
587
+ a.btn.primary[aria-disabled='true'] {
560
588
  background: var(--panel-2);
561
589
  border-color: var(--border);
562
590
  color: var(--muted);
@@ -626,13 +654,15 @@ button[aria-busy='true']::after {
626
654
 
627
655
  /* Quiet: no border, no fill. For the action beside the action -- Cancel next to
628
656
  Save -- where a bordered box competes with the thing it is next to. */
629
- button.ghost {
657
+ button.ghost,
658
+ a.btn.ghost {
630
659
  background: transparent;
631
660
  border-color: transparent;
632
661
  color: var(--muted);
633
662
  }
634
663
 
635
- button.ghost:hover:not(:disabled) {
664
+ button.ghost:hover:not(:disabled),
665
+ a.btn.ghost:hover:not([aria-disabled='true']) {
636
666
  background: var(--panel-2);
637
667
  border-color: transparent;
638
668
  color: var(--text);
@@ -839,19 +869,22 @@ button.ghost:hover:not(:disabled) {
839
869
  /* `:where(button)` so this carries no specificity of its own: a component's
840
870
  press rule below -- a card, a tab, a rail item, all of them buttons --
841
871
  wins by coming later, instead of every one having to restate `button`. */
842
- :where(button):active:not(:disabled) {
872
+ :where(button):active:not(:disabled),
873
+ :where(a.btn):active:not([aria-disabled='true']) {
843
874
  background: color-mix(in srgb, var(--text) var(--press-ink), var(--control));
844
875
  border-color: var(--accent);
845
876
  transform: scale(var(--press-scale));
846
877
  transition: none;
847
878
  }
848
879
 
849
- button.primary:active:not(:disabled) {
880
+ button.primary:active:not(:disabled),
881
+ a.btn.primary:active:not([aria-disabled='true']) {
850
882
  background: color-mix(in srgb, var(--text) var(--press-ink), var(--accent));
851
883
  border-color: color-mix(in srgb, var(--text) var(--press-ink), var(--accent));
852
884
  }
853
885
 
854
- button.ghost:active:not(:disabled) {
886
+ button.ghost:active:not(:disabled),
887
+ a.btn.ghost:active:not([aria-disabled='true']) {
855
888
  background: color-mix(in srgb, var(--text) var(--press-ink), var(--panel-2));
856
889
  border-color: transparent;
857
890
  }
@@ -1074,7 +1107,8 @@ input:active, textarea:active, select:active { transform: none; }
1074
1107
  /* Full width, for the one action a card or a step is about. Not a size: a
1075
1108
  `block` button is the same height as any other, it just stops being a thing
1076
1109
  you have to aim at. */
1077
- button.block { display: flex; width: 100%; }
1110
+ button.block,
1111
+ a.btn.block { display: flex; width: 100%; }
1078
1112
 
1079
1113
  /* The default is `size-md`, spelled once for every control.
1080
1114
  The paragraph above promised one scale for buttons, inputs and selects, and
@@ -1083,6 +1117,7 @@ button.block { display: flex; width: 100%; }
1083
1117
  could line up. The download modal's search box against its Search button was
1084
1118
  the version you could see from across the room. */
1085
1119
  button,
1120
+ a.btn,
1086
1121
  input,
1087
1122
  textarea,
1088
1123
  select,
@@ -1233,18 +1268,21 @@ select,
1233
1268
 
1234
1269
  /* ---- ./dangerzone.css ---- */
1235
1270
  /* Destructive, and legible as such standing still. */
1236
- button.danger {
1271
+ button.danger,
1272
+ a.btn.danger {
1237
1273
  color: var(--bad);
1238
1274
  border-color: color-mix(in srgb, var(--bad) 45%, var(--border-strong));
1239
1275
  }
1240
1276
 
1241
- button.danger:hover:not(:disabled) {
1277
+ button.danger:hover:not(:disabled),
1278
+ a.btn.danger:hover:not([aria-disabled='true']) {
1242
1279
  background: color-mix(in srgb, var(--bad) 12%, var(--panel));
1243
1280
  border-color: var(--bad);
1244
1281
  color: var(--bad);
1245
1282
  }
1246
1283
 
1247
- button.danger:active:not(:disabled) {
1284
+ button.danger:active:not(:disabled),
1285
+ a.btn.danger:active:not([aria-disabled='true']) {
1248
1286
  background: color-mix(in srgb, var(--bad) 20%, var(--panel));
1249
1287
  border-color: var(--bad);
1250
1288
  }
@@ -3421,6 +3459,72 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
3421
3459
  anchored surfaces (`.pop`, `.menu-sheet`, `.cmd`) sit over everything and a
3422
3460
  rule of equal specificity that came earlier would lose to whatever the
3423
3461
  sheets they cover happen to set. */
3462
+ /* ---- ./kbd.css ---- */
3463
+ /* One rule where there were two identical ones, in `menu.css` and
3464
+ `command.css`. Both keep their class as well, so `Menu` and `Command` are
3465
+ `.kbd .menu-key` and `.kbd .cmd-key` now: the declarations are the same, so
3466
+ nothing moves, and the context classes stay available for a rule that ever
3467
+ needs to tell the two apart. */
3468
+ .kbd {
3469
+ flex: none;
3470
+ font-family: var(--font-mono);
3471
+ font-size: var(--text-2xs);
3472
+ color: var(--muted);
3473
+ letter-spacing: var(--tracking);
3474
+ }
3475
+
3476
+ /* ---- ./stat.css ---- */
3477
+ /* A figure with furniture. `--space-1` between the three lines because they
3478
+ are one object read top to bottom, not three paragraphs. */
3479
+ .stat {
3480
+ display: grid;
3481
+ gap: var(--space-1);
3482
+ padding: var(--space-4);
3483
+ border: var(--border-width) solid var(--border);
3484
+ border-radius: var(--radius-md);
3485
+ background: var(--panel);
3486
+ }
3487
+
3488
+ /* Inside something already bordered. A bordered tile in a bordered row is two
3489
+ boxes saying one thing. */
3490
+ .stat-bare {
3491
+ padding: 0;
3492
+ border: 0;
3493
+ border-radius: 0;
3494
+ background: none;
3495
+ gap: 0;
3496
+ line-height: 1.25;
3497
+ }
3498
+
3499
+ .stat > p { margin: 0; }
3500
+
3501
+ .stat-label {
3502
+ color: var(--muted);
3503
+ font-size: var(--text-xs);
3504
+ }
3505
+
3506
+ /* Tabular figures are the point: a column of numbers is compared by its
3507
+ digits' positions, and proportional ones move them per row. */
3508
+ .stat-value {
3509
+ font-size: var(--text-lg);
3510
+ font-weight: var(--weight-strong);
3511
+ font-variant-numeric: tabular-nums;
3512
+ }
3513
+
3514
+ .stat-bare .stat-value { font-size: var(--text-sm); }
3515
+
3516
+ .stat-note {
3517
+ color: var(--muted);
3518
+ font-size: var(--text-xs);
3519
+ }
3520
+
3521
+ /* Only the figure takes the colour. Colouring the label too makes the tile a
3522
+ status box, and a tone here is a remark about the number. */
3523
+ .stat[data-tone='info'] .stat-value { color: var(--info); }
3524
+ .stat[data-tone='good'] .stat-value { color: var(--good); }
3525
+ .stat[data-tone='warn'] .stat-value { color: var(--warn); }
3526
+ .stat[data-tone='bad'] .stat-value { color: var(--bad); }
3527
+
3424
3528
  /* ---- ./scrollarea.css ---- */
3425
3529
  /* A box that scrolls, with its edges drawn.
3426
3530
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wtfalch/design",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "wtfalch's design system: themeable components on a fixed token vocabulary.",
5
5
  "keywords": [
6
6
  "design-system",
@@ -65,6 +65,7 @@
65
65
  "react-dom": "^19.0.0"
66
66
  },
67
67
  "dependencies": {
68
+ "@radix-ui/react-slot": "^1.3.3",
68
69
  "dompurify": "^3.4.13",
69
70
  "marked": "^18.0.9",
70
71
  "react-aria-components": "^1.21.0"