@inchurch/matcha-theme 21.3.3 → 22.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/abstracts/_colors.scss +236 -229
- package/abstracts/_elevation.scss +108 -108
- package/abstracts/_functions.scss +321 -321
- package/abstracts/_media-breakpoint.scss +26 -26
- package/abstracts/_theme-api.scss +219 -219
- package/abstracts/_typography.scss +128 -128
- package/base/_reset.scss +445 -432
- package/components/app-page-header.scss +260 -260
- package/components/matcha-accordion.scss +293 -293
- package/components/matcha-audio-player.scss +31 -31
- package/components/matcha-autocomplete.scss +145 -145
- package/components/matcha-avatar.scss +440 -301
- package/components/matcha-badge.scss +120 -120
- package/components/matcha-breadcrumb.scss +231 -231
- package/components/matcha-button-toggle.scss +384 -384
- package/components/matcha-buttons.scss +913 -913
- package/components/matcha-calendar.scss +218 -218
- package/components/matcha-cards.scss +230 -230
- package/components/matcha-chart-card.scss +53 -53
- package/components/matcha-checkbox.scss +255 -255
- package/components/matcha-chip.scss +292 -292
- package/components/matcha-color-pick.scss +34 -34
- package/components/matcha-command-palette.scss +316 -316
- package/components/matcha-crop.scss +406 -406
- package/components/matcha-date.scss +81 -81
- package/components/matcha-divider.scss +100 -100
- package/components/matcha-draggable.scss +23 -23
- package/components/matcha-drawer.scss +376 -376
- package/components/matcha-drop-image.scss +14 -14
- package/components/matcha-drop-list.scss +430 -430
- package/components/matcha-emoji.scss +69 -69
- package/components/matcha-empty-state.scss +230 -230
- package/components/matcha-file-uploader.scss +471 -471
- package/components/matcha-flag.scss +103 -103
- package/components/matcha-footer.scss +91 -91
- package/components/matcha-form-field.scss +606 -606
- package/components/matcha-form-section.scss +100 -100
- package/components/matcha-header.scss +135 -135
- package/components/matcha-highlight.scss +164 -164
- package/components/matcha-hint-text.scss +90 -90
- package/components/matcha-horizontal-tree.scss +316 -316
- package/components/matcha-icon.scss +98 -98
- package/components/matcha-image.scss +61 -61
- package/components/matcha-list.scss +211 -211
- package/components/matcha-menu.scss +99 -99
- package/components/matcha-modal.scss +210 -210
- package/components/matcha-nav.scss +581 -581
- package/components/matcha-notification.scss +413 -413
- package/components/matcha-option.scss +170 -170
- package/components/matcha-page-builder.scss +4196 -4196
- package/components/matcha-paginator.scss +689 -689
- package/components/matcha-panel.scss +194 -194
- package/components/matcha-profile-card.scss +50 -50
- package/components/matcha-progress-bar.scss +313 -313
- package/components/matcha-radio.scss +320 -320
- package/components/matcha-ripple.scss +7 -7
- package/components/matcha-scrollbar.scss +33 -33
- package/components/matcha-scrollbox-shadow.scss +120 -120
- package/components/matcha-section.scss +102 -102
- package/components/matcha-select-multiple.scss +56 -56
- package/components/matcha-select.scss +667 -667
- package/components/matcha-skeleton.scss +155 -155
- package/components/matcha-slide-toggle.scss +369 -369
- package/components/matcha-slider.scss +285 -285
- package/components/matcha-snack-bar.scss +259 -259
- package/components/matcha-spin.scss +164 -164
- package/components/matcha-spinner.scss +97 -97
- package/components/matcha-status-pill.scss +38 -18
- package/components/matcha-stepper.scss +376 -376
- package/components/matcha-table-cell.scss +74 -41
- package/components/matcha-table.scss +579 -578
- package/components/matcha-tabs.scss +600 -600
- package/components/matcha-text-editor.scss +105 -105
- package/components/matcha-time.scss +33 -33
- package/components/matcha-timepicker.scss +13 -13
- package/components/matcha-toolbar.scss +359 -359
- package/components/matcha-tooltip.scss +224 -224
- package/components/matcha-tree-view.scss +257 -212
- package/layout/matcha-page-layout.scss +778 -778
- package/main.scss +329 -329
- package/package.json +1 -1
- package/tokens/_animations-tokens.scss +37 -37
- package/tokens/_breakpoints-tokens.scss +35 -35
- package/tokens/_color-tokens.scss +274 -261
- package/tokens/_elevation-tokens.scss +33 -33
- package/tokens/_emit-tokens.scss +324 -324
- package/tokens/_material-palette.scss +1149 -1149
- package/tokens/_primitives.scss +98 -98
- package/tokens/_semantic-aliases.scss +120 -120
- package/tokens/_spacing-tokens.scss +94 -94
- package/tokens/_static-tokens.scss +137 -137
- package/tokens/_typography-tokens.scss +65 -65
- package/vendors/charts.scss +90 -90
|
@@ -1,606 +1,606 @@
|
|
|
1
|
-
@use "../abstracts/media-breakpoint" as *;
|
|
2
|
-
@use "../tokens/breakpoints-tokens" as *;
|
|
3
|
-
// =============================================================================
|
|
4
|
-
// matcha-form-field.scss — Theme mixin (stacked pattern, Figma matcha/field/_base)
|
|
5
|
-
// Border colors vêm do data-color (component SCSS). Theme mixin cuida de:
|
|
6
|
-
// - tipografia do input (size por breakpoint)
|
|
7
|
-
// - placeholder color
|
|
8
|
-
// - disabled text color
|
|
9
|
-
// =============================================================================
|
|
10
|
-
|
|
11
|
-
// ── Structural (inputs) — sem border, sem bg (box wraps) ────────────────────
|
|
12
|
-
|
|
13
|
-
// ─── Filhos projetáveis do form-field ────────────────────────────────────
|
|
14
|
-
// Todos os tipos de input que podem ser projetados DEVEM preencher o espaço
|
|
15
|
-
// disponível e herdar padding/border/bg do wrapper externo (.matcha-form-field).
|
|
16
|
-
// O componente filho NÃO deve ter padding/border próprio quando dentro do field.
|
|
17
|
-
.matcha-form-field {
|
|
18
|
-
input,
|
|
19
|
-
input[type="text"],
|
|
20
|
-
input[type="email"],
|
|
21
|
-
input[type="tel"],
|
|
22
|
-
input[type="url"],
|
|
23
|
-
input[type="password"],
|
|
24
|
-
input[type="number"],
|
|
25
|
-
input[type="search"],
|
|
26
|
-
input[type="date"],
|
|
27
|
-
input[type="time"],
|
|
28
|
-
textarea {
|
|
29
|
-
flex: 1 1 auto;
|
|
30
|
-
width: 100%;
|
|
31
|
-
min-width: 0;
|
|
32
|
-
min-height: 0; // evita que altura natural do input expanda o container
|
|
33
|
-
background-color: transparent;
|
|
34
|
-
outline: none;
|
|
35
|
-
box-shadow: none;
|
|
36
|
-
border: none;
|
|
37
|
-
padding: 0; // wrapper fornece padding horizontal
|
|
38
|
-
margin: 0;
|
|
39
|
-
font-family: var(--matcha-font-family);
|
|
40
|
-
font-size: var(--matcha-font-size-sm, 14px); // Figma MD placeholder/value 14/400/20
|
|
41
|
-
font-weight: var(--matcha-weight-regular, 400);
|
|
42
|
-
line-height: var(--matcha-leading-body-md, 20px);
|
|
43
|
-
color: var(--matcha-color-text-primary); // Figma filled value: #E8EAED dark / #0E1116 light
|
|
44
|
-
resize: none;
|
|
45
|
-
|
|
46
|
-
&:disabled {
|
|
47
|
-
color: var(--matcha-color-interaction-disabled-fg);
|
|
48
|
-
-webkit-text-fill-color: var(--matcha-color-interaction-disabled-fg); // Safari override
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Textarea ocupa TODA a altura disponível do wrapper (que é column mode).
|
|
53
|
-
// Quando `matchaAutoGrow` está ligado, a directive aplica `.matcha-autogrow`
|
|
54
|
-
// e controla altura via JS — o override abaixo solta o 100% forçado.
|
|
55
|
-
textarea {
|
|
56
|
-
height: 100%;
|
|
57
|
-
min-height: 100%;
|
|
58
|
-
align-self: stretch;
|
|
59
|
-
|
|
60
|
-
&.matcha-autogrow {
|
|
61
|
-
height: auto; // directive calcula e seta inline
|
|
62
|
-
min-height: 0; // flex: 1 já garante piso via wrapper min-height
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// ── Scrollbar estilizada no textarea (Webkit + Firefox) ──────────────────
|
|
67
|
-
// Usa tokens do DS em vez do scrollbar nativo cinza feio do Chrome/Windows.
|
|
68
|
-
// Aplica tanto no textarea "rows fixo" (se user passar rows pequeno + muito texto)
|
|
69
|
-
// quanto no `.matcha-autogrow` depois de atingir `maxRows`.
|
|
70
|
-
textarea {
|
|
71
|
-
scrollbar-width: thin; // Firefox
|
|
72
|
-
scrollbar-color: var(--matcha-color-text-placeholder)
|
|
73
|
-
transparent; // thumb + track
|
|
74
|
-
|
|
75
|
-
&::-webkit-scrollbar { width: 6px; height: 6px; }
|
|
76
|
-
&::-webkit-scrollbar-track { background: transparent; }
|
|
77
|
-
&::-webkit-scrollbar-thumb {
|
|
78
|
-
background: var(--matcha-color-text-placeholder);
|
|
79
|
-
border-radius: var(--matcha-radius-pill, 999px);
|
|
80
|
-
}
|
|
81
|
-
&::-webkit-scrollbar-thumb:hover { background: var(--matcha-color-text-secondary); }
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
input:focus,
|
|
85
|
-
textarea:focus {
|
|
86
|
-
outline: none;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Truncate: quando o campo é menor que placeholder/value, corta com ellipsis
|
|
90
|
-
// Evita overflow feio em sidebars, colunas estreitas, responsive mobile.
|
|
91
|
-
input {
|
|
92
|
-
text-overflow: ellipsis;
|
|
93
|
-
overflow: hidden;
|
|
94
|
-
white-space: nowrap;
|
|
95
|
-
|
|
96
|
-
// Placeholder também trunca (Chrome/Safari precisam do ::placeholder explícito)
|
|
97
|
-
&::placeholder {
|
|
98
|
-
text-overflow: ellipsis;
|
|
99
|
-
overflow: hidden;
|
|
100
|
-
white-space: nowrap;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// ── Autofill (Chrome/Safari) — mata o background amarelo/azul e usa os tokens ──
|
|
105
|
-
// Browsers injetam background-color inline no -webkit-autofill (prioridade sobre CSS normal).
|
|
106
|
-
// O workaround padrão: box-shadow inset transparente (não sobreposto) + text-fill-color pro texto.
|
|
107
|
-
// `transition: ... 5000s` é o "truque dos 5000 segundos" — impede o browser de re-aplicar o bg.
|
|
108
|
-
input:-webkit-autofill,
|
|
109
|
-
input:-webkit-autofill:hover,
|
|
110
|
-
input:-webkit-autofill:focus,
|
|
111
|
-
input:-webkit-autofill:active,
|
|
112
|
-
textarea:-webkit-autofill {
|
|
113
|
-
-webkit-box-shadow: 0 0 0 1000px transparent inset !important;
|
|
114
|
-
-webkit-text-fill-color: var(--matcha-color-text-primary) !important;
|
|
115
|
-
caret-color: var(--matcha-color-primary) !important;
|
|
116
|
-
transition: background-color 5000s ease-in-out 0s, color 5000s ease-in-out 0s;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Caret color (cursor piscando) = primary pra match com focus border
|
|
120
|
-
input,
|
|
121
|
-
textarea {
|
|
122
|
-
caret-color: var(--matcha-color-primary);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Selection highlight (quando user seleciona texto) — usa token de primary com alpha
|
|
126
|
-
input::selection,
|
|
127
|
-
textarea::selection {
|
|
128
|
-
background: var(--matcha-color-primary-alpha);
|
|
129
|
-
color: var(--matcha-color-text-primary);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Componentes projetados — todos preenchem a largura e não adicionam borda/padding próprio
|
|
133
|
-
matcha-select,
|
|
134
|
-
matcha-autocomplete,
|
|
135
|
-
matcha-date,
|
|
136
|
-
matcha-field-range,
|
|
137
|
-
matcha-time,
|
|
138
|
-
matcha-phone {
|
|
139
|
-
flex: 1 1 auto;
|
|
140
|
-
width: 100%;
|
|
141
|
-
min-width: 0;
|
|
142
|
-
display: flex;
|
|
143
|
-
align-items: center;
|
|
144
|
-
background: transparent;
|
|
145
|
-
border: none;
|
|
146
|
-
padding: 0;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// matcha-phone: padding/bg próprios do componente quebram o layout dentro do field
|
|
150
|
-
matcha-phone .matcha-phone {
|
|
151
|
-
padding: 0;
|
|
152
|
-
background: transparent;
|
|
153
|
-
font-size: inherit;
|
|
154
|
-
width: 100%;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// matcha-date/time: container do componente preenche o espaço sem padding/border próprios
|
|
158
|
-
matcha-date .matcha-date-container,
|
|
159
|
-
matcha-time .matcha-time-container {
|
|
160
|
-
width: 100%;
|
|
161
|
-
background: transparent;
|
|
162
|
-
border: none;
|
|
163
|
-
padding: 0;
|
|
164
|
-
min-width: 0;
|
|
165
|
-
gap: var(--matcha-space-100, 8px);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// ── matchaPasswordToggle: botão do olho injetado ao lado de input[type="password"] ──
|
|
169
|
-
// Figma matcha/field/password: ícone 16/20/24 por size, cor text-placeholder (#9AA0A6)
|
|
170
|
-
.matcha-password-toggle-button {
|
|
171
|
-
flex: none;
|
|
172
|
-
display: inline-flex;
|
|
173
|
-
align-items: center;
|
|
174
|
-
justify-content: center;
|
|
175
|
-
width: 16px; // SM default
|
|
176
|
-
height: 16px;
|
|
177
|
-
padding: 0;
|
|
178
|
-
margin: 0;
|
|
179
|
-
background: transparent;
|
|
180
|
-
border: none;
|
|
181
|
-
cursor: pointer;
|
|
182
|
-
color: var(--matcha-color-text-placeholder); // #9AA0A6
|
|
183
|
-
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
184
|
-
|
|
185
|
-
&:hover:not(:disabled) {
|
|
186
|
-
color: var(--matcha-color-text-primary);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
&:disabled {
|
|
190
|
-
cursor: not-allowed;
|
|
191
|
-
color: var(--matcha-color-interaction-disabled-fg);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
&:focus { outline: none; }
|
|
195
|
-
&:focus-visible {
|
|
196
|
-
outline: 2px solid var(--matcha-color-primary);
|
|
197
|
-
outline-offset: 2px;
|
|
198
|
-
border-radius: var(--matcha-radius-md, 4px);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
> [class^="i-matcha-"],
|
|
202
|
-
> [class*=" i-matcha-"] {
|
|
203
|
-
font-size: inherit !important;
|
|
204
|
-
width: 1em !important;
|
|
205
|
-
height: 1em !important;
|
|
206
|
-
line-height: 1 !important;
|
|
207
|
-
color: inherit !important;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// ── matchaQuantityStepper: wrapper flex-row + dois botões (−/+) ──────
|
|
212
|
-
// Figma matcha/field/quantity: gap 4, ícones 16px constante, cor #9AA0A6
|
|
213
|
-
.matcha-quantity-stepper {
|
|
214
|
-
flex: none;
|
|
215
|
-
display: inline-flex;
|
|
216
|
-
align-items: center;
|
|
217
|
-
gap: var(--matcha-space-050, 4px);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
.matcha-quantity-stepper-button {
|
|
221
|
-
flex: none;
|
|
222
|
-
display: inline-flex;
|
|
223
|
-
align-items: center;
|
|
224
|
-
justify-content: center;
|
|
225
|
-
width: 16px; // Figma: constante 16px em todos os sizes
|
|
226
|
-
height: 16px;
|
|
227
|
-
padding: 0;
|
|
228
|
-
margin: 0;
|
|
229
|
-
background: transparent;
|
|
230
|
-
border: none;
|
|
231
|
-
cursor: pointer;
|
|
232
|
-
color: var(--matcha-color-text-placeholder); // #9AA0A6
|
|
233
|
-
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
234
|
-
|
|
235
|
-
&:hover:not(:disabled) {
|
|
236
|
-
color: var(--matcha-color-text-primary);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
&:disabled {
|
|
240
|
-
cursor: not-allowed;
|
|
241
|
-
color: var(--matcha-color-interaction-disabled-fg);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
&:focus { outline: none; }
|
|
245
|
-
&:focus-visible {
|
|
246
|
-
outline: 2px solid var(--matcha-color-primary);
|
|
247
|
-
outline-offset: 2px;
|
|
248
|
-
border-radius: var(--matcha-radius-md, 4px);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
> [class^="i-matcha-"],
|
|
252
|
-
> [class*=" i-matcha-"] {
|
|
253
|
-
font-size: 16px !important;
|
|
254
|
-
width: 16px !important;
|
|
255
|
-
height: 16px !important;
|
|
256
|
-
line-height: 1 !important;
|
|
257
|
-
color: inherit !important;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Esconde spinner nativo (Figma usa botões customizados)
|
|
262
|
-
input[type="number"][matchaQuantityStepper] {
|
|
263
|
-
-moz-appearance: textfield;
|
|
264
|
-
appearance: textfield;
|
|
265
|
-
|
|
266
|
-
&::-webkit-outer-spin-button,
|
|
267
|
-
&::-webkit-inner-spin-button {
|
|
268
|
-
-webkit-appearance: none;
|
|
269
|
-
appearance: none;
|
|
270
|
-
margin: 0;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Esconde botão × nativo do Chrome/Safari em input[type="search"]
|
|
275
|
-
// (o matchaClearButton directive injeta nosso próprio — não duplicar)
|
|
276
|
-
input[type="search"] {
|
|
277
|
-
&::-webkit-search-cancel-button,
|
|
278
|
-
&::-webkit-search-decoration,
|
|
279
|
-
&::-webkit-search-results-button,
|
|
280
|
-
&::-webkit-search-results-decoration {
|
|
281
|
-
-webkit-appearance: none;
|
|
282
|
-
appearance: none;
|
|
283
|
-
display: none;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// ── matchaClearButton: botão × ao lado de search/text ────────────────
|
|
288
|
-
// Figma-consistent: 16/20/24 por size, cor text-placeholder
|
|
289
|
-
.matcha-clear-button {
|
|
290
|
-
flex: none;
|
|
291
|
-
display: inline-flex;
|
|
292
|
-
align-items: center;
|
|
293
|
-
justify-content: center;
|
|
294
|
-
width: 16px; height: 16px;
|
|
295
|
-
padding: 0;
|
|
296
|
-
// margin-left: auto empurra o × pro final do flex row, imune a irmãos
|
|
297
|
-
// invisíveis (ng-content placeholders, matcha-autocomplete host que
|
|
298
|
-
// acaba como sibling quando projetado via matcha-field, etc).
|
|
299
|
-
margin: 0 0 0 auto;
|
|
300
|
-
background: transparent;
|
|
301
|
-
border: none;
|
|
302
|
-
cursor: pointer;
|
|
303
|
-
color: var(--matcha-color-text-placeholder);
|
|
304
|
-
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
305
|
-
position: relative;
|
|
306
|
-
|
|
307
|
-
&:hover:not(:disabled) { color: var(--matcha-color-text-primary); }
|
|
308
|
-
|
|
309
|
-
&:focus { outline: none; }
|
|
310
|
-
&:focus-visible {
|
|
311
|
-
outline: 2px solid var(--matcha-color-primary);
|
|
312
|
-
outline-offset: 2px;
|
|
313
|
-
border-radius: var(--matcha-radius-md, 4px);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
> [class^="i-matcha-"],
|
|
317
|
-
> [class*=" i-matcha-"] {
|
|
318
|
-
font-size: 16px !important;
|
|
319
|
-
width: 16px !important; height: 16px !important;
|
|
320
|
-
line-height: 1 !important;
|
|
321
|
-
color: inherit !important;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// matchaCharCounter removido daqui — agora é irmão do .matcha-form-field
|
|
326
|
-
// (vive no wrapper), estilizado fora deste bloco pra funcionar em qualquer size.
|
|
327
|
-
// Nota: estilo precisa ser GLOBAL (este arquivo) porque o span é injetado via
|
|
328
|
-
// Renderer2 sem _ngcontent — CSS scoped do Emulated não matcha.
|
|
329
|
-
|
|
330
|
-
// ── Loading spinner no suffix do field ────────────────────────────────
|
|
331
|
-
.matcha-form-field-spinner {
|
|
332
|
-
flex: none;
|
|
333
|
-
display: inline-block;
|
|
334
|
-
width: 16px; height: 16px;
|
|
335
|
-
border: 2px solid var(--matcha-color-surface-border);
|
|
336
|
-
border-top-color: var(--matcha-color-primary);
|
|
337
|
-
border-radius: 50%;
|
|
338
|
-
animation: matcha-spin 800ms linear infinite;
|
|
339
|
-
|
|
340
|
-
@media (prefers-reduced-motion: reduce) {
|
|
341
|
-
animation-duration: 2000ms;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// Select trigger ocupa altura total do form-field (clique abre dropdown em qualquer ponto)
|
|
346
|
-
matcha-select,
|
|
347
|
-
.matcha-select-container,
|
|
348
|
-
.matcha-select-trigger {
|
|
349
|
-
height: 100%;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
.matcha-suffix {
|
|
353
|
-
display: flex;
|
|
354
|
-
flex-wrap: nowrap;
|
|
355
|
-
align-items: center;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// ─── Password toggle: tamanho do ícone por size do form-field ──────────────
|
|
360
|
-
// (Figma matcha/field/password: SM 16 · MD 20 · LG 24)
|
|
361
|
-
matcha-form-field[size="md"] .matcha-password-toggle-button,
|
|
362
|
-
matcha-form-field[size="medium"] .matcha-password-toggle-button {
|
|
363
|
-
width: 20px;
|
|
364
|
-
height: 20px;
|
|
365
|
-
font-size: 20px;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
matcha-form-field[size="lg"] .matcha-password-toggle-button,
|
|
369
|
-
matcha-form-field[size="large"] .matcha-password-toggle-button,
|
|
370
|
-
matcha-form-field[size="huge"] .matcha-password-toggle-button {
|
|
371
|
-
width: 24px;
|
|
372
|
-
height: 24px;
|
|
373
|
-
font-size: 24px;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// ── Spinner keyframes ────────────────────────────────────────────────────
|
|
377
|
-
@keyframes matcha-spin {
|
|
378
|
-
to { transform: rotate(360deg); }
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
// ── Readonly state ───────────────────────────────────────────────────────
|
|
382
|
-
// Visual mais sutil que disabled: texto legível, selecionável, copiável.
|
|
383
|
-
// Diferença vs disabled: cor normal do texto (não muted) + cursor `text` no input
|
|
384
|
-
// (sinaliza "você pode selecionar e copiar"), enquanto disabled = not-allowed.
|
|
385
|
-
matcha-form-field[readonly="true"] .matcha-form-field {
|
|
386
|
-
background: var(--matcha-color-surface-bg);
|
|
387
|
-
|
|
388
|
-
input, textarea {
|
|
389
|
-
cursor: text; // nativo do input — reforça que texto é selecionável
|
|
390
|
-
user-select: text; // explícito pra evitar reset acidental
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// Remove hover border change (não é editável, hover não deve sugerir edição)
|
|
394
|
-
&:hover { border-color: var(--matcha-color-surface-border); }
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// ── Touch targets (WCAG 2.5.5: 44x44 mínimo em coarse pointers) ─────────
|
|
398
|
-
// Expande hit area sem mudar visual (pseudo-element overlay).
|
|
399
|
-
@media (pointer: coarse) {
|
|
400
|
-
.matcha-password-toggle-button,
|
|
401
|
-
.matcha-quantity-stepper-button,
|
|
402
|
-
.matcha-clear-button,
|
|
403
|
-
matcha-date .matcha-date-picker-button,
|
|
404
|
-
matcha-time .matcha-time-picker-button,
|
|
405
|
-
matcha-field-range .matcha-field-range-button,
|
|
406
|
-
matcha-phone .matcha-phone-country {
|
|
407
|
-
position: relative;
|
|
408
|
-
|
|
409
|
-
&::before {
|
|
410
|
-
content: '';
|
|
411
|
-
position: absolute;
|
|
412
|
-
inset: -14px; // expande 14px em cada lado = 44x44 total (16 + 14*2)
|
|
413
|
-
// invisível, mas capturavel — só expande o hit area
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
// ── Char counter (injetado via Renderer2 pelo matchaCharCounter directive) ──
|
|
419
|
-
// Figma matcha/field/textarea: body-sm 12/16, text-secondary, align right.
|
|
420
|
-
// Precisa ser global (sem ngcontent) porque o span vem de fora da view do form-field.
|
|
421
|
-
.matcha-form-field-wrapper > .matcha-char-counter {
|
|
422
|
-
align-self: flex-end;
|
|
423
|
-
font-family: var(--matcha-font-family);
|
|
424
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
425
|
-
font-weight: var(--matcha-weight-regular, 400);
|
|
426
|
-
line-height: var(--matcha-leading-body-sm, 16px);
|
|
427
|
-
color: var(--matcha-color-text-secondary);
|
|
428
|
-
text-align: right;
|
|
429
|
-
margin: 0;
|
|
430
|
-
padding: 0;
|
|
431
|
-
user-select: none;
|
|
432
|
-
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
433
|
-
|
|
434
|
-
// 3 níveis visuais (0-89% = neutro, 90-99% = warn, 100%+ = danger).
|
|
435
|
-
// `is-near-limit` é aplicado a partir de 90%; `is-at-limit` sobrepõe a partir de 100%.
|
|
436
|
-
&.is-near-limit:not(.is-at-limit) {
|
|
437
|
-
color: var(--matcha-color-warn);
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
&.is-at-limit {
|
|
441
|
-
color: var(--matcha-color-danger);
|
|
442
|
-
font-weight: var(--matcha-weight-semibold, 600);
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// ── Caps Lock hint (injetado pelo matchaCapsLockHint em input[type="password"]) ──
|
|
447
|
-
// Renderiza abaixo do field, mesmo nível do char counter. Usa cor warn (amarelo/laranja)
|
|
448
|
-
// pra sinalizar risco sem ser erro (user pode estar digitando intencionalmente).
|
|
449
|
-
.matcha-form-field-wrapper > .matcha-caps-lock-hint {
|
|
450
|
-
display: inline-flex;
|
|
451
|
-
align-items: center;
|
|
452
|
-
gap: var(--matcha-space-050, 4px);
|
|
453
|
-
align-self: flex-start;
|
|
454
|
-
font-family: var(--matcha-font-family);
|
|
455
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
456
|
-
font-weight: var(--matcha-weight-regular, 400);
|
|
457
|
-
line-height: var(--matcha-leading-body-sm, 16px);
|
|
458
|
-
color: var(--matcha-color-warn);
|
|
459
|
-
margin-top: var(--matcha-space-050, 4px);
|
|
460
|
-
user-select: none;
|
|
461
|
-
|
|
462
|
-
> [class^="i-matcha-"] {
|
|
463
|
-
font-size: 14px;
|
|
464
|
-
line-height: 14px;
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
// ── Responsive size classes (aligned with Figma SM/MD/LG) ───────────────────
|
|
469
|
-
|
|
470
|
-
@mixin generate-matcha-form-field-size-classes($helper-breakpoints) {
|
|
471
|
-
@each $breakpoint, $materialBreakpoint in $helper-breakpoints {
|
|
472
|
-
@include media-breakpoint($materialBreakpoint) {
|
|
473
|
-
$infix: if($materialBreakpoint == null, "", "-#{$breakpoint}");
|
|
474
|
-
|
|
475
|
-
&[size#{$infix}="sm"],
|
|
476
|
-
&[size#{$infix}="tiny"],
|
|
477
|
-
&[size#{$infix}="small"] {
|
|
478
|
-
.matcha-form-field input,
|
|
479
|
-
.matcha-form-field textarea {
|
|
480
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
481
|
-
line-height: var(--matcha-leading-body-sm, 16px);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
&[size#{$infix}="md"],
|
|
486
|
-
&[size#{$infix}="medium"] {
|
|
487
|
-
.matcha-form-field input,
|
|
488
|
-
.matcha-form-field textarea {
|
|
489
|
-
font-size: var(--matcha-font-size-sm, 14px);
|
|
490
|
-
line-height: var(--matcha-leading-body-md, 20px);
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
&[size#{$infix}="lg"],
|
|
495
|
-
&[size#{$infix}="large"],
|
|
496
|
-
&[size#{$infix}="huge"] {
|
|
497
|
-
.matcha-form-field input,
|
|
498
|
-
.matcha-form-field textarea {
|
|
499
|
-
font-size: var(--matcha-font-size-md, 16px);
|
|
500
|
-
line-height: var(--matcha-leading-body-lg, 24px);
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
// ── Theme mixin ─────────────────────────────────────────────────────────────
|
|
508
|
-
|
|
509
|
-
@mixin matcha-form-field($theme) {
|
|
510
|
-
.matcha-form-field {
|
|
511
|
-
input[type="text"],
|
|
512
|
-
input[type="email"],
|
|
513
|
-
input[type="tel"],
|
|
514
|
-
input[type="url"],
|
|
515
|
-
input[type="password"],
|
|
516
|
-
input[type="number"],
|
|
517
|
-
input[type="search"],
|
|
518
|
-
input[type="date"],
|
|
519
|
-
input[type="time"],
|
|
520
|
-
textarea {
|
|
521
|
-
color: var(--matcha-color-text-primary);
|
|
522
|
-
|
|
523
|
-
&::placeholder {
|
|
524
|
-
color: var(--matcha-color-text-placeholder);
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
input:disabled,
|
|
529
|
-
textarea:disabled {
|
|
530
|
-
color: var(--matcha-color-interaction-disabled-fg);
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
// Disabled: muted text, cursor not-allowed (sinalização inequívoca de "não pode interagir").
|
|
534
|
-
// `cursor: not-allowed` vai no wrapper; `pointer-events: none` fica só no input/textarea
|
|
535
|
-
// pra herdar o cursor do parent e não bloquear eventos no wrapper (senão cursor não aparece).
|
|
536
|
-
&.matcha-form-field-disabled {
|
|
537
|
-
cursor: not-allowed;
|
|
538
|
-
|
|
539
|
-
input, textarea {
|
|
540
|
-
pointer-events: none;
|
|
541
|
-
color: var(--matcha-color-interaction-disabled-fg);
|
|
542
|
-
|
|
543
|
-
&::placeholder {
|
|
544
|
-
color: var(--matcha-color-interaction-disabled-fg);
|
|
545
|
-
opacity: 0.7;
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
matcha-form-field {
|
|
552
|
-
@include generate-matcha-form-field-size-classes($helper-breakpoints);
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
// ── Forced colors ──
|
|
557
|
-
// Field precisa border + bg explícitos pra ser visível como input.
|
|
558
|
-
@media (forced-colors: active) {
|
|
559
|
-
matcha-form-field {
|
|
560
|
-
.matcha-field-control,
|
|
561
|
-
.matcha-form-field__control {
|
|
562
|
-
border: 1px solid CanvasText !important;
|
|
563
|
-
background: Canvas !important;
|
|
564
|
-
color: CanvasText !important;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
// Estado focused
|
|
568
|
-
&.is-focused .matcha-field-control,
|
|
569
|
-
&.is-focused .matcha-form-field__control,
|
|
570
|
-
.matcha-field-control:focus-within,
|
|
571
|
-
.matcha-form-field__control:focus-within {
|
|
572
|
-
outline: 2px solid CanvasText !important;
|
|
573
|
-
outline-offset: 2px;
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
// Estado erro/invalid
|
|
577
|
-
&.is-invalid .matcha-field-control,
|
|
578
|
-
&.has-error .matcha-form-field__control {
|
|
579
|
-
border-color: CanvasText !important;
|
|
580
|
-
border-width: 2px !important;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
&[disabled],
|
|
584
|
-
&.is-disabled {
|
|
585
|
-
opacity: 0.5;
|
|
586
|
-
|
|
587
|
-
.matcha-field-control,
|
|
588
|
-
.matcha-form-field__control {
|
|
589
|
-
border-color: GrayText !important;
|
|
590
|
-
color: GrayText !important;
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
// ── Print ──
|
|
597
|
-
// Form fields preservam estado (form values). Sem fundo decorativo.
|
|
598
|
-
@media print {
|
|
599
|
-
matcha-form-field {
|
|
600
|
-
.matcha-field-control,
|
|
601
|
-
.matcha-form-field__control {
|
|
602
|
-
border: 1px solid currentColor !important;
|
|
603
|
-
background: transparent !important;
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
}
|
|
1
|
+
@use "../abstracts/media-breakpoint" as *;
|
|
2
|
+
@use "../tokens/breakpoints-tokens" as *;
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// matcha-form-field.scss — Theme mixin (stacked pattern, Figma matcha/field/_base)
|
|
5
|
+
// Border colors vêm do data-color (component SCSS). Theme mixin cuida de:
|
|
6
|
+
// - tipografia do input (size por breakpoint)
|
|
7
|
+
// - placeholder color
|
|
8
|
+
// - disabled text color
|
|
9
|
+
// =============================================================================
|
|
10
|
+
|
|
11
|
+
// ── Structural (inputs) — sem border, sem bg (box wraps) ────────────────────
|
|
12
|
+
|
|
13
|
+
// ─── Filhos projetáveis do form-field ────────────────────────────────────
|
|
14
|
+
// Todos os tipos de input que podem ser projetados DEVEM preencher o espaço
|
|
15
|
+
// disponível e herdar padding/border/bg do wrapper externo (.matcha-form-field).
|
|
16
|
+
// O componente filho NÃO deve ter padding/border próprio quando dentro do field.
|
|
17
|
+
.matcha-form-field {
|
|
18
|
+
input,
|
|
19
|
+
input[type="text"],
|
|
20
|
+
input[type="email"],
|
|
21
|
+
input[type="tel"],
|
|
22
|
+
input[type="url"],
|
|
23
|
+
input[type="password"],
|
|
24
|
+
input[type="number"],
|
|
25
|
+
input[type="search"],
|
|
26
|
+
input[type="date"],
|
|
27
|
+
input[type="time"],
|
|
28
|
+
textarea {
|
|
29
|
+
flex: 1 1 auto;
|
|
30
|
+
width: 100%;
|
|
31
|
+
min-width: 0;
|
|
32
|
+
min-height: 0; // evita que altura natural do input expanda o container
|
|
33
|
+
background-color: transparent;
|
|
34
|
+
outline: none;
|
|
35
|
+
box-shadow: none;
|
|
36
|
+
border: none;
|
|
37
|
+
padding: 0; // wrapper fornece padding horizontal
|
|
38
|
+
margin: 0;
|
|
39
|
+
font-family: var(--matcha-font-family);
|
|
40
|
+
font-size: var(--matcha-font-size-sm, 14px); // Figma MD placeholder/value 14/400/20
|
|
41
|
+
font-weight: var(--matcha-weight-regular, 400);
|
|
42
|
+
line-height: var(--matcha-leading-body-md, 20px);
|
|
43
|
+
color: var(--matcha-color-text-primary); // Figma filled value: #E8EAED dark / #0E1116 light
|
|
44
|
+
resize: none;
|
|
45
|
+
|
|
46
|
+
&:disabled {
|
|
47
|
+
color: var(--matcha-color-interaction-disabled-fg);
|
|
48
|
+
-webkit-text-fill-color: var(--matcha-color-interaction-disabled-fg); // Safari override
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Textarea ocupa TODA a altura disponível do wrapper (que é column mode).
|
|
53
|
+
// Quando `matchaAutoGrow` está ligado, a directive aplica `.matcha-autogrow`
|
|
54
|
+
// e controla altura via JS — o override abaixo solta o 100% forçado.
|
|
55
|
+
textarea {
|
|
56
|
+
height: 100%;
|
|
57
|
+
min-height: 100%;
|
|
58
|
+
align-self: stretch;
|
|
59
|
+
|
|
60
|
+
&.matcha-autogrow {
|
|
61
|
+
height: auto; // directive calcula e seta inline
|
|
62
|
+
min-height: 0; // flex: 1 já garante piso via wrapper min-height
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ── Scrollbar estilizada no textarea (Webkit + Firefox) ──────────────────
|
|
67
|
+
// Usa tokens do DS em vez do scrollbar nativo cinza feio do Chrome/Windows.
|
|
68
|
+
// Aplica tanto no textarea "rows fixo" (se user passar rows pequeno + muito texto)
|
|
69
|
+
// quanto no `.matcha-autogrow` depois de atingir `maxRows`.
|
|
70
|
+
textarea {
|
|
71
|
+
scrollbar-width: thin; // Firefox
|
|
72
|
+
scrollbar-color: var(--matcha-color-text-placeholder)
|
|
73
|
+
transparent; // thumb + track
|
|
74
|
+
|
|
75
|
+
&::-webkit-scrollbar { width: 6px; height: 6px; }
|
|
76
|
+
&::-webkit-scrollbar-track { background: transparent; }
|
|
77
|
+
&::-webkit-scrollbar-thumb {
|
|
78
|
+
background: var(--matcha-color-text-placeholder);
|
|
79
|
+
border-radius: var(--matcha-radius-pill, 999px);
|
|
80
|
+
}
|
|
81
|
+
&::-webkit-scrollbar-thumb:hover { background: var(--matcha-color-text-secondary); }
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
input:focus,
|
|
85
|
+
textarea:focus {
|
|
86
|
+
outline: none;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Truncate: quando o campo é menor que placeholder/value, corta com ellipsis
|
|
90
|
+
// Evita overflow feio em sidebars, colunas estreitas, responsive mobile.
|
|
91
|
+
input {
|
|
92
|
+
text-overflow: ellipsis;
|
|
93
|
+
overflow: hidden;
|
|
94
|
+
white-space: nowrap;
|
|
95
|
+
|
|
96
|
+
// Placeholder também trunca (Chrome/Safari precisam do ::placeholder explícito)
|
|
97
|
+
&::placeholder {
|
|
98
|
+
text-overflow: ellipsis;
|
|
99
|
+
overflow: hidden;
|
|
100
|
+
white-space: nowrap;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ── Autofill (Chrome/Safari) — mata o background amarelo/azul e usa os tokens ──
|
|
105
|
+
// Browsers injetam background-color inline no -webkit-autofill (prioridade sobre CSS normal).
|
|
106
|
+
// O workaround padrão: box-shadow inset transparente (não sobreposto) + text-fill-color pro texto.
|
|
107
|
+
// `transition: ... 5000s` é o "truque dos 5000 segundos" — impede o browser de re-aplicar o bg.
|
|
108
|
+
input:-webkit-autofill,
|
|
109
|
+
input:-webkit-autofill:hover,
|
|
110
|
+
input:-webkit-autofill:focus,
|
|
111
|
+
input:-webkit-autofill:active,
|
|
112
|
+
textarea:-webkit-autofill {
|
|
113
|
+
-webkit-box-shadow: 0 0 0 1000px transparent inset !important;
|
|
114
|
+
-webkit-text-fill-color: var(--matcha-color-text-primary) !important;
|
|
115
|
+
caret-color: var(--matcha-color-primary) !important;
|
|
116
|
+
transition: background-color 5000s ease-in-out 0s, color 5000s ease-in-out 0s;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Caret color (cursor piscando) = primary pra match com focus border
|
|
120
|
+
input,
|
|
121
|
+
textarea {
|
|
122
|
+
caret-color: var(--matcha-color-primary);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Selection highlight (quando user seleciona texto) — usa token de primary com alpha
|
|
126
|
+
input::selection,
|
|
127
|
+
textarea::selection {
|
|
128
|
+
background: var(--matcha-color-primary-alpha);
|
|
129
|
+
color: var(--matcha-color-text-primary);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Componentes projetados — todos preenchem a largura e não adicionam borda/padding próprio
|
|
133
|
+
matcha-select,
|
|
134
|
+
matcha-autocomplete,
|
|
135
|
+
matcha-date,
|
|
136
|
+
matcha-field-range,
|
|
137
|
+
matcha-time,
|
|
138
|
+
matcha-phone {
|
|
139
|
+
flex: 1 1 auto;
|
|
140
|
+
width: 100%;
|
|
141
|
+
min-width: 0;
|
|
142
|
+
display: flex;
|
|
143
|
+
align-items: center;
|
|
144
|
+
background: transparent;
|
|
145
|
+
border: none;
|
|
146
|
+
padding: 0;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// matcha-phone: padding/bg próprios do componente quebram o layout dentro do field
|
|
150
|
+
matcha-phone .matcha-phone {
|
|
151
|
+
padding: 0;
|
|
152
|
+
background: transparent;
|
|
153
|
+
font-size: inherit;
|
|
154
|
+
width: 100%;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// matcha-date/time: container do componente preenche o espaço sem padding/border próprios
|
|
158
|
+
matcha-date .matcha-date-container,
|
|
159
|
+
matcha-time .matcha-time-container {
|
|
160
|
+
width: 100%;
|
|
161
|
+
background: transparent;
|
|
162
|
+
border: none;
|
|
163
|
+
padding: 0;
|
|
164
|
+
min-width: 0;
|
|
165
|
+
gap: var(--matcha-space-100, 8px);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ── matchaPasswordToggle: botão do olho injetado ao lado de input[type="password"] ──
|
|
169
|
+
// Figma matcha/field/password: ícone 16/20/24 por size, cor text-placeholder (#9AA0A6)
|
|
170
|
+
.matcha-password-toggle-button {
|
|
171
|
+
flex: none;
|
|
172
|
+
display: inline-flex;
|
|
173
|
+
align-items: center;
|
|
174
|
+
justify-content: center;
|
|
175
|
+
width: 16px; // SM default
|
|
176
|
+
height: 16px;
|
|
177
|
+
padding: 0;
|
|
178
|
+
margin: 0;
|
|
179
|
+
background: transparent;
|
|
180
|
+
border: none;
|
|
181
|
+
cursor: pointer;
|
|
182
|
+
color: var(--matcha-color-text-placeholder); // #9AA0A6
|
|
183
|
+
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
184
|
+
|
|
185
|
+
&:hover:not(:disabled) {
|
|
186
|
+
color: var(--matcha-color-text-primary);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
&:disabled {
|
|
190
|
+
cursor: not-allowed;
|
|
191
|
+
color: var(--matcha-color-interaction-disabled-fg);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
&:focus { outline: none; }
|
|
195
|
+
&:focus-visible {
|
|
196
|
+
outline: 2px solid var(--matcha-color-primary);
|
|
197
|
+
outline-offset: 2px;
|
|
198
|
+
border-radius: var(--matcha-radius-md, 4px);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
> [class^="i-matcha-"],
|
|
202
|
+
> [class*=" i-matcha-"] {
|
|
203
|
+
font-size: inherit !important;
|
|
204
|
+
width: 1em !important;
|
|
205
|
+
height: 1em !important;
|
|
206
|
+
line-height: 1 !important;
|
|
207
|
+
color: inherit !important;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ── matchaQuantityStepper: wrapper flex-row + dois botões (−/+) ──────
|
|
212
|
+
// Figma matcha/field/quantity: gap 4, ícones 16px constante, cor #9AA0A6
|
|
213
|
+
.matcha-quantity-stepper {
|
|
214
|
+
flex: none;
|
|
215
|
+
display: inline-flex;
|
|
216
|
+
align-items: center;
|
|
217
|
+
gap: var(--matcha-space-050, 4px);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.matcha-quantity-stepper-button {
|
|
221
|
+
flex: none;
|
|
222
|
+
display: inline-flex;
|
|
223
|
+
align-items: center;
|
|
224
|
+
justify-content: center;
|
|
225
|
+
width: 16px; // Figma: constante 16px em todos os sizes
|
|
226
|
+
height: 16px;
|
|
227
|
+
padding: 0;
|
|
228
|
+
margin: 0;
|
|
229
|
+
background: transparent;
|
|
230
|
+
border: none;
|
|
231
|
+
cursor: pointer;
|
|
232
|
+
color: var(--matcha-color-text-placeholder); // #9AA0A6
|
|
233
|
+
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
234
|
+
|
|
235
|
+
&:hover:not(:disabled) {
|
|
236
|
+
color: var(--matcha-color-text-primary);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
&:disabled {
|
|
240
|
+
cursor: not-allowed;
|
|
241
|
+
color: var(--matcha-color-interaction-disabled-fg);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
&:focus { outline: none; }
|
|
245
|
+
&:focus-visible {
|
|
246
|
+
outline: 2px solid var(--matcha-color-primary);
|
|
247
|
+
outline-offset: 2px;
|
|
248
|
+
border-radius: var(--matcha-radius-md, 4px);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
> [class^="i-matcha-"],
|
|
252
|
+
> [class*=" i-matcha-"] {
|
|
253
|
+
font-size: 16px !important;
|
|
254
|
+
width: 16px !important;
|
|
255
|
+
height: 16px !important;
|
|
256
|
+
line-height: 1 !important;
|
|
257
|
+
color: inherit !important;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Esconde spinner nativo (Figma usa botões customizados)
|
|
262
|
+
input[type="number"][matchaQuantityStepper] {
|
|
263
|
+
-moz-appearance: textfield;
|
|
264
|
+
appearance: textfield;
|
|
265
|
+
|
|
266
|
+
&::-webkit-outer-spin-button,
|
|
267
|
+
&::-webkit-inner-spin-button {
|
|
268
|
+
-webkit-appearance: none;
|
|
269
|
+
appearance: none;
|
|
270
|
+
margin: 0;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Esconde botão × nativo do Chrome/Safari em input[type="search"]
|
|
275
|
+
// (o matchaClearButton directive injeta nosso próprio — não duplicar)
|
|
276
|
+
input[type="search"] {
|
|
277
|
+
&::-webkit-search-cancel-button,
|
|
278
|
+
&::-webkit-search-decoration,
|
|
279
|
+
&::-webkit-search-results-button,
|
|
280
|
+
&::-webkit-search-results-decoration {
|
|
281
|
+
-webkit-appearance: none;
|
|
282
|
+
appearance: none;
|
|
283
|
+
display: none;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ── matchaClearButton: botão × ao lado de search/text ────────────────
|
|
288
|
+
// Figma-consistent: 16/20/24 por size, cor text-placeholder
|
|
289
|
+
.matcha-clear-button {
|
|
290
|
+
flex: none;
|
|
291
|
+
display: inline-flex;
|
|
292
|
+
align-items: center;
|
|
293
|
+
justify-content: center;
|
|
294
|
+
width: 16px; height: 16px;
|
|
295
|
+
padding: 0;
|
|
296
|
+
// margin-left: auto empurra o × pro final do flex row, imune a irmãos
|
|
297
|
+
// invisíveis (ng-content placeholders, matcha-autocomplete host que
|
|
298
|
+
// acaba como sibling quando projetado via matcha-field, etc).
|
|
299
|
+
margin: 0 0 0 auto;
|
|
300
|
+
background: transparent;
|
|
301
|
+
border: none;
|
|
302
|
+
cursor: pointer;
|
|
303
|
+
color: var(--matcha-color-text-placeholder);
|
|
304
|
+
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
305
|
+
position: relative;
|
|
306
|
+
|
|
307
|
+
&:hover:not(:disabled) { color: var(--matcha-color-text-primary); }
|
|
308
|
+
|
|
309
|
+
&:focus { outline: none; }
|
|
310
|
+
&:focus-visible {
|
|
311
|
+
outline: 2px solid var(--matcha-color-primary);
|
|
312
|
+
outline-offset: 2px;
|
|
313
|
+
border-radius: var(--matcha-radius-md, 4px);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
> [class^="i-matcha-"],
|
|
317
|
+
> [class*=" i-matcha-"] {
|
|
318
|
+
font-size: 16px !important;
|
|
319
|
+
width: 16px !important; height: 16px !important;
|
|
320
|
+
line-height: 1 !important;
|
|
321
|
+
color: inherit !important;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// matchaCharCounter removido daqui — agora é irmão do .matcha-form-field
|
|
326
|
+
// (vive no wrapper), estilizado fora deste bloco pra funcionar em qualquer size.
|
|
327
|
+
// Nota: estilo precisa ser GLOBAL (este arquivo) porque o span é injetado via
|
|
328
|
+
// Renderer2 sem _ngcontent — CSS scoped do Emulated não matcha.
|
|
329
|
+
|
|
330
|
+
// ── Loading spinner no suffix do field ────────────────────────────────
|
|
331
|
+
.matcha-form-field-spinner {
|
|
332
|
+
flex: none;
|
|
333
|
+
display: inline-block;
|
|
334
|
+
width: 16px; height: 16px;
|
|
335
|
+
border: 2px solid var(--matcha-color-surface-border);
|
|
336
|
+
border-top-color: var(--matcha-color-primary);
|
|
337
|
+
border-radius: 50%;
|
|
338
|
+
animation: matcha-spin 800ms linear infinite;
|
|
339
|
+
|
|
340
|
+
@media (prefers-reduced-motion: reduce) {
|
|
341
|
+
animation-duration: 2000ms;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Select trigger ocupa altura total do form-field (clique abre dropdown em qualquer ponto)
|
|
346
|
+
matcha-select,
|
|
347
|
+
.matcha-select-container,
|
|
348
|
+
.matcha-select-trigger {
|
|
349
|
+
height: 100%;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.matcha-suffix {
|
|
353
|
+
display: flex;
|
|
354
|
+
flex-wrap: nowrap;
|
|
355
|
+
align-items: center;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// ─── Password toggle: tamanho do ícone por size do form-field ──────────────
|
|
360
|
+
// (Figma matcha/field/password: SM 16 · MD 20 · LG 24)
|
|
361
|
+
matcha-form-field[size="md"] .matcha-password-toggle-button,
|
|
362
|
+
matcha-form-field[size="medium"] .matcha-password-toggle-button {
|
|
363
|
+
width: 20px;
|
|
364
|
+
height: 20px;
|
|
365
|
+
font-size: 20px;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
matcha-form-field[size="lg"] .matcha-password-toggle-button,
|
|
369
|
+
matcha-form-field[size="large"] .matcha-password-toggle-button,
|
|
370
|
+
matcha-form-field[size="huge"] .matcha-password-toggle-button {
|
|
371
|
+
width: 24px;
|
|
372
|
+
height: 24px;
|
|
373
|
+
font-size: 24px;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// ── Spinner keyframes ────────────────────────────────────────────────────
|
|
377
|
+
@keyframes matcha-spin {
|
|
378
|
+
to { transform: rotate(360deg); }
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// ── Readonly state ───────────────────────────────────────────────────────
|
|
382
|
+
// Visual mais sutil que disabled: texto legível, selecionável, copiável.
|
|
383
|
+
// Diferença vs disabled: cor normal do texto (não muted) + cursor `text` no input
|
|
384
|
+
// (sinaliza "você pode selecionar e copiar"), enquanto disabled = not-allowed.
|
|
385
|
+
matcha-form-field[readonly="true"] .matcha-form-field {
|
|
386
|
+
background: var(--matcha-color-surface-bg);
|
|
387
|
+
|
|
388
|
+
input, textarea {
|
|
389
|
+
cursor: text; // nativo do input — reforça que texto é selecionável
|
|
390
|
+
user-select: text; // explícito pra evitar reset acidental
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Remove hover border change (não é editável, hover não deve sugerir edição)
|
|
394
|
+
&:hover { border-color: var(--matcha-color-surface-border); }
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// ── Touch targets (WCAG 2.5.5: 44x44 mínimo em coarse pointers) ─────────
|
|
398
|
+
// Expande hit area sem mudar visual (pseudo-element overlay).
|
|
399
|
+
@media (pointer: coarse) {
|
|
400
|
+
.matcha-password-toggle-button,
|
|
401
|
+
.matcha-quantity-stepper-button,
|
|
402
|
+
.matcha-clear-button,
|
|
403
|
+
matcha-date .matcha-date-picker-button,
|
|
404
|
+
matcha-time .matcha-time-picker-button,
|
|
405
|
+
matcha-field-range .matcha-field-range-button,
|
|
406
|
+
matcha-phone .matcha-phone-country {
|
|
407
|
+
position: relative;
|
|
408
|
+
|
|
409
|
+
&::before {
|
|
410
|
+
content: '';
|
|
411
|
+
position: absolute;
|
|
412
|
+
inset: -14px; // expande 14px em cada lado = 44x44 total (16 + 14*2)
|
|
413
|
+
// invisível, mas capturavel — só expande o hit area
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// ── Char counter (injetado via Renderer2 pelo matchaCharCounter directive) ──
|
|
419
|
+
// Figma matcha/field/textarea: body-sm 12/16, text-secondary, align right.
|
|
420
|
+
// Precisa ser global (sem ngcontent) porque o span vem de fora da view do form-field.
|
|
421
|
+
.matcha-form-field-wrapper > .matcha-char-counter {
|
|
422
|
+
align-self: flex-end;
|
|
423
|
+
font-family: var(--matcha-font-family);
|
|
424
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
425
|
+
font-weight: var(--matcha-weight-regular, 400);
|
|
426
|
+
line-height: var(--matcha-leading-body-sm, 16px);
|
|
427
|
+
color: var(--matcha-color-text-secondary);
|
|
428
|
+
text-align: right;
|
|
429
|
+
margin: 0;
|
|
430
|
+
padding: 0;
|
|
431
|
+
user-select: none;
|
|
432
|
+
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
433
|
+
|
|
434
|
+
// 3 níveis visuais (0-89% = neutro, 90-99% = warn, 100%+ = danger).
|
|
435
|
+
// `is-near-limit` é aplicado a partir de 90%; `is-at-limit` sobrepõe a partir de 100%.
|
|
436
|
+
&.is-near-limit:not(.is-at-limit) {
|
|
437
|
+
color: var(--matcha-color-warn);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
&.is-at-limit {
|
|
441
|
+
color: var(--matcha-color-danger);
|
|
442
|
+
font-weight: var(--matcha-weight-semibold, 600);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// ── Caps Lock hint (injetado pelo matchaCapsLockHint em input[type="password"]) ──
|
|
447
|
+
// Renderiza abaixo do field, mesmo nível do char counter. Usa cor warn (amarelo/laranja)
|
|
448
|
+
// pra sinalizar risco sem ser erro (user pode estar digitando intencionalmente).
|
|
449
|
+
.matcha-form-field-wrapper > .matcha-caps-lock-hint {
|
|
450
|
+
display: inline-flex;
|
|
451
|
+
align-items: center;
|
|
452
|
+
gap: var(--matcha-space-050, 4px);
|
|
453
|
+
align-self: flex-start;
|
|
454
|
+
font-family: var(--matcha-font-family);
|
|
455
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
456
|
+
font-weight: var(--matcha-weight-regular, 400);
|
|
457
|
+
line-height: var(--matcha-leading-body-sm, 16px);
|
|
458
|
+
color: var(--matcha-color-warn);
|
|
459
|
+
margin-top: var(--matcha-space-050, 4px);
|
|
460
|
+
user-select: none;
|
|
461
|
+
|
|
462
|
+
> [class^="i-matcha-"] {
|
|
463
|
+
font-size: 14px;
|
|
464
|
+
line-height: 14px;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// ── Responsive size classes (aligned with Figma SM/MD/LG) ───────────────────
|
|
469
|
+
|
|
470
|
+
@mixin generate-matcha-form-field-size-classes($helper-breakpoints) {
|
|
471
|
+
@each $breakpoint, $materialBreakpoint in $helper-breakpoints {
|
|
472
|
+
@include media-breakpoint($materialBreakpoint) {
|
|
473
|
+
$infix: if($materialBreakpoint == null, "", "-#{$breakpoint}");
|
|
474
|
+
|
|
475
|
+
&[size#{$infix}="sm"],
|
|
476
|
+
&[size#{$infix}="tiny"],
|
|
477
|
+
&[size#{$infix}="small"] {
|
|
478
|
+
.matcha-form-field input,
|
|
479
|
+
.matcha-form-field textarea {
|
|
480
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
481
|
+
line-height: var(--matcha-leading-body-sm, 16px);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
&[size#{$infix}="md"],
|
|
486
|
+
&[size#{$infix}="medium"] {
|
|
487
|
+
.matcha-form-field input,
|
|
488
|
+
.matcha-form-field textarea {
|
|
489
|
+
font-size: var(--matcha-font-size-sm, 14px);
|
|
490
|
+
line-height: var(--matcha-leading-body-md, 20px);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
&[size#{$infix}="lg"],
|
|
495
|
+
&[size#{$infix}="large"],
|
|
496
|
+
&[size#{$infix}="huge"] {
|
|
497
|
+
.matcha-form-field input,
|
|
498
|
+
.matcha-form-field textarea {
|
|
499
|
+
font-size: var(--matcha-font-size-md, 16px);
|
|
500
|
+
line-height: var(--matcha-leading-body-lg, 24px);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// ── Theme mixin ─────────────────────────────────────────────────────────────
|
|
508
|
+
|
|
509
|
+
@mixin matcha-form-field($theme) {
|
|
510
|
+
.matcha-form-field {
|
|
511
|
+
input[type="text"],
|
|
512
|
+
input[type="email"],
|
|
513
|
+
input[type="tel"],
|
|
514
|
+
input[type="url"],
|
|
515
|
+
input[type="password"],
|
|
516
|
+
input[type="number"],
|
|
517
|
+
input[type="search"],
|
|
518
|
+
input[type="date"],
|
|
519
|
+
input[type="time"],
|
|
520
|
+
textarea {
|
|
521
|
+
color: var(--matcha-color-text-primary);
|
|
522
|
+
|
|
523
|
+
&::placeholder {
|
|
524
|
+
color: var(--matcha-color-text-placeholder);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
input:disabled,
|
|
529
|
+
textarea:disabled {
|
|
530
|
+
color: var(--matcha-color-interaction-disabled-fg);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// Disabled: muted text, cursor not-allowed (sinalização inequívoca de "não pode interagir").
|
|
534
|
+
// `cursor: not-allowed` vai no wrapper; `pointer-events: none` fica só no input/textarea
|
|
535
|
+
// pra herdar o cursor do parent e não bloquear eventos no wrapper (senão cursor não aparece).
|
|
536
|
+
&.matcha-form-field-disabled {
|
|
537
|
+
cursor: not-allowed;
|
|
538
|
+
|
|
539
|
+
input, textarea {
|
|
540
|
+
pointer-events: none;
|
|
541
|
+
color: var(--matcha-color-interaction-disabled-fg);
|
|
542
|
+
|
|
543
|
+
&::placeholder {
|
|
544
|
+
color: var(--matcha-color-interaction-disabled-fg);
|
|
545
|
+
opacity: 0.7;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
matcha-form-field {
|
|
552
|
+
@include generate-matcha-form-field-size-classes($helper-breakpoints);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// ── Forced colors ──
|
|
557
|
+
// Field precisa border + bg explícitos pra ser visível como input.
|
|
558
|
+
@media (forced-colors: active) {
|
|
559
|
+
matcha-form-field {
|
|
560
|
+
.matcha-field-control,
|
|
561
|
+
.matcha-form-field__control {
|
|
562
|
+
border: 1px solid CanvasText !important;
|
|
563
|
+
background: Canvas !important;
|
|
564
|
+
color: CanvasText !important;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// Estado focused
|
|
568
|
+
&.is-focused .matcha-field-control,
|
|
569
|
+
&.is-focused .matcha-form-field__control,
|
|
570
|
+
.matcha-field-control:focus-within,
|
|
571
|
+
.matcha-form-field__control:focus-within {
|
|
572
|
+
outline: 2px solid CanvasText !important;
|
|
573
|
+
outline-offset: 2px;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// Estado erro/invalid
|
|
577
|
+
&.is-invalid .matcha-field-control,
|
|
578
|
+
&.has-error .matcha-form-field__control {
|
|
579
|
+
border-color: CanvasText !important;
|
|
580
|
+
border-width: 2px !important;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
&[disabled],
|
|
584
|
+
&.is-disabled {
|
|
585
|
+
opacity: 0.5;
|
|
586
|
+
|
|
587
|
+
.matcha-field-control,
|
|
588
|
+
.matcha-form-field__control {
|
|
589
|
+
border-color: GrayText !important;
|
|
590
|
+
color: GrayText !important;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// ── Print ──
|
|
597
|
+
// Form fields preservam estado (form values). Sem fundo decorativo.
|
|
598
|
+
@media print {
|
|
599
|
+
matcha-form-field {
|
|
600
|
+
.matcha-field-control,
|
|
601
|
+
.matcha-form-field__control {
|
|
602
|
+
border: 1px solid currentColor !important;
|
|
603
|
+
background: transparent !important;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|