dowel-ui 0.26.1 → 0.28.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.
package/dist/theme.css CHANGED
@@ -618,6 +618,25 @@
618
618
  --tracking-caption: 0.085em;
619
619
  --tracking-tight: -0.01em;
620
620
 
621
+ /*
622
+ * A step between the steps.
623
+ *
624
+ * The spacing scale runs in fours - 2, 4, 6, 8 - and four different
625
+ * primitives independently reached past it for three pixels: the gap
626
+ * between segments of a rating and of an axis, the gap between cells of a
627
+ * heatmap, and how far a tooltip's arrow tucks under its popup. Four hands
628
+ * arriving at the same number is not four accidents; it is a step the scale
629
+ * was missing, and each of them wrote `[3px]` because there was nothing to
630
+ * name.
631
+ *
632
+ * It exists for hairline gaps between things that are themselves small -
633
+ * where two pixels reads as touching and four as separate objects. Nothing
634
+ * larger belongs here: this is the bottom of the scale, not a licence to
635
+ * measure by eye.
636
+ */
637
+ --spacing-hair: 3px;
638
+
639
+ /*
621
640
  /* Easing. `out` for anything the user asked for - it arrives fast and
622
641
  * settles, which reads as responsive. `in-out` for something moving on its
623
642
  * own. `in` is deliberately absent: it starts slowly, which on a control
@@ -633,6 +652,148 @@
633
652
  --shadow-lift: var(--shadow-lift);
634
653
  --shadow-raise: var(--shadow-raise);
635
654
  --shadow-float: var(--shadow-float);
655
+
656
+ /*
657
+ * The smallest a pointer target may be.
658
+ *
659
+ * 24 CSS pixels, which is WCAG 2.2's 2.5.8 at AA. Not a matter of taste, and
660
+ * measured rather than assumed: a live run of the stand found four different
661
+ * answers to the same question in one set - a chip's cross at 16, Copyable
662
+ * at 19, CopyButton at 21, a search field's clear at 24. Three of the four
663
+ * fail, and the failure is silent. A cross missed by a thumb on a tablet, or
664
+ * by anyone whose hand is not steady, does not delete the tag and does not
665
+ * say anything either.
666
+ *
667
+ * It is a size token rather than a spacing step because it is a floor, not a
668
+ * rhythm: nothing is ever `--target-min` tall on purpose, things are at
669
+ * least that big. `size-target` and `min-size-target` come free from the
670
+ * namespace, but the way a primitive usually reaches it is `target-min`
671
+ * below, which grows the hit area without growing the glyph.
672
+ */
673
+ --size-target: 24px;
674
+ }
675
+
676
+ /*
677
+ * `target-min` - visually smaller, clickably larger.
678
+ *
679
+ * The obvious fix for a 16px cross is to make it 24px, and it is the wrong
680
+ * one: a chip is a small thing by design and a cross a third of its height
681
+ * reads as a button with a chip around it. The set's appearance is a
682
+ * decision, and an accessibility floor should not overturn it.
683
+ *
684
+ * So the target grows and the glyph does not. The pseudo-element is centred on
685
+ * the control, takes its size, and refuses to go under the floor - so a
686
+ * control already large enough is untouched, and a smaller one gains an
687
+ * invisible margin of hit area on every side.
688
+ *
689
+ * `position: relative` comes with it rather than being left to the caller: a
690
+ * target that silently does nothing because its parent forgot to establish a
691
+ * containing block is exactly the failure this exists to prevent.
692
+ *
693
+ * Not `padding`, which was the other candidate: padding moves the glyph inside
694
+ * its box and changes how the control sits in a flex row, so every call site
695
+ * would need a compensating negative margin. This changes nothing about
696
+ * layout.
697
+ */
698
+ @utility target-min {
699
+ position: relative;
700
+
701
+ &::after {
702
+ content: '';
703
+ position: absolute;
704
+ top: 50%;
705
+ left: 50%;
706
+ translate: -50% -50%;
707
+ width: 100%;
708
+ height: 100%;
709
+ min-width: var(--size-target);
710
+ min-height: var(--size-target);
711
+ }
712
+ }
713
+
714
+ /*
715
+ * How tall a control is, and how much room a screen gives each row.
716
+ *
717
+ * `h-9` appeared in nine primitives - every field the set has - each spelling
718
+ * it out, which is why `Input` could not be made compact without editing
719
+ * `Input`. One decision made nine times gets one name.
720
+ *
721
+ * **Not in `@theme`, and that is the whole mechanism.** A token declared there
722
+ * is inlined by the compiler: `h-control` came out as `height: 36px`, the
723
+ * override on a container had nothing to bind to, and the density attribute
724
+ * did exactly nothing. Measured in the browser rather than assumed - the
725
+ * container's `--row-control` read 32px while the field it contained stayed
726
+ * 36. Tailwind also writes a fallback for any `var()` it recognises from the
727
+ * theme, so the name has to live outside the theme's namespaces entirely.
728
+ *
729
+ * Declared here as plain custom properties and turned into utilities by hand
730
+ * below, the reference survives, and an override on an ancestor reaches every
731
+ * control under it - which is what makes density a property of a region
732
+ * rather than of a component.
733
+ */
734
+ :root {
735
+ --row-control: 36px;
736
+ --row-control-sm: 32px;
737
+ --row-control-lg: 40px;
738
+
739
+ /* The same question for a table, whose rows are sized by what is above and
740
+ * below the text rather than by a height. `Table` had its own `density`
741
+ * prop for this, with its own words - `base` and `dense` - which meant the
742
+ * set used one word for two mechanisms and a product had to set both. */
743
+ --row-cell: 10px;
744
+ }
745
+
746
+ @utility h-control {
747
+ height: var(--row-control);
748
+ }
749
+
750
+ @utility py-row {
751
+ padding-block: var(--row-cell);
752
+ }
753
+
754
+ @utility h-control-sm {
755
+ height: var(--row-control-sm);
756
+ }
757
+
758
+ @utility h-control-lg {
759
+ height: var(--row-control-lg);
760
+ }
761
+
762
+ /*
763
+ * Density.
764
+ *
765
+ * Two answers to one question, and the set had neither: a product wanting a
766
+ * tighter table wrote `h-8` at every call site, which is the drift the scale
767
+ * exists to stop, one screen at a time.
768
+ *
769
+ * **It is an attribute on a container, not a prop on a component.** A prop
770
+ * would have to be added to every primitive, threaded through every wrapper a
771
+ * product writes, and passed by hand at each call site - and a primitive
772
+ * written next year would not have it. An attribute is inherited:
773
+ *
774
+ * <form data-density="compact"> …every field inside it…
775
+ *
776
+ * That reaches components which did not exist when the product was built, and
777
+ * a product's own components too, as long as they measure in `h-control` like
778
+ * everything else.
779
+ *
780
+ * The floor does not move with it. `--size-target` stays 24px at every
781
+ * density, because WCAG does not care how tight a table is - which is exactly
782
+ * why `target-min` grows the hit area rather than the control: a compact row
783
+ * is still one a hand can hit.
784
+ */
785
+ [data-density='compact'] {
786
+ --row-control: 32px;
787
+ --row-control-sm: 28px;
788
+ --row-control-lg: 36px;
789
+ --row-cell: 6px;
790
+ }
791
+
792
+ [data-density='comfortable'] {
793
+ --row-control: 40px;
794
+ --row-control-sm: 36px;
795
+ --row-control-lg: 44px;
796
+ --row-cell: 14px;
636
797
  }
637
798
 
638
799
  /*
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dowel-ui",
3
- "version": "0.26.1",
3
+ "version": "0.28.0",
4
4
  "description": "The lacodda line design system: theme tokens and React primitives, distributed as a shadcn-compatible registry.",
5
5
  "license": "MIT",
6
6
  "type": "module",