@kwtv/components 0.3.0 → 0.5.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/README.md +35 -0
  2. package/package.json +2 -2
  3. package/src/astro/Accordion.astro +10 -6
  4. package/src/astro/AccordionItem.astro +47 -43
  5. package/src/astro/ActiveFilterTags.astro +29 -25
  6. package/src/astro/Alert.astro +46 -41
  7. package/src/astro/Badge.astro +80 -76
  8. package/src/astro/Band.astro +104 -58
  9. package/src/astro/Breadcrumb.astro +33 -29
  10. package/src/astro/Button.astro +132 -128
  11. package/src/astro/Card.astro +64 -60
  12. package/src/astro/CartLine.astro +59 -55
  13. package/src/astro/Checkbox.astro +37 -32
  14. package/src/astro/Chip.astro +68 -64
  15. package/src/astro/DotGrid.astro +50 -46
  16. package/src/astro/EmptyState.astro +26 -22
  17. package/src/astro/FilterGroup.astro +29 -25
  18. package/src/astro/Filters.astro +50 -46
  19. package/src/astro/Footer.astro +179 -175
  20. package/src/astro/FooterColumn.astro +39 -35
  21. package/src/astro/Header.astro +67 -63
  22. package/src/astro/Icon.astro +1 -1
  23. package/src/astro/IconButton.astro +64 -60
  24. package/src/astro/Marquee.astro +33 -29
  25. package/src/astro/NavDropdown.astro +120 -116
  26. package/src/astro/NavLink.astro +59 -55
  27. package/src/astro/Newsletter.astro +58 -54
  28. package/src/astro/Pager.astro +43 -39
  29. package/src/astro/PickCard.astro +72 -68
  30. package/src/astro/ProductCard.astro +120 -116
  31. package/src/astro/Radio.astro +36 -32
  32. package/src/astro/Skeleton.astro +43 -39
  33. package/src/astro/Social.astro +26 -22
  34. package/src/astro/StepIndicator.astro +55 -51
  35. package/src/astro/Sticker.astro +50 -46
  36. package/src/astro/Swatch.astro +44 -40
  37. package/src/astro/Table.astro +58 -54
  38. package/src/astro/TableCard.astro +39 -35
  39. package/src/astro/TextField.astro +92 -88
  40. package/src/astro/Totals.astro +39 -35
  41. package/src/react/Drawer.css +60 -56
  42. package/src/react/Modal.css +97 -93
  43. package/src/react/NewsCarousel.css +108 -104
  44. package/src/react/QuantityStepper.css +84 -80
  45. package/src/react/Select.css +159 -155
  46. package/src/react/Toast.css +128 -124
  47. package/src/styles/base.css +30 -26
  48. package/src/styles/controls.css +183 -179
  49. package/src/styles/motion.css +203 -199
@@ -1,140 +1,144 @@
1
1
  /* Toast. All values from the design-system tokens. */
2
2
 
3
- .ui-toast-region {
4
- position: fixed;
5
- z-index: var(--z-toast);
6
- display: flex;
7
- flex-direction: column;
8
- gap: var(--space-2);
9
- padding: var(--space-4);
10
- /* Shrink-wrap to the toasts instead of covering a whole corner, so the empty
11
- area never overlays or blocks clicks on the page behind it. */
12
- width: max-content;
13
- max-width: 100vw;
14
- }
3
+ @layer reset, tokens, base, components, motion, utilities;
15
4
 
16
- .ui-toast-region--bottom-right {
17
- right: 0;
18
- bottom: 0;
19
- align-items: flex-end;
20
- }
5
+ @layer components {
6
+ .ui-toast-region {
7
+ position: fixed;
8
+ z-index: var(--z-toast);
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: var(--space-2);
12
+ padding: var(--space-4);
13
+ /* Shrink-wrap to the toasts instead of covering a whole corner, so the empty
14
+ area never overlays or blocks clicks on the page behind it. */
15
+ width: max-content;
16
+ max-width: 100vw;
17
+ }
21
18
 
22
- .ui-toast-region--bottom-center {
23
- left: 50%;
24
- bottom: 0;
25
- transform: translateX(-50%);
26
- align-items: center;
27
- }
19
+ .ui-toast-region--bottom-right {
20
+ right: 0;
21
+ bottom: 0;
22
+ align-items: flex-end;
23
+ }
28
24
 
29
- /* A light card lifted off the page by its shadow. Dark text keeps every word
30
- at full contrast; the tone shows in a coloured icon, not the surface. */
31
- .ui-toast {
32
- display: flex;
33
- align-items: flex-start;
34
- gap: var(--space-3);
35
- width: 100%;
36
- max-width: 380px;
37
- padding: var(--space-4);
38
- /* ivory-light, not ivory-base: ivory-base (#C9C2B1) is dark enough that the
39
- undo link drops to 3.79 on it, the very contrast problem this redesign
40
- fixes. ivory-light keeps a warm card distinct from the page and clears AA
41
- for the link (5.65) and everything on it. */
42
- background: var(--surface-hover);
43
- border: 1px solid var(--border);
44
- border-radius: var(--radius-lg);
45
- box-shadow: var(--shadow-xl);
46
- font-size: var(--text-sm);
47
- line-height: var(--leading-sm);
48
- color: var(--text);
49
- pointer-events: auto;
50
- animation: ui-toast-in var(--duration-base) var(--ease-enter);
51
- }
25
+ .ui-toast-region--bottom-center {
26
+ left: 50%;
27
+ bottom: 0;
28
+ transform: translateX(-50%);
29
+ align-items: center;
30
+ }
52
31
 
53
- .ui-toast__icon {
54
- display: inline-flex;
55
- flex: none;
56
- margin-top: 1px;
57
- }
32
+ /* A light card lifted off the page by its shadow. Dark text keeps every word
33
+ at full contrast; the tone shows in a coloured icon, not the surface. */
34
+ .ui-toast {
35
+ display: flex;
36
+ align-items: flex-start;
37
+ gap: var(--space-3);
38
+ width: 100%;
39
+ max-width: 380px;
40
+ padding: var(--space-4);
41
+ /* ivory-light, not ivory-base: ivory-base (#C9C2B1) is dark enough that the
42
+ undo link drops to 3.79 on it, the very contrast problem this redesign
43
+ fixes. ivory-light keeps a warm card distinct from the page and clears AA
44
+ for the link (5.65) and everything on it. */
45
+ background: var(--surface-hover);
46
+ border: 1px solid var(--border);
47
+ border-radius: var(--radius-lg);
48
+ box-shadow: var(--shadow-xl);
49
+ font-size: var(--text-sm);
50
+ line-height: var(--leading-sm);
51
+ color: var(--text);
52
+ pointer-events: auto;
53
+ animation: ui-toast-in var(--duration-base) var(--ease-enter);
54
+ }
58
55
 
59
- /* One coloured icon per tone. The status roles already clear 4.5:1 on the
60
- light surface, so the glyph carries the meaning without tinting the card. */
61
- .ui-toast--success .ui-toast__icon {
62
- color: var(--success);
63
- }
64
- .ui-toast--danger .ui-toast__icon {
65
- color: var(--danger);
66
- }
67
- .ui-toast--warning .ui-toast__icon {
68
- color: var(--warning);
69
- }
70
- .ui-toast--info .ui-toast__icon {
71
- color: var(--primary);
72
- }
56
+ .ui-toast__icon {
57
+ display: inline-flex;
58
+ flex: none;
59
+ margin-top: 1px;
60
+ }
73
61
 
74
- .ui-toast__msg {
75
- flex: 1;
76
- }
62
+ /* One coloured icon per tone. The status roles already clear 4.5:1 on the
63
+ light surface, so the glyph carries the meaning without tinting the card. */
64
+ .ui-toast--success .ui-toast__icon {
65
+ color: var(--success);
66
+ }
67
+ .ui-toast--danger .ui-toast__icon {
68
+ color: var(--danger);
69
+ }
70
+ .ui-toast--warning .ui-toast__icon {
71
+ color: var(--warning);
72
+ }
73
+ .ui-toast--info .ui-toast__icon {
74
+ color: var(--primary);
75
+ }
77
76
 
78
- .ui-toast__action {
79
- display: inline-block;
80
- margin-top: var(--space-1);
81
- background: none;
82
- border: 0;
83
- padding: 0;
84
- font: inherit;
85
- font-weight: var(--weight-semibold);
86
- color: var(--link);
87
- text-decoration: underline;
88
- cursor: pointer;
89
- }
90
- .ui-toast__action:hover {
91
- color: var(--link-hover);
92
- }
93
- .ui-toast__action:focus-visible {
94
- outline: 2px solid var(--focus);
95
- outline-offset: 2px;
96
- border-radius: var(--radius-sm);
97
- }
77
+ .ui-toast__msg {
78
+ flex: 1;
79
+ }
98
80
 
99
- .ui-toast__x {
100
- display: inline-flex;
101
- flex: none;
102
- align-items: center;
103
- justify-content: center;
104
- width: 24px;
105
- height: 24px;
106
- margin: -2px -2px 0 0;
107
- background: none;
108
- border: 0;
109
- border-radius: var(--radius-sm);
110
- color: var(--text-muted);
111
- cursor: pointer;
112
- }
113
- .ui-toast__x:hover {
114
- color: var(--text);
115
- background: var(--surface-hover);
116
- }
117
- .ui-toast__x:focus-visible {
118
- outline: 2px solid var(--focus);
119
- outline-offset: 2px;
120
- }
81
+ .ui-toast__action {
82
+ display: inline-block;
83
+ margin-top: var(--space-1);
84
+ background: none;
85
+ border: 0;
86
+ padding: 0;
87
+ font: inherit;
88
+ font-weight: var(--weight-semibold);
89
+ color: var(--link);
90
+ text-decoration: underline;
91
+ cursor: pointer;
92
+ }
93
+ .ui-toast__action:hover {
94
+ color: var(--link-hover);
95
+ }
96
+ .ui-toast__action:focus-visible {
97
+ outline: 2px solid var(--focus);
98
+ outline-offset: 2px;
99
+ border-radius: var(--radius-sm);
100
+ }
121
101
 
122
- /* The SVG in the close button is decorative. Let clicks and the cursor fall
123
- through to the button, so its pointer cursor always shows. */
124
- .ui-toast__x svg,
125
- .ui-toast__action svg {
126
- pointer-events: none;
127
- }
102
+ .ui-toast__x {
103
+ display: inline-flex;
104
+ flex: none;
105
+ align-items: center;
106
+ justify-content: center;
107
+ width: 24px;
108
+ height: 24px;
109
+ margin: -2px -2px 0 0;
110
+ background: none;
111
+ border: 0;
112
+ border-radius: var(--radius-sm);
113
+ color: var(--text-muted);
114
+ cursor: pointer;
115
+ }
116
+ .ui-toast__x:hover {
117
+ color: var(--text);
118
+ background: var(--surface-hover);
119
+ }
120
+ .ui-toast__x:focus-visible {
121
+ outline: 2px solid var(--focus);
122
+ outline-offset: 2px;
123
+ }
128
124
 
129
- @keyframes ui-toast-in {
130
- from {
131
- opacity: 0;
132
- transform: translateY(8px);
125
+ /* The SVG in the close button is decorative. Let clicks and the cursor fall
126
+ through to the button, so its pointer cursor always shows. */
127
+ .ui-toast__x svg,
128
+ .ui-toast__action svg {
129
+ pointer-events: none;
133
130
  }
134
- }
135
131
 
136
- @media (prefers-reduced-motion: reduce) {
137
- .ui-toast {
138
- animation: none;
132
+ @keyframes ui-toast-in {
133
+ from {
134
+ opacity: 0;
135
+ transform: translateY(8px);
136
+ }
137
+ }
138
+
139
+ @media (prefers-reduced-motion: reduce) {
140
+ .ui-toast {
141
+ animation: none;
142
+ }
139
143
  }
140
144
  }
@@ -7,33 +7,37 @@
7
7
  * `@kwtv/tokens/tokens.css` before this file.
8
8
  */
9
9
 
10
- /* Screen-reader-only, still announced. */
11
- .ui-sr-only {
12
- position: absolute;
13
- width: 1px;
14
- height: 1px;
15
- padding: 0;
16
- margin: -1px;
17
- overflow: hidden;
18
- clip-path: inset(50%);
19
- white-space: nowrap;
20
- border: 0;
21
- }
10
+ @layer reset, tokens, base, components, motion, utilities;
22
11
 
23
- /* The two-tone focus ring. An outer halo keeps the ring visible on mid-tone
24
- fills where a single colour would disappear. SC 2.4.7 and 2.4.11. */
25
- .ui-focus-ring:focus-visible,
26
- .ui-focus-ring.ui-focus-ring--pinned {
27
- outline: 2px solid var(--focus);
28
- outline-offset: 2px;
29
- box-shadow: 0 0 0 4px var(--focus-outer);
30
- }
12
+ @layer base {
13
+ /* Screen-reader-only, still announced. */
14
+ .ui-sr-only {
15
+ position: absolute;
16
+ width: 1px;
17
+ height: 1px;
18
+ padding: 0;
19
+ margin: -1px;
20
+ overflow: hidden;
21
+ clip-path: inset(50%);
22
+ white-space: nowrap;
23
+ border: 0;
24
+ }
25
+
26
+ /* The two-tone focus ring. An outer halo keeps the ring visible on mid-tone
27
+ fills where a single colour would disappear. SC 2.4.7 and 2.4.11. */
28
+ .ui-focus-ring:focus-visible,
29
+ .ui-focus-ring.ui-focus-ring--pinned {
30
+ outline: 2px solid var(--focus);
31
+ outline-offset: 2px;
32
+ box-shadow: 0 0 0 4px var(--focus-outer);
33
+ }
31
34
 
32
- /* Touch-target floor. Labelled rows and small controls hold 32 px, icon-only
33
- controls hold 44 px, the mobile primary action holds 48 px. The lever is the
34
- label or the row, not the native control inside it. */
35
- @media (max-width: 700px), (pointer: coarse) {
36
- .ui-touch :where(button, a, label, [role="button"]):not(.ui-touch--exempt) {
37
- min-height: 32px;
35
+ /* Touch-target floor. Labelled rows and small controls hold 32 px, icon-only
36
+ controls hold 44 px, the mobile primary action holds 48 px. The lever is the
37
+ label or the row, not the native control inside it. */
38
+ @media (max-width: 700px), (pointer: coarse) {
39
+ .ui-touch :where(button, a, label, [role="button"]):not(.ui-touch--exempt) {
40
+ min-height: 32px;
41
+ }
38
42
  }
39
43
  }