@kwtv/components 0.2.0 → 0.4.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 (56) hide show
  1. package/README.md +52 -9
  2. package/package.json +2 -2
  3. package/src/astro/Accordion.astro +10 -6
  4. package/src/astro/AccordionItem.astro +55 -45
  5. package/src/astro/ActiveFilterTags.astro +41 -28
  6. package/src/astro/Alert.astro +45 -41
  7. package/src/astro/Badge.astro +80 -76
  8. package/src/astro/Band.astro +104 -58
  9. package/src/astro/Breadcrumb.astro +38 -30
  10. package/src/astro/Button.astro +135 -129
  11. package/src/astro/Card.astro +72 -62
  12. package/src/astro/CartLine.astro +72 -58
  13. package/src/astro/Checkbox.astro +36 -32
  14. package/src/astro/Chip.astro +68 -64
  15. package/src/astro/ChipRail.astro +6 -1
  16. package/src/astro/DotGrid.astro +55 -42
  17. package/src/astro/EmptyState.astro +29 -23
  18. package/src/astro/FilterGroup.astro +29 -26
  19. package/src/astro/Filters.astro +57 -47
  20. package/src/astro/Footer.astro +195 -178
  21. package/src/astro/FooterColumn.astro +39 -35
  22. package/src/astro/Header.astro +80 -67
  23. package/src/astro/Icon.astro +4 -2
  24. package/src/astro/IconButton.astro +67 -61
  25. package/src/astro/Marquee.astro +43 -41
  26. package/src/astro/NavDropdown.astro +169 -149
  27. package/src/astro/NavLink.astro +59 -56
  28. package/src/astro/Newsletter.astro +64 -56
  29. package/src/astro/Pager.astro +71 -46
  30. package/src/astro/PickCard.astro +72 -68
  31. package/src/astro/ProductCard.astro +134 -119
  32. package/src/astro/Radio.astro +36 -32
  33. package/src/astro/Skeleton.astro +60 -42
  34. package/src/astro/Social.astro +26 -21
  35. package/src/astro/StepIndicator.astro +70 -54
  36. package/src/astro/Sticker.astro +74 -49
  37. package/src/astro/Swatch.astro +44 -40
  38. package/src/astro/SwipeCarousel.astro +5 -1
  39. package/src/astro/Table.astro +66 -56
  40. package/src/astro/TableCard.astro +45 -37
  41. package/src/astro/TextField.astro +104 -91
  42. package/src/astro/Totals.astro +39 -35
  43. package/src/react/Drawer.css +60 -56
  44. package/src/react/Drawer.tsx +1 -5
  45. package/src/react/Modal.css +97 -93
  46. package/src/react/Modal.tsx +4 -6
  47. package/src/react/NewsCarousel.css +108 -104
  48. package/src/react/NewsCarousel.tsx +7 -1
  49. package/src/react/QuantityStepper.css +84 -80
  50. package/src/react/Select.css +159 -155
  51. package/src/react/Select.tsx +8 -2
  52. package/src/react/Toast.css +128 -124
  53. package/src/react/Toast.tsx +38 -4
  54. package/src/styles/base.css +30 -26
  55. package/src/styles/controls.css +183 -179
  56. package/src/styles/motion.css +203 -199
@@ -27,8 +27,14 @@ interface Props {
27
27
  class?: string;
28
28
  }
29
29
 
30
- const { columns, numeric = false, busy = false, caption, class: className, ...rest } =
31
- Astro.props;
30
+ const {
31
+ columns,
32
+ numeric = false,
33
+ busy = false,
34
+ caption,
35
+ class: className,
36
+ ...rest
37
+ } = Astro.props;
32
38
 
33
39
  const classes = ["ui-table", numeric && "ui-table--numeric", className]
34
40
  .filter(Boolean)
@@ -52,66 +58,70 @@ const classes = ["ui-table", numeric && "ui-table--numeric", className]
52
58
  </table>
53
59
 
54
60
  <style>
55
- .ui-table {
56
- width: 100%;
57
- border-collapse: collapse;
58
- font-family: var(--font-sans);
59
- font-size: var(--text-sm);
60
- color: var(--text);
61
- }
61
+ @layer reset, tokens, base, components, motion, utilities;
62
62
 
63
- .ui-table :global(th),
64
- .ui-table :global(td) {
65
- padding: var(--space-3) var(--space-4);
66
- text-align: left;
67
- border-bottom: 1px solid var(--border);
68
- vertical-align: middle;
69
- }
63
+ @layer components {
64
+ .ui-table {
65
+ width: 100%;
66
+ border-collapse: collapse;
67
+ font-family: var(--font-sans);
68
+ font-size: var(--text-sm);
69
+ color: var(--text);
70
+ }
70
71
 
71
- .ui-table :global(th) {
72
- font-size: var(--text-xs);
73
- font-weight: var(--weight-semibold);
74
- color: var(--text-muted);
75
- white-space: nowrap;
76
- }
72
+ .ui-table :global(th),
73
+ .ui-table :global(td) {
74
+ padding: var(--space-3) var(--space-4);
75
+ text-align: left;
76
+ border-bottom: 1px solid var(--border);
77
+ vertical-align: middle;
78
+ }
77
79
 
78
- .ui-table :global(tbody tr) {
79
- transition: background-color var(--duration-fast) var(--ease-standard);
80
- }
81
- .ui-table :global(tbody tr:hover) {
82
- background: var(--surface-hover);
83
- }
84
- .ui-table :global(tbody tr:last-child td) {
85
- border-bottom: 0;
86
- }
80
+ .ui-table :global(th) {
81
+ font-size: var(--text-xs);
82
+ font-weight: var(--weight-semibold);
83
+ color: var(--text-muted);
84
+ white-space: nowrap;
85
+ }
87
86
 
88
- .ui-table :global(a) {
89
- color: var(--link);
90
- text-decoration: none;
91
- font-weight: var(--weight-medium);
92
- }
93
- .ui-table :global(a:hover) {
94
- text-decoration: underline;
95
- }
96
- .ui-table :global(a:focus-visible) {
97
- outline: 2px solid var(--focus);
98
- outline-offset: 2px;
99
- border-radius: var(--radius-sm);
100
- }
87
+ .ui-table :global(tbody tr) {
88
+ transition: background-color var(--duration-fast) var(--ease-standard);
89
+ }
90
+ .ui-table :global(tbody tr:hover) {
91
+ background: var(--surface-hover);
92
+ }
93
+ .ui-table :global(tbody tr:last-child td) {
94
+ border-bottom: 0;
95
+ }
101
96
 
102
- /* Numeric: the last column and any marked cell use tabular numerals and
103
- align right. */
104
- .ui-table--numeric :global(th:last-child),
105
- .ui-table--numeric :global(td:last-child),
106
- .ui-table :global(th.is-numeric),
107
- .ui-table :global(td.is-numeric) {
108
- text-align: right;
109
- font-variant-numeric: tabular-nums;
110
- }
97
+ .ui-table :global(a) {
98
+ color: var(--link);
99
+ text-decoration: none;
100
+ font-weight: var(--weight-medium);
101
+ }
102
+ .ui-table :global(a:hover) {
103
+ text-decoration: underline;
104
+ }
105
+ .ui-table :global(a:focus-visible) {
106
+ outline: 2px solid var(--focus);
107
+ outline-offset: 2px;
108
+ border-radius: var(--radius-sm);
109
+ }
111
110
 
112
- @media (prefers-reduced-motion: reduce) {
113
- .ui-table :global(tbody tr) {
114
- transition: none;
111
+ /* Numeric: the last column and any marked cell use tabular numerals and */
112
+ /* align right. */
113
+ .ui-table--numeric :global(th:last-child),
114
+ .ui-table--numeric :global(td:last-child),
115
+ .ui-table :global(th.is-numeric),
116
+ .ui-table :global(td.is-numeric) {
117
+ text-align: right;
118
+ font-variant-numeric: tabular-nums;
119
+ }
120
+
121
+ @media (prefers-reduced-motion: reduce) {
122
+ .ui-table :global(tbody tr) {
123
+ transition: none;
124
+ }
115
125
  }
116
126
  }
117
127
  </style>
@@ -15,49 +15,57 @@ const classes = ["ui-tablecard", className].filter(Boolean).join(" ");
15
15
  ---
16
16
 
17
17
  <div class={classes} aria-hidden={busy ? "true" : undefined} {...rest}>
18
- <span class="ui-tablecard__main"><slot name="main" /></span>
19
- <span class="ui-tablecard__end"><slot name="end" /></span>
18
+ <span class="ui-tablecard__main">
19
+ <slot name="main" />
20
+ </span>
21
+ <span class="ui-tablecard__end">
22
+ <slot name="end" />
23
+ </span>
20
24
  </div>
21
25
 
22
26
  <style>
23
- .ui-tablecard {
24
- display: flex;
25
- align-items: flex-start;
26
- justify-content: space-between;
27
- gap: var(--space-4);
28
- padding: var(--space-4) 0;
29
- border-bottom: 1px solid var(--border);
30
- }
27
+ @layer reset, tokens, base, components, motion, utilities;
31
28
 
32
- .ui-tablecard__main {
33
- display: flex;
34
- flex-direction: column;
35
- gap: var(--space-1);
36
- min-width: 0;
37
- }
29
+ @layer components {
30
+ .ui-tablecard {
31
+ display: flex;
32
+ align-items: flex-start;
33
+ justify-content: space-between;
34
+ gap: var(--space-4);
35
+ padding: var(--space-4) 0;
36
+ border-bottom: 1px solid var(--border);
37
+ }
38
38
 
39
- .ui-tablecard__end {
40
- display: flex;
41
- flex-direction: column;
42
- align-items: flex-end;
43
- gap: var(--space-1);
44
- text-align: right;
45
- }
39
+ .ui-tablecard__main {
40
+ display: flex;
41
+ flex-direction: column;
42
+ gap: var(--space-1);
43
+ min-width: 0;
44
+ }
46
45
 
47
- .ui-tablecard__end :global(b) {
48
- font-variant-numeric: tabular-nums;
49
- }
46
+ .ui-tablecard__end {
47
+ display: flex;
48
+ flex-direction: column;
49
+ align-items: flex-end;
50
+ gap: var(--space-1);
51
+ text-align: right;
52
+ }
50
53
 
51
- .ui-tablecard :global(a) {
52
- color: var(--link);
53
- text-decoration: none;
54
- }
55
- .ui-tablecard :global(a:hover) {
56
- text-decoration: underline;
57
- }
58
- .ui-tablecard :global(a:focus-visible) {
59
- outline: 2px solid var(--focus);
60
- outline-offset: 2px;
61
- border-radius: var(--radius-sm);
54
+ .ui-tablecard__end :global(b) {
55
+ font-variant-numeric: tabular-nums;
56
+ }
57
+
58
+ .ui-tablecard :global(a) {
59
+ color: var(--link);
60
+ text-decoration: none;
61
+ }
62
+ .ui-tablecard :global(a:hover) {
63
+ text-decoration: underline;
64
+ }
65
+ .ui-tablecard :global(a:focus-visible) {
66
+ outline: 2px solid var(--focus);
67
+ outline-offset: 2px;
68
+ border-radius: var(--radius-sm);
69
+ }
62
70
  }
63
71
  </style>
@@ -64,14 +64,19 @@ const inputClasses = [
64
64
  .filter(Boolean)
65
65
  .join(" ");
66
66
 
67
- const charCount = count && maxlength ? `${String(value).length} / ${maxlength}` : null;
67
+ const charCount =
68
+ count && maxlength ? `${String(value).length} / ${maxlength}` : null;
68
69
  ---
69
70
 
70
71
  <label class={["ui-field", className].filter(Boolean).join(" ")}>
71
72
  {label && (
72
73
  <span class="ui-field__label">
73
74
  {label}
74
- {required && <span class="ui-field__req" aria-hidden="true">*</span>}
75
+ {required && (
76
+ <span class="ui-field__req" aria-hidden="true">
77
+ *
78
+ </span>
79
+ )}
75
80
  </span>
76
81
  )}
77
82
 
@@ -115,117 +120,125 @@ const charCount = count && maxlength ? `${String(value).length} / ${maxlength}`
115
120
  {error}
116
121
  </span>
117
122
  ) : (
118
- hint && <span class="ui-field__hint" id={hintId}>{hint}</span>
123
+ hint && (
124
+ <span class="ui-field__hint" id={hintId}>
125
+ {hint}
126
+ </span>
127
+ )
119
128
  )}
120
129
 
121
130
  {charCount && <span class="ui-field__count">{charCount}</span>}
122
131
  </label>
123
132
 
124
133
  <style>
125
- .ui-field {
126
- display: flex;
127
- flex-direction: column;
128
- gap: var(--space-1-5);
129
- font-family: var(--font-sans);
130
- }
134
+ @layer reset, tokens, base, components, motion, utilities;
135
+
136
+ @layer components {
137
+ .ui-field {
138
+ display: flex;
139
+ flex-direction: column;
140
+ gap: var(--space-1-5);
141
+ font-family: var(--font-sans);
142
+ }
131
143
 
132
- .ui-field__label {
133
- font-size: var(--text-sm);
134
- font-weight: var(--weight-medium);
135
- color: var(--text);
136
- }
144
+ .ui-field__label {
145
+ font-size: var(--text-sm);
146
+ font-weight: var(--weight-medium);
147
+ color: var(--text);
148
+ }
137
149
 
138
- .ui-field__req {
139
- color: var(--danger);
140
- margin-left: 2px;
141
- }
150
+ .ui-field__req {
151
+ color: var(--danger);
152
+ margin-left: 2px;
153
+ }
142
154
 
143
- .ui-input {
144
- min-height: 40px;
145
- padding: var(--space-2) var(--space-3);
146
- background: var(--surface);
147
- border: 1px solid var(--border-strong);
148
- border-radius: var(--radius-md);
149
- font-family: var(--font-sans);
150
- font-size: var(--text-sm);
151
- color: var(--text);
152
- transition:
153
- border-color var(--duration-fast) var(--ease-standard),
154
- box-shadow var(--duration-fast) var(--ease-standard);
155
- }
155
+ .ui-input {
156
+ min-height: 40px;
157
+ padding: var(--space-2) var(--space-3);
158
+ background: var(--surface);
159
+ border: 1px solid var(--border-strong);
160
+ border-radius: var(--radius-md);
161
+ font-family: var(--font-sans);
162
+ font-size: var(--text-sm);
163
+ color: var(--text);
164
+ transition:
165
+ border-color var(--duration-fast) var(--ease-standard),
166
+ box-shadow var(--duration-fast) var(--ease-standard);
167
+ }
156
168
 
157
- textarea.ui-input {
158
- min-height: 96px;
159
- resize: vertical;
160
- line-height: var(--leading-sm);
161
- }
169
+ textarea.ui-input {
170
+ min-height: 96px;
171
+ resize: vertical;
172
+ line-height: var(--leading-sm);
173
+ }
162
174
 
163
- .ui-input::placeholder {
164
- color: var(--text-muted);
165
- }
175
+ .ui-input::placeholder {
176
+ color: var(--text-muted);
177
+ }
166
178
 
167
- .ui-input:hover,
168
- .ui-input.is-hover {
169
- border-color: var(--border-strong);
170
- }
179
+ .ui-input:hover,
180
+ .ui-input.is-hover {
181
+ border-color: var(--border-strong);
182
+ }
171
183
 
172
- .ui-input:focus-visible,
173
- .ui-input.is-focus {
174
- outline: 2px solid var(--focus);
175
- outline-offset: 1px;
176
- border-color: var(--border-strong);
177
- box-shadow: 0 0 0 4px var(--focus-outer);
178
- }
184
+ .ui-input:focus-visible,
185
+ .ui-input.is-focus {
186
+ outline: 2px solid var(--focus);
187
+ outline-offset: 1px;
188
+ border-color: var(--border-strong);
189
+ box-shadow: 0 0 0 4px var(--focus-outer);
190
+ }
179
191
 
180
- /* Invalid: 2 px danger border. */
181
- .ui-input.is-invalid,
182
- .ui-input[aria-invalid="true"] {
183
- border-width: 2px;
184
- border-color: var(--danger);
185
- }
192
+ /* Invalid: 2 px danger border. */
193
+ .ui-input.is-invalid,
194
+ .ui-input[aria-invalid="true"] {
195
+ border-width: 2px;
196
+ border-color: var(--danger);
197
+ }
186
198
 
187
- .ui-input.is-valid {
188
- border-color: var(--success);
189
- }
199
+ .ui-input.is-valid {
200
+ border-color: var(--success);
201
+ }
190
202
 
191
- .ui-input:disabled,
192
- .ui-input.is-disabled {
193
- opacity: 0.5;
194
- cursor: not-allowed;
195
- }
203
+ .ui-input:disabled,
204
+ .ui-input.is-disabled {
205
+ opacity: 0.5;
206
+ cursor: not-allowed;
207
+ }
196
208
 
197
- .ui-field__hint {
198
- font-size: var(--text-xs);
199
- line-height: var(--leading-xs);
200
- color: var(--text-muted);
201
- }
209
+ .ui-field__hint {
210
+ font-size: var(--text-xs);
211
+ line-height: var(--leading-xs);
212
+ color: var(--text-muted);
213
+ }
202
214
 
203
- .ui-field__error {
204
- display: flex;
205
- align-items: center;
206
- gap: var(--space-1);
207
- font-size: var(--text-xs);
208
- line-height: var(--leading-xs);
209
- color: var(--danger);
210
- }
215
+ .ui-field__error {
216
+ display: flex;
217
+ align-items: center;
218
+ gap: var(--space-1);
219
+ font-size: var(--text-xs);
220
+ line-height: var(--leading-xs);
221
+ color: var(--danger);
222
+ }
211
223
 
212
- .ui-field__count {
213
- align-self: flex-end;
214
- font-size: var(--text-xs);
215
- color: var(--text-muted);
216
- font-variant-numeric: tabular-nums;
217
- }
224
+ .ui-field__count {
225
+ align-self: flex-end;
226
+ font-size: var(--text-xs);
227
+ color: var(--text-muted);
228
+ font-variant-numeric: tabular-nums;
229
+ }
218
230
 
219
- @media (prefers-reduced-motion: reduce) {
220
- .ui-input {
221
- transition: none;
231
+ @media (prefers-reduced-motion: reduce) {
232
+ .ui-input {
233
+ transition: none;
234
+ }
222
235
  }
223
- }
224
236
 
225
- /* Mobile inputs grow to 44 px under a touch scope. */
226
- @media (max-width: 700px), (pointer: coarse) {
227
- .ui-input {
228
- min-height: 44px;
237
+ /* Mobile inputs grow to 44 px under a touch scope. */
238
+ @media (max-width: 700px), (pointer: coarse) {
239
+ .ui-input {
240
+ min-height: 44px;
241
+ }
229
242
  }
230
243
  }
231
244
  </style>
@@ -47,46 +47,50 @@ const classes = ["ui-totals", className].filter(Boolean).join(" ");
47
47
  </div>
48
48
 
49
49
  <style>
50
- .ui-totals {
51
- display: flex;
52
- flex-direction: column;
53
- gap: var(--space-2-5);
54
- }
50
+ @layer reset, tokens, base, components, motion, utilities;
55
51
 
56
- .ui-trow {
57
- display: flex;
58
- align-items: baseline;
59
- justify-content: space-between;
60
- gap: var(--space-4);
61
- font-size: var(--text-sm);
62
- color: var(--text-muted);
63
- }
52
+ @layer components {
53
+ .ui-totals {
54
+ display: flex;
55
+ flex-direction: column;
56
+ gap: var(--space-2-5);
57
+ }
64
58
 
65
- .ui-trow b {
66
- font-weight: var(--weight-medium);
67
- font-variant-numeric: tabular-nums;
68
- text-align: right;
69
- color: var(--text-muted);
70
- }
59
+ .ui-trow {
60
+ display: flex;
61
+ align-items: baseline;
62
+ justify-content: space-between;
63
+ gap: var(--space-4);
64
+ font-size: var(--text-sm);
65
+ color: var(--text-muted);
66
+ }
71
67
 
72
- .ui-trow b[data-emphasis] {
73
- color: var(--text);
74
- }
68
+ .ui-trow b {
69
+ font-weight: var(--weight-medium);
70
+ font-variant-numeric: tabular-nums;
71
+ text-align: right;
72
+ color: var(--text-muted);
73
+ }
75
74
 
76
- .ui-trow--total {
77
- padding-top: var(--space-3);
78
- border-top: 1px solid var(--border);
79
- font-size: var(--text-lg);
80
- }
75
+ .ui-trow b[data-emphasis] {
76
+ color: var(--text);
77
+ }
81
78
 
82
- .ui-trow--total span {
83
- color: var(--text);
84
- font-weight: var(--weight-semibold);
85
- }
79
+ .ui-trow--total {
80
+ padding-top: var(--space-3);
81
+ border-top: 1px solid var(--border);
82
+ font-size: var(--text-lg);
83
+ }
84
+
85
+ .ui-trow--total span {
86
+ color: var(--text);
87
+ font-weight: var(--weight-semibold);
88
+ }
86
89
 
87
- .ui-trow--total b {
88
- font-size: var(--text-2xl);
89
- font-weight: var(--weight-semibold);
90
- color: var(--text);
90
+ .ui-trow--total b {
91
+ font-size: var(--text-2xl);
92
+ font-weight: var(--weight-semibold);
93
+ color: var(--text);
94
+ }
91
95
  }
92
96
  </style>