@wovenui/components 0.0.0-stage → 1.0.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/LICENSE +21 -0
- package/README.md +284 -2
- package/dist/components.json +4204 -0
- package/dist/llms-full.txt +2839 -0
- package/dist/wovenui-kit.css +5002 -0
- package/dist/wovenui-kit.css.map +1 -0
- package/dist/wovenui-kit.iife.js +532 -0
- package/dist/wovenui-kit.js +529 -0
- package/dist/wovenui-kit.min.css +2 -0
- package/dist/wovenui-kit.min.css.map +1 -0
- package/package.json +268 -4
- package/src/_close.scss +45 -0
- package/src/_helpers.scss +11 -0
- package/src/_kit.scss +124 -0
- package/src/_shared.scss +10 -0
- package/src/components/_accordion.scss +132 -0
- package/src/components/_alert.scss +161 -0
- package/src/components/_autocomplete.scss +129 -0
- package/src/components/_avatar-group.scss +80 -0
- package/src/components/_avatar.scss +134 -0
- package/src/components/_badge.scss +91 -0
- package/src/components/_breadcrumb.scss +115 -0
- package/src/components/_btn-group.scss +113 -0
- package/src/components/_button.scss +301 -0
- package/src/components/_card.scss +120 -0
- package/src/components/_checkbox.scss +168 -0
- package/src/components/_code-block.scss +78 -0
- package/src/components/_confirm-modal.scss +75 -0
- package/src/components/_data-table.scss +79 -0
- package/src/components/_desc-list.scss +180 -0
- package/src/components/_divider.scss +66 -0
- package/src/components/_dot.scss +115 -0
- package/src/components/_drawer.scss +200 -0
- package/src/components/_dropdown.scss +182 -0
- package/src/components/_empty-state.scss +146 -0
- package/src/components/_field-group.scss +68 -0
- package/src/components/_field-message.scss +75 -0
- package/src/components/_field.scss +127 -0
- package/src/components/_form-actions.scss +58 -0
- package/src/components/_info-row.scss +69 -0
- package/src/components/_input-group.scss +87 -0
- package/src/components/_input.scss +278 -0
- package/src/components/_list.scss +76 -0
- package/src/components/_modal.scss +168 -0
- package/src/components/_page-header.scss +85 -0
- package/src/components/_pagination.scss +138 -0
- package/src/components/_panel.scss +69 -0
- package/src/components/_popover.scss +154 -0
- package/src/components/_progress-circle.scss +123 -0
- package/src/components/_progress.scss +122 -0
- package/src/components/_radio.scss +162 -0
- package/src/components/_segmented.scss +183 -0
- package/src/components/_select.scss +154 -0
- package/src/components/_sidebar.scss +300 -0
- package/src/components/_skeleton.scss +90 -0
- package/src/components/_spinner.scss +84 -0
- package/src/components/_stat.scss +92 -0
- package/src/components/_table.scss +460 -0
- package/src/components/_tabs.scss +327 -0
- package/src/components/_tag.scss +143 -0
- package/src/components/_text.scss +42 -0
- package/src/components/_textarea.scss +57 -0
- package/src/components/_timeline.scss +196 -0
- package/src/components/_title.scss +41 -0
- package/src/components/_toast.scss +221 -0
- package/src/components/_toggle.scss +171 -0
- package/src/components/_toolbar.scss +74 -0
- package/src/components/_topbar.scss +204 -0
- package/src/entries/accordion.scss +4 -0
- package/src/entries/alert.scss +4 -0
- package/src/entries/autocomplete.scss +4 -0
- package/src/entries/avatar-group.scss +4 -0
- package/src/entries/avatar.scss +4 -0
- package/src/entries/badge.scss +4 -0
- package/src/entries/breadcrumb.scss +4 -0
- package/src/entries/btn-group.scss +4 -0
- package/src/entries/button.scss +4 -0
- package/src/entries/card.scss +4 -0
- package/src/entries/checkbox.scss +4 -0
- package/src/entries/code-block.scss +4 -0
- package/src/entries/confirm-modal.scss +4 -0
- package/src/entries/data-table.scss +4 -0
- package/src/entries/desc-list.scss +4 -0
- package/src/entries/divider.scss +4 -0
- package/src/entries/dot.scss +4 -0
- package/src/entries/drawer.scss +4 -0
- package/src/entries/dropdown.scss +4 -0
- package/src/entries/empty-state.scss +4 -0
- package/src/entries/field-group.scss +4 -0
- package/src/entries/field-message.scss +4 -0
- package/src/entries/field.scss +4 -0
- package/src/entries/form-actions.scss +4 -0
- package/src/entries/info-row.scss +4 -0
- package/src/entries/input-group.scss +4 -0
- package/src/entries/input.scss +4 -0
- package/src/entries/list.scss +4 -0
- package/src/entries/modal.scss +4 -0
- package/src/entries/page-header.scss +4 -0
- package/src/entries/pagination.scss +4 -0
- package/src/entries/panel.scss +4 -0
- package/src/entries/popover.scss +4 -0
- package/src/entries/progress-circle.scss +4 -0
- package/src/entries/progress.scss +4 -0
- package/src/entries/radio.scss +4 -0
- package/src/entries/segmented.scss +4 -0
- package/src/entries/select.scss +4 -0
- package/src/entries/sidebar.scss +4 -0
- package/src/entries/skeleton.scss +4 -0
- package/src/entries/spinner.scss +4 -0
- package/src/entries/stat.scss +4 -0
- package/src/entries/table.scss +4 -0
- package/src/entries/tabs.scss +4 -0
- package/src/entries/tag.scss +4 -0
- package/src/entries/text.scss +4 -0
- package/src/entries/textarea.scss +4 -0
- package/src/entries/timeline.scss +4 -0
- package/src/entries/title.scss +4 -0
- package/src/entries/toast.scss +4 -0
- package/src/entries/toggle.scss +4 -0
- package/src/entries/toolbar.scss +4 -0
- package/src/entries/topbar.scss +4 -0
- package/src/index.scss +7 -0
- package/src/js/autocomplete.js +86 -0
- package/src/js/data-table.js +141 -0
- package/src/js/index.js +34 -0
- package/src/js/input-clear.js +25 -0
- package/src/js/package.json +3 -0
- package/src/js/tabs.js +73 -0
- package/src/js/toast.js +161 -0
- package/src/js/util.js +21 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
////
|
|
2
|
+
//// @component wu-tabs
|
|
3
|
+
//// Tabs that show one panel at a time, following the WAI-ARIA tabs pattern, in line, card, boxed and vertical styles.
|
|
4
|
+
////
|
|
5
|
+
//// The kit script adds arrow keys, Home and End, switches the panels and fills in roles, ids, `aria-controls`, `aria-labelledby` and `tabindex` when they are missing. Without it the first panel shows.
|
|
6
|
+
////
|
|
7
|
+
//// In `vertical` tabs the script sets `aria-orientation="vertical"` on the list; without the script, add it yourself.
|
|
8
|
+
////
|
|
9
|
+
//// @since 1.0.0
|
|
10
|
+
//// @needs none
|
|
11
|
+
//// @js required initTabs
|
|
12
|
+
//// @example html
|
|
13
|
+
//// <div class="wu-tabs">
|
|
14
|
+
//// <div class="wu-tabs-list" role="tablist" aria-label="Account">
|
|
15
|
+
//// <button class="wu-tabs-tab" type="button" role="tab" id="tab-profile" aria-controls="panel-profile" aria-selected="true">Profile</button>
|
|
16
|
+
//// <button class="wu-tabs-tab" type="button" role="tab" id="tab-billing" aria-controls="panel-billing" aria-selected="false" tabindex="-1">Billing</button>
|
|
17
|
+
//// </div>
|
|
18
|
+
//// <div class="wu-tabs-panel" role="tabpanel" id="panel-profile" aria-labelledby="tab-profile" tabindex="0">Profile settings</div>
|
|
19
|
+
//// <div class="wu-tabs-panel" role="tabpanel" id="panel-billing" aria-labelledby="tab-billing" tabindex="0" hidden>Billing settings</div>
|
|
20
|
+
//// </div>
|
|
21
|
+
//// @example html
|
|
22
|
+
//// <div class="wu-tabs vertical boxed">
|
|
23
|
+
//// <div class="wu-tabs-list" role="tablist" aria-label="Settings" aria-orientation="vertical">
|
|
24
|
+
//// <button class="wu-tabs-tab" type="button" role="tab" id="tab-general" aria-controls="panel-general" aria-selected="true">General</button>
|
|
25
|
+
//// <button class="wu-tabs-tab" type="button" role="tab" id="tab-team" aria-controls="panel-team" aria-selected="false" tabindex="-1" disabled>Team</button>
|
|
26
|
+
//// </div>
|
|
27
|
+
//// <div class="wu-tabs-panel" role="tabpanel" id="panel-general" aria-labelledby="tab-general" tabindex="0">General settings</div>
|
|
28
|
+
//// <div class="wu-tabs-panel" role="tabpanel" id="panel-team" aria-labelledby="tab-team" tabindex="0" hidden>Team settings</div>
|
|
29
|
+
//// </div>
|
|
30
|
+
//// @modifier card - Joined tab boxes; the selected tab opens into the panel @since 1.0.0
|
|
31
|
+
//// @modifier boxed - Tabs and panels inside one bordered box @since 1.0.0
|
|
32
|
+
//// @modifier vertical - Tab list at the inline start, selected bar on its inline end edge @since 1.0.0
|
|
33
|
+
//// @modifier animated - Selected bar grows from the center and the panel fades in when the user allows motion; `wu-animated` on an ancestor does the same @since 1.0.0
|
|
34
|
+
//// @part wu-tabs-list - Row of tabs; scrolls sideways and fades the edge with more tabs @since 1.0.0
|
|
35
|
+
//// @part wu-tabs-tab - One tab button; a direct child `svg` is sized to `1em` @since 1.0.0
|
|
36
|
+
//// @part wu-tabs-panel - Content shown for the selected tab @since 1.0.0
|
|
37
|
+
//// @state aria-selected="true" - On a tab: regular text color and a brand bar @since 1.0.0
|
|
38
|
+
//// @state disabled | aria-disabled="true" - On a tab: half opacity and a not-allowed cursor @since 1.0.0
|
|
39
|
+
////
|
|
40
|
+
|
|
41
|
+
@use "@wovenui/core/mixins" as woven;
|
|
42
|
+
|
|
43
|
+
.wu-tabs-list {
|
|
44
|
+
display: flex;
|
|
45
|
+
gap: woven.token(space-1);
|
|
46
|
+
border-block-end: woven.token(border-width-1) solid woven.token(border-regular);
|
|
47
|
+
overflow-x: auto;
|
|
48
|
+
scrollbar-width: thin;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Scroll cue: the edge with more tabs behind it fades out; the scrollbar hides where the cue works
|
|
52
|
+
@property --wu-kit-tabs-fade-start {
|
|
53
|
+
syntax: "<length>";
|
|
54
|
+
inherits: false;
|
|
55
|
+
initial-value: 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@property --wu-kit-tabs-fade-end {
|
|
59
|
+
syntax: "<length>";
|
|
60
|
+
inherits: false;
|
|
61
|
+
initial-value: 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@supports (animation-timeline: scroll()) {
|
|
65
|
+
.wu-tabs-list {
|
|
66
|
+
scrollbar-width: none;
|
|
67
|
+
mask-image: linear-gradient(to right, transparent, #000 var(--wu-kit-tabs-fade-start), #000 calc(100% - var(--wu-kit-tabs-fade-end)), transparent);
|
|
68
|
+
animation-name: wu-tabs-fade;
|
|
69
|
+
animation-timing-function: linear;
|
|
70
|
+
animation-fill-mode: both;
|
|
71
|
+
animation-timeline: scroll(self inline);
|
|
72
|
+
|
|
73
|
+
&:dir(rtl) {
|
|
74
|
+
mask-image: linear-gradient(to left, transparent, #000 var(--wu-kit-tabs-fade-start), #000 calc(100% - var(--wu-kit-tabs-fade-end)), transparent);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@keyframes wu-tabs-fade {
|
|
80
|
+
0% {
|
|
81
|
+
--wu-kit-tabs-fade-start: 0px;
|
|
82
|
+
--wu-kit-tabs-fade-end: #{woven.token(space-8)};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
8% {
|
|
86
|
+
--wu-kit-tabs-fade-start: #{woven.token(space-8)};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
92% {
|
|
90
|
+
--wu-kit-tabs-fade-end: #{woven.token(space-8)};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
100% {
|
|
94
|
+
--wu-kit-tabs-fade-start: #{woven.token(space-8)};
|
|
95
|
+
--wu-kit-tabs-fade-end: 0px;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.wu-tabs-tab {
|
|
100
|
+
position: relative;
|
|
101
|
+
display: inline-flex;
|
|
102
|
+
flex: none;
|
|
103
|
+
align-items: center;
|
|
104
|
+
gap: woven.token(space-2);
|
|
105
|
+
min-block-size: woven.token(control-height-md);
|
|
106
|
+
margin: 0;
|
|
107
|
+
padding-block: 0;
|
|
108
|
+
padding-inline: woven.token(space-3);
|
|
109
|
+
border: 0;
|
|
110
|
+
border-radius: woven.token(radius-sm) woven.token(radius-sm) 0 0;
|
|
111
|
+
background: transparent;
|
|
112
|
+
color: woven.token(text-muted);
|
|
113
|
+
font: inherit;
|
|
114
|
+
font-size: woven.token(font-size-sm);
|
|
115
|
+
font-weight: woven.token(font-weight-medium);
|
|
116
|
+
line-height: 1;
|
|
117
|
+
white-space: nowrap;
|
|
118
|
+
cursor: pointer;
|
|
119
|
+
transition: color woven.token(duration-150) woven.token(ease-out);
|
|
120
|
+
|
|
121
|
+
// Selected bar, drawn inside the tab so the scrolling list does not clip it
|
|
122
|
+
&::after {
|
|
123
|
+
content: "";
|
|
124
|
+
position: absolute;
|
|
125
|
+
inset-inline: 0;
|
|
126
|
+
inset-block-end: 0;
|
|
127
|
+
block-size: woven.token(border-width-2);
|
|
128
|
+
border-radius: woven.token(radius-full);
|
|
129
|
+
background: transparent;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
&:hover {
|
|
133
|
+
color: woven.token(text-regular);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
&:focus-visible {
|
|
137
|
+
outline: woven.token(border-focus-width) solid woven.token(border-focus);
|
|
138
|
+
outline-offset: calc(-1 * #{woven.token(border-focus-width)});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
&[aria-selected="true"] {
|
|
142
|
+
color: woven.token(text-regular);
|
|
143
|
+
|
|
144
|
+
&::after {
|
|
145
|
+
background: woven.token(brand);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
&:disabled,
|
|
150
|
+
&[aria-disabled="true"] {
|
|
151
|
+
opacity: woven.token(opacity-50);
|
|
152
|
+
cursor: not-allowed;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
> svg {
|
|
156
|
+
flex-shrink: 0;
|
|
157
|
+
width: 1em;
|
|
158
|
+
height: 1em;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Inline padding lines the text up with the tab labels and keeps the inset focus ring off the text
|
|
163
|
+
.wu-tabs-panel {
|
|
164
|
+
padding-block: woven.token(space-4);
|
|
165
|
+
padding-inline: woven.token(space-3);
|
|
166
|
+
|
|
167
|
+
&:focus-visible {
|
|
168
|
+
border-radius: woven.token(radius-sm);
|
|
169
|
+
outline: woven.token(border-focus-width) solid woven.token(border-focus);
|
|
170
|
+
outline-offset: calc(-1 * #{woven.token(border-focus-width)});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Card: joined tab boxes; the selected one has no bottom line, so it opens into the content.
|
|
175
|
+
// A filler after the tabs carries the line to the end of the list.
|
|
176
|
+
.wu-tabs.card > .wu-tabs-list {
|
|
177
|
+
gap: 0;
|
|
178
|
+
border-block-end: 0;
|
|
179
|
+
|
|
180
|
+
&::after {
|
|
181
|
+
content: "";
|
|
182
|
+
flex: 1 0 0;
|
|
183
|
+
border-block-end: woven.token(border-width-1) solid woven.token(border-regular);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.wu-tabs.card > .wu-tabs-list > .wu-tabs-tab {
|
|
188
|
+
border: woven.token(border-width-1) solid woven.token(border-regular);
|
|
189
|
+
border-radius: 0;
|
|
190
|
+
background: woven.token(bg-alternate);
|
|
191
|
+
|
|
192
|
+
& + .wu-tabs-tab {
|
|
193
|
+
margin-inline-start: calc(-1 * #{woven.token(border-width-1)});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
&:first-child {
|
|
197
|
+
border-start-start-radius: woven.token(radius-md);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
&:last-child {
|
|
201
|
+
border-start-end-radius: woven.token(radius-md);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
&[aria-selected="true"] {
|
|
205
|
+
border-block-end-color: transparent;
|
|
206
|
+
background: transparent;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Boxed: the list line is an inset shadow, so the selected tab's background can cover it
|
|
211
|
+
.wu-tabs.boxed > .wu-tabs-list {
|
|
212
|
+
border-block-end: 0;
|
|
213
|
+
box-shadow: inset 0 calc(-1 * #{woven.token(border-width-1)}) 0 woven.token(border-regular);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Boxed: tabs and panels inside one bordered box, the selected tab joined to the panel
|
|
217
|
+
.wu-tabs.boxed {
|
|
218
|
+
border: woven.token(border-width-1) solid woven.token(border-regular);
|
|
219
|
+
border-radius: woven.token(radius-md);
|
|
220
|
+
background: woven.token(bg-surface);
|
|
221
|
+
|
|
222
|
+
> .wu-tabs-list {
|
|
223
|
+
gap: 0;
|
|
224
|
+
border-start-start-radius: calc(#{woven.token(radius-md)} - #{woven.token(border-width-1)});
|
|
225
|
+
border-start-end-radius: calc(#{woven.token(radius-md)} - #{woven.token(border-width-1)});
|
|
226
|
+
background: woven.token(bg-alternate);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
> .wu-tabs-list > .wu-tabs-tab {
|
|
230
|
+
border-inline: woven.token(border-width-1) solid transparent;
|
|
231
|
+
border-radius: 0;
|
|
232
|
+
|
|
233
|
+
&[aria-selected="true"] {
|
|
234
|
+
border-inline-color: woven.token(border-regular);
|
|
235
|
+
background: woven.token(bg-surface);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
&:first-child {
|
|
239
|
+
border-inline-start-color: transparent;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
> .wu-tabs-panel {
|
|
244
|
+
padding: woven.token(space-4);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.wu-tabs:is(.card, .boxed) > .wu-tabs-list > .wu-tabs-tab::after {
|
|
249
|
+
content: none;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Vertical: the list sits at the inline start, the selected bar on its inline end edge
|
|
253
|
+
.wu-tabs.vertical {
|
|
254
|
+
display: flex;
|
|
255
|
+
align-items: flex-start;
|
|
256
|
+
|
|
257
|
+
> .wu-tabs-list {
|
|
258
|
+
flex: none;
|
|
259
|
+
flex-direction: column;
|
|
260
|
+
align-self: stretch;
|
|
261
|
+
border-block-end: 0;
|
|
262
|
+
border-inline-end: woven.token(border-width-1) solid woven.token(border-regular);
|
|
263
|
+
overflow: visible;
|
|
264
|
+
mask-image: none;
|
|
265
|
+
animation: none;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
> .wu-tabs-list > .wu-tabs-tab {
|
|
269
|
+
border-radius: 0;
|
|
270
|
+
border-start-start-radius: woven.token(radius-sm);
|
|
271
|
+
border-end-start-radius: woven.token(radius-sm);
|
|
272
|
+
justify-content: flex-start;
|
|
273
|
+
text-align: start;
|
|
274
|
+
|
|
275
|
+
&::after {
|
|
276
|
+
inset-block: 0;
|
|
277
|
+
inset-inline: auto 0;
|
|
278
|
+
inline-size: woven.token(border-width-2);
|
|
279
|
+
block-size: auto;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
> .wu-tabs-panel {
|
|
284
|
+
flex: 1;
|
|
285
|
+
min-inline-size: 0;
|
|
286
|
+
padding-block: woven.token(space-2);
|
|
287
|
+
padding-inline: woven.token(space-4);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Opt-in motion: the bar grows from the center, the panel fades in
|
|
292
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
293
|
+
.wu-tabs.animated,
|
|
294
|
+
.wu-animated .wu-tabs {
|
|
295
|
+
.wu-tabs-tab::after {
|
|
296
|
+
scale: 0 1;
|
|
297
|
+
transition:
|
|
298
|
+
scale woven.token(duration-300) var(--wu-kit-ease-spring),
|
|
299
|
+
background-color woven.token(duration-150) woven.token(ease-out);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.wu-tabs-tab[aria-selected="true"]::after {
|
|
303
|
+
scale: 1;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
&.vertical .wu-tabs-tab:not([aria-selected="true"])::after {
|
|
307
|
+
scale: 1 0;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.wu-tabs-panel {
|
|
311
|
+
transition:
|
|
312
|
+
opacity woven.token(duration-200) woven.token(ease-out),
|
|
313
|
+
translate woven.token(duration-200) woven.token(ease-out);
|
|
314
|
+
|
|
315
|
+
@starting-style {
|
|
316
|
+
opacity: 0;
|
|
317
|
+
translate: 0 woven.token(space-1);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
@media (forced-colors: active) {
|
|
324
|
+
.wu-tabs-tab[aria-selected="true"]::after {
|
|
325
|
+
background: Highlight;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
////
|
|
2
|
+
//// @component wu-tag
|
|
3
|
+
//// Label for a category or a filter, in seven hues, as plain text, a link or a button.
|
|
4
|
+
////
|
|
5
|
+
//// A link or button tag gets a pointer, a hover color and the focus ring. `aria-pressed` on a button tag makes a checkable filter chip; toggling the attribute is up to your script.
|
|
6
|
+
////
|
|
7
|
+
//// A direct child `svg` is sized to `1em`. The remove button needs an `aria-label` that names the tag.
|
|
8
|
+
////
|
|
9
|
+
//// @since 1.0.0
|
|
10
|
+
//// @needs none
|
|
11
|
+
//// @js none
|
|
12
|
+
//// @example html
|
|
13
|
+
//// <span class="wu-tag">Design</span>
|
|
14
|
+
//// <span class="wu-tag blue">Frontend</span>
|
|
15
|
+
//// @example html
|
|
16
|
+
//// <div role="group" aria-label="Filter by topic">
|
|
17
|
+
//// <button class="wu-tag" type="button" aria-pressed="true">Design</button>
|
|
18
|
+
//// <button class="wu-tag" type="button" aria-pressed="false">Research</button>
|
|
19
|
+
//// </div>
|
|
20
|
+
//// @example html
|
|
21
|
+
//// <span class="wu-tag purple">Research <button class="wu-tag-remove" type="button" aria-label="Remove Research"></button></span>
|
|
22
|
+
//// @modifier gray | red | blue | green | yellow | purple | pink - Hue color: subtle background, hue border and hue text @since 1.0.0
|
|
23
|
+
//// @part wu-tag-remove - Remove button inside the tag, its cross drawn in CSS @since 1.0.0
|
|
24
|
+
//// @state aria-pressed="true" - On a button tag: brand tint, ring and a check mark @since 1.0.0
|
|
25
|
+
////
|
|
26
|
+
|
|
27
|
+
@use "@wovenui/core/mixins" as woven;
|
|
28
|
+
|
|
29
|
+
$hues: "gray", "red", "blue", "green", "yellow", "purple", "pink";
|
|
30
|
+
|
|
31
|
+
.wu-tag {
|
|
32
|
+
display: inline-flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
gap: woven.token(space-1);
|
|
35
|
+
min-height: woven.token(space-6);
|
|
36
|
+
padding-inline: woven.token(space-2);
|
|
37
|
+
border: woven.token(border-width-1) solid woven.token(border-regular);
|
|
38
|
+
border-radius: woven.token(radius-sm);
|
|
39
|
+
background: woven.token(bg-surface);
|
|
40
|
+
color: woven.token(text-regular);
|
|
41
|
+
font: inherit;
|
|
42
|
+
font-size: woven.token(font-size-xs);
|
|
43
|
+
font-weight: woven.token(font-weight-medium);
|
|
44
|
+
line-height: 1;
|
|
45
|
+
text-decoration: none;
|
|
46
|
+
white-space: nowrap;
|
|
47
|
+
vertical-align: middle;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// App svg beside the label
|
|
51
|
+
.wu-tag > svg {
|
|
52
|
+
flex-shrink: 0;
|
|
53
|
+
width: 1em;
|
|
54
|
+
height: 1em;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Link and button tags are interactive
|
|
58
|
+
.wu-tag:is(a[href], button) {
|
|
59
|
+
cursor: pointer;
|
|
60
|
+
transition-property: background-color, border-color;
|
|
61
|
+
transition-duration: woven.token(duration-150);
|
|
62
|
+
transition-timing-function: woven.token(ease-out);
|
|
63
|
+
|
|
64
|
+
&:hover {
|
|
65
|
+
border-color: woven.token(border-strong);
|
|
66
|
+
background: woven.token(bg-hover);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Checkable chip: aria-pressed on a button tag. A check mark and a ring carry the state, not color alone
|
|
71
|
+
.wu-tag:is(button)[aria-pressed="true"] {
|
|
72
|
+
border-color: woven.token(brand-border);
|
|
73
|
+
background: woven.token(brand-subtle);
|
|
74
|
+
color: woven.token(text-brand);
|
|
75
|
+
box-shadow: inset 0 0 0 woven.token(border-width-1) woven.token(brand-border);
|
|
76
|
+
|
|
77
|
+
&::before {
|
|
78
|
+
content: "";
|
|
79
|
+
flex-shrink: 0;
|
|
80
|
+
width: 0.5em;
|
|
81
|
+
height: 0.9em;
|
|
82
|
+
margin-block-start: -0.2em;
|
|
83
|
+
border-bottom: 0.15em solid currentcolor;
|
|
84
|
+
border-right: 0.15em solid currentcolor;
|
|
85
|
+
rotate: 45deg;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
&:hover {
|
|
89
|
+
border-color: woven.token(brand);
|
|
90
|
+
background: woven.token(brand-subtle);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@each $hue in $hues {
|
|
95
|
+
.wu-tag.#{$hue} {
|
|
96
|
+
border-color: woven.token(#{$hue}-border);
|
|
97
|
+
background: woven.token(#{$hue}-subtle);
|
|
98
|
+
color: woven.token(text-#{$hue});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Remove button, the cross drawn with two rotated bars
|
|
103
|
+
.wu-tag-remove {
|
|
104
|
+
display: inline-grid;
|
|
105
|
+
place-items: center;
|
|
106
|
+
width: woven.token(space-5);
|
|
107
|
+
height: woven.token(space-5);
|
|
108
|
+
min-height: 0;
|
|
109
|
+
margin-inline-end: calc(-1 * #{woven.token(space-1)});
|
|
110
|
+
padding: 0;
|
|
111
|
+
border: 0;
|
|
112
|
+
border-radius: woven.token(radius-xs);
|
|
113
|
+
background: transparent;
|
|
114
|
+
color: inherit;
|
|
115
|
+
font: inherit;
|
|
116
|
+
line-height: 1;
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
|
|
119
|
+
&::before,
|
|
120
|
+
&::after {
|
|
121
|
+
content: "";
|
|
122
|
+
grid-area: 1 / 1;
|
|
123
|
+
width: woven.token(space-2);
|
|
124
|
+
height: woven.token(border-width-2);
|
|
125
|
+
border-radius: woven.token(radius-full);
|
|
126
|
+
background: currentcolor;
|
|
127
|
+
rotate: 45deg;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
&::after {
|
|
131
|
+
rotate: -45deg;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
&:hover {
|
|
135
|
+
background: color-mix(in srgb, currentcolor 15%, transparent);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.wu-tag:is(a[href], button):focus-visible,
|
|
140
|
+
.wu-tag-remove:focus-visible {
|
|
141
|
+
outline: woven.token(border-focus-width) solid woven.token(border-focus);
|
|
142
|
+
outline-offset: woven.token(border-focus-offset);
|
|
143
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
////
|
|
2
|
+
//// @component wu-text
|
|
3
|
+
//// Body text on any element, with relaxed leading and space between paragraphs in a row.
|
|
4
|
+
////
|
|
5
|
+
//// @since 1.0.0
|
|
6
|
+
//// @needs none
|
|
7
|
+
//// @js none
|
|
8
|
+
//// @example html
|
|
9
|
+
//// <p class="wu-text lg">A lead paragraph introduces the page.</p>
|
|
10
|
+
//// <p class="wu-text">Body text follows with relaxed leading.</p>
|
|
11
|
+
//// <p class="wu-text sm muted">Small, muted text for notes and fine print.</p>
|
|
12
|
+
//// @modifier sm - Small size @since 1.0.0
|
|
13
|
+
//// @modifier lg - Large size, for a lead paragraph @since 1.0.0
|
|
14
|
+
//// @modifier muted - Muted color @since 1.0.0
|
|
15
|
+
////
|
|
16
|
+
|
|
17
|
+
@use "@wovenui/core/mixins" as woven;
|
|
18
|
+
|
|
19
|
+
.wu-text {
|
|
20
|
+
margin: 0;
|
|
21
|
+
color: woven.token(text-regular);
|
|
22
|
+
font-size: woven.token(font-size-md);
|
|
23
|
+
line-height: woven.token(line-height-relaxed);
|
|
24
|
+
text-wrap: pretty;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.wu-text + .wu-text {
|
|
28
|
+
margin-block-start: woven.token(space-3);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.wu-text.sm {
|
|
32
|
+
font-size: woven.token(font-size-sm);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Lead paragraph
|
|
36
|
+
.wu-text.lg {
|
|
37
|
+
font-size: woven.token(font-size-lg);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.wu-text.muted {
|
|
41
|
+
color: woven.token(text-muted);
|
|
42
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
////
|
|
2
|
+
//// @component wu-textarea
|
|
3
|
+
//// Multi-line field with a bounded height that grows with the content, where the browser supports it.
|
|
4
|
+
////
|
|
5
|
+
//// Core base already styles a `textarea` like an input (border, focus ring, invalid border, disabled). The kit adds the radius, the type size and a height between three and twelve lines.
|
|
6
|
+
////
|
|
7
|
+
//// Growth uses `field-sizing: content`, and `rows` is ignored there.
|
|
8
|
+
////
|
|
9
|
+
//// @since 1.0.0
|
|
10
|
+
//// @needs none
|
|
11
|
+
//// @js none
|
|
12
|
+
//// @example html
|
|
13
|
+
//// <div class="wu-field">
|
|
14
|
+
//// <label class="wu-field-label" for="textarea-notes">Notes</label>
|
|
15
|
+
//// <textarea class="wu-textarea" id="textarea-notes">Type more lines to see the field grow.</textarea>
|
|
16
|
+
//// </div>
|
|
17
|
+
//// @example html
|
|
18
|
+
//// <textarea class="wu-textarea" aria-label="Short note" style="--wu-textarea--MinHeight: 2.5rem; --wu-textarea--MaxHeight: 6rem">One line to start.</textarea>
|
|
19
|
+
//// @variable --wu-textarea--MinHeight [3 lines plus padding and border] - Minimum height @since 1.0.0
|
|
20
|
+
//// @variable --wu-textarea--MaxHeight [12 lines plus padding and border] - Maximum height @since 1.0.0
|
|
21
|
+
//// @state :disabled - Not-allowed cursor and no resize @since 1.0.0
|
|
22
|
+
//// @state readonly - Alternate background @since 1.0.0
|
|
23
|
+
//// @state aria-invalid="true" | :user-invalid - Danger border doubled to 2px, so the change is not color alone @since 1.0.0
|
|
24
|
+
////
|
|
25
|
+
|
|
26
|
+
@use "@wovenui/core/mixins" as woven;
|
|
27
|
+
|
|
28
|
+
.wu-textarea {
|
|
29
|
+
display: block;
|
|
30
|
+
min-height: var(--wu-textarea--MinHeight, calc(3lh + 2 * #{woven.token(space-2)} + 2 * #{woven.token(border-width-1)}));
|
|
31
|
+
max-height: var(--wu-textarea--MaxHeight, calc(12lh + 2 * #{woven.token(space-2)} + 2 * #{woven.token(border-width-1)}));
|
|
32
|
+
border-radius: woven.token(radius-md);
|
|
33
|
+
font-size: woven.token(font-size-md);
|
|
34
|
+
line-height: woven.token(line-height-normal);
|
|
35
|
+
resize: vertical;
|
|
36
|
+
|
|
37
|
+
&:disabled {
|
|
38
|
+
cursor: not-allowed;
|
|
39
|
+
resize: none;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&[readonly] {
|
|
43
|
+
background-color: woven.token(bg-alternate);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Invalid: core's danger border doubled to 2px, so the change is not color alone
|
|
47
|
+
&:is([aria-invalid="true"], :user-invalid) {
|
|
48
|
+
box-shadow: inset 0 0 0 woven.token(border-width-1) woven.token(danger);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Grows with typing between the min and max height; rows is ignored here
|
|
53
|
+
@supports (field-sizing: content) {
|
|
54
|
+
.wu-textarea {
|
|
55
|
+
field-sizing: content;
|
|
56
|
+
}
|
|
57
|
+
}
|