@threadlabs/looma 0.7.3 → 0.7.4
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/components/ui-badge/ui-badge.html +20 -0
- package/components/ui-button/ui-button.html +36 -13
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/styles/ui-badge.css +22 -0
- package/styles/ui-button.css +18 -12
- package/vanilla/UiBadge.d.ts +1 -0
- package/vanilla/UiBadge.js +4 -2
- package/vanilla/UiButton.d.ts +5 -0
- package/vanilla/UiButton.js +8 -6
- package/vue/UiBadge.d.ts +2 -0
- package/vue/UiBadge.vue +29 -0
- package/vue/UiButton.d.ts +9 -2
- package/vue/UiButton.vue +46 -16
- package/vue/chunks/UiBadge.js +7 -2
- package/vue/chunks/UiButton.js +52 -10
- package/vue/components.css +76 -47
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
<defs>
|
|
3
3
|
<prop name="variant" type="solid | subtle" default="subtle">variant token.</prop>
|
|
4
4
|
<prop name="tone" type="neutral | accent | info | success | warning | danger" default="neutral">tone token.</prop>
|
|
5
|
+
<prop name="shape" type="pill | tag" default="pill"
|
|
6
|
+
>Silhouette. pill is rounded at both ends; tag is a label: flat at the start and coming to a point at the end, for a tag or a chosen chip.</prop>
|
|
5
7
|
</defs>
|
|
6
8
|
<span><slot></slot></span>
|
|
7
9
|
<style>
|
|
@@ -100,6 +102,24 @@
|
|
|
100
102
|
--_badge-text: var(--ui-info-subtle-text, var(--ui-info-solid));
|
|
101
103
|
}
|
|
102
104
|
|
|
105
|
+
/* A tag is flat at the start and points at the end. The point is cut from the box, so it has no
|
|
106
|
+
outline to follow: the edge is the fill. The end padding grows by the point's depth so the
|
|
107
|
+
label never runs into it. */
|
|
108
|
+
:host-state([shape="tag"]) {
|
|
109
|
+
--_badge-point: var(--ui-badge-point, var(--ui-space-2));
|
|
110
|
+
|
|
111
|
+
border-color: transparent;
|
|
112
|
+
border-radius: 0;
|
|
113
|
+
padding-inline-end: calc(var(--ui-badge-padding-inline, var(--ui-space-2)) + var(--_badge-point));
|
|
114
|
+
clip-path: polygon(0 0, calc(100% - var(--_badge-point)) 0, 100% 50%, calc(100% - var(--_badge-point)) 100%, 0 100%);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
:host-state([shape="tag"]):dir(rtl) {
|
|
118
|
+
padding-inline-end: var(--ui-badge-padding-inline, var(--ui-space-2));
|
|
119
|
+
padding-inline-start: calc(var(--ui-badge-padding-inline, var(--ui-space-2)) + var(--_badge-point));
|
|
120
|
+
clip-path: polygon(var(--_badge-point) 0, 100% 0, 100% 100%, var(--_badge-point) 100%, 0 50%);
|
|
121
|
+
}
|
|
122
|
+
|
|
103
123
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
104
124
|
:host[hidden] {
|
|
105
125
|
display: none;
|
|
@@ -11,8 +11,28 @@
|
|
|
11
11
|
<prop name="align" type="center | start" default="center"
|
|
12
12
|
>Content alignment. start lays the content out like a list option: from the start edge, with start-aligned text.</prop>
|
|
13
13
|
<prop name="stretch" type="boolean" default="false">Fills the inline size of its container.</prop>
|
|
14
|
+
<prop name="type" type="button | submit | reset" default="button"
|
|
15
|
+
>The button's type, as on a native button. button by default, so it never submits a form by accident. A link has no type.</prop>
|
|
16
|
+
<prop name="href" type="string"
|
|
17
|
+
>The link's destination. Pair it with as="a" so the button renders as a real link that navigates. A disabled link drops its href and states
|
|
18
|
+
aria-disabled="true", so it cannot be followed.</prop>
|
|
19
|
+
<prop name="target" type="string">Where a link opens, as on a native link. Only meaningful with as="a".</prop>
|
|
20
|
+
<prop name="rel" type="string">The link's relationship to its destination, as on a native link. Only meaningful with as="a".</prop>
|
|
21
|
+
<!-- One root, a button or a link (as="a"). The language has no conditional expression, so a table keyed
|
|
22
|
+
by a boolean's text picks each value, and null leaves the attribute off: a link never carries type or
|
|
23
|
+
disabled, and a disabled link loses its href and states aria-disabled instead. -->
|
|
14
24
|
</defs>
|
|
15
|
-
<button
|
|
25
|
+
<button
|
|
26
|
+
as="button|a"
|
|
27
|
+
:type="{ true: type, false: null }[format('%s', not href)]"
|
|
28
|
+
:disabled="{ true: true, false: null }[format('%s', disabled and not href)]"
|
|
29
|
+
:href="{ true: null, false: href }[format('%s', disabled)]"
|
|
30
|
+
:target="target"
|
|
31
|
+
:rel="rel"
|
|
32
|
+
:aria-disabled="{ true: 'true', false: null }[format('%s', disabled and href)]"
|
|
33
|
+
>
|
|
34
|
+
<slot></slot>
|
|
35
|
+
</button>
|
|
16
36
|
<style>
|
|
17
37
|
:host {
|
|
18
38
|
--_hue: var(--ui-accent);
|
|
@@ -55,6 +75,7 @@
|
|
|
55
75
|
color: var(--ui-button-text, var(--_tone-text));
|
|
56
76
|
font: inherit;
|
|
57
77
|
font-weight: var(--ui-font-medium);
|
|
78
|
+
text-decoration: none;
|
|
58
79
|
line-height: var(--ui-line-height-tight);
|
|
59
80
|
padding: var(--ui-space-2) var(--ui-space-3);
|
|
60
81
|
background-image: var(--ui-raised-highlight);
|
|
@@ -87,13 +108,15 @@
|
|
|
87
108
|
font-size: 1rem;
|
|
88
109
|
}
|
|
89
110
|
|
|
90
|
-
:
|
|
111
|
+
/* A link is never :enabled, so interactive states test "not unavailable" instead: for a button that
|
|
112
|
+
is exactly :enabled, at the same specificity, and it also matches a link that can be followed. */
|
|
113
|
+
:host:hover:not(:disabled, [aria-disabled="true"]) {
|
|
91
114
|
border-color: var(--ui-button-hover-border, var(--_tone-hover));
|
|
92
115
|
background-color: var(--ui-button-hover-surface, oklch(from var(--_tone) l c h / 12%));
|
|
93
116
|
}
|
|
94
117
|
|
|
95
118
|
/* Pressed reads as pressed in: the highlight goes, and the shadow moves inside. */
|
|
96
|
-
:host:active:
|
|
119
|
+
:host:active:not(:disabled, [aria-disabled="true"]) {
|
|
97
120
|
background-color: var(--ui-button-active-surface, oklch(from var(--_tone) l c h / 18%));
|
|
98
121
|
background-image: none;
|
|
99
122
|
box-shadow: var(--ui-pressed);
|
|
@@ -106,12 +129,12 @@
|
|
|
106
129
|
box-shadow: var(--ui-button-solid-shadow, var(--ui-raised));
|
|
107
130
|
}
|
|
108
131
|
|
|
109
|
-
:is(:host-state([variant="solid"]), :host-state([variant="danger"])):hover:
|
|
132
|
+
:is(:host-state([variant="solid"]), :host-state([variant="danger"])):hover:not(:disabled, [aria-disabled="true"]) {
|
|
110
133
|
background-color: var(--_tone-hover);
|
|
111
134
|
border-color: var(--_tone-hover);
|
|
112
135
|
}
|
|
113
136
|
|
|
114
|
-
:is(:host-state([variant="solid"]), :host-state([variant="danger"])):active:
|
|
137
|
+
:is(:host-state([variant="solid"]), :host-state([variant="danger"])):active:not(:disabled, [aria-disabled="true"]) {
|
|
115
138
|
background-color: var(--_tone-active);
|
|
116
139
|
border-color: var(--_tone-active);
|
|
117
140
|
background-image: none;
|
|
@@ -168,12 +191,12 @@
|
|
|
168
191
|
}
|
|
169
192
|
|
|
170
193
|
/* Tints derive from the text colour, not a surface token, so hover and press show on any background. */
|
|
171
|
-
:host-state([variant="ghost"]):hover:
|
|
194
|
+
:host-state([variant="ghost"]):hover:not(:disabled, [aria-disabled="true"]) {
|
|
172
195
|
background-color: var(--ui-button-ghost-hover-surface, oklch(from var(--_tone) l c h / 10%));
|
|
173
196
|
border-color: transparent;
|
|
174
197
|
}
|
|
175
198
|
|
|
176
|
-
:host-state([variant="ghost"]):active:
|
|
199
|
+
:host-state([variant="ghost"]):active:not(:disabled, [aria-disabled="true"]) {
|
|
177
200
|
background-color: var(--ui-button-ghost-active-surface, oklch(from var(--_tone) l c h / 16%));
|
|
178
201
|
border-color: transparent;
|
|
179
202
|
box-shadow: var(--ui-pressed);
|
|
@@ -197,7 +220,7 @@
|
|
|
197
220
|
disabled outline is still an outline and a disabled ghost still has no edge. Intent goes — an
|
|
198
221
|
unavailable action says "unavailable", not "unavailable, and destructive" — and so do the
|
|
199
222
|
highlight and shadow, because nothing that cannot be pressed should look raised. */
|
|
200
|
-
:host:disabled {
|
|
223
|
+
:host:is(:disabled, [aria-disabled="true"]) {
|
|
201
224
|
/* Derived from the tone itself, not from a separate disabled palette: faded toward the
|
|
202
225
|
page, which desaturates it at the same time. Toward the page rather than toward white,
|
|
203
226
|
so a dark theme dims where a light one lightens — the same rule, both schemes. */
|
|
@@ -214,7 +237,7 @@
|
|
|
214
237
|
}
|
|
215
238
|
|
|
216
239
|
/* A filled button keeps its fill, faded further so its text stays legible on it. */
|
|
217
|
-
:is(:host-state([variant="solid"]), :host-state([variant="danger"])):disabled {
|
|
240
|
+
:is(:host-state([variant="solid"]), :host-state([variant="danger"])):is(:disabled, [aria-disabled="true"]) {
|
|
218
241
|
--_tone: color-mix(in oklab, var(--_hue) 34%, var(--ui-surface));
|
|
219
242
|
}
|
|
220
243
|
|
|
@@ -222,7 +245,7 @@
|
|
|
222
245
|
it takes a surface rather than reading as plain text. The surface is a wash of the faded tone,
|
|
223
246
|
the way hover washes the live one, so it stays light in every tone. An opaque mix toward the
|
|
224
247
|
hue came out a mid-grey slab for neutral, whose hue is the ink: louder than the enabled button. */
|
|
225
|
-
:host-state([variant="ghost"]):disabled {
|
|
248
|
+
:host-state([variant="ghost"]):is(:disabled, [aria-disabled="true"]) {
|
|
226
249
|
background-color: oklch(from var(--_tone) l c h / 14%);
|
|
227
250
|
border-color: transparent;
|
|
228
251
|
}
|
|
@@ -252,19 +275,19 @@
|
|
|
252
275
|
transition: color var(--ui-motion-fast) var(--ui-motion-ease), text-decoration-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
253
276
|
}
|
|
254
277
|
|
|
255
|
-
:host-state([variant="link"]):hover:
|
|
278
|
+
:host-state([variant="link"]):hover:not(:disabled, [aria-disabled="true"]) {
|
|
256
279
|
color: var(--ui-button-link-hover-text, var(--ui-text-primary));
|
|
257
280
|
text-decoration-color: currentColor;
|
|
258
281
|
background: none;
|
|
259
282
|
transform: none;
|
|
260
283
|
}
|
|
261
284
|
|
|
262
|
-
:host-state([variant="link"]):active:
|
|
285
|
+
:host-state([variant="link"]):active:not(:disabled, [aria-disabled="true"]) {
|
|
263
286
|
background: none;
|
|
264
287
|
transform: none;
|
|
265
288
|
}
|
|
266
289
|
|
|
267
|
-
:host-state([variant="link"]):disabled {
|
|
290
|
+
:host-state([variant="link"]):is(:disabled, [aria-disabled="true"]) {
|
|
268
291
|
background: none;
|
|
269
292
|
border-color: transparent;
|
|
270
293
|
color: var(--ui-button-disabled-text, var(--ui-disabled-text));
|