@inchurch/matcha-theme 22.33.0 → 22.35.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.
@@ -66,6 +66,12 @@
66
66
  border-color: var(--matcha-color-#{$colorName});
67
67
  }
68
68
 
69
+ // O loop gerava `-alpha` para background e color, mas não para border-color — então
70
+ // `border-color-green-alpha` era classe morta, sem aviso nenhum. O token existe.
71
+ .border-color-#{$colorName}-alpha {
72
+ border-color: var(--matcha-color-#{$colorName}-alpha);
73
+ }
74
+
69
75
  .color-#{$colorName} {
70
76
  color: var(--matcha-color-#{$colorName}) !important;
71
77
  }
@@ -158,6 +164,51 @@
158
164
  .color-text-muted { color: var(--matcha-color-text-muted) !important; }
159
165
  .color-text-hint { color: var(--matcha-color-text-hint) !important; }
160
166
 
167
+ // -------------------------------------------------------------------------------------------------------------------
168
+ // @ Namespaces documentados no Figma que NÃO tinham classe utilitária
169
+ // -------------------------------------------------------------------------------------------------------------------
170
+ // Estes tokens sempre foram emitidos por matcha-css-custom-properties, mas nenhuma classe os
171
+ // alcançava: o consumidor só chegava neles por `var(--matcha-color-*)` dentro de SCSS de
172
+ // componente — exatamente o que a regra do painel proíbe ("nenhum estilo mora só na aplicação").
173
+ // Na prática isso empurrava o consumidor de volta pra paleta Material legada ou pra hex cravado.
174
+ //
175
+ // A lista é fechada de propósito, e cada nome existe em tokens/_color-tokens.scss. Ao acrescentar
176
+ // um token novo por lá, acrescente aqui também — ou ele nasce inalcançável por classe.
177
+ $-namespaced-tokens:
178
+ // Palette — cor de IDENTIDADE (categoria, marca, série). Não confundir com semântica de estado.
179
+ "palette-teal", "palette-teal-light", "palette-teal-alpha",
180
+ "palette-light-blue", "palette-light-blue-light", "palette-light-blue-alpha",
181
+ "palette-purple", "palette-purple-light", "palette-purple-alpha", "palette-purple-contrast",
182
+ "palette-pink", "palette-pink-light", "palette-pink-alpha",
183
+ "palette-orange", "palette-orange-light", "palette-orange-alpha",
184
+ "palette-yellow", "palette-yellow-light", "palette-yellow-alpha",
185
+ // Chart — séries de gráfico, com contrast e alpha
186
+ "chart-series-1", "chart-series-2", "chart-series-3", "chart-series-4", "chart-series-5",
187
+ "chart-series-1-contrast", "chart-series-2-contrast", "chart-series-3-contrast",
188
+ "chart-series-4-contrast", "chart-series-5-contrast",
189
+ "chart-series-1-alpha", "chart-series-2-alpha", "chart-series-3-alpha",
190
+ "chart-series-4-alpha", "chart-series-5-alpha",
191
+ // Icon
192
+ "icon-default", "icon-active",
193
+ // Interaction
194
+ "interaction-disabled-bg", "interaction-disabled-bg-alpha", "interaction-disabled-fg",
195
+ "interaction-disabled-border",
196
+ // Surface — as variantes que o bloco estático acima não cobria
197
+ "surface-bg-inverse", "surface-bg-inverse-alpha", "surface-card", "surface-card-strong",
198
+ "surface-inner", "surface-card-inverse", "surface-sidebar", "surface-sidebar-hover",
199
+ "surface-table-row-hover", "surface-border-strong", "surface-hover";
200
+
201
+ // Os cinco atributos, uniformemente — mesma convenção do loop de $color-names acima. Gerar só o
202
+ // "atributo que faz sentido" para cada token exigiria julgamento por nome, e a experiência do
203
+ // painel mostra que a lacuna é pior que o excesso: classe faltando vira hex cravado.
204
+ @each $-token in $-namespaced-tokens {
205
+ .background-#{$-token} { background: var(--matcha-color-#{$-token}); }
206
+ .border-color-#{$-token} { border-color: var(--matcha-color-#{$-token}); }
207
+ .color-#{$-token} { color: var(--matcha-color-#{$-token}) !important; }
208
+ .fill-#{$-token} { fill: var(--matcha-color-#{$-token}); }
209
+ .stroke-#{$-token} { stroke: var(--matcha-color-#{$-token}); }
210
+ }
211
+
161
212
  .color-unset {
162
213
  color: unset;
163
214
  }
@@ -55,7 +55,10 @@
55
55
  }
56
56
 
57
57
  .matcha-file-uploader-file__thumb {
58
- background: var(--matcha-color-elevation-surface-3, var(--matcha-color-surface-card));
58
+ // interaction-disabled-bg, e nao elevation-surface-3: a moldura do arquivo nao e uma
59
+ // superficie elevada, e um fundo neutro atras de um icone — e o surface-3 desaparecia
60
+ // sobre o card em que a linha vive.
61
+ background: var(--matcha-color-interaction-disabled-bg);
59
62
  color: var(--matcha-color-text-muted);
60
63
  }
61
64
 
@@ -12,6 +12,10 @@
12
12
  display: block;
13
13
  }
14
14
 
15
+ .matcha-panel-overlay[hidden] {
16
+ overflow: hidden;
17
+ }
18
+
15
19
  .matcha-panel-pane {
16
20
  position: absolute;
17
21
  display: block;
@@ -86,9 +90,15 @@
86
90
  // IMPORTANTE: !important porque o mixin matcha-panel-theme pode ser aplicado com
87
91
  // wrapper de tema (ex: body.theme-dark .matcha-panel), elevando especificidade pra
88
92
  // 0-2-0, empatando com :has() e vencendo por ordem no cascade.
89
- .matcha-panel:has(.matcha-calendar),
90
- .matcha-panel:has(matcha-time-panel),
91
- .matcha-panel:has(.matcha-time-panel) {
93
+ // FILHO DIRETO (`> `), não descendente: o alvo é "o conteúdo do painel É um
94
+ // calendário/time-panel". Um painel COMPOSTO que só contém um campo de data mais
95
+ // embaixo (matcha-period: presets + dois matcha-date) tem o calendar aninhado no
96
+ // DOM mesmo com o picker fechado — com `:has(.matcha-calendar)` descendente ele
97
+ // perdia fundo, sombra, padding e o max-height (virava lista solta e transbordava
98
+ // a viewport).
99
+ .matcha-panel:has(> .matcha-calendar),
100
+ .matcha-panel:has(> matcha-time-panel),
101
+ .matcha-panel:has(> .matcha-time-panel) {
92
102
  background: transparent !important;
93
103
  box-shadow: none !important;
94
104
  border: none !important;
@@ -109,14 +119,18 @@
109
119
  // matcha-date pintava o scrim blurred permanente em mobile e o `pointer-events:
110
120
  // auto` bloqueava TODOS os cliques da tela.
111
121
  @media (max-width: 639px) {
112
- .matcha-panel-overlay:not([hidden]):has(.matcha-calendar) {
122
+ // Cadeia completa (`> pane > panel > calendar`): o alvo é o overlay do PRÓPRIO
123
+ // painel-calendário. Sem a cadeia, um painel composto que só aninha um
124
+ // matcha-date (matcha-period) casava pelo calendar do filho e ganhava scrim
125
+ // + blur em mobile sem nunca virar sheet.
126
+ .matcha-panel-overlay:not([hidden]):has(> .matcha-panel-pane > .matcha-panel > .matcha-calendar) {
113
127
  pointer-events: auto !important; // precisa capturar o backdrop
114
128
  background: var(--matcha-scrim-drawer, rgba(0, 0, 0, 0.3));
115
129
  backdrop-filter: blur(var(--matcha-scrim-drawer-blur, 4px));
116
130
  animation: matcha-panel-backdrop-fade var(--matcha-duration-fast, 200ms) var(--matcha-easing-standard, cubic-bezier(0.4, 0, 0.2, 1));
117
131
  }
118
132
 
119
- .matcha-panel-overlay:not([hidden]) .matcha-panel-pane:has(.matcha-calendar) {
133
+ .matcha-panel-overlay:not([hidden]) .matcha-panel-pane:has(> .matcha-panel > .matcha-calendar) {
120
134
  position: fixed !important;
121
135
  inset: auto 0 0 0 !important;
122
136
  top: auto !important;
@@ -131,7 +145,7 @@
131
145
  }
132
146
 
133
147
  // Cartão do calendar ocupa a largura toda, com radius só em cima
134
- .matcha-panel:has(.matcha-calendar) .matcha-calendar {
148
+ .matcha-panel:has(> .matcha-calendar) > .matcha-calendar {
135
149
  width: 100%;
136
150
  min-width: 0;
137
151
  border-radius: var(--matcha-radius-xl, 16px) var(--matcha-radius-xl, 16px) 0 0;
@@ -139,10 +153,10 @@
139
153
  }
140
154
 
141
155
  // Dual-month cai pra empilhado em mobile
142
- .matcha-panel:has(.matcha-calendar) .matcha-calendar.is-dual {
156
+ .matcha-panel:has(> .matcha-calendar) > .matcha-calendar.is-dual {
143
157
  min-width: 0;
144
158
  }
145
- .matcha-panel:has(.matcha-calendar) .matcha-calendar.is-dual .matcha-calendar-months {
159
+ .matcha-panel:has(> .matcha-calendar) > .matcha-calendar.is-dual .matcha-calendar-months {
146
160
  flex-direction: column;
147
161
  }
148
162
  }
@@ -0,0 +1,174 @@
1
+ // =============================================================================
2
+ // matcha-period.scss — Seletor de período (presets + período personalizado)
3
+ // Gatilho espelha matcha/field/select (mesma altura/tipografia/caret);
4
+ // o conteúdo do painel é lista de matcha-option + editor de duas datas.
5
+ // =============================================================================
6
+
7
+ // ── Structural (fora do mixin) ──────────────────────────────────────────────
8
+
9
+ .matcha-period-trigger {
10
+ position: relative;
11
+
12
+ &[aria-disabled='true'] {
13
+ pointer-events: none;
14
+ cursor: default;
15
+ }
16
+ }
17
+
18
+ // ── Theme mixin ─────────────────────────────────────────────────────────────
19
+
20
+ @mixin matcha-period-theme($theme) {
21
+ matcha-period {
22
+ display: block;
23
+ width: 100%;
24
+ }
25
+
26
+ .matcha-period-container {
27
+ position: relative;
28
+ display: block;
29
+ width: 100%;
30
+ }
31
+
32
+ // ── Gatilho ────────────────────────────────────────────────────────────
33
+ .matcha-period-trigger {
34
+ display: flex;
35
+ align-items: center;
36
+ justify-content: space-between;
37
+ width: 100%;
38
+ padding: 0;
39
+ border: none;
40
+ background-color: transparent;
41
+ cursor: pointer;
42
+ box-sizing: border-box;
43
+
44
+ &:focus {
45
+ outline: none;
46
+ }
47
+
48
+ &:focus-visible {
49
+ outline: var(--matcha-state-focus-ring-width, 2px) solid var(--matcha-color-accent);
50
+ outline-offset: var(--matcha-state-focus-ring-offset, 2px);
51
+ }
52
+ }
53
+
54
+ .matcha-period-value {
55
+ flex: 1;
56
+ text-align: left;
57
+ overflow: hidden;
58
+ text-overflow: ellipsis;
59
+ white-space: nowrap;
60
+ color: var(--matcha-color-fg);
61
+
62
+ &.matcha-period-placeholder {
63
+ color: var(--matcha-color-text-placeholder);
64
+ }
65
+ }
66
+
67
+ .matcha-period-arrow {
68
+ display: inline-flex;
69
+ align-items: center;
70
+ justify-content: center;
71
+ flex: none;
72
+ width: var(--matcha-icon-size-sm, 16px);
73
+ height: var(--matcha-icon-size-sm, 16px);
74
+ margin-left: var(--matcha-space-100, 8px);
75
+ color: var(--matcha-color-text-placeholder);
76
+ transition: transform var(--matcha-duration-fast, 200ms) ease;
77
+
78
+ &.matcha-period-arrow-open {
79
+ transform: rotate(180deg);
80
+ }
81
+
82
+ @media (prefers-reduced-motion: reduce) {
83
+ transition: none;
84
+ }
85
+ }
86
+
87
+ // Tipografia do valor por size — mesma escala do matcha-select/input:
88
+ // SM body-sm 12/16 · MD 14/20 · LG 16/24.
89
+ matcha-form-field[size='sm'] .matcha-period-value,
90
+ matcha-form-field[size='tiny'] .matcha-period-value,
91
+ matcha-form-field[size='small'] .matcha-period-value {
92
+ font-size: var(--matcha-text-body-sm, 12px);
93
+ line-height: var(--matcha-leading-body-sm, 16px);
94
+ }
95
+
96
+ matcha-form-field[size='md'] .matcha-period-value,
97
+ matcha-form-field[size='medium'] .matcha-period-value {
98
+ font-size: var(--matcha-text-body-md, 14px);
99
+ line-height: var(--matcha-leading-body-md, 20px);
100
+ }
101
+
102
+ matcha-form-field[size='lg'] .matcha-period-value,
103
+ matcha-form-field[size='large'] .matcha-period-value,
104
+ matcha-form-field[size='huge'] .matcha-period-value {
105
+ font-size: var(--matcha-text-body-lg, 16px);
106
+ line-height: var(--matcha-leading-body-lg, 24px);
107
+ }
108
+
109
+ // O caret NÃO escala por size (fica 16 em todos os tiers): o glyph vem do
110
+ // <matcha-icon size="sm">, então crescer só a caixa deixaria o ícone flutuando
111
+ // no meio. Escalar de verdade (16/20/24, como o matcha-select) depende do field
112
+ // repassar `size` pro matcha-period — backlog matcha-period-002.
113
+
114
+ // Disabled: caret esmaecido (o esmaecimento do texto vem do matcha-form-field)
115
+ matcha-form-field[disabled] .matcha-period-arrow,
116
+ matcha-form-field[disabled='true'] .matcha-period-arrow,
117
+ .matcha-period-disabled .matcha-period-arrow {
118
+ color: var(--matcha-color-interaction-disabled-fg);
119
+ }
120
+
121
+ // ── Conteúdo do painel ────────────────────────────────────────────────
122
+ .matcha-period-panel {
123
+ display: flex;
124
+ flex-direction: column;
125
+ padding: var(--matcha-space-050, 4px) 0;
126
+ }
127
+
128
+ .matcha-period-presets {
129
+ display: flex;
130
+ flex-direction: column;
131
+ }
132
+
133
+ // Atalho "Período personalizado" — ghost com texto accent. O ghost canônico
134
+ // usa text-primary (intent do Figma pro botão); aqui o atalho precisa ler como
135
+ // ação secundária dentro do painel, e o slot --matcha-button-ghost-text é o
136
+ // ponto de override previsto pelo matcha-button (token, não hex).
137
+ .matcha-period-custom-toggle {
138
+ --matcha-button-ghost-text: var(--matcha-color-accent);
139
+ align-self: flex-start;
140
+ margin: var(--matcha-space-050, 4px) var(--matcha-space-150, 12px);
141
+ }
142
+
143
+ .matcha-period-custom {
144
+ display: flex;
145
+ flex-direction: column;
146
+ gap: var(--matcha-space-150, 12px);
147
+ padding: 0 var(--matcha-space-150, 12px) var(--matcha-space-150, 12px);
148
+ }
149
+
150
+ .matcha-period-custom-fields {
151
+ display: grid;
152
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
153
+ gap: var(--matcha-space-100, 8px);
154
+ }
155
+
156
+ .matcha-period-error {
157
+ margin: 0;
158
+ color: var(--matcha-color-danger);
159
+ font-size: var(--matcha-text-body-sm, 12px);
160
+ line-height: var(--matcha-leading-body-sm, 16px);
161
+ }
162
+
163
+ .matcha-period-apply {
164
+ width: 100%;
165
+ }
166
+
167
+ // Mobile: uma data por linha sempre — 2 colunas caberiam em largura, mas
168
+ // ficam apertadas demais pro alvo de toque do ícone de calendário.
169
+ @media (max-width: 639px) {
170
+ .matcha-period-custom-fields {
171
+ grid-template-columns: 1fr;
172
+ }
173
+ }
174
+ }
@@ -285,6 +285,46 @@
285
285
  }
286
286
  }
287
287
 
288
+ // ═══════════════════════════════════════════════════════════════════════
289
+ // Selecionadas fixadas no topo ([pinSelected]) — companheiro do modo sem chips
290
+ // ═══════════════════════════════════════════════════════════════════════
291
+ // Sem a lista de chips abaixo do campo, o que já foi escolhido só existe DENTRO do
292
+ // painel — e numa lista longa some no primeiro scroll. A fixação sobe o bloco
293
+ // selecionado pro topo com `order`: as options são content-projected (quase sempre
294
+ // por um `@for` do consumidor), então mover os nós quebraria o próximo update da
295
+ // lista. `order` reordena só a pintura; o DOM fica intacto.
296
+ //
297
+ // Quem congela a ordem é o TS (snapshot na abertura do painel) — sem isso a option
298
+ // pularia de lugar debaixo do cursor a cada clique.
299
+ .matcha-select-options-pinned {
300
+ display: flex;
301
+ flex-direction: column;
302
+
303
+ // Ordens explícitas: com `order` no jogo, quem não declara cai em 0. A busca e o
304
+ // header de ações em lote precisam continuar ACIMA do bloco fixado; carregando e
305
+ // vazio, ABAIXO de tudo.
306
+ > .matcha-select-search { order: -3; }
307
+ > .matcha-select-bulk-actions { order: -2; }
308
+ > .matcha-select-option-pinned { order: -1; }
309
+ > .matcha-select-loading,
310
+ > .matcha-select-empty { order: 1; }
311
+ }
312
+
313
+ // Divisória do bloco fixado — ancorada na ÚLTIMA fixada VISÍVEL, e só quando existe
314
+ // opção não fixada embaixo (senão seria uma linha solta no fim da lista).
315
+ // Pseudo-elemento, não `border-bottom`: a option tem margem lateral própria (4px) e a
316
+ // borda pararia antes da parede do painel, ao contrário da divisória do header de
317
+ // ações em lote — o negativo sangra até lá sem deslocar o item.
318
+ .matcha-select-option-pinned-last::after {
319
+ content: '';
320
+ position: absolute;
321
+ left: calc(var(--matcha-space-050, 4px) * -1);
322
+ right: calc(var(--matcha-space-050, 4px) * -1);
323
+ // Meio do respiro entre duas options (margem vertical de 2px em cada uma).
324
+ bottom: calc((var(--matcha-space-025, 2px) + 1px) * -1);
325
+ border-bottom: var(--matcha-border-hairline, 1px) solid var(--matcha-color-border-subtle, rgba(0, 0, 0, 0.08));
326
+ }
327
+
288
328
  // Bulk actions header (Selecionar todos / Limpar / contagem)
289
329
  .matcha-select-bulk-actions {
290
330
  display: flex;
package/main.scss CHANGED
@@ -135,6 +135,8 @@
135
135
  @use "./components/matcha-date" as *; // matcha-date-theme($theme)
136
136
  @forward "./components/matcha-calendar";
137
137
  @use "./components/matcha-calendar" as *; // matcha-calendar-theme($theme)
138
+ @forward "./components/matcha-period";
139
+ @use "./components/matcha-period" as *; // matcha-period-theme($theme)
138
140
  @forward "./components/matcha-page-builder";
139
141
  @use "./components/matcha-page-builder" as *; // matcha-page-builder($theme)
140
142
  @forward "./components/matcha-snack-bar";
@@ -294,6 +296,7 @@
294
296
  @include matcha-chip-theme($theme);
295
297
  @include matcha-date-theme($theme);
296
298
  @include matcha-calendar-theme($theme);
299
+ @include matcha-period-theme($theme);
297
300
  @include matcha-timepicker-theme($theme);
298
301
  @include matcha-badge-theme($theme);
299
302
  @include matcha-empty-state-theme($theme);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inchurch/matcha-theme",
3
- "version": "22.33.0",
3
+ "version": "22.35.0",
4
4
  "description": "Themes for matcha-design-system",
5
5
  "main": "main.scss",
6
6
  "scripts": {