al-design-system 1.6.0 → 1.8.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/README.md +8 -5
- package/README.pt-BR.md +8 -5
- package/dist/al.css +572 -2
- package/dist/components/empty-state.css +143 -0
- package/dist/components/rating.css +192 -0
- package/dist/components/slider.css +232 -0
- package/dist/components/slider.js +52 -0
- package/dist/foundation.css +1 -1
- package/dist/tokens.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ An open-source design system, from Figma to code. Plain CSS, a little vanilla Ja
|
|
|
10
10
|
|
|
11
11
|
## What it is
|
|
12
12
|
|
|
13
|
-
- **Foundation +
|
|
13
|
+
- **Foundation + 32 components**, designed in Figma and coded from the same tokens.
|
|
14
14
|
- **Light and dark themes** built in. It follows the operating system by default, and you can force one.
|
|
15
15
|
- **Accessibility is checked by the build.** Every rendered combination (variant × state × theme) is measured for contrast against the background it actually sits on, and each component's markup contract is verified. If something fails, the build stops.
|
|
16
16
|
- **Nothing is typed by hand.** Tokens, CSS variables, `tokens.json` and the documentation tables are all generated from one source.
|
|
@@ -34,6 +34,8 @@ An open-source design system, from Figma to code. Plain CSS, a little vanilla Ja
|
|
|
34
34
|
| | Textarea | | [guidelines](src/components/textarea/guidelines.md) |
|
|
35
35
|
| | Password | ✓ | [guidelines](src/components/password/guidelines.md) |
|
|
36
36
|
| | Number field | ✓ | [guidelines](src/components/number-field/guidelines.md) |
|
|
37
|
+
| | Slider | ✓ | [guidelines](src/components/slider/guidelines.md) |
|
|
38
|
+
| | Rating | | [guidelines](src/components/rating/guidelines.md) |
|
|
37
39
|
| Structure and overlays | Divider | | [guidelines](src/components/divider/guidelines.md) |
|
|
38
40
|
| | Card | | [guidelines](src/components/card/guidelines.md) |
|
|
39
41
|
| | Tab | ✓ | [guidelines](src/components/tab/guidelines.md) |
|
|
@@ -48,6 +50,7 @@ An open-source design system, from Figma to code. Plain CSS, a little vanilla Ja
|
|
|
48
50
|
| | Toast | ✓ | [guidelines](src/components/toast/guidelines.md) |
|
|
49
51
|
| | Alert | ✓ | [guidelines](src/components/alert/guidelines.md) |
|
|
50
52
|
| | Progress | | [guidelines](src/components/progress/guidelines.md) |
|
|
53
|
+
| | Empty state | | [guidelines](src/components/empty-state/guidelines.md) |
|
|
51
54
|
|
|
52
55
|
Each guidelines file holds the usage rules (when to use it, when not to, content, behavior and accessibility) and, when there are any, the contrast exceptions the component declares.
|
|
53
56
|
|
|
@@ -60,7 +63,7 @@ npm install al-design-system
|
|
|
60
63
|
Or straight from a CDN, pinned to a version:
|
|
61
64
|
|
|
62
65
|
```html
|
|
63
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/al-design-system@1.
|
|
66
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/al-design-system@1.8.0/dist/al.css">
|
|
64
67
|
```
|
|
65
68
|
|
|
66
69
|
Each [GitHub Release](https://github.com/guilhermedworakowski/al-design-system/releases) also carries the `dist/` folder as a zip.
|
|
@@ -69,10 +72,10 @@ Each [GitHub Release](https://github.com/guilhermedworakowski/al-design-system/r
|
|
|
69
72
|
|
|
70
73
|
| File | What it is |
|
|
71
74
|
|---|---|
|
|
72
|
-
| `al.css` | Foundation + all
|
|
75
|
+
| `al.css` | Foundation + all 32 components, in one file |
|
|
73
76
|
| `foundation.css` | Only the Foundation: color, typography, spacing, radius, icon size, elevation, focus ring and motion |
|
|
74
77
|
| `components/<name>.css` | One component (its tokens + its CSS) |
|
|
75
|
-
| `components/<name>.js` | The behavior, for the
|
|
78
|
+
| `components/<name>.js` | The behavior, for the 12 components that have a script |
|
|
76
79
|
| `icons/*.svg`, `icons/icons.json` | The 70 icons |
|
|
77
80
|
| `tokens.json` | The Foundation tokens, to read from code |
|
|
78
81
|
|
|
@@ -103,7 +106,7 @@ The exact markup of each component (which element, which attributes) is describe
|
|
|
103
106
|
|
|
104
107
|
### Scripts
|
|
105
108
|
|
|
106
|
-
Password, Number field, Menu, Tab, Modal, Drawer, Sidebar, Breadcrumb, Tooltip, Toast and Alert need their script, loaded once per page. Each one wires up the components already on the page by itself:
|
|
109
|
+
Password, Number field, Slider, Menu, Tab, Modal, Drawer, Sidebar, Breadcrumb, Tooltip, Toast and Alert need their script, loaded once per page. Each one wires up the components already on the page by itself:
|
|
107
110
|
|
|
108
111
|
```html
|
|
109
112
|
<script src="node_modules/al-design-system/dist/components/modal.js" defer></script>
|
package/README.pt-BR.md
CHANGED
|
@@ -10,7 +10,7 @@ Design system open source, do Figma ao código. CSS puro, um pouco de JavaScript
|
|
|
10
10
|
|
|
11
11
|
## O que é
|
|
12
12
|
|
|
13
|
-
- **Foundation +
|
|
13
|
+
- **Foundation + 32 componentes**, desenhados no Figma e codados a partir dos mesmos tokens.
|
|
14
14
|
- **Temas claro e escuro** já incluídos. Por padrão segue o sistema operacional, e dá para forçar um.
|
|
15
15
|
- **A acessibilidade é conferida no build.** Cada combinação renderizada (variante × estado × tema) tem o contraste medido contra o fundo onde ela realmente aparece, e o contrato de marcação de cada componente é verificado. Se algo reprova, o build para.
|
|
16
16
|
- **Nada é digitado à mão.** Tokens, variáveis CSS, `tokens.json` e as tabelas da documentação saem todos de uma fonte só.
|
|
@@ -34,6 +34,8 @@ Design system open source, do Figma ao código. CSS puro, um pouco de JavaScript
|
|
|
34
34
|
| | Textarea | | [diretrizes](src/components/textarea/guidelines.md) |
|
|
35
35
|
| | Password | ✓ | [diretrizes](src/components/password/guidelines.md) |
|
|
36
36
|
| | Number field | ✓ | [diretrizes](src/components/number-field/guidelines.md) |
|
|
37
|
+
| | Slider | ✓ | [diretrizes](src/components/slider/guidelines.md) |
|
|
38
|
+
| | Rating | | [diretrizes](src/components/rating/guidelines.md) |
|
|
37
39
|
| Estrutura e sobreposição | Divider | | [diretrizes](src/components/divider/guidelines.md) |
|
|
38
40
|
| | Card | | [diretrizes](src/components/card/guidelines.md) |
|
|
39
41
|
| | Tab | ✓ | [diretrizes](src/components/tab/guidelines.md) |
|
|
@@ -48,6 +50,7 @@ Design system open source, do Figma ao código. CSS puro, um pouco de JavaScript
|
|
|
48
50
|
| | Toast | ✓ | [diretrizes](src/components/toast/guidelines.md) |
|
|
49
51
|
| | Alert | ✓ | [diretrizes](src/components/alert/guidelines.md) |
|
|
50
52
|
| | Progress | | [diretrizes](src/components/progress/guidelines.md) |
|
|
53
|
+
| | Empty state | | [diretrizes](src/components/empty-state/guidelines.md) |
|
|
51
54
|
|
|
52
55
|
Cada arquivo de diretrizes traz as regras de uso (quando usar, quando não usar, conteúdo, comportamento e acessibilidade) e, quando houver, as exceções de contraste que o componente declara. Por enquanto as diretrizes estão em inglês; a versão em português chega junto com o site novo.
|
|
53
56
|
|
|
@@ -60,7 +63,7 @@ npm install al-design-system
|
|
|
60
63
|
Ou direto de uma CDN, fixado numa versão:
|
|
61
64
|
|
|
62
65
|
```html
|
|
63
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/al-design-system@1.
|
|
66
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/al-design-system@1.8.0/dist/al.css">
|
|
64
67
|
```
|
|
65
68
|
|
|
66
69
|
Cada [Release no GitHub](https://github.com/guilhermedworakowski/al-design-system/releases) também traz a pasta `dist/` num zip.
|
|
@@ -69,10 +72,10 @@ Cada [Release no GitHub](https://github.com/guilhermedworakowski/al-design-syste
|
|
|
69
72
|
|
|
70
73
|
| Arquivo | O que é |
|
|
71
74
|
|---|---|
|
|
72
|
-
| `al.css` | Foundation + os
|
|
75
|
+
| `al.css` | Foundation + os 32 componentes, num arquivo só |
|
|
73
76
|
| `foundation.css` | Só a Foundation: cor, tipografia, espaçamento, radius, tamanho de ícone, elevação, anel de foco e motion |
|
|
74
77
|
| `components/<nome>.css` | Um componente (os tokens + o CSS dele) |
|
|
75
|
-
| `components/<nome>.js` | O comportamento, para os
|
|
78
|
+
| `components/<nome>.js` | O comportamento, para os 12 componentes que têm script |
|
|
76
79
|
| `icons/*.svg`, `icons/icons.json` | Os 70 ícones |
|
|
77
80
|
| `tokens.json` | Os tokens da Foundation, para ler por código |
|
|
78
81
|
|
|
@@ -103,7 +106,7 @@ A marcação exata de cada componente (qual elemento, quais atributos) está des
|
|
|
103
106
|
|
|
104
107
|
### Scripts
|
|
105
108
|
|
|
106
|
-
Password, Number field, Menu, Tab, Modal, Drawer, Sidebar, Breadcrumb, Tooltip, Toast e Alert precisam do script, carregado uma vez por página. Cada um liga sozinho os componentes que já estão na página:
|
|
109
|
+
Password, Number field, Slider, Menu, Tab, Modal, Drawer, Sidebar, Breadcrumb, Tooltip, Toast e Alert precisam do script, carregado uma vez por página. Cada um liga sozinho os componentes que já estão na página:
|
|
107
110
|
|
|
108
111
|
```html
|
|
109
112
|
<script src="node_modules/al-design-system/dist/components/modal.js" defer></script>
|
package/dist/al.css
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/* AL Design System 1.
|
|
1
|
+
/* AL Design System 1.8.0 - Foundation + 32 components.
|
|
2
2
|
* MIT. https://github.com/guilhermedworakowski/al-design-system
|
|
3
3
|
*/
|
|
4
4
|
/* AL Design System - Foundation
|
|
5
|
-
* v1.
|
|
5
|
+
* v1.8.0 - MIT
|
|
6
6
|
* GENERATED by src/foundation/css.py. Do not edit by hand: run the script.
|
|
7
7
|
*/
|
|
8
8
|
|
|
@@ -8109,3 +8109,573 @@
|
|
|
8109
8109
|
clip-path: inset(50%);
|
|
8110
8110
|
white-space: nowrap;
|
|
8111
8111
|
}
|
|
8112
|
+
|
|
8113
|
+
/* AL Design System - Empty state tokens
|
|
8114
|
+
* GENERATED by src/components/empty-state/tokens.py. Do not edit by hand.
|
|
8115
|
+
*
|
|
8116
|
+
* Every color is a semantic the theme switches on :root.
|
|
8117
|
+
*/
|
|
8118
|
+
|
|
8119
|
+
:root {
|
|
8120
|
+
/* color */
|
|
8121
|
+
--al-empty-state-bg: var(--al-bg-surface-raised);
|
|
8122
|
+
--al-empty-state-border: var(--al-border-default);
|
|
8123
|
+
--al-empty-state-icon: var(--al-text-primary);
|
|
8124
|
+
--al-empty-state-title: var(--al-text-primary);
|
|
8125
|
+
--al-empty-state-description: var(--al-text-secondary);
|
|
8126
|
+
|
|
8127
|
+
/* geometry */
|
|
8128
|
+
--al-empty-state-border-width: var(--al-border-width-1);
|
|
8129
|
+
--al-empty-state-radius: var(--al-radius-3xl);
|
|
8130
|
+
--al-empty-state-padding: var(--al-space-48);
|
|
8131
|
+
--al-empty-state-icon-size: var(--al-icon-size-32);
|
|
8132
|
+
--al-empty-state-gap-icon: var(--al-space-16);
|
|
8133
|
+
--al-empty-state-gap-text: var(--al-space-8);
|
|
8134
|
+
--al-empty-state-gap-action: var(--al-space-24);
|
|
8135
|
+
|
|
8136
|
+
/* width - declared value, no scale in the Foundation */
|
|
8137
|
+
--al-empty-state-max-width: 600px;
|
|
8138
|
+
|
|
8139
|
+
/* typography - one style becomes four vars */
|
|
8140
|
+
--al-empty-state-title-font-size: var(--al-font-size-xl);
|
|
8141
|
+
--al-empty-state-title-line-height: var(--al-line-height-xl);
|
|
8142
|
+
--al-empty-state-title-font-weight: 600;
|
|
8143
|
+
--al-empty-state-title-tracking: -0.01em;
|
|
8144
|
+
--al-empty-state-description-font-size: var(--al-font-size-md);
|
|
8145
|
+
--al-empty-state-description-line-height: var(--al-line-height-md);
|
|
8146
|
+
--al-empty-state-description-font-weight: 400;
|
|
8147
|
+
--al-empty-state-description-tracking: 0em;
|
|
8148
|
+
}
|
|
8149
|
+
|
|
8150
|
+
/* AL Design System - Empty state
|
|
8151
|
+
* Written by hand. Depends on al-foundation.css and al-empty-state-tokens.css,
|
|
8152
|
+
* in that order.
|
|
8153
|
+
*
|
|
8154
|
+
* No value here is literal: color, space, radius and typography come in
|
|
8155
|
+
* through var(--al-empty-state-*). The check.py next to it rejects the file if
|
|
8156
|
+
* any escapes.
|
|
8157
|
+
*
|
|
8158
|
+
* MARKUP CONTRACT
|
|
8159
|
+
*
|
|
8160
|
+
* <section class="al-empty-state" aria-labelledby="es-title">
|
|
8161
|
+
* <svg class="al-empty-state__icon" aria-hidden="true">...</svg>
|
|
8162
|
+
* <div class="al-empty-state__text">
|
|
8163
|
+
* <h2 class="al-empty-state__title" id="es-title">No projects yet</h2>
|
|
8164
|
+
* <p class="al-empty-state__description">Projects you create show up
|
|
8165
|
+
* here.</p>
|
|
8166
|
+
* </div>
|
|
8167
|
+
* <button class="al-btn al-btn--primary al-btn--md" type="button">
|
|
8168
|
+
* <span class="al-btn__label">Create project</span>
|
|
8169
|
+
* </button>
|
|
8170
|
+
* </section>
|
|
8171
|
+
*
|
|
8172
|
+
* Icon, description and button are optional (rules 9, 13, 16). At most one
|
|
8173
|
+
* button, always Primary (rule 15). No Link inside: Figma has none, and a
|
|
8174
|
+
* second action has no place here (rule 18).
|
|
8175
|
+
*
|
|
8176
|
+
* After a search or filter (decision A=a), the empty state is rendered into
|
|
8177
|
+
* a container with role="status", so it is announced once. On first load it
|
|
8178
|
+
* is static, with no role.
|
|
8179
|
+
*
|
|
8180
|
+
* THE TITLE IS ALWAYS A HEADING (B=a), THE LEVEL BELONGS TO THE PAGE
|
|
8181
|
+
* The class doesn't pin a tag (rule 19), same as the Card.
|
|
8182
|
+
*
|
|
8183
|
+
* THE BORDER IS OUTSIDE
|
|
8184
|
+
* In Figma the stroke is OUTSIDE. Here it is a 1px shadow with no blur, the
|
|
8185
|
+
* same as the Card Border: the 48 of padding discounts nothing.
|
|
8186
|
+
*
|
|
8187
|
+
* ONLY ON bg-canvas OR bg-surface (rule 5). Nothing here stops it; it is a
|
|
8188
|
+
* usage rule.
|
|
8189
|
+
*
|
|
8190
|
+
* HIGH CONTRAST
|
|
8191
|
+
* In `forced-colors` the shadow is removed and the box would vanish: it
|
|
8192
|
+
* gets an outline in the system's text color, the same as the Card.
|
|
8193
|
+
*/
|
|
8194
|
+
|
|
8195
|
+
.al-empty-state {
|
|
8196
|
+
box-sizing: border-box;
|
|
8197
|
+
display: flex;
|
|
8198
|
+
flex-direction: column;
|
|
8199
|
+
align-items: center;
|
|
8200
|
+
gap: var(--al-empty-state-gap-action);
|
|
8201
|
+
width: 100%;
|
|
8202
|
+
max-width: var(--al-empty-state-max-width);
|
|
8203
|
+
margin-inline: auto;
|
|
8204
|
+
padding: var(--al-empty-state-padding);
|
|
8205
|
+
border-radius: var(--al-empty-state-radius);
|
|
8206
|
+
background-color: var(--al-empty-state-bg);
|
|
8207
|
+
box-shadow: 0 0 0 var(--al-empty-state-border-width) var(--al-empty-state-border);
|
|
8208
|
+
text-align: center;
|
|
8209
|
+
}
|
|
8210
|
+
|
|
8211
|
+
/* The box gap is gap-action (text -> button). Icon -> text is shorter, so the
|
|
8212
|
+
text block pulls itself up by the difference (24 - 16 = 8). */
|
|
8213
|
+
.al-empty-state__icon {
|
|
8214
|
+
flex: none;
|
|
8215
|
+
width: var(--al-empty-state-icon-size);
|
|
8216
|
+
height: var(--al-empty-state-icon-size);
|
|
8217
|
+
color: var(--al-empty-state-icon);
|
|
8218
|
+
}
|
|
8219
|
+
|
|
8220
|
+
.al-empty-state__icon + .al-empty-state__text {
|
|
8221
|
+
margin-top: calc(var(--al-empty-state-gap-icon) - var(--al-empty-state-gap-action));
|
|
8222
|
+
}
|
|
8223
|
+
|
|
8224
|
+
.al-empty-state__text {
|
|
8225
|
+
display: flex;
|
|
8226
|
+
flex-direction: column;
|
|
8227
|
+
gap: var(--al-empty-state-gap-text);
|
|
8228
|
+
}
|
|
8229
|
+
|
|
8230
|
+
.al-empty-state__title {
|
|
8231
|
+
margin: 0;
|
|
8232
|
+
font-family: var(--al-font-sans);
|
|
8233
|
+
font-size: var(--al-empty-state-title-font-size);
|
|
8234
|
+
line-height: var(--al-empty-state-title-line-height);
|
|
8235
|
+
font-weight: var(--al-empty-state-title-font-weight);
|
|
8236
|
+
letter-spacing: var(--al-empty-state-title-tracking);
|
|
8237
|
+
color: var(--al-empty-state-title);
|
|
8238
|
+
}
|
|
8239
|
+
|
|
8240
|
+
.al-empty-state__description {
|
|
8241
|
+
margin: 0;
|
|
8242
|
+
font-family: var(--al-font-sans);
|
|
8243
|
+
font-size: var(--al-empty-state-description-font-size);
|
|
8244
|
+
line-height: var(--al-empty-state-description-line-height);
|
|
8245
|
+
font-weight: var(--al-empty-state-description-font-weight);
|
|
8246
|
+
letter-spacing: var(--al-empty-state-description-tracking);
|
|
8247
|
+
color: var(--al-empty-state-description);
|
|
8248
|
+
}
|
|
8249
|
+
|
|
8250
|
+
/* ---------------------------------------------------------- high contrast */
|
|
8251
|
+
@media (forced-colors: active) {
|
|
8252
|
+
.al-empty-state {
|
|
8253
|
+
outline: var(--al-empty-state-border-width) solid CanvasText;
|
|
8254
|
+
}
|
|
8255
|
+
}
|
|
8256
|
+
|
|
8257
|
+
/* AL Design System - Slider tokens
|
|
8258
|
+
* GENERATED by src/components/slider/tokens.py. Do not edit by hand.
|
|
8259
|
+
*
|
|
8260
|
+
* Every color is a semantic the theme switches on :root.
|
|
8261
|
+
*/
|
|
8262
|
+
|
|
8263
|
+
:root {
|
|
8264
|
+
/* color */
|
|
8265
|
+
--al-slider-label-text: var(--al-text-primary);
|
|
8266
|
+
--al-slider-value-text: var(--al-text-primary);
|
|
8267
|
+
--al-slider-range-text: var(--al-text-secondary);
|
|
8268
|
+
--al-slider-track-bg: var(--al-bg-track);
|
|
8269
|
+
--al-slider-fill-bg: var(--al-bg-brand);
|
|
8270
|
+
--al-slider-thumb-bg: var(--al-bg-brand);
|
|
8271
|
+
--al-slider-thumb-bg-hover: var(--al-bg-brand-hover);
|
|
8272
|
+
--al-slider-thumb-bg-active: var(--al-bg-brand-active);
|
|
8273
|
+
--al-slider-thumb-focus-gap: var(--al-bg-canvas);
|
|
8274
|
+
--al-slider-label-text-disabled: var(--al-text-disabled);
|
|
8275
|
+
--al-slider-track-bg-disabled: var(--al-bg-disabled);
|
|
8276
|
+
--al-slider-fill-bg-disabled: var(--al-text-disabled);
|
|
8277
|
+
--al-slider-thumb-bg-disabled: var(--al-text-disabled);
|
|
8278
|
+
|
|
8279
|
+
/* geometry */
|
|
8280
|
+
--al-slider-track-height: var(--al-space-4);
|
|
8281
|
+
--al-slider-thumb-size: var(--al-space-20);
|
|
8282
|
+
--al-slider-thumb-hit: var(--al-space-24);
|
|
8283
|
+
--al-slider-radius: var(--al-radius-full);
|
|
8284
|
+
--al-slider-gap: var(--al-space-8);
|
|
8285
|
+
|
|
8286
|
+
/* type - label and value share body-md, the range uses caption */
|
|
8287
|
+
--al-slider-font-size: var(--al-font-size-md);
|
|
8288
|
+
--al-slider-line-height: var(--al-line-height-md);
|
|
8289
|
+
--al-slider-font-weight: var(--al-font-weight-regular);
|
|
8290
|
+
--al-slider-range-font-size: var(--al-font-size-xs);
|
|
8291
|
+
--al-slider-range-line-height: var(--al-line-height-xs);
|
|
8292
|
+
}
|
|
8293
|
+
|
|
8294
|
+
/* AL Design System - Slider
|
|
8295
|
+
*
|
|
8296
|
+
* One thumb, one size, no error. The control is a native
|
|
8297
|
+
* <input type="range">: the browser gives the keyboard (arrows, Page Up/Down,
|
|
8298
|
+
* Home/End - rule 16), the click on the track (rule 21) and the value to
|
|
8299
|
+
* assistive tech. The name comes from the visible <label for> (rule 17).
|
|
8300
|
+
*
|
|
8301
|
+
* <div class="al-slider">
|
|
8302
|
+
* <div class="al-slider__header">
|
|
8303
|
+
* <label class="al-slider__label" for="vol">Volume</label>
|
|
8304
|
+
* <output class="al-slider__value" for="vol">60%</output>
|
|
8305
|
+
* </div>
|
|
8306
|
+
* <input class="al-slider__input" id="vol" type="range"
|
|
8307
|
+
* min="0" max="100" value="60" data-unit="%">
|
|
8308
|
+
* <div class="al-slider__range"><span>0%</span><span>100%</span></div>
|
|
8309
|
+
* </div>
|
|
8310
|
+
*
|
|
8311
|
+
* THE FILL NEEDS slider.js
|
|
8312
|
+
*
|
|
8313
|
+
* Only Firefox paints the filled part (::-moz-range-progress). WebKit/Blink
|
|
8314
|
+
* paint it from --al-slider-progress, a percentage slider.js keeps in sync
|
|
8315
|
+
* with the value (it also writes the <output> and aria-valuetext). Without
|
|
8316
|
+
* the script the track still works; the fill shows only in Firefox.
|
|
8317
|
+
*
|
|
8318
|
+
* THE HIT AREA IS THE INPUT, NOT THE THUMB
|
|
8319
|
+
*
|
|
8320
|
+
* The input is 24px tall (slider-thumb-hit) and the whole row takes the
|
|
8321
|
+
* pointer; the thumb is drawn at 20px inside it (WCAG 2.5.8, audit A2).
|
|
8322
|
+
* Figma's track frame is 20px - the 4px are the hit area.
|
|
8323
|
+
*
|
|
8324
|
+
* Vendor pseudo-elements can't share a rule: a selector list with one the
|
|
8325
|
+
* browser doesn't know is dropped whole. That is why the track and the thumb
|
|
8326
|
+
* are written twice.
|
|
8327
|
+
*/
|
|
8328
|
+
|
|
8329
|
+
.al-slider {
|
|
8330
|
+
/* public adjustment point: slider.js writes it from value/min/max */
|
|
8331
|
+
--al-slider-progress: 0%;
|
|
8332
|
+
|
|
8333
|
+
display: flex;
|
|
8334
|
+
flex-direction: column;
|
|
8335
|
+
gap: var(--al-slider-gap);
|
|
8336
|
+
inline-size: 100%;
|
|
8337
|
+
font-family: var(--al-font-sans);
|
|
8338
|
+
font-size: var(--al-slider-font-size);
|
|
8339
|
+
line-height: var(--al-slider-line-height);
|
|
8340
|
+
font-weight: var(--al-slider-font-weight);
|
|
8341
|
+
}
|
|
8342
|
+
|
|
8343
|
+
.al-slider__header,
|
|
8344
|
+
.al-slider__range {
|
|
8345
|
+
display: flex;
|
|
8346
|
+
justify-content: space-between;
|
|
8347
|
+
gap: var(--al-slider-gap);
|
|
8348
|
+
}
|
|
8349
|
+
|
|
8350
|
+
.al-slider__label {
|
|
8351
|
+
color: var(--al-slider-label-text);
|
|
8352
|
+
}
|
|
8353
|
+
|
|
8354
|
+
/* tabular figures keep the number from jittering while it is dragged */
|
|
8355
|
+
.al-slider__value {
|
|
8356
|
+
flex: none;
|
|
8357
|
+
color: var(--al-slider-value-text);
|
|
8358
|
+
font-variant-numeric: tabular-nums;
|
|
8359
|
+
}
|
|
8360
|
+
|
|
8361
|
+
.al-slider__range {
|
|
8362
|
+
color: var(--al-slider-range-text);
|
|
8363
|
+
font-size: var(--al-slider-range-font-size);
|
|
8364
|
+
line-height: var(--al-slider-range-line-height);
|
|
8365
|
+
}
|
|
8366
|
+
|
|
8367
|
+
/* ---------------------------------------------------------------- input */
|
|
8368
|
+
.al-slider__input {
|
|
8369
|
+
--_thumb-bg: var(--al-slider-thumb-bg);
|
|
8370
|
+
--_fill: var(--al-slider-fill-bg);
|
|
8371
|
+
--_track: var(--al-slider-track-bg);
|
|
8372
|
+
|
|
8373
|
+
-webkit-appearance: none;
|
|
8374
|
+
appearance: none;
|
|
8375
|
+
display: block;
|
|
8376
|
+
inline-size: 100%;
|
|
8377
|
+
block-size: var(--al-slider-thumb-hit);
|
|
8378
|
+
margin: 0;
|
|
8379
|
+
background: none;
|
|
8380
|
+
cursor: pointer;
|
|
8381
|
+
}
|
|
8382
|
+
|
|
8383
|
+
/* the ring is a shadow on the thumb, never an outline on the whole row */
|
|
8384
|
+
.al-slider__input:focus {
|
|
8385
|
+
outline: none;
|
|
8386
|
+
}
|
|
8387
|
+
|
|
8388
|
+
/* ---------------------------------------------------------------- track */
|
|
8389
|
+
.al-slider__input::-webkit-slider-runnable-track {
|
|
8390
|
+
block-size: var(--al-slider-track-height);
|
|
8391
|
+
border-radius: var(--al-slider-radius);
|
|
8392
|
+
background: linear-gradient(to right,
|
|
8393
|
+
var(--_fill) var(--al-slider-progress),
|
|
8394
|
+
var(--_track) var(--al-slider-progress));
|
|
8395
|
+
}
|
|
8396
|
+
|
|
8397
|
+
.al-slider__input::-moz-range-track {
|
|
8398
|
+
block-size: var(--al-slider-track-height);
|
|
8399
|
+
border-radius: var(--al-slider-radius);
|
|
8400
|
+
background-color: var(--_track);
|
|
8401
|
+
}
|
|
8402
|
+
|
|
8403
|
+
.al-slider__input::-moz-range-progress {
|
|
8404
|
+
block-size: var(--al-slider-track-height);
|
|
8405
|
+
border-radius: var(--al-slider-radius);
|
|
8406
|
+
background-color: var(--_fill);
|
|
8407
|
+
}
|
|
8408
|
+
|
|
8409
|
+
/* ---------------------------------------------------------------- thumb */
|
|
8410
|
+
/* WebKit puts the thumb at the top of the track: the margin centers it. */
|
|
8411
|
+
.al-slider__input::-webkit-slider-thumb {
|
|
8412
|
+
-webkit-appearance: none;
|
|
8413
|
+
appearance: none;
|
|
8414
|
+
inline-size: var(--al-slider-thumb-size);
|
|
8415
|
+
block-size: var(--al-slider-thumb-size);
|
|
8416
|
+
margin-block-start: calc((var(--al-slider-track-height) - var(--al-slider-thumb-size)) / 2);
|
|
8417
|
+
border: none;
|
|
8418
|
+
border-radius: var(--al-slider-radius);
|
|
8419
|
+
background-color: var(--_thumb-bg);
|
|
8420
|
+
transition:
|
|
8421
|
+
background-color var(--al-motion-duration-feedback) var(--al-motion-easing-exit),
|
|
8422
|
+
box-shadow var(--al-motion-duration-feedback) var(--al-motion-easing-exit);
|
|
8423
|
+
}
|
|
8424
|
+
|
|
8425
|
+
.al-slider__input::-moz-range-thumb {
|
|
8426
|
+
inline-size: var(--al-slider-thumb-size);
|
|
8427
|
+
block-size: var(--al-slider-thumb-size);
|
|
8428
|
+
border: none;
|
|
8429
|
+
border-radius: var(--al-slider-radius);
|
|
8430
|
+
background-color: var(--_thumb-bg);
|
|
8431
|
+
transition:
|
|
8432
|
+
background-color var(--al-motion-duration-feedback) var(--al-motion-easing-exit),
|
|
8433
|
+
box-shadow var(--al-motion-duration-feedback) var(--al-motion-easing-exit);
|
|
8434
|
+
}
|
|
8435
|
+
|
|
8436
|
+
/* --------------------------------------------------------------- states */
|
|
8437
|
+
/* hover and active are transient: below 3:1 in dark is the declared
|
|
8438
|
+
thumb-transient exception (rule 15) */
|
|
8439
|
+
.al-slider__input:hover {
|
|
8440
|
+
--_thumb-bg: var(--al-slider-thumb-bg-hover);
|
|
8441
|
+
}
|
|
8442
|
+
|
|
8443
|
+
.al-slider__input:active {
|
|
8444
|
+
--_thumb-bg: var(--al-slider-thumb-bg-active);
|
|
8445
|
+
}
|
|
8446
|
+
|
|
8447
|
+
/* focus: an inner gap in bg-canvas, then the Foundation ring. Without the
|
|
8448
|
+
gap the orange ring reads as a bigger thumb in light (audit A1). */
|
|
8449
|
+
.al-slider__input:focus-visible::-webkit-slider-thumb {
|
|
8450
|
+
box-shadow:
|
|
8451
|
+
inset 0 0 0 var(--al-border-width-2) var(--al-slider-thumb-focus-gap),
|
|
8452
|
+
var(--al-focus-ring-default);
|
|
8453
|
+
}
|
|
8454
|
+
|
|
8455
|
+
.al-slider__input:focus-visible::-moz-range-thumb {
|
|
8456
|
+
box-shadow:
|
|
8457
|
+
inset 0 0 0 var(--al-border-width-2) var(--al-slider-thumb-focus-gap),
|
|
8458
|
+
var(--al-focus-ring-default);
|
|
8459
|
+
}
|
|
8460
|
+
|
|
8461
|
+
/* disabled - last, because it wins over all */
|
|
8462
|
+
.al-slider__input:disabled {
|
|
8463
|
+
--_thumb-bg: var(--al-slider-thumb-bg-disabled);
|
|
8464
|
+
--_fill: var(--al-slider-fill-bg-disabled);
|
|
8465
|
+
--_track: var(--al-slider-track-bg-disabled);
|
|
8466
|
+
cursor: not-allowed;
|
|
8467
|
+
}
|
|
8468
|
+
|
|
8469
|
+
.al-slider:has(.al-slider__input:disabled) :is(.al-slider__label, .al-slider__value, .al-slider__range) {
|
|
8470
|
+
color: var(--al-slider-label-text-disabled);
|
|
8471
|
+
}
|
|
8472
|
+
|
|
8473
|
+
/* ENTER - the destination states take the enter curve */
|
|
8474
|
+
.al-slider__input:hover::-webkit-slider-thumb,
|
|
8475
|
+
.al-slider__input:focus-visible::-webkit-slider-thumb {
|
|
8476
|
+
transition-timing-function: var(--al-motion-easing-enter);
|
|
8477
|
+
}
|
|
8478
|
+
|
|
8479
|
+
.al-slider__input:hover::-moz-range-thumb,
|
|
8480
|
+
.al-slider__input:focus-visible::-moz-range-thumb {
|
|
8481
|
+
transition-timing-function: var(--al-motion-easing-enter);
|
|
8482
|
+
}
|
|
8483
|
+
|
|
8484
|
+
/* --------------------------------------------------------- environment */
|
|
8485
|
+
@media (prefers-reduced-motion: reduce) {
|
|
8486
|
+
.al-slider__input::-webkit-slider-thumb { transition: none; }
|
|
8487
|
+
.al-slider__input::-moz-range-thumb { transition: none; }
|
|
8488
|
+
}
|
|
8489
|
+
|
|
8490
|
+
/* AL Design System - Rating tokens
|
|
8491
|
+
* GENERATED by src/components/rating/tokens.py. Do not edit by hand.
|
|
8492
|
+
*
|
|
8493
|
+
* Every color is a semantic the theme switches on :root.
|
|
8494
|
+
*/
|
|
8495
|
+
|
|
8496
|
+
:root {
|
|
8497
|
+
/* color */
|
|
8498
|
+
--al-rating-label-text: var(--al-text-primary);
|
|
8499
|
+
--al-rating-label-text-disabled: var(--al-text-disabled);
|
|
8500
|
+
--al-rating-star-on: var(--al-bg-brand);
|
|
8501
|
+
--al-rating-star-preview: var(--al-bg-brand-hover);
|
|
8502
|
+
--al-rating-star-off: var(--al-border-strong);
|
|
8503
|
+
--al-rating-star-disabled: var(--al-text-disabled);
|
|
8504
|
+
--al-rating-focus-gap: var(--al-bg-canvas);
|
|
8505
|
+
|
|
8506
|
+
/* geometry */
|
|
8507
|
+
--al-rating-star-size: var(--al-icon-size-24);
|
|
8508
|
+
--al-rating-star-stroke: var(--al-border-width-2);
|
|
8509
|
+
--al-rating-gap: var(--al-space-4);
|
|
8510
|
+
--al-rating-label-gap: var(--al-space-8);
|
|
8511
|
+
--al-rating-focus-radius: var(--al-radius-sm);
|
|
8512
|
+
|
|
8513
|
+
/* type */
|
|
8514
|
+
--al-rating-font-size: var(--al-font-size-md);
|
|
8515
|
+
--al-rating-line-height: var(--al-line-height-md);
|
|
8516
|
+
--al-rating-font-weight: var(--al-font-weight-regular);
|
|
8517
|
+
}
|
|
8518
|
+
|
|
8519
|
+
/* AL Design System - Rating
|
|
8520
|
+
*
|
|
8521
|
+
* A radio group of five whole stars (APG rating pattern, rule 15). The radios
|
|
8522
|
+
* are native and sit invisible on top of each star: the browser gives the
|
|
8523
|
+
* single Tab stop, the arrows that move and check (rule 17) and the group
|
|
8524
|
+
* announcement. No script.
|
|
8525
|
+
*
|
|
8526
|
+
* <fieldset class="al-rating">
|
|
8527
|
+
* <legend class="al-rating__label">Como foi a entrega?</legend>
|
|
8528
|
+
* <div class="al-rating__stars">
|
|
8529
|
+
* <label class="al-rating__star">
|
|
8530
|
+
* <input class="al-rating__input" type="radio" name="entrega" value="1"
|
|
8531
|
+
* aria-label="1 estrela">
|
|
8532
|
+
* <svg class="al-rating__glyph" viewBox="0 0 24 24" aria-hidden="true">
|
|
8533
|
+
* <path d="..."/></svg>
|
|
8534
|
+
* </label>
|
|
8535
|
+
* ... x5
|
|
8536
|
+
* </div>
|
|
8537
|
+
* </fieldset>
|
|
8538
|
+
*
|
|
8539
|
+
* READ-ONLY IS ANOTHER MARKUP (rule 12, H=a)
|
|
8540
|
+
*
|
|
8541
|
+
* <span class="al-rating al-rating--readonly" role="img"
|
|
8542
|
+
* aria-label="4,3 de 5 estrelas">
|
|
8543
|
+
* <span class="al-rating__stars">
|
|
8544
|
+
* <svg class="al-rating__glyph al-rating__glyph--on" ...> x4 (rounded)
|
|
8545
|
+
* <svg class="al-rating__glyph" ...> x1
|
|
8546
|
+
* </span>
|
|
8547
|
+
* </span>
|
|
8548
|
+
* No radios, no focus, no hover. Looks the same as Default (rule 14).
|
|
8549
|
+
*
|
|
8550
|
+
* WHICH STARS ARE ON
|
|
8551
|
+
*
|
|
8552
|
+
* A star is on when its radio is checked or a later one is: `:has()` on the
|
|
8553
|
+
* star and on its following siblings. Nothing checked = all off (rule 8).
|
|
8554
|
+
*/
|
|
8555
|
+
|
|
8556
|
+
.al-rating {
|
|
8557
|
+
display: flex;
|
|
8558
|
+
flex-direction: column;
|
|
8559
|
+
margin: 0;
|
|
8560
|
+
padding: 0;
|
|
8561
|
+
border: none;
|
|
8562
|
+
min-inline-size: 0;
|
|
8563
|
+
font-family: var(--al-font-sans);
|
|
8564
|
+
font-size: var(--al-rating-font-size);
|
|
8565
|
+
line-height: var(--al-rating-line-height);
|
|
8566
|
+
font-weight: var(--al-rating-font-weight);
|
|
8567
|
+
}
|
|
8568
|
+
|
|
8569
|
+
/* a <legend> is not a flex item, so the fieldset's gap doesn't reach it:
|
|
8570
|
+
the space below it is its own margin */
|
|
8571
|
+
.al-rating__label {
|
|
8572
|
+
padding: 0;
|
|
8573
|
+
margin-block-end: var(--al-rating-label-gap);
|
|
8574
|
+
color: var(--al-rating-label-text);
|
|
8575
|
+
}
|
|
8576
|
+
|
|
8577
|
+
.al-rating__stars {
|
|
8578
|
+
display: flex;
|
|
8579
|
+
gap: var(--al-rating-gap);
|
|
8580
|
+
}
|
|
8581
|
+
|
|
8582
|
+
.al-rating__star {
|
|
8583
|
+
--_ink: var(--al-rating-star-off);
|
|
8584
|
+
--_fill: none;
|
|
8585
|
+
|
|
8586
|
+
position: relative;
|
|
8587
|
+
display: block;
|
|
8588
|
+
inline-size: var(--al-rating-star-size);
|
|
8589
|
+
block-size: var(--al-rating-star-size);
|
|
8590
|
+
border-radius: var(--al-rating-focus-radius);
|
|
8591
|
+
cursor: pointer;
|
|
8592
|
+
}
|
|
8593
|
+
|
|
8594
|
+
/* the radio covers the star: it takes the click and the focus, and stays
|
|
8595
|
+
in the accessibility tree (never display:none) */
|
|
8596
|
+
.al-rating__input {
|
|
8597
|
+
position: absolute;
|
|
8598
|
+
inset: 0;
|
|
8599
|
+
margin: 0;
|
|
8600
|
+
opacity: 0;
|
|
8601
|
+
cursor: inherit;
|
|
8602
|
+
}
|
|
8603
|
+
|
|
8604
|
+
.al-rating__glyph {
|
|
8605
|
+
display: block;
|
|
8606
|
+
inline-size: 100%;
|
|
8607
|
+
block-size: 100%;
|
|
8608
|
+
fill: var(--_fill);
|
|
8609
|
+
stroke: var(--_ink);
|
|
8610
|
+
stroke-width: var(--al-rating-star-stroke);
|
|
8611
|
+
stroke-linejoin: round;
|
|
8612
|
+
pointer-events: none;
|
|
8613
|
+
transition:
|
|
8614
|
+
fill var(--al-motion-duration-feedback) var(--al-motion-easing-exit),
|
|
8615
|
+
stroke var(--al-motion-duration-feedback) var(--al-motion-easing-exit);
|
|
8616
|
+
}
|
|
8617
|
+
|
|
8618
|
+
/* --------------------------------------------------------------- states */
|
|
8619
|
+
/* hover preview: the hovered star and the ones before it (rule 10). The
|
|
8620
|
+
on rule below comes later, so a checked star stays brand. */
|
|
8621
|
+
.al-rating:not(:disabled) .al-rating__star:hover,
|
|
8622
|
+
.al-rating:not(:disabled) .al-rating__star:has(~ .al-rating__star:hover) {
|
|
8623
|
+
--_ink: var(--al-rating-star-preview);
|
|
8624
|
+
--_fill: var(--al-rating-star-preview);
|
|
8625
|
+
}
|
|
8626
|
+
|
|
8627
|
+
/* on: checked, or before the checked one */
|
|
8628
|
+
.al-rating__star:has(.al-rating__input:checked),
|
|
8629
|
+
.al-rating__star:has(~ .al-rating__star .al-rating__input:checked),
|
|
8630
|
+
.al-rating__glyph--on {
|
|
8631
|
+
--_ink: var(--al-rating-star-on);
|
|
8632
|
+
--_fill: var(--al-rating-star-on);
|
|
8633
|
+
}
|
|
8634
|
+
|
|
8635
|
+
/* focus: the ring on the star that holds it (rule 18); the box gets
|
|
8636
|
+
bg-canvas so the ring's gap shows (audit A4) */
|
|
8637
|
+
.al-rating__star:has(.al-rating__input:focus-visible) {
|
|
8638
|
+
background-color: var(--al-rating-focus-gap);
|
|
8639
|
+
box-shadow: var(--al-focus-ring-default);
|
|
8640
|
+
}
|
|
8641
|
+
|
|
8642
|
+
/* disabled - last, because it wins over all. The on stars stay filled.
|
|
8643
|
+
The on selectors carry :has() specificity, so the ink is set again there. */
|
|
8644
|
+
.al-rating:disabled .al-rating__star {
|
|
8645
|
+
--_ink: var(--al-rating-star-disabled);
|
|
8646
|
+
cursor: not-allowed;
|
|
8647
|
+
}
|
|
8648
|
+
|
|
8649
|
+
.al-rating:disabled .al-rating__star:has(.al-rating__input:checked),
|
|
8650
|
+
.al-rating:disabled .al-rating__star:has(~ .al-rating__star .al-rating__input:checked) {
|
|
8651
|
+
--_ink: var(--al-rating-star-disabled);
|
|
8652
|
+
--_fill: var(--al-rating-star-disabled);
|
|
8653
|
+
}
|
|
8654
|
+
|
|
8655
|
+
.al-rating:disabled .al-rating__label {
|
|
8656
|
+
color: var(--al-rating-label-text-disabled);
|
|
8657
|
+
}
|
|
8658
|
+
|
|
8659
|
+
/* read-only: the glyphs paint themselves, nothing reacts */
|
|
8660
|
+
.al-rating--readonly .al-rating__glyph {
|
|
8661
|
+
fill: none;
|
|
8662
|
+
stroke: var(--al-rating-star-off);
|
|
8663
|
+
inline-size: var(--al-rating-star-size);
|
|
8664
|
+
block-size: var(--al-rating-star-size);
|
|
8665
|
+
}
|
|
8666
|
+
|
|
8667
|
+
.al-rating--readonly .al-rating__glyph--on {
|
|
8668
|
+
fill: var(--al-rating-star-on);
|
|
8669
|
+
stroke: var(--al-rating-star-on);
|
|
8670
|
+
}
|
|
8671
|
+
|
|
8672
|
+
/* ENTER - the destination states take the enter curve */
|
|
8673
|
+
.al-rating:not(:disabled) .al-rating__star:hover .al-rating__glyph,
|
|
8674
|
+
.al-rating:not(:disabled) .al-rating__star:has(~ .al-rating__star:hover) .al-rating__glyph {
|
|
8675
|
+
transition-timing-function: var(--al-motion-easing-enter);
|
|
8676
|
+
}
|
|
8677
|
+
|
|
8678
|
+
/* --------------------------------------------------------- environment */
|
|
8679
|
+
@media (prefers-reduced-motion: reduce) {
|
|
8680
|
+
.al-rating__glyph { transition: none; }
|
|
8681
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/* AL Design System - Empty state tokens
|
|
2
|
+
* GENERATED by src/components/empty-state/tokens.py. Do not edit by hand.
|
|
3
|
+
*
|
|
4
|
+
* Every color is a semantic the theme switches on :root.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
:root {
|
|
8
|
+
/* color */
|
|
9
|
+
--al-empty-state-bg: var(--al-bg-surface-raised);
|
|
10
|
+
--al-empty-state-border: var(--al-border-default);
|
|
11
|
+
--al-empty-state-icon: var(--al-text-primary);
|
|
12
|
+
--al-empty-state-title: var(--al-text-primary);
|
|
13
|
+
--al-empty-state-description: var(--al-text-secondary);
|
|
14
|
+
|
|
15
|
+
/* geometry */
|
|
16
|
+
--al-empty-state-border-width: var(--al-border-width-1);
|
|
17
|
+
--al-empty-state-radius: var(--al-radius-3xl);
|
|
18
|
+
--al-empty-state-padding: var(--al-space-48);
|
|
19
|
+
--al-empty-state-icon-size: var(--al-icon-size-32);
|
|
20
|
+
--al-empty-state-gap-icon: var(--al-space-16);
|
|
21
|
+
--al-empty-state-gap-text: var(--al-space-8);
|
|
22
|
+
--al-empty-state-gap-action: var(--al-space-24);
|
|
23
|
+
|
|
24
|
+
/* width - declared value, no scale in the Foundation */
|
|
25
|
+
--al-empty-state-max-width: 600px;
|
|
26
|
+
|
|
27
|
+
/* typography - one style becomes four vars */
|
|
28
|
+
--al-empty-state-title-font-size: var(--al-font-size-xl);
|
|
29
|
+
--al-empty-state-title-line-height: var(--al-line-height-xl);
|
|
30
|
+
--al-empty-state-title-font-weight: 600;
|
|
31
|
+
--al-empty-state-title-tracking: -0.01em;
|
|
32
|
+
--al-empty-state-description-font-size: var(--al-font-size-md);
|
|
33
|
+
--al-empty-state-description-line-height: var(--al-line-height-md);
|
|
34
|
+
--al-empty-state-description-font-weight: 400;
|
|
35
|
+
--al-empty-state-description-tracking: 0em;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* AL Design System - Empty state
|
|
39
|
+
* Written by hand. Depends on al-foundation.css and al-empty-state-tokens.css,
|
|
40
|
+
* in that order.
|
|
41
|
+
*
|
|
42
|
+
* No value here is literal: color, space, radius and typography come in
|
|
43
|
+
* through var(--al-empty-state-*). The check.py next to it rejects the file if
|
|
44
|
+
* any escapes.
|
|
45
|
+
*
|
|
46
|
+
* MARKUP CONTRACT
|
|
47
|
+
*
|
|
48
|
+
* <section class="al-empty-state" aria-labelledby="es-title">
|
|
49
|
+
* <svg class="al-empty-state__icon" aria-hidden="true">...</svg>
|
|
50
|
+
* <div class="al-empty-state__text">
|
|
51
|
+
* <h2 class="al-empty-state__title" id="es-title">No projects yet</h2>
|
|
52
|
+
* <p class="al-empty-state__description">Projects you create show up
|
|
53
|
+
* here.</p>
|
|
54
|
+
* </div>
|
|
55
|
+
* <button class="al-btn al-btn--primary al-btn--md" type="button">
|
|
56
|
+
* <span class="al-btn__label">Create project</span>
|
|
57
|
+
* </button>
|
|
58
|
+
* </section>
|
|
59
|
+
*
|
|
60
|
+
* Icon, description and button are optional (rules 9, 13, 16). At most one
|
|
61
|
+
* button, always Primary (rule 15). No Link inside: Figma has none, and a
|
|
62
|
+
* second action has no place here (rule 18).
|
|
63
|
+
*
|
|
64
|
+
* After a search or filter (decision A=a), the empty state is rendered into
|
|
65
|
+
* a container with role="status", so it is announced once. On first load it
|
|
66
|
+
* is static, with no role.
|
|
67
|
+
*
|
|
68
|
+
* THE TITLE IS ALWAYS A HEADING (B=a), THE LEVEL BELONGS TO THE PAGE
|
|
69
|
+
* The class doesn't pin a tag (rule 19), same as the Card.
|
|
70
|
+
*
|
|
71
|
+
* THE BORDER IS OUTSIDE
|
|
72
|
+
* In Figma the stroke is OUTSIDE. Here it is a 1px shadow with no blur, the
|
|
73
|
+
* same as the Card Border: the 48 of padding discounts nothing.
|
|
74
|
+
*
|
|
75
|
+
* ONLY ON bg-canvas OR bg-surface (rule 5). Nothing here stops it; it is a
|
|
76
|
+
* usage rule.
|
|
77
|
+
*
|
|
78
|
+
* HIGH CONTRAST
|
|
79
|
+
* In `forced-colors` the shadow is removed and the box would vanish: it
|
|
80
|
+
* gets an outline in the system's text color, the same as the Card.
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
.al-empty-state {
|
|
84
|
+
box-sizing: border-box;
|
|
85
|
+
display: flex;
|
|
86
|
+
flex-direction: column;
|
|
87
|
+
align-items: center;
|
|
88
|
+
gap: var(--al-empty-state-gap-action);
|
|
89
|
+
width: 100%;
|
|
90
|
+
max-width: var(--al-empty-state-max-width);
|
|
91
|
+
margin-inline: auto;
|
|
92
|
+
padding: var(--al-empty-state-padding);
|
|
93
|
+
border-radius: var(--al-empty-state-radius);
|
|
94
|
+
background-color: var(--al-empty-state-bg);
|
|
95
|
+
box-shadow: 0 0 0 var(--al-empty-state-border-width) var(--al-empty-state-border);
|
|
96
|
+
text-align: center;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* The box gap is gap-action (text -> button). Icon -> text is shorter, so the
|
|
100
|
+
text block pulls itself up by the difference (24 - 16 = 8). */
|
|
101
|
+
.al-empty-state__icon {
|
|
102
|
+
flex: none;
|
|
103
|
+
width: var(--al-empty-state-icon-size);
|
|
104
|
+
height: var(--al-empty-state-icon-size);
|
|
105
|
+
color: var(--al-empty-state-icon);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.al-empty-state__icon + .al-empty-state__text {
|
|
109
|
+
margin-top: calc(var(--al-empty-state-gap-icon) - var(--al-empty-state-gap-action));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.al-empty-state__text {
|
|
113
|
+
display: flex;
|
|
114
|
+
flex-direction: column;
|
|
115
|
+
gap: var(--al-empty-state-gap-text);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.al-empty-state__title {
|
|
119
|
+
margin: 0;
|
|
120
|
+
font-family: var(--al-font-sans);
|
|
121
|
+
font-size: var(--al-empty-state-title-font-size);
|
|
122
|
+
line-height: var(--al-empty-state-title-line-height);
|
|
123
|
+
font-weight: var(--al-empty-state-title-font-weight);
|
|
124
|
+
letter-spacing: var(--al-empty-state-title-tracking);
|
|
125
|
+
color: var(--al-empty-state-title);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.al-empty-state__description {
|
|
129
|
+
margin: 0;
|
|
130
|
+
font-family: var(--al-font-sans);
|
|
131
|
+
font-size: var(--al-empty-state-description-font-size);
|
|
132
|
+
line-height: var(--al-empty-state-description-line-height);
|
|
133
|
+
font-weight: var(--al-empty-state-description-font-weight);
|
|
134
|
+
letter-spacing: var(--al-empty-state-description-tracking);
|
|
135
|
+
color: var(--al-empty-state-description);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* ---------------------------------------------------------- high contrast */
|
|
139
|
+
@media (forced-colors: active) {
|
|
140
|
+
.al-empty-state {
|
|
141
|
+
outline: var(--al-empty-state-border-width) solid CanvasText;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/* AL Design System - Rating tokens
|
|
2
|
+
* GENERATED by src/components/rating/tokens.py. Do not edit by hand.
|
|
3
|
+
*
|
|
4
|
+
* Every color is a semantic the theme switches on :root.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
:root {
|
|
8
|
+
/* color */
|
|
9
|
+
--al-rating-label-text: var(--al-text-primary);
|
|
10
|
+
--al-rating-label-text-disabled: var(--al-text-disabled);
|
|
11
|
+
--al-rating-star-on: var(--al-bg-brand);
|
|
12
|
+
--al-rating-star-preview: var(--al-bg-brand-hover);
|
|
13
|
+
--al-rating-star-off: var(--al-border-strong);
|
|
14
|
+
--al-rating-star-disabled: var(--al-text-disabled);
|
|
15
|
+
--al-rating-focus-gap: var(--al-bg-canvas);
|
|
16
|
+
|
|
17
|
+
/* geometry */
|
|
18
|
+
--al-rating-star-size: var(--al-icon-size-24);
|
|
19
|
+
--al-rating-star-stroke: var(--al-border-width-2);
|
|
20
|
+
--al-rating-gap: var(--al-space-4);
|
|
21
|
+
--al-rating-label-gap: var(--al-space-8);
|
|
22
|
+
--al-rating-focus-radius: var(--al-radius-sm);
|
|
23
|
+
|
|
24
|
+
/* type */
|
|
25
|
+
--al-rating-font-size: var(--al-font-size-md);
|
|
26
|
+
--al-rating-line-height: var(--al-line-height-md);
|
|
27
|
+
--al-rating-font-weight: var(--al-font-weight-regular);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* AL Design System - Rating
|
|
31
|
+
*
|
|
32
|
+
* A radio group of five whole stars (APG rating pattern, rule 15). The radios
|
|
33
|
+
* are native and sit invisible on top of each star: the browser gives the
|
|
34
|
+
* single Tab stop, the arrows that move and check (rule 17) and the group
|
|
35
|
+
* announcement. No script.
|
|
36
|
+
*
|
|
37
|
+
* <fieldset class="al-rating">
|
|
38
|
+
* <legend class="al-rating__label">Como foi a entrega?</legend>
|
|
39
|
+
* <div class="al-rating__stars">
|
|
40
|
+
* <label class="al-rating__star">
|
|
41
|
+
* <input class="al-rating__input" type="radio" name="entrega" value="1"
|
|
42
|
+
* aria-label="1 estrela">
|
|
43
|
+
* <svg class="al-rating__glyph" viewBox="0 0 24 24" aria-hidden="true">
|
|
44
|
+
* <path d="..."/></svg>
|
|
45
|
+
* </label>
|
|
46
|
+
* ... x5
|
|
47
|
+
* </div>
|
|
48
|
+
* </fieldset>
|
|
49
|
+
*
|
|
50
|
+
* READ-ONLY IS ANOTHER MARKUP (rule 12, H=a)
|
|
51
|
+
*
|
|
52
|
+
* <span class="al-rating al-rating--readonly" role="img"
|
|
53
|
+
* aria-label="4,3 de 5 estrelas">
|
|
54
|
+
* <span class="al-rating__stars">
|
|
55
|
+
* <svg class="al-rating__glyph al-rating__glyph--on" ...> x4 (rounded)
|
|
56
|
+
* <svg class="al-rating__glyph" ...> x1
|
|
57
|
+
* </span>
|
|
58
|
+
* </span>
|
|
59
|
+
* No radios, no focus, no hover. Looks the same as Default (rule 14).
|
|
60
|
+
*
|
|
61
|
+
* WHICH STARS ARE ON
|
|
62
|
+
*
|
|
63
|
+
* A star is on when its radio is checked or a later one is: `:has()` on the
|
|
64
|
+
* star and on its following siblings. Nothing checked = all off (rule 8).
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
.al-rating {
|
|
68
|
+
display: flex;
|
|
69
|
+
flex-direction: column;
|
|
70
|
+
margin: 0;
|
|
71
|
+
padding: 0;
|
|
72
|
+
border: none;
|
|
73
|
+
min-inline-size: 0;
|
|
74
|
+
font-family: var(--al-font-sans);
|
|
75
|
+
font-size: var(--al-rating-font-size);
|
|
76
|
+
line-height: var(--al-rating-line-height);
|
|
77
|
+
font-weight: var(--al-rating-font-weight);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* a <legend> is not a flex item, so the fieldset's gap doesn't reach it:
|
|
81
|
+
the space below it is its own margin */
|
|
82
|
+
.al-rating__label {
|
|
83
|
+
padding: 0;
|
|
84
|
+
margin-block-end: var(--al-rating-label-gap);
|
|
85
|
+
color: var(--al-rating-label-text);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.al-rating__stars {
|
|
89
|
+
display: flex;
|
|
90
|
+
gap: var(--al-rating-gap);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.al-rating__star {
|
|
94
|
+
--_ink: var(--al-rating-star-off);
|
|
95
|
+
--_fill: none;
|
|
96
|
+
|
|
97
|
+
position: relative;
|
|
98
|
+
display: block;
|
|
99
|
+
inline-size: var(--al-rating-star-size);
|
|
100
|
+
block-size: var(--al-rating-star-size);
|
|
101
|
+
border-radius: var(--al-rating-focus-radius);
|
|
102
|
+
cursor: pointer;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* the radio covers the star: it takes the click and the focus, and stays
|
|
106
|
+
in the accessibility tree (never display:none) */
|
|
107
|
+
.al-rating__input {
|
|
108
|
+
position: absolute;
|
|
109
|
+
inset: 0;
|
|
110
|
+
margin: 0;
|
|
111
|
+
opacity: 0;
|
|
112
|
+
cursor: inherit;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.al-rating__glyph {
|
|
116
|
+
display: block;
|
|
117
|
+
inline-size: 100%;
|
|
118
|
+
block-size: 100%;
|
|
119
|
+
fill: var(--_fill);
|
|
120
|
+
stroke: var(--_ink);
|
|
121
|
+
stroke-width: var(--al-rating-star-stroke);
|
|
122
|
+
stroke-linejoin: round;
|
|
123
|
+
pointer-events: none;
|
|
124
|
+
transition:
|
|
125
|
+
fill var(--al-motion-duration-feedback) var(--al-motion-easing-exit),
|
|
126
|
+
stroke var(--al-motion-duration-feedback) var(--al-motion-easing-exit);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* --------------------------------------------------------------- states */
|
|
130
|
+
/* hover preview: the hovered star and the ones before it (rule 10). The
|
|
131
|
+
on rule below comes later, so a checked star stays brand. */
|
|
132
|
+
.al-rating:not(:disabled) .al-rating__star:hover,
|
|
133
|
+
.al-rating:not(:disabled) .al-rating__star:has(~ .al-rating__star:hover) {
|
|
134
|
+
--_ink: var(--al-rating-star-preview);
|
|
135
|
+
--_fill: var(--al-rating-star-preview);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* on: checked, or before the checked one */
|
|
139
|
+
.al-rating__star:has(.al-rating__input:checked),
|
|
140
|
+
.al-rating__star:has(~ .al-rating__star .al-rating__input:checked),
|
|
141
|
+
.al-rating__glyph--on {
|
|
142
|
+
--_ink: var(--al-rating-star-on);
|
|
143
|
+
--_fill: var(--al-rating-star-on);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* focus: the ring on the star that holds it (rule 18); the box gets
|
|
147
|
+
bg-canvas so the ring's gap shows (audit A4) */
|
|
148
|
+
.al-rating__star:has(.al-rating__input:focus-visible) {
|
|
149
|
+
background-color: var(--al-rating-focus-gap);
|
|
150
|
+
box-shadow: var(--al-focus-ring-default);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* disabled - last, because it wins over all. The on stars stay filled.
|
|
154
|
+
The on selectors carry :has() specificity, so the ink is set again there. */
|
|
155
|
+
.al-rating:disabled .al-rating__star {
|
|
156
|
+
--_ink: var(--al-rating-star-disabled);
|
|
157
|
+
cursor: not-allowed;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.al-rating:disabled .al-rating__star:has(.al-rating__input:checked),
|
|
161
|
+
.al-rating:disabled .al-rating__star:has(~ .al-rating__star .al-rating__input:checked) {
|
|
162
|
+
--_ink: var(--al-rating-star-disabled);
|
|
163
|
+
--_fill: var(--al-rating-star-disabled);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.al-rating:disabled .al-rating__label {
|
|
167
|
+
color: var(--al-rating-label-text-disabled);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/* read-only: the glyphs paint themselves, nothing reacts */
|
|
171
|
+
.al-rating--readonly .al-rating__glyph {
|
|
172
|
+
fill: none;
|
|
173
|
+
stroke: var(--al-rating-star-off);
|
|
174
|
+
inline-size: var(--al-rating-star-size);
|
|
175
|
+
block-size: var(--al-rating-star-size);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.al-rating--readonly .al-rating__glyph--on {
|
|
179
|
+
fill: var(--al-rating-star-on);
|
|
180
|
+
stroke: var(--al-rating-star-on);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/* ENTER - the destination states take the enter curve */
|
|
184
|
+
.al-rating:not(:disabled) .al-rating__star:hover .al-rating__glyph,
|
|
185
|
+
.al-rating:not(:disabled) .al-rating__star:has(~ .al-rating__star:hover) .al-rating__glyph {
|
|
186
|
+
transition-timing-function: var(--al-motion-easing-enter);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* --------------------------------------------------------- environment */
|
|
190
|
+
@media (prefers-reduced-motion: reduce) {
|
|
191
|
+
.al-rating__glyph { transition: none; }
|
|
192
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/* AL Design System - Slider tokens
|
|
2
|
+
* GENERATED by src/components/slider/tokens.py. Do not edit by hand.
|
|
3
|
+
*
|
|
4
|
+
* Every color is a semantic the theme switches on :root.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
:root {
|
|
8
|
+
/* color */
|
|
9
|
+
--al-slider-label-text: var(--al-text-primary);
|
|
10
|
+
--al-slider-value-text: var(--al-text-primary);
|
|
11
|
+
--al-slider-range-text: var(--al-text-secondary);
|
|
12
|
+
--al-slider-track-bg: var(--al-bg-track);
|
|
13
|
+
--al-slider-fill-bg: var(--al-bg-brand);
|
|
14
|
+
--al-slider-thumb-bg: var(--al-bg-brand);
|
|
15
|
+
--al-slider-thumb-bg-hover: var(--al-bg-brand-hover);
|
|
16
|
+
--al-slider-thumb-bg-active: var(--al-bg-brand-active);
|
|
17
|
+
--al-slider-thumb-focus-gap: var(--al-bg-canvas);
|
|
18
|
+
--al-slider-label-text-disabled: var(--al-text-disabled);
|
|
19
|
+
--al-slider-track-bg-disabled: var(--al-bg-disabled);
|
|
20
|
+
--al-slider-fill-bg-disabled: var(--al-text-disabled);
|
|
21
|
+
--al-slider-thumb-bg-disabled: var(--al-text-disabled);
|
|
22
|
+
|
|
23
|
+
/* geometry */
|
|
24
|
+
--al-slider-track-height: var(--al-space-4);
|
|
25
|
+
--al-slider-thumb-size: var(--al-space-20);
|
|
26
|
+
--al-slider-thumb-hit: var(--al-space-24);
|
|
27
|
+
--al-slider-radius: var(--al-radius-full);
|
|
28
|
+
--al-slider-gap: var(--al-space-8);
|
|
29
|
+
|
|
30
|
+
/* type - label and value share body-md, the range uses caption */
|
|
31
|
+
--al-slider-font-size: var(--al-font-size-md);
|
|
32
|
+
--al-slider-line-height: var(--al-line-height-md);
|
|
33
|
+
--al-slider-font-weight: var(--al-font-weight-regular);
|
|
34
|
+
--al-slider-range-font-size: var(--al-font-size-xs);
|
|
35
|
+
--al-slider-range-line-height: var(--al-line-height-xs);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* AL Design System - Slider
|
|
39
|
+
*
|
|
40
|
+
* One thumb, one size, no error. The control is a native
|
|
41
|
+
* <input type="range">: the browser gives the keyboard (arrows, Page Up/Down,
|
|
42
|
+
* Home/End - rule 16), the click on the track (rule 21) and the value to
|
|
43
|
+
* assistive tech. The name comes from the visible <label for> (rule 17).
|
|
44
|
+
*
|
|
45
|
+
* <div class="al-slider">
|
|
46
|
+
* <div class="al-slider__header">
|
|
47
|
+
* <label class="al-slider__label" for="vol">Volume</label>
|
|
48
|
+
* <output class="al-slider__value" for="vol">60%</output>
|
|
49
|
+
* </div>
|
|
50
|
+
* <input class="al-slider__input" id="vol" type="range"
|
|
51
|
+
* min="0" max="100" value="60" data-unit="%">
|
|
52
|
+
* <div class="al-slider__range"><span>0%</span><span>100%</span></div>
|
|
53
|
+
* </div>
|
|
54
|
+
*
|
|
55
|
+
* THE FILL NEEDS slider.js
|
|
56
|
+
*
|
|
57
|
+
* Only Firefox paints the filled part (::-moz-range-progress). WebKit/Blink
|
|
58
|
+
* paint it from --al-slider-progress, a percentage slider.js keeps in sync
|
|
59
|
+
* with the value (it also writes the <output> and aria-valuetext). Without
|
|
60
|
+
* the script the track still works; the fill shows only in Firefox.
|
|
61
|
+
*
|
|
62
|
+
* THE HIT AREA IS THE INPUT, NOT THE THUMB
|
|
63
|
+
*
|
|
64
|
+
* The input is 24px tall (slider-thumb-hit) and the whole row takes the
|
|
65
|
+
* pointer; the thumb is drawn at 20px inside it (WCAG 2.5.8, audit A2).
|
|
66
|
+
* Figma's track frame is 20px - the 4px are the hit area.
|
|
67
|
+
*
|
|
68
|
+
* Vendor pseudo-elements can't share a rule: a selector list with one the
|
|
69
|
+
* browser doesn't know is dropped whole. That is why the track and the thumb
|
|
70
|
+
* are written twice.
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
.al-slider {
|
|
74
|
+
/* public adjustment point: slider.js writes it from value/min/max */
|
|
75
|
+
--al-slider-progress: 0%;
|
|
76
|
+
|
|
77
|
+
display: flex;
|
|
78
|
+
flex-direction: column;
|
|
79
|
+
gap: var(--al-slider-gap);
|
|
80
|
+
inline-size: 100%;
|
|
81
|
+
font-family: var(--al-font-sans);
|
|
82
|
+
font-size: var(--al-slider-font-size);
|
|
83
|
+
line-height: var(--al-slider-line-height);
|
|
84
|
+
font-weight: var(--al-slider-font-weight);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.al-slider__header,
|
|
88
|
+
.al-slider__range {
|
|
89
|
+
display: flex;
|
|
90
|
+
justify-content: space-between;
|
|
91
|
+
gap: var(--al-slider-gap);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.al-slider__label {
|
|
95
|
+
color: var(--al-slider-label-text);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* tabular figures keep the number from jittering while it is dragged */
|
|
99
|
+
.al-slider__value {
|
|
100
|
+
flex: none;
|
|
101
|
+
color: var(--al-slider-value-text);
|
|
102
|
+
font-variant-numeric: tabular-nums;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.al-slider__range {
|
|
106
|
+
color: var(--al-slider-range-text);
|
|
107
|
+
font-size: var(--al-slider-range-font-size);
|
|
108
|
+
line-height: var(--al-slider-range-line-height);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* ---------------------------------------------------------------- input */
|
|
112
|
+
.al-slider__input {
|
|
113
|
+
--_thumb-bg: var(--al-slider-thumb-bg);
|
|
114
|
+
--_fill: var(--al-slider-fill-bg);
|
|
115
|
+
--_track: var(--al-slider-track-bg);
|
|
116
|
+
|
|
117
|
+
-webkit-appearance: none;
|
|
118
|
+
appearance: none;
|
|
119
|
+
display: block;
|
|
120
|
+
inline-size: 100%;
|
|
121
|
+
block-size: var(--al-slider-thumb-hit);
|
|
122
|
+
margin: 0;
|
|
123
|
+
background: none;
|
|
124
|
+
cursor: pointer;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* the ring is a shadow on the thumb, never an outline on the whole row */
|
|
128
|
+
.al-slider__input:focus {
|
|
129
|
+
outline: none;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* ---------------------------------------------------------------- track */
|
|
133
|
+
.al-slider__input::-webkit-slider-runnable-track {
|
|
134
|
+
block-size: var(--al-slider-track-height);
|
|
135
|
+
border-radius: var(--al-slider-radius);
|
|
136
|
+
background: linear-gradient(to right,
|
|
137
|
+
var(--_fill) var(--al-slider-progress),
|
|
138
|
+
var(--_track) var(--al-slider-progress));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.al-slider__input::-moz-range-track {
|
|
142
|
+
block-size: var(--al-slider-track-height);
|
|
143
|
+
border-radius: var(--al-slider-radius);
|
|
144
|
+
background-color: var(--_track);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.al-slider__input::-moz-range-progress {
|
|
148
|
+
block-size: var(--al-slider-track-height);
|
|
149
|
+
border-radius: var(--al-slider-radius);
|
|
150
|
+
background-color: var(--_fill);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* ---------------------------------------------------------------- thumb */
|
|
154
|
+
/* WebKit puts the thumb at the top of the track: the margin centers it. */
|
|
155
|
+
.al-slider__input::-webkit-slider-thumb {
|
|
156
|
+
-webkit-appearance: none;
|
|
157
|
+
appearance: none;
|
|
158
|
+
inline-size: var(--al-slider-thumb-size);
|
|
159
|
+
block-size: var(--al-slider-thumb-size);
|
|
160
|
+
margin-block-start: calc((var(--al-slider-track-height) - var(--al-slider-thumb-size)) / 2);
|
|
161
|
+
border: none;
|
|
162
|
+
border-radius: var(--al-slider-radius);
|
|
163
|
+
background-color: var(--_thumb-bg);
|
|
164
|
+
transition:
|
|
165
|
+
background-color var(--al-motion-duration-feedback) var(--al-motion-easing-exit),
|
|
166
|
+
box-shadow var(--al-motion-duration-feedback) var(--al-motion-easing-exit);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.al-slider__input::-moz-range-thumb {
|
|
170
|
+
inline-size: var(--al-slider-thumb-size);
|
|
171
|
+
block-size: var(--al-slider-thumb-size);
|
|
172
|
+
border: none;
|
|
173
|
+
border-radius: var(--al-slider-radius);
|
|
174
|
+
background-color: var(--_thumb-bg);
|
|
175
|
+
transition:
|
|
176
|
+
background-color var(--al-motion-duration-feedback) var(--al-motion-easing-exit),
|
|
177
|
+
box-shadow var(--al-motion-duration-feedback) var(--al-motion-easing-exit);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* --------------------------------------------------------------- states */
|
|
181
|
+
/* hover and active are transient: below 3:1 in dark is the declared
|
|
182
|
+
thumb-transient exception (rule 15) */
|
|
183
|
+
.al-slider__input:hover {
|
|
184
|
+
--_thumb-bg: var(--al-slider-thumb-bg-hover);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.al-slider__input:active {
|
|
188
|
+
--_thumb-bg: var(--al-slider-thumb-bg-active);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/* focus: an inner gap in bg-canvas, then the Foundation ring. Without the
|
|
192
|
+
gap the orange ring reads as a bigger thumb in light (audit A1). */
|
|
193
|
+
.al-slider__input:focus-visible::-webkit-slider-thumb {
|
|
194
|
+
box-shadow:
|
|
195
|
+
inset 0 0 0 var(--al-border-width-2) var(--al-slider-thumb-focus-gap),
|
|
196
|
+
var(--al-focus-ring-default);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.al-slider__input:focus-visible::-moz-range-thumb {
|
|
200
|
+
box-shadow:
|
|
201
|
+
inset 0 0 0 var(--al-border-width-2) var(--al-slider-thumb-focus-gap),
|
|
202
|
+
var(--al-focus-ring-default);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* disabled - last, because it wins over all */
|
|
206
|
+
.al-slider__input:disabled {
|
|
207
|
+
--_thumb-bg: var(--al-slider-thumb-bg-disabled);
|
|
208
|
+
--_fill: var(--al-slider-fill-bg-disabled);
|
|
209
|
+
--_track: var(--al-slider-track-bg-disabled);
|
|
210
|
+
cursor: not-allowed;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.al-slider:has(.al-slider__input:disabled) :is(.al-slider__label, .al-slider__value, .al-slider__range) {
|
|
214
|
+
color: var(--al-slider-label-text-disabled);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/* ENTER - the destination states take the enter curve */
|
|
218
|
+
.al-slider__input:hover::-webkit-slider-thumb,
|
|
219
|
+
.al-slider__input:focus-visible::-webkit-slider-thumb {
|
|
220
|
+
transition-timing-function: var(--al-motion-easing-enter);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.al-slider__input:hover::-moz-range-thumb,
|
|
224
|
+
.al-slider__input:focus-visible::-moz-range-thumb {
|
|
225
|
+
transition-timing-function: var(--al-motion-easing-enter);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/* --------------------------------------------------------- environment */
|
|
229
|
+
@media (prefers-reduced-motion: reduce) {
|
|
230
|
+
.al-slider__input::-webkit-slider-thumb { transition: none; }
|
|
231
|
+
.al-slider__input::-moz-range-thumb { transition: none; }
|
|
232
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/* AL Design System - Slider, fill and value
|
|
2
|
+
*
|
|
3
|
+
* What it does on every .al-slider__input inside `root`:
|
|
4
|
+
* - writes --al-slider-progress on the .al-slider (the WebKit/Blink fill;
|
|
5
|
+
* Firefox paints it natively);
|
|
6
|
+
* - writes the value into the <output for="id">, with data-unit appended;
|
|
7
|
+
* - with data-unit, writes aria-valuetext too ("60%" and not "60",
|
|
8
|
+
* rule 18).
|
|
9
|
+
* The keyboard, the click on the track and the value itself stay native.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* <script src="slider.js"></script> -> binds itself when the page loads
|
|
13
|
+
* alSlider.init(container) -> binds content inserted later
|
|
14
|
+
* Binding the same input twice duplicates nothing.
|
|
15
|
+
*/
|
|
16
|
+
(function () {
|
|
17
|
+
'use strict';
|
|
18
|
+
|
|
19
|
+
function sync(input) {
|
|
20
|
+
var min = parseFloat(input.min) || 0;
|
|
21
|
+
var max = input.max === '' ? 100 : parseFloat(input.max);
|
|
22
|
+
var pct = max > min ? (parseFloat(input.value) - min) / (max - min) * 100 : 0;
|
|
23
|
+
var box = input.closest('.al-slider');
|
|
24
|
+
if (box) box.style.setProperty('--al-slider-progress', pct + '%');
|
|
25
|
+
|
|
26
|
+
var unit = input.getAttribute('data-unit');
|
|
27
|
+
var text = input.value + (unit || '');
|
|
28
|
+
if (unit) input.setAttribute('aria-valuetext', text);
|
|
29
|
+
if (input.id && box) {
|
|
30
|
+
var out = box.querySelector('output[for~="' + input.id + '"]');
|
|
31
|
+
if (out) out.textContent = text;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function bind(input) {
|
|
36
|
+
if (input.hasAttribute('data-al-slider')) return;
|
|
37
|
+
input.setAttribute('data-al-slider', '');
|
|
38
|
+
input.addEventListener('input', function () { sync(input); });
|
|
39
|
+
sync(input);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function init(root) {
|
|
43
|
+
[].forEach.call((root || document).querySelectorAll('.al-slider__input'), bind);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
window.alSlider = { init: init };
|
|
47
|
+
if (document.readyState === 'loading') {
|
|
48
|
+
document.addEventListener('DOMContentLoaded', function () { init(); });
|
|
49
|
+
} else {
|
|
50
|
+
init();
|
|
51
|
+
}
|
|
52
|
+
})();
|
package/dist/foundation.css
CHANGED
package/dist/tokens.json
CHANGED