@inchurch/matcha-theme 22.28.3 → 22.29.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.
|
@@ -181,6 +181,11 @@ $-matcha-required-seeds: (surface-bg, surface, text-primary, accent, primary, su
|
|
|
181
181
|
$derived: map.merge($derived, (
|
|
182
182
|
accent-2: $accent-2,
|
|
183
183
|
accent-2-contrast: matcha-text-on($accent-2),
|
|
184
|
+
// Espelha accent-text-on (linha ~168): mesmo cálculo do contrast, mas com
|
|
185
|
+
// nome dedicado a foreground de TEXTO — na rota de tokens estáticos os dois
|
|
186
|
+
// divergem (o -contrast lá é branco fixo, 1:1 Figma), então quem quer texto
|
|
187
|
+
// legível deve mirar text-on nas duas rotas.
|
|
188
|
+
accent-2-text-on: matcha-text-on($accent-2),
|
|
184
189
|
accent-2-alpha: rgba($accent-2, .1),
|
|
185
190
|
accent-2-surface: color.mix($accent-2, $surface-bg, 14%),
|
|
186
191
|
));
|
|
@@ -408,8 +408,10 @@ matcha-button-toggle {
|
|
|
408
408
|
width: 100%;
|
|
409
409
|
|
|
410
410
|
// Children flex-share — each button takes equal width across the row.
|
|
411
|
-
//
|
|
412
|
-
// (
|
|
411
|
+
// O piso de encolhimento é o `min-width` do size do próprio botão
|
|
412
|
+
// (matcha-buttons.scss) — NÃO o min-content: o botão tem
|
|
413
|
+
// `overflow: hidden`, o que anula a automatic minimum size do
|
|
414
|
+
// flexbox. Quando nem esse piso cabe, o overflow-x do grupo rola.
|
|
413
415
|
> button[matcha-button],
|
|
414
416
|
> a[matcha-button] {
|
|
415
417
|
flex: 1 1 0;
|
|
@@ -47,6 +47,18 @@
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// ── Size classes (responsive, aligned with Figma XS/SM/MD/LG/XL) ────────────
|
|
50
|
+
//
|
|
51
|
+
// Cada size define `min-width` igual à sua `height`: o botão nunca fica mais
|
|
52
|
+
// estreito que alto. Sem esse piso a largura é só `padding + conteúdo`, e um
|
|
53
|
+
// label curto ("OK", "X") vira um retângulo VERTICAL — no XS, 23×28. Com o
|
|
54
|
+
// piso o pior caso é um quadrado, com o conteúdo centrado pelo
|
|
55
|
+
// `justify-content: center` do bloco estrutural. Label longo nunca atinge o
|
|
56
|
+
// piso, então nada muda onde já estava certo.
|
|
57
|
+
//
|
|
58
|
+
// Efeito colateral desejado em flex container: o botão tem `overflow: hidden`,
|
|
59
|
+
// o que já anula o `min-width: auto` (a automatic minimum size do flexbox só
|
|
60
|
+
// vale para item com `overflow: visible`) — ou seja, hoje ele encolhe até ~0 e
|
|
61
|
+
// corta o label. O piso troca esse colapso por um mínimo quadrado.
|
|
50
62
|
|
|
51
63
|
@mixin generate-matcha-button-size-classes($helper-breakpoints) {
|
|
52
64
|
@each $breakpoint, $materialBreakpoint in $helper-breakpoints {
|
|
@@ -62,6 +74,7 @@
|
|
|
62
74
|
line-height: var(--matcha-leading-p-tiny, 14px);
|
|
63
75
|
letter-spacing: var(--matcha-letter-spacing-caption, 0.3px);
|
|
64
76
|
height: 28px;
|
|
77
|
+
min-width: 28px;
|
|
65
78
|
gap: var(--matcha-space-025, 2px);
|
|
66
79
|
}
|
|
67
80
|
|
|
@@ -73,6 +86,7 @@
|
|
|
73
86
|
font-weight: var(--matcha-weight-medium, 500);
|
|
74
87
|
line-height: var(--matcha-leading-label-sm, 19px);
|
|
75
88
|
height: 32px;
|
|
89
|
+
min-width: 32px;
|
|
76
90
|
gap: var(--matcha-space-050, 4px);
|
|
77
91
|
}
|
|
78
92
|
|
|
@@ -84,6 +98,7 @@
|
|
|
84
98
|
font-weight: var(--matcha-weight-medium, 500);
|
|
85
99
|
line-height: var(--matcha-leading-md, 20px);
|
|
86
100
|
height: 40px;
|
|
101
|
+
min-width: 40px;
|
|
87
102
|
gap: var(--matcha-space-100, 8px);
|
|
88
103
|
}
|
|
89
104
|
|
|
@@ -95,6 +110,7 @@
|
|
|
95
110
|
font-weight: var(--matcha-weight-semibold, 600);
|
|
96
111
|
line-height: var(--matcha-leading-label-lg, 22px);
|
|
97
112
|
height: 48px;
|
|
113
|
+
min-width: 48px;
|
|
98
114
|
gap: var(--matcha-space-100, 8px);
|
|
99
115
|
}
|
|
100
116
|
|
|
@@ -106,6 +122,7 @@
|
|
|
106
122
|
font-weight: var(--matcha-weight-semibold, 600);
|
|
107
123
|
line-height: var(--matcha-leading-label-lg, 22px);
|
|
108
124
|
height: 56px;
|
|
125
|
+
min-width: 56px;
|
|
109
126
|
gap: var(--matcha-space-100, 8px);
|
|
110
127
|
}
|
|
111
128
|
}
|
|
@@ -126,6 +143,7 @@ a[matcha-link] {
|
|
|
126
143
|
font-weight: var(--matcha-weight-medium, 500);
|
|
127
144
|
font-family: inherit;
|
|
128
145
|
height: px-to-rem(40px); // default MD; overridden by size attribute selectors
|
|
146
|
+
min-width: px-to-rem(40px); // piso quadrado do default MD; ver mixin de sizes
|
|
129
147
|
appearance: auto;
|
|
130
148
|
text-rendering: auto;
|
|
131
149
|
letter-spacing: var(--matcha-letter-spacing-button, 0.2px);
|
|
@@ -245,6 +263,14 @@ a[matcha-link] {
|
|
|
245
263
|
background: transparent;
|
|
246
264
|
}
|
|
247
265
|
|
|
266
|
+
// Link legado é texto inline (padding 0) — o piso quadrado do size viraria
|
|
267
|
+
// espaço morto clicável em volta do label, então cai aqui.
|
|
268
|
+
// O `:not([outline])` é deliberado: o combo [outline][link] é um botão com
|
|
269
|
+
// borda e padding real (bloco acima), esse MANTÉM o piso.
|
|
270
|
+
&[link]:not([link="false"]):not([outline]) {
|
|
271
|
+
min-width: 0;
|
|
272
|
+
}
|
|
273
|
+
|
|
248
274
|
// ── matcha-link specific (Figma spec 16914:500) ──
|
|
249
275
|
// SM=11/14 Regular letter 0.3 · MD=14/20 Medium · LG=16/22 SemiBold
|
|
250
276
|
// Hover/Active → underline automático. Underline=true → permanente.
|
|
@@ -253,6 +279,7 @@ a[matcha-link] {
|
|
|
253
279
|
height: auto;
|
|
254
280
|
min-height: 0;
|
|
255
281
|
max-height: none;
|
|
282
|
+
min-width: 0; // texto inline não tem piso quadrado (ver mixin de sizes)
|
|
256
283
|
padding: 0;
|
|
257
284
|
background: transparent;
|
|
258
285
|
border-radius: 0;
|
|
@@ -251,6 +251,19 @@
|
|
|
251
251
|
outline: var(--matcha-state-focus-ring-width, 2px) solid var(--matcha-color-accent);
|
|
252
252
|
outline-offset: var(--matcha-state-focus-ring-offset, 2px);
|
|
253
253
|
}
|
|
254
|
+
|
|
255
|
+
// Desabilitado — irmão do .matcha-nav-item--disabled (mesma dupla
|
|
256
|
+
// pointer-events/cursor aqui; a cor fica no mixin de tema). Cobre as 3 formas:
|
|
257
|
+
// o `disabled` nativo do <button>, o atributo em elemento que não é button
|
|
258
|
+
// (o slot aceita <a>) e o aria-disabled de quem precisa manter o foco.
|
|
259
|
+
// Sem isto, um módulo desabilitado renderiza IDÊNTICO ao habilitado e o
|
|
260
|
+
// usuário clica sem entender por que nada acontece.
|
|
261
|
+
&:disabled,
|
|
262
|
+
&[disabled],
|
|
263
|
+
&[aria-disabled="true"] {
|
|
264
|
+
cursor: default;
|
|
265
|
+
pointer-events: none;
|
|
266
|
+
}
|
|
254
267
|
}
|
|
255
268
|
|
|
256
269
|
// ── Nav Rail labeled (84px — nome do módulo embaixo do ícone) ───────────────
|
|
@@ -710,6 +723,19 @@
|
|
|
710
723
|
font-weight: var(--matcha-weight-medium, 500);
|
|
711
724
|
}
|
|
712
725
|
}
|
|
726
|
+
|
|
727
|
+
// Desabilitado — mesmo token de cor do nav-item disabled, pra os dois
|
|
728
|
+
// estados lerem igual. Depois do bloco ativo de propósito: um módulo
|
|
729
|
+
// desabilitado não deve ficar com a cor de ativo.
|
|
730
|
+
&:disabled,
|
|
731
|
+
&[disabled],
|
|
732
|
+
&[aria-disabled="true"] {
|
|
733
|
+
color: var(--matcha-color-interaction-disabled-fg);
|
|
734
|
+
|
|
735
|
+
matcha-icon {
|
|
736
|
+
color: var(--matcha-color-interaction-disabled-fg);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
713
739
|
}
|
|
714
740
|
|
|
715
741
|
.matcha-nav-rail__divider {
|
|
@@ -25,10 +25,21 @@
|
|
|
25
25
|
// Default fill = accent
|
|
26
26
|
--matcha-progress-fill: var(--matcha-color-accent);
|
|
27
27
|
|
|
28
|
+
// Foreground do label inline, em duas alturas:
|
|
29
|
+
// • on-fill → sobre a barra preenchida. Cada semântica já tem o seu par
|
|
30
|
+
// `<nome>-contrast` ("o foreground correto sobre esta cor"),
|
|
31
|
+
// então não há contraste calculado à mão em lugar nenhum.
|
|
32
|
+
// • on-track → sobre o rail não preenchido (disabled-bg).
|
|
33
|
+
// O default accent-contrast resolve pra rgba(0,0,0,.87) nos dois modos — o
|
|
34
|
+
// mesmo valor que estava cravado antes, então o caso default não muda de cor.
|
|
35
|
+
--matcha-progress-label-on-fill: var(--matcha-color-accent-contrast);
|
|
36
|
+
--matcha-progress-label-on-track: var(--matcha-color-fg);
|
|
37
|
+
|
|
28
38
|
// Bind por color attr → CSS var (mesma estratégia do slider/spinner)
|
|
29
39
|
@each $name, $fn in $semantic-colors {
|
|
30
40
|
&[color="#{$name}"] {
|
|
31
41
|
--matcha-progress-fill: var(--matcha-color-#{$name});
|
|
42
|
+
--matcha-progress-label-on-fill: var(--matcha-color-#{$name}-contrast);
|
|
32
43
|
}
|
|
33
44
|
}
|
|
34
45
|
}
|
|
@@ -62,23 +73,48 @@ matcha-progress-bar {
|
|
|
62
73
|
overflow: hidden;
|
|
63
74
|
}
|
|
64
75
|
|
|
65
|
-
// Fill determinate (standard + informative)
|
|
76
|
+
// Fill determinate (standard + informative).
|
|
77
|
+
// position/z-index colocam o fill ENTRE os dois labels (bg z-1 · fill z-2 · fg z-3),
|
|
78
|
+
// que é o que faz o fill opaco mascarar o label de trás no trecho preenchido.
|
|
66
79
|
.progress-fill {
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
position: relative;
|
|
81
|
+
z-index: 2;
|
|
69
82
|
height: 100%;
|
|
70
83
|
background-color: var(--matcha-progress-fill);
|
|
71
84
|
border-radius: var(--matcha-radius-sm, 2px);
|
|
72
85
|
transition: width var(--matcha-duration-fast, 200ms) ease;
|
|
73
86
|
}
|
|
74
87
|
|
|
75
|
-
// Inline label (standard sm/md)
|
|
76
|
-
.
|
|
88
|
+
// ── Inline label (standard sm/md) ──────────────────────────────────────
|
|
89
|
+
// Base comum aos dois labels. Ambos cobrem o track inteiro (inset: 0), então
|
|
90
|
+
// ficam alinhados pixel a pixel e a única diferença entre eles é cor + clip.
|
|
91
|
+
// Se a tipografia divergir entre os dois, o recorte desalinha e aparece degrau
|
|
92
|
+
// na borda do fill — por isso size/weight moram num seletor só (blocos de size
|
|
93
|
+
// abaixo miram .progress-text, nunca um dos dois isolado).
|
|
94
|
+
.progress-text {
|
|
95
|
+
position: absolute;
|
|
96
|
+
inset: 0;
|
|
97
|
+
display: flex;
|
|
98
|
+
align-items: center;
|
|
77
99
|
padding-left: var(--matcha-space-100, 8px);
|
|
78
100
|
font-family: var(--matcha-font-family);
|
|
79
|
-
// Figma: text inverse/escuro sobre fill claro (accent é claro em dark mode)
|
|
80
|
-
color: rgba(0, 0, 0, 0.87);
|
|
81
101
|
white-space: nowrap;
|
|
102
|
+
pointer-events: none;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Trecho NÃO preenchido: atrás do fill, cor que contrasta com o track.
|
|
106
|
+
.progress-text-bg {
|
|
107
|
+
z-index: 1;
|
|
108
|
+
color: var(--matcha-progress-label-on-track);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Trecho preenchido: na frente do fill, cor que contrasta com o fill.
|
|
112
|
+
// clip-path recorta na largura exata do progresso; a transition acompanha
|
|
113
|
+
// a mesma duração da width do fill pra recorte e barra andarem juntos.
|
|
114
|
+
.progress-text-fg {
|
|
115
|
+
z-index: 3;
|
|
116
|
+
color: var(--matcha-progress-label-on-fill);
|
|
117
|
+
transition: clip-path var(--matcha-duration-fast, 200ms) ease;
|
|
82
118
|
}
|
|
83
119
|
|
|
84
120
|
// Indeterminate animation (standard, sem progress) — Material-style dual-scan.
|
|
@@ -126,7 +162,7 @@ matcha-progress-bar {
|
|
|
126
162
|
&[size="sm"], &[size="small"] {
|
|
127
163
|
.progress { height: var(--matcha-space-200, 16px); border-radius: var(--matcha-radius-md, 4px); }
|
|
128
164
|
.progress-fill { border-radius: var(--matcha-radius-md, 4px); }
|
|
129
|
-
.progress-
|
|
165
|
+
.progress-text {
|
|
130
166
|
font-size: var(--matcha-text-p-tiny, 11px);
|
|
131
167
|
font-weight: var(--matcha-weight-regular, 400);
|
|
132
168
|
line-height: var(--matcha-leading-p-tiny, 14px);
|
|
@@ -136,7 +172,7 @@ matcha-progress-bar {
|
|
|
136
172
|
&[size="md"], &[size="medium"] {
|
|
137
173
|
.progress { height: var(--matcha-space-400, 32px); border-radius: var(--matcha-radius-md, 4px); }
|
|
138
174
|
.progress-fill { border-radius: var(--matcha-radius-md, 4px); }
|
|
139
|
-
.progress-
|
|
175
|
+
.progress-text {
|
|
140
176
|
font-size: var(--matcha-text-label-md, 14px);
|
|
141
177
|
font-weight: var(--matcha-weight-medium, 500);
|
|
142
178
|
line-height: var(--matcha-leading-label-md, 20px);
|
|
@@ -289,6 +325,7 @@ matcha-progress-bar[type="segmented"] {
|
|
|
289
325
|
@media (prefers-reduced-motion: reduce) {
|
|
290
326
|
matcha-progress-bar {
|
|
291
327
|
.progress-fill { transition: none; }
|
|
328
|
+
.progress-text-fg { transition: none; }
|
|
292
329
|
.progress-indeterminate,
|
|
293
330
|
.progress-indeterminate::before,
|
|
294
331
|
.progress-indeterminate::after { animation: none; }
|
package/package.json
CHANGED
|
@@ -154,7 +154,15 @@ $matcha-color-tokens: (
|
|
|
154
154
|
// ── Accent Secondary (teal — 4 tokens Figma matcha/color/accent-2/*) ─────
|
|
155
155
|
// Light #00796b (teal-700) | Dark #4fb7ad (teal-light)
|
|
156
156
|
accent-2: (light: #00796b, dark: #4fb7ad),
|
|
157
|
+
// accent-2-contrast 1:1 Figma DSV3: {common.white} em AMBOS os modos. Serve no Light
|
|
158
|
+
// (#00796b + branco = 5.3:1), mas NÃO no Dark: accent-2 clareia pra #4fb7ad e o branco
|
|
159
|
+
// cai pra ~2.3:1 (reprova AA). Mesma situação do accent/contrast — por isso a saída é a
|
|
160
|
+
// mesma: um accent-2/text-on dedicado a FOREGROUND DE TEXTO, que inverte por modo.
|
|
161
|
+
// O -contrast fica intacto, fiel ao Figma (drift = o Figma vence).
|
|
157
162
|
accent-2-contrast: (light: #ffffff, dark: #ffffff),
|
|
163
|
+
// Espelha accent-text-on. Valores batem com matcha-text-on() (rota whitelabel):
|
|
164
|
+
// yiq(#00796b)=83 → #ffffff · yiq(#4fb7ad)=151 → #1a1d21.
|
|
165
|
+
accent-2-text-on: (light: #ffffff, dark: #1a1d21),
|
|
158
166
|
accent-2-alpha: (light: rgba(#00796b, .10), dark: rgba(#4fb7ad, .12)),
|
|
159
167
|
accent-2-surface: (light: #e0f0ee, dark: #1d332e),
|
|
160
168
|
|
|
@@ -215,7 +223,7 @@ $matcha-color-tokens: (
|
|
|
215
223
|
info-surface-hover: (light: #ebeefa, dark: #0f141e),
|
|
216
224
|
info-surface-pressed: (light: #d8def5, dark: #131f31),
|
|
217
225
|
|
|
218
|
-
// ── Palette (
|
|
226
|
+
// ── Palette (19) — matcha/color/palette/* ────────────────────────────────
|
|
219
227
|
palette-teal: (light: #00796b, dark: #4fb7ad),
|
|
220
228
|
palette-teal-light: (light: #4fb7ad, dark: #009688),
|
|
221
229
|
palette-teal-alpha: (light: rgba(#00796b, .1), dark: rgba(#4fb7ad, .1)),
|
|
@@ -225,6 +233,12 @@ $matcha-color-tokens: (
|
|
|
225
233
|
palette-purple: (light: #9c27b0, dark: #bb6ac8),
|
|
226
234
|
palette-purple-light: (light: #bb6ac8, dark: #9c27b0),
|
|
227
235
|
palette-purple-alpha: (light: rgba(#9c27b0, .1), dark: rgba(#bb6ac8, .1)),
|
|
236
|
+
// Contraste (texto sobre a cor sólida), mesmo critério dos chart-series-*-contrast.
|
|
237
|
+
// Light #9c27b0 + branco = 5.6:1 · Dark #bb6ac8 + preto .87 = ~7:1 (AA nos 2 modos).
|
|
238
|
+
// Só o purple tem o par por enquanto: é a única cor da paleta usada como fill de
|
|
239
|
+
// superfície com texto em cima (barra de Jornada do dashboard). As outras ganham o
|
|
240
|
+
// seu quando aparecer o caso — não gerar 6 pares especulativos.
|
|
241
|
+
palette-purple-contrast: (light: #ffffff, dark: rgba(0, 0, 0, .87)),
|
|
228
242
|
palette-pink: (light: #d81b60, dark: #e46291),
|
|
229
243
|
palette-pink-light: (light: #e46291, dark: #d81b60),
|
|
230
244
|
palette-pink-alpha: (light: rgba(#d81b60, .1), dark: rgba(#e46291, .1)),
|