@dillingerstaffing/strand-ui 0.6.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 (32) hide show
  1. package/HTML_REFERENCE.md +64 -1
  2. package/README.md +1 -1
  3. package/dist/components/InstrumentViewport/InstrumentViewport.d.ts +10 -0
  4. package/dist/components/InstrumentViewport/InstrumentViewport.d.ts.map +1 -0
  5. package/dist/components/InstrumentViewport/index.d.ts +3 -0
  6. package/dist/components/InstrumentViewport/index.d.ts.map +1 -0
  7. package/dist/components/ScrollReveal/ScrollReveal.d.ts +12 -0
  8. package/dist/components/ScrollReveal/ScrollReveal.d.ts.map +1 -0
  9. package/dist/components/ScrollReveal/index.d.ts +3 -0
  10. package/dist/components/ScrollReveal/index.d.ts.map +1 -0
  11. package/dist/css/strand-ui.css +96 -16
  12. package/dist/index.d.ts +4 -0
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +568 -527
  15. package/package.json +2 -2
  16. package/src/__tests__/build-output.test.ts +1 -0
  17. package/src/components/Avatar/Avatar.css +2 -2
  18. package/src/components/Button/Button.css +4 -4
  19. package/src/components/Checkbox/Checkbox.css +3 -2
  20. package/src/components/InstrumentViewport/InstrumentViewport.css +36 -0
  21. package/src/components/InstrumentViewport/InstrumentViewport.test.tsx +70 -0
  22. package/src/components/InstrumentViewport/InstrumentViewport.tsx +31 -0
  23. package/src/components/InstrumentViewport/index.ts +2 -0
  24. package/src/components/Nav/Nav.css +2 -2
  25. package/src/components/Radio/Radio.css +3 -2
  26. package/src/components/ScrollReveal/ScrollReveal.css +29 -0
  27. package/src/components/ScrollReveal/ScrollReveal.test.tsx +68 -0
  28. package/src/components/ScrollReveal/ScrollReveal.tsx +64 -0
  29. package/src/components/ScrollReveal/index.ts +2 -0
  30. package/src/components/Slider/Slider.css +10 -4
  31. package/src/components/Switch/Switch.css +1 -0
  32. package/src/index.ts +8 -0
package/HTML_REFERENCE.md CHANGED
@@ -6,6 +6,10 @@
6
6
 
7
7
  > **Before writing any Strand HTML**, read [DESIGN_LANGUAGE.md Part II: Named Principles (L57-L193)](./DESIGN_LANGUAGE.md#L57). These 10 principles are hard constraints, not guidelines. Violating them produces valid HTML that looks wrong.
8
8
 
9
+ > **Principle 1 (Cognitive Economy):** Every element must earn its place. Test: remove an element. If the task still works, it was decoration. If you're not adding back 10% of what you delete, you're not deleting enough. See [DL L61-69](./DESIGN_LANGUAGE.md#L61).
10
+
11
+ > **Principle 2 (Biosynthetic Restraint):** Max 12 distinct visual elements per screen. See [DL L71-79](./DESIGN_LANGUAGE.md#L71).
12
+
9
13
  ## Required CSS
10
14
 
11
15
  **CDN (no install):**
@@ -24,6 +28,8 @@
24
28
  <link rel="stylesheet" href="node_modules/@dillingerstaffing/strand-ui/dist/css/strand-ui.css">
25
29
  ```
26
30
 
31
+ > **Principle 7 (Grain of Precision):** Include reset.css and base.css for the laboratory surface texture (dot grid, LED glow, grain). Without these, the page is a blank canvas, not a lab. See [DL L141-147](./DESIGN_LANGUAGE.md#L141).
32
+
27
33
  > **Token roles:** Don't guess which token to use. See [DESIGN_LANGUAGE.md 3.8: Color Roles (L290-L311)](./DESIGN_LANGUAGE.md#L290) for which color in which context, and [Appendix B: Token Quick Reference (L1372-L1431)](./DESIGN_LANGUAGE.md#L1372) for the full lookup table.
28
34
 
29
35
  ## Presentation Mode
@@ -75,6 +81,10 @@ All container components (Grid, Stack, Card, Container) enforce boundary integri
75
81
 
76
82
  ## Input Components
77
83
 
84
+ > **Principle 10 (Instrument Principle):** Forms are specimen collection instruments. Labels use monospace uppercase tracking. The form should feel like filling out a specimen record, not a generic web form. See [DL L171-192](./DESIGN_LANGUAGE.md#L171).
85
+
86
+ > **Microcopy voice:** Use instrument language. "Processing..." not "Loading...". "Format unrecognized" not "Invalid input". See [DL L1034-1049](./DESIGN_LANGUAGE.md#L1034).
87
+
78
88
  > **Interaction states for all inputs** (hover, focus, pressed, disabled, loading): [DESIGN_LANGUAGE.md Part XII: Interaction State System (L1013-L1067)](./DESIGN_LANGUAGE.md#L1013).
79
89
 
80
90
  ### Button
@@ -451,7 +461,9 @@ All container components (Grid, Stack, Card, Container) enforce boundary integri
451
461
  **Gap:** `strand-grid--gap-1` through `strand-grid--gap-8`
452
462
  **Note:** For column counts beyond 4, use inline style: `style="grid-template-columns: repeat(6, 1fr); gap: var(--strand-space-4);"`.
453
463
 
454
- > **Composability:** Before nesting grids inside cards inside previews, check content width. See [DESIGN_LANGUAGE.md 10.5: Composability Constraint (L873-L877)](./DESIGN_LANGUAGE.md#L873).
464
+ > **Principle 6 (Compound Silence):** Gap between siblings must exceed padding within components. If card padding is md (24px), card-to-card gap must be at least 32px. See [DL L127-140](./DESIGN_LANGUAGE.md#L127).
465
+
466
+ > **Composability (DL 10.5):** Before nesting more than 2 padded containers, calculate remaining content width at narrowest viewport. See [DL L873-877](./DESIGN_LANGUAGE.md#L873).
455
467
 
456
468
  ---
457
469
 
@@ -615,6 +627,8 @@ All container components (Grid, Stack, Card, Container) enforce boundary integri
615
627
 
616
628
  ## Feedback Components
617
629
 
630
+ > **Microcopy voice:** Alerts are diagnostic events. Use "Process interrupted" not "Something went wrong". Use "Retry sequence" not "Please try again". See [DL L1034-1049](./DESIGN_LANGUAGE.md#L1034).
631
+
618
632
  ### Toast
619
633
 
620
634
  ```html
@@ -634,6 +648,7 @@ All container components (Grid, Stack, Card, Container) enforce boundary integri
634
648
  </div>
635
649
  ```
636
650
 
651
+ **Status prefix:** Include `<span class="strand-toast__status">LABEL</span>` before the message. Labels: `INFO`, `COMPLETE` (success), `WARNING`, `ERROR`.
637
652
  **Note:** Container is fixed to bottom-right. Use `aria-live="assertive"` for `warning` and `error`.
638
653
 
639
654
  ---
@@ -648,6 +663,7 @@ All container components (Grid, Stack, Card, Container) enforce boundary integri
648
663
  ```
649
664
 
650
665
  **Statuses:** `strand-alert--info` | `strand-alert--success` | `strand-alert--warning` | `strand-alert--error`
666
+ **Status prefix:** Include `<span class="strand-alert__status">LABEL</span>` before the content div. Labels: `INFO`, `COMPLETE` (success), `WARNING`, `ERROR`.
651
667
  **Dismissible:** Add `<button type="button" class="strand-alert__dismiss" aria-label="Dismiss">&times;</button>` after content.
652
668
  **Note:** Use `role="alert"` for `warning` and `error`, `role="status"` for `info` and `success`.
653
669
 
@@ -771,3 +787,50 @@ All container components (Grid, Stack, Card, Container) enforce boundary integri
771
787
  **Note:** Always include `aria-hidden="true"`. Skeletons are placeholder visuals, not interactive.
772
788
 
773
789
  > **Animation:** Shimmer is 1.8s cycle. All animations respect `prefers-reduced-motion`. See [DESIGN_LANGUAGE.md 6.7: Reduced Motion (L656-L669)](./DESIGN_LANGUAGE.md#L656).
790
+
791
+ ---
792
+
793
+ ## InstrumentViewport
794
+
795
+ ```html
796
+ <div class="strand-instrument-viewport">
797
+ <!-- Dark data-dense content -->
798
+ </div>
799
+
800
+ <!-- With grid overlay -->
801
+ <div class="strand-instrument-viewport strand-instrument-viewport--grid">
802
+ <!-- Dark content with grid lines -->
803
+ </div>
804
+ ```
805
+
806
+ > **Dual-surface principle:** The white lab frame contains dark instrument viewports for data-dense contexts (maps, charts, terminal displays). The viewport is recessed INTO the lab, not floating above it. See [DL L795-814](./DESIGN_LANGUAGE.md#L795).
807
+
808
+ > **Decision framework:** Use dark viewport for data-dense displays. Use clean white for dashboards. Use lab surface for content pages. See [DL L816-825](./DESIGN_LANGUAGE.md#L816).
809
+
810
+ ---
811
+
812
+ ## ScrollReveal
813
+
814
+ ```html
815
+ <div class="strand-reveal">Fades up on scroll</div>
816
+
817
+ <div class="strand-reveal-group">
818
+ <div class="strand-reveal">Staggers 0ms</div>
819
+ <div class="strand-reveal">Staggers 80ms</div>
820
+ <div class="strand-reveal">Staggers 160ms</div>
821
+ </div>
822
+ ```
823
+
824
+ > **Scientific reveal:** Scroll-triggered entrance. 24px translate, trigger once. Stagger 80ms between siblings. See [DL L538-563](./DESIGN_LANGUAGE.md#L538).
825
+
826
+ ---
827
+
828
+ ## Accessibility and Motion
829
+
830
+ > **Accessibility checklist:** Exactly one h1 per page. Heading hierarchy (no skipping levels). All form inputs have visible labels. ARIA labels on non-text controls. ARIA live regions on dynamic content. Landmark regions (nav, main, footer). See [DL L1206-1213](./DESIGN_LANGUAGE.md#L1206).
831
+
832
+ > **Touch targets:** All interactive elements must be at least 44x44px. See [DL L1215-1217](./DESIGN_LANGUAGE.md#L1215).
833
+
834
+ > **Keyboard navigation:** Tab/Shift+Tab reaches all interactive elements. Arrow keys navigate within Tabs and menus (requires JavaScript). Escape closes overlays. Enter/Space activates buttons. Dialog must trap focus. See [DL L1197-1204](./DESIGN_LANGUAGE.md#L1197).
835
+
836
+ > **Motion anti-patterns (never do):** Never re-animate on viewport exit/re-enter. Never hijack scroll. Never animate width/height/margin/padding (use transform). Never use bounce/elastic easing. Never animate more than 3-4 elements simultaneously. Never use parallax on text. See [DL L671-680](./DESIGN_LANGUAGE.md#L671).
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @dillingerstaffing/strand-ui
2
2
 
3
- Preact/React component library built on the [Strand Design Language](https://github.com/dillingerstaffing/strand/blob/main/DESIGN_LANGUAGE.md). 32 components. Zero-runtime CSS. WCAG 2.2 AA.
3
+ Preact/React component library built on the [Strand Design Language](https://github.com/dillingerstaffing/strand/blob/main/DESIGN_LANGUAGE.md). 34 components. Zero-runtime CSS. WCAG 2.2 AA.
4
4
 
5
5
  ## Install
6
6
 
@@ -0,0 +1,10 @@
1
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2
+ import type { JSX } from "preact";
3
+ export interface InstrumentViewportProps extends JSX.HTMLAttributes<HTMLDivElement> {
4
+ /** Show subtle grid overlay */
5
+ grid?: boolean;
6
+ }
7
+ export declare const InstrumentViewport: import("preact").FunctionalComponent<import("preact/compat").PropsWithoutRef<InstrumentViewportProps> & {
8
+ ref?: import("preact").Ref<HTMLDivElement> | undefined;
9
+ }>;
10
+ //# sourceMappingURL=InstrumentViewport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InstrumentViewport.d.ts","sourceRoot":"","sources":["../../../src/components/InstrumentViewport/InstrumentViewport.tsx"],"names":[],"mappings":"AAAA,sDAAsD;AAEtD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAGlC,MAAM,WAAW,uBACf,SAAQ,GAAG,CAAC,cAAc,CAAC,cAAc,CAAC;IAC1C,+BAA+B;IAC/B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,kBAAkB;;EAiB7B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { InstrumentViewport } from "./InstrumentViewport.js";
2
+ export type { InstrumentViewportProps } from "./InstrumentViewport.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/InstrumentViewport/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,12 @@
1
+ /*! Strand UI | MIT License | dillingerstaffing.com */
2
+ import type { JSX } from "preact";
3
+ export interface ScrollRevealProps extends JSX.HTMLAttributes<HTMLDivElement> {
4
+ /** IntersectionObserver visibility threshold (0-1) */
5
+ threshold?: number;
6
+ /** Only trigger reveal once */
7
+ once?: boolean;
8
+ }
9
+ export declare const ScrollReveal: import("preact").FunctionalComponent<import("preact/compat").PropsWithoutRef<ScrollRevealProps> & {
10
+ ref?: import("preact").Ref<HTMLDivElement> | undefined;
11
+ }>;
12
+ //# sourceMappingURL=ScrollReveal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScrollReveal.d.ts","sourceRoot":"","sources":["../../../src/components/ScrollReveal/ScrollReveal.tsx"],"names":[],"mappings":"AAAA,sDAAsD;AAEtD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAIlC,MAAM,WAAW,iBACf,SAAQ,GAAG,CAAC,cAAc,CAAC,cAAc,CAAC;IAC1C,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+BAA+B;IAC/B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,YAAY;;EA+CxB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { ScrollReveal } from "./ScrollReveal.js";
2
+ export type { ScrollRevealProps } from "./ScrollReveal.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ScrollReveal/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -141,8 +141,8 @@
141
141
  }
142
142
 
143
143
  .strand-avatar--xl {
144
- width: 64px;
145
- height: 64px;
144
+ width: var(--strand-space-16);
145
+ height: var(--strand-space-16);
146
146
  font-size: var(--strand-text-lg);
147
147
  }
148
148
 
@@ -315,13 +315,13 @@
315
315
  .strand-btn--sm {
316
316
  padding: var(--strand-space-1) var(--strand-space-3);
317
317
  font-size: var(--strand-text-sm);
318
- min-height: 32px;
318
+ min-height: var(--strand-touch-target);
319
319
  }
320
320
 
321
321
  .strand-btn--md {
322
322
  padding: calc(var(--strand-space-2) + var(--strand-space-1) / 2) var(--strand-space-5);
323
323
  font-size: var(--strand-text-sm);
324
- min-height: 40px;
324
+ min-height: var(--strand-touch-target);
325
325
  }
326
326
 
327
327
  .strand-btn--lg {
@@ -333,12 +333,12 @@
333
333
  /* ── Icon-only ── */
334
334
  .strand-btn--icon-only.strand-btn--sm {
335
335
  padding: var(--strand-space-1);
336
- min-width: 32px;
336
+ min-width: var(--strand-touch-target);
337
337
  }
338
338
 
339
339
  .strand-btn--icon-only.strand-btn--md {
340
340
  padding: var(--strand-space-2);
341
- min-width: 40px;
341
+ min-width: var(--strand-touch-target);
342
342
  }
343
343
 
344
344
  .strand-btn--icon-only.strand-btn--lg {
@@ -552,6 +552,7 @@
552
552
  display: inline-flex;
553
553
  align-items: center;
554
554
  gap: var(--strand-space-2);
555
+ min-height: var(--strand-touch-target);
555
556
  cursor: pointer;
556
557
  user-select: none;
557
558
  font-family: var(--strand-font-sans);
@@ -578,8 +579,8 @@
578
579
  display: flex;
579
580
  align-items: center;
580
581
  justify-content: center;
581
- width: 18px;
582
- height: 18px;
582
+ width: var(--strand-control-size);
583
+ height: var(--strand-control-size);
583
584
  border: 1px solid var(--strand-gray-200);
584
585
  border-radius: var(--strand-radius-sm);
585
586
  background: var(--strand-surface-elevated);
@@ -1064,6 +1065,45 @@
1064
1065
  }
1065
1066
 
1066
1067
 
1068
+ /* InstrumentViewport */
1069
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1070
+
1071
+ .strand-instrument-viewport {
1072
+ background: var(--strand-blue-abyss);
1073
+ color: var(--strand-gray-100);
1074
+ border-radius: var(--strand-radius-lg);
1075
+ overflow: hidden;
1076
+ position: relative;
1077
+ }
1078
+
1079
+ .strand-instrument-viewport__label {
1080
+ color: var(--strand-gray-400);
1081
+ font-family: var(--strand-font-mono);
1082
+ font-size: var(--strand-text-xs);
1083
+ font-weight: var(--strand-weight-medium);
1084
+ letter-spacing: var(--strand-tracking-widest);
1085
+ text-transform: uppercase;
1086
+ }
1087
+
1088
+ .strand-instrument-viewport__value {
1089
+ color: var(--strand-on-blue-primary);
1090
+ font-family: var(--strand-font-mono);
1091
+ font-variant-numeric: tabular-nums;
1092
+ }
1093
+
1094
+ /* Optional grid overlay */
1095
+ .strand-instrument-viewport--grid::before {
1096
+ content: '';
1097
+ position: absolute;
1098
+ inset: 0;
1099
+ background:
1100
+ linear-gradient(rgba(59, 142, 246, 0.04) 1px, transparent 1px),
1101
+ linear-gradient(90deg, rgba(59, 142, 246, 0.04) 1px, transparent 1px);
1102
+ background-size: var(--strand-viewport-grid-size) var(--strand-viewport-grid-size);
1103
+ pointer-events: none;
1104
+ }
1105
+
1106
+
1067
1107
  /* Link */
1068
1108
  /*! Strand UI | MIT License | dillingerstaffing.com */
1069
1109
 
@@ -1104,7 +1144,7 @@
1104
1144
  .strand-nav {
1105
1145
  position: relative;
1106
1146
  width: 100%;
1107
- height: 64px;
1147
+ height: var(--strand-nav-height);
1108
1148
  background: var(--strand-surface-elevated);
1109
1149
  border-bottom: 1px solid var(--strand-gray-200);
1110
1150
  font-family: var(--strand-font-sans);
@@ -1265,7 +1305,7 @@
1265
1305
 
1266
1306
  .strand-nav {
1267
1307
  height: auto;
1268
- min-height: 64px;
1308
+ min-height: var(--strand-nav-height);
1269
1309
  }
1270
1310
  }
1271
1311
 
@@ -1383,6 +1423,7 @@
1383
1423
  display: inline-flex;
1384
1424
  align-items: center;
1385
1425
  gap: var(--strand-space-2);
1426
+ min-height: var(--strand-touch-target);
1386
1427
  cursor: pointer;
1387
1428
  user-select: none;
1388
1429
  font-family: var(--strand-font-sans);
@@ -1409,8 +1450,8 @@
1409
1450
  display: flex;
1410
1451
  align-items: center;
1411
1452
  justify-content: center;
1412
- width: 18px;
1413
- height: 18px;
1453
+ width: var(--strand-control-size);
1454
+ height: var(--strand-control-size);
1414
1455
  border: 1px solid var(--strand-gray-200);
1415
1456
  border-radius: var(--strand-radius-full);
1416
1457
  background: var(--strand-surface-elevated);
@@ -1476,6 +1517,38 @@
1476
1517
  }
1477
1518
 
1478
1519
 
1520
+ /* ScrollReveal */
1521
+ /*! Strand UI | MIT License | dillingerstaffing.com */
1522
+
1523
+ .strand-reveal {
1524
+ opacity: 0;
1525
+ transform: translateY(24px);
1526
+ transition: opacity var(--strand-duration-glacial) var(--strand-ease-out-expo),
1527
+ transform var(--strand-duration-glacial) var(--strand-ease-out-expo);
1528
+ }
1529
+
1530
+ .strand-reveal--visible {
1531
+ opacity: 1;
1532
+ transform: translateY(0);
1533
+ }
1534
+
1535
+ /* Stagger children */
1536
+ .strand-reveal-group > .strand-reveal:nth-child(1) { transition-delay: 0ms; }
1537
+ .strand-reveal-group > .strand-reveal:nth-child(2) { transition-delay: var(--strand-stagger-delay); }
1538
+ .strand-reveal-group > .strand-reveal:nth-child(3) { transition-delay: calc(var(--strand-stagger-delay) * 2); }
1539
+ .strand-reveal-group > .strand-reveal:nth-child(4) { transition-delay: calc(var(--strand-stagger-delay) * 3); }
1540
+ .strand-reveal-group > .strand-reveal:nth-child(5) { transition-delay: calc(var(--strand-stagger-delay) * 4); }
1541
+ .strand-reveal-group > .strand-reveal:nth-child(6) { transition-delay: var(--strand-duration-slow); }
1542
+
1543
+ @media (prefers-reduced-motion: reduce) {
1544
+ .strand-reveal {
1545
+ opacity: 1;
1546
+ transform: none;
1547
+ transition: none;
1548
+ }
1549
+ }
1550
+
1551
+
1479
1552
  /* Section */
1480
1553
  /*! Strand UI | MIT License | dillingerstaffing.com */
1481
1554
 
@@ -1663,14 +1736,15 @@
1663
1736
  transition: background var(--strand-duration-fast) var(--strand-ease-out-quart);
1664
1737
  }
1665
1738
 
1666
- /* ── Thumb: Webkit ── */
1739
+ /* ── Thumb: Webkit (44px touch target, 20px visual) ── */
1667
1740
  .strand-slider__field::-webkit-slider-thumb {
1668
1741
  appearance: none;
1669
1742
  width: 20px;
1670
1743
  height: 20px;
1671
1744
  background: var(--strand-blue-primary);
1672
- border: 2px solid var(--strand-surface-elevated);
1745
+ border: 12px solid transparent;
1673
1746
  border-radius: var(--strand-radius-full);
1747
+ background-clip: padding-box;
1674
1748
  cursor: pointer;
1675
1749
  box-shadow: var(--strand-elevation-1);
1676
1750
  transition:
@@ -1680,21 +1754,24 @@
1680
1754
 
1681
1755
  .strand-slider__field:hover:not(:disabled)::-webkit-slider-thumb {
1682
1756
  background: var(--strand-blue-vivid);
1757
+ background-clip: padding-box;
1683
1758
  transform: scale(1.15);
1684
1759
  }
1685
1760
 
1686
1761
  .strand-slider__field:active:not(:disabled)::-webkit-slider-thumb {
1687
1762
  background: var(--strand-blue-deep);
1763
+ background-clip: padding-box;
1688
1764
  transform: scale(1.05);
1689
1765
  }
1690
1766
 
1691
- /* ── Thumb: Firefox ── */
1767
+ /* ── Thumb: Firefox (44px touch target, 20px visual) ── */
1692
1768
  .strand-slider__field::-moz-range-thumb {
1693
1769
  width: 20px;
1694
1770
  height: 20px;
1695
1771
  background: var(--strand-blue-primary);
1696
- border: 2px solid var(--strand-surface-elevated);
1772
+ border: 12px solid transparent;
1697
1773
  border-radius: var(--strand-radius-full);
1774
+ background-clip: padding-box;
1698
1775
  cursor: pointer;
1699
1776
  box-shadow: var(--strand-elevation-1);
1700
1777
  transition:
@@ -1704,11 +1781,13 @@
1704
1781
 
1705
1782
  .strand-slider__field:hover:not(:disabled)::-moz-range-thumb {
1706
1783
  background: var(--strand-blue-vivid);
1784
+ background-clip: padding-box;
1707
1785
  transform: scale(1.15);
1708
1786
  }
1709
1787
 
1710
1788
  .strand-slider__field:active:not(:disabled)::-moz-range-thumb {
1711
1789
  background: var(--strand-blue-deep);
1790
+ background-clip: padding-box;
1712
1791
  transform: scale(1.05);
1713
1792
  }
1714
1793
 
@@ -1896,6 +1975,7 @@
1896
1975
  display: inline-flex;
1897
1976
  align-items: center;
1898
1977
  gap: var(--strand-space-2);
1978
+ min-height: var(--strand-touch-target);
1899
1979
  cursor: pointer;
1900
1980
  user-select: none;
1901
1981
  font-family: var(--strand-font-sans);
package/dist/index.d.ts CHANGED
@@ -63,4 +63,8 @@ export { Spinner } from "./components/Spinner/index.js";
63
63
  export type { SpinnerProps } from "./components/Spinner/index.js";
64
64
  export { Skeleton } from "./components/Skeleton/index.js";
65
65
  export type { SkeletonProps } from "./components/Skeleton/index.js";
66
+ export { InstrumentViewport } from "./components/InstrumentViewport/index.js";
67
+ export type { InstrumentViewportProps } from "./components/InstrumentViewport/index.js";
68
+ export { ScrollReveal } from "./components/ScrollReveal/index.js";
69
+ export type { ScrollRevealProps } from "./components/ScrollReveal/index.js";
66
70
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}