@inchurch/matcha-theme 22.38.2 → 22.38.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/abstracts/_colors.scss +291 -291
- package/abstracts/_elevation.scss +108 -108
- package/abstracts/_functions.scss +321 -321
- package/abstracts/_media-breakpoint.scss +26 -26
- package/abstracts/_theme-api.scss +224 -224
- package/abstracts/_typography.scss +128 -128
- package/base/_reset.scss +487 -487
- package/components/app-page-header.scss +260 -260
- package/components/matcha-accordion.scss +297 -297
- package/components/matcha-audio-player.scss +31 -31
- package/components/matcha-autocomplete.scss +145 -145
- package/components/matcha-avatar.scss +426 -426
- package/components/matcha-badge.scss +120 -120
- package/components/matcha-breadcrumb.scss +231 -231
- package/components/matcha-button-toggle.scss +484 -484
- package/components/matcha-buttons.scss +973 -973
- package/components/matcha-calendar.scss +253 -253
- package/components/matcha-cards.scss +212 -212
- package/components/matcha-chart-card.scss +53 -53
- package/components/matcha-checkbox.scss +266 -266
- package/components/matcha-chip.scss +311 -311
- package/components/matcha-color-pick.scss +34 -34
- package/components/matcha-command-palette.scss +316 -316
- package/components/matcha-crop.scss +419 -419
- 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 +650 -637
- package/components/matcha-flag.scss +103 -103
- package/components/matcha-footer.scss +91 -91
- package/components/matcha-form-field.scss +883 -883
- 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 +247 -247
- package/components/matcha-icon.scss +111 -111
- package/components/matcha-image.scss +60 -60
- 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 +770 -770
- package/components/matcha-notification.scss +417 -417
- package/components/matcha-option.scss +170 -170
- package/components/matcha-page-builder.scss +4196 -4196
- package/components/matcha-paginator.scss +699 -699
- package/components/matcha-panel.scss +216 -216
- package/components/matcha-period.scss +174 -174
- package/components/matcha-profile-card.scss +50 -50
- package/components/matcha-progress-bar.scss +355 -355
- package/components/matcha-radio.scss +325 -325
- 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 +629 -629
- package/components/matcha-skeleton.scss +182 -182
- 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-stepper.scss +376 -376
- package/components/matcha-table-cell.scss +107 -107
- package/components/matcha-table.scss +722 -722
- package/components/matcha-tabs.scss +642 -642
- package/components/matcha-text-editor.scss +111 -111
- package/components/matcha-time.scss +33 -33
- package/components/matcha-timepicker.scss +13 -13
- package/components/matcha-toolbar.scss +366 -366
- package/components/matcha-tooltip.scss +235 -235
- package/components/matcha-tree-view.scss +636 -636
- package/layout/matcha-page-layout.scss +778 -778
- package/main.scss +334 -334
- package/package.json +1 -1
- package/tokens/_animations-tokens.scss +37 -37
- package/tokens/_breakpoints-tokens.scss +35 -35
- package/tokens/_color-tokens.scss +288 -288
- package/tokens/_elevation-tokens.scss +33 -33
- package/tokens/_emit-tokens.scss +329 -329
- 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,883 +1,883 @@
|
|
|
1
|
-
@use "../abstracts/media-breakpoint" as *;
|
|
2
|
-
@use "../tokens/breakpoints-tokens" as *;
|
|
3
|
-
// =============================================================================
|
|
4
|
-
// matcha-form-field.scss — FONTE ÚNICA de estilo do matcha-form-field
|
|
5
|
-
// (estrutura, states, sizes, tipografia). O component SCSS é comment-only.
|
|
6
|
-
// =============================================================================
|
|
7
|
-
|
|
8
|
-
// ═══ Estrutura e states (migrado do matcha-form-field.component.scss) ═══════
|
|
9
|
-
// Histórico: estas regras viviam no SCSS do componente (ViewEncapsulation.
|
|
10
|
-
// Emulated). Seletor de host escrito como `matcha-form-field[...]` ganhava
|
|
11
|
-
// sufixo [_ngcontent-…] e virava CSS morto — caso do disabled, cuja opacity
|
|
12
|
-
// nunca aplicou. Global no tema, o que está escrito é o que vale; os antigos
|
|
13
|
-
// ::ng-deep viram seletores diretos.
|
|
14
|
-
|
|
15
|
-
// Wrapper stacked: Label → gap → Box → gap → Hint (Figma matcha/field/_base)
|
|
16
|
-
.matcha-form-field-wrapper {
|
|
17
|
-
display: flex;
|
|
18
|
-
flex-direction: column;
|
|
19
|
-
align-items: flex-start;
|
|
20
|
-
gap: var(--matcha-space-075, 6px); // Figma matcha/field/text: gap 6px entre label/box/hint
|
|
21
|
-
width: 100%;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Box do input — onde fica o input/select/textarea
|
|
25
|
-
// Figma: align-self: stretch → ocupa toda a largura do wrapper
|
|
26
|
-
.matcha-form-field {
|
|
27
|
-
display: flex;
|
|
28
|
-
flex-direction: row;
|
|
29
|
-
align-items: center;
|
|
30
|
-
gap: var(--matcha-space-100, 8px);
|
|
31
|
-
width: 100%; // stretch pro wrapper
|
|
32
|
-
min-height: 44px; // MD default
|
|
33
|
-
padding: 0 var(--matcha-space-150, 12px); // pad horizontal 12
|
|
34
|
-
border: var(--matcha-border-thin, 2px) solid var(--matcha-color-surface-border, #E1E7E2);
|
|
35
|
-
border-radius: var(--matcha-radius-lg, 8px);
|
|
36
|
-
background: transparent;
|
|
37
|
-
box-sizing: border-box;
|
|
38
|
-
transition: border-color var(--matcha-duration-fast, 200ms);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Slots prefix/suffix — elementos decorativos antes/depois do input
|
|
42
|
-
.matcha-form-field .matcha-form-field-prefix,
|
|
43
|
-
.matcha-form-field .matcha-form-field-suffix {
|
|
44
|
-
display: inline-flex;
|
|
45
|
-
align-items: center;
|
|
46
|
-
flex: none;
|
|
47
|
-
color: var(--matcha-color-text-label);
|
|
48
|
-
font-family: var(--matcha-font-family);
|
|
49
|
-
font-size: var(--matcha-font-size-sm, 14px);
|
|
50
|
-
font-weight: var(--matcha-weight-regular, 400);
|
|
51
|
-
line-height: var(--matcha-leading-body-md, 20px);
|
|
52
|
-
user-select: none;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.matcha-form-field .matcha-form-field-prefix:not(:empty) + * {
|
|
56
|
-
padding-left: 0;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Hover / focus-within (Figma matcha/field/_base State=Focus).
|
|
60
|
-
// Disabled não chega aqui (pointer-events: none nas regras de disabled abaixo);
|
|
61
|
-
// readonly neutraliza o hover na regra própria de readonly; error e data-color
|
|
62
|
-
// vencem por especificidade/ordem.
|
|
63
|
-
.matcha-form-field:hover {
|
|
64
|
-
border-color: var(--matcha-color-surface-border-strong);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.matcha-form-field:focus-within {
|
|
68
|
-
border-color: var(--matcha-color-primary, #1664C2);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Color variants via data-color — override border-color
|
|
72
|
-
.matcha-form-field[data-color="accent"] { border-color: var(--matcha-color-accent); }
|
|
73
|
-
.matcha-form-field[data-color="primary"] { border-color: var(--matcha-color-primary); }
|
|
74
|
-
.matcha-form-field[data-color="danger"] { border-color: var(--matcha-color-danger); }
|
|
75
|
-
.matcha-form-field[data-color="warn"] { border-color: var(--matcha-color-warn); }
|
|
76
|
-
.matcha-form-field[data-color="success"] { border-color: var(--matcha-color-success); }
|
|
77
|
-
.matcha-form-field[data-color="info"] { border-color: var(--matcha-color-info); }
|
|
78
|
-
|
|
79
|
-
// Sizes (Figma heights): SM 36, MD 44, LG 52.
|
|
80
|
-
// Alturas não são responsivas — a tipografia responsiva fica no mixin abaixo.
|
|
81
|
-
matcha-form-field[size="sm"] .matcha-form-field,
|
|
82
|
-
matcha-form-field[size="tiny"] .matcha-form-field,
|
|
83
|
-
matcha-form-field[size="small"] .matcha-form-field {
|
|
84
|
-
min-height: 36px;
|
|
85
|
-
padding: 0 var(--matcha-space-150, 12px);
|
|
86
|
-
}
|
|
87
|
-
matcha-form-field[size="md"] .matcha-form-field,
|
|
88
|
-
matcha-form-field[size="medium"] .matcha-form-field {
|
|
89
|
-
min-height: 44px;
|
|
90
|
-
padding: 0 var(--matcha-space-150, 12px);
|
|
91
|
-
}
|
|
92
|
-
matcha-form-field[size="lg"] .matcha-form-field,
|
|
93
|
-
matcha-form-field[size="large"] .matcha-form-field,
|
|
94
|
-
matcha-form-field[size="huge"] .matcha-form-field {
|
|
95
|
-
min-height: 52px;
|
|
96
|
-
padding: 0 var(--matcha-space-200, 16px);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Disabled — Figma aplica opacity 0.38 no WRAPPER inteiro
|
|
100
|
-
// (label, field-box e hint ficam apagados de uma vez).
|
|
101
|
-
// EXCEÇÃO: tooltip do label preserva opacity=1 e pointer-events pra manter a
|
|
102
|
-
// pergunta "por que desabilitado?" respondível (UX crítico pra forms complexos).
|
|
103
|
-
// Sem border-color especial: o token interaction-disabled-border tem MAIS
|
|
104
|
-
// contraste que a borda normal e anulava o esmaecimento — a borda fica a normal
|
|
105
|
-
// e a opacity apaga o conjunto uniformemente.
|
|
106
|
-
matcha-form-field[disabled]:not([disabled="false"]) {
|
|
107
|
-
opacity: var(--matcha-opacity-disabled, 0.38);
|
|
108
|
-
|
|
109
|
-
.matcha-form-field {
|
|
110
|
-
pointer-events: none;
|
|
111
|
-
cursor: default;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Tooltip icon continua interativo e legível mesmo com wrapper disabled
|
|
115
|
-
.matcha-label-tooltip {
|
|
116
|
-
opacity: calc(1 / var(--matcha-opacity-disabled, 0.38));
|
|
117
|
-
pointer-events: auto;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Fallback legado (classe aplicada via JS quando o input interno tem disabled);
|
|
122
|
-
// cursor/cores de texto dessa classe vivem no theme mixin mais abaixo.
|
|
123
|
-
.matcha-form-field-disabled {
|
|
124
|
-
pointer-events: none;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Error state (Figma: border danger) — via @Input() error ou data-color="danger"
|
|
128
|
-
matcha-form-field[error]:not([error="false"]) .matcha-form-field {
|
|
129
|
-
border-color: var(--matcha-color-danger);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// ─── Simulação de states em docs/playgrounds ────────────────────────────
|
|
133
|
-
matcha-form-field.is-state-focus .matcha-form-field {
|
|
134
|
-
border-color: var(--matcha-color-primary) !important;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
matcha-form-field.is-state-disabled {
|
|
138
|
-
opacity: var(--matcha-opacity-disabled, 0.38);
|
|
139
|
-
pointer-events: none;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// ─── Field-range override (Figma matcha/field/range) ────────────────────
|
|
143
|
-
// Field-range renderiza DUAS caixas bordadas próprias (start/end com separador).
|
|
144
|
-
// O form-field externo NÃO deve desenhar sua box — apenas empilha label + range + hint.
|
|
145
|
-
.matcha-form-field:has(matcha-field-range) {
|
|
146
|
-
border: none;
|
|
147
|
-
background: transparent;
|
|
148
|
-
padding: 0;
|
|
149
|
-
min-height: 0;
|
|
150
|
-
gap: 0;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
matcha-form-field[size="sm"] .matcha-form-field:has(matcha-field-range),
|
|
154
|
-
matcha-form-field[size="tiny"] .matcha-form-field:has(matcha-field-range),
|
|
155
|
-
matcha-form-field[size="small"] .matcha-form-field:has(matcha-field-range),
|
|
156
|
-
matcha-form-field[size="md"] .matcha-form-field:has(matcha-field-range),
|
|
157
|
-
matcha-form-field[size="medium"] .matcha-form-field:has(matcha-field-range),
|
|
158
|
-
matcha-form-field[size="lg"] .matcha-form-field:has(matcha-field-range),
|
|
159
|
-
matcha-form-field[size="large"] .matcha-form-field:has(matcha-field-range),
|
|
160
|
-
matcha-form-field[size="huge"] .matcha-form-field:has(matcha-field-range) {
|
|
161
|
-
min-height: 0;
|
|
162
|
-
padding: 0;
|
|
163
|
-
border: none;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Erro: não mexe na borda do wrapper (já é none), a cor do erro vai para as halves
|
|
167
|
-
matcha-form-field[error]:not([error="false"]) .matcha-form-field:has(matcha-field-range) {
|
|
168
|
-
border: none;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// ─── Textarea override (Figma matcha/field/textarea) ────────────────────
|
|
172
|
-
// Quando o field contém textarea, o wrapper vira column + padding all-sides
|
|
173
|
-
// Heights por size: SM 80px · MD 100px · LG 120px
|
|
174
|
-
.matcha-form-field:has(textarea) {
|
|
175
|
-
flex-direction: column;
|
|
176
|
-
align-items: flex-start;
|
|
177
|
-
padding: var(--matcha-space-150, 12px);
|
|
178
|
-
min-height: 80px; // fallback SM
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
matcha-form-field[size="sm"] .matcha-form-field:has(textarea),
|
|
182
|
-
matcha-form-field[size="tiny"] .matcha-form-field:has(textarea),
|
|
183
|
-
matcha-form-field[size="small"] .matcha-form-field:has(textarea) {
|
|
184
|
-
min-height: 80px;
|
|
185
|
-
padding: var(--matcha-space-150, 12px);
|
|
186
|
-
}
|
|
187
|
-
matcha-form-field[size="md"] .matcha-form-field:has(textarea),
|
|
188
|
-
matcha-form-field[size="medium"] .matcha-form-field:has(textarea) {
|
|
189
|
-
min-height: 100px;
|
|
190
|
-
padding: var(--matcha-space-150, 12px);
|
|
191
|
-
}
|
|
192
|
-
matcha-form-field[size="lg"] .matcha-form-field:has(textarea),
|
|
193
|
-
matcha-form-field[size="large"] .matcha-form-field:has(textarea),
|
|
194
|
-
matcha-form-field[size="huge"] .matcha-form-field:has(textarea) {
|
|
195
|
-
min-height: 120px;
|
|
196
|
-
padding: var(--matcha-space-150, 12px) var(--matcha-space-200, 16px);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// ─── Search: ícone lupa automático após o input[type=search] (Figma suffix icon) ──
|
|
200
|
-
// Mesmo padding horizontal dos outros fields. Por size: SM 16 · MD 20 · LG 24.
|
|
201
|
-
.matcha-form-field:has(input[type="search"])::after {
|
|
202
|
-
content: '\e90c'; // codepoint "search" em MatchaIcons
|
|
203
|
-
font-family: 'MatchaIcons' !important; // fonte registrada no projects/matcha-icons/matcha-icons.css
|
|
204
|
-
font-weight: normal;
|
|
205
|
-
font-style: normal;
|
|
206
|
-
font-variant: normal;
|
|
207
|
-
speak: none;
|
|
208
|
-
text-transform: none;
|
|
209
|
-
-webkit-font-smoothing: antialiased;
|
|
210
|
-
color: var(--matcha-color-text-placeholder);
|
|
211
|
-
font-size: 16px;
|
|
212
|
-
line-height: 16px;
|
|
213
|
-
flex: none;
|
|
214
|
-
pointer-events: none;
|
|
215
|
-
display: inline-flex;
|
|
216
|
-
align-items: center;
|
|
217
|
-
justify-content: center;
|
|
218
|
-
}
|
|
219
|
-
matcha-form-field[size="md"] .matcha-form-field:has(input[type="search"])::after,
|
|
220
|
-
matcha-form-field[size="medium"] .matcha-form-field:has(input[type="search"])::after {
|
|
221
|
-
font-size: 20px;
|
|
222
|
-
line-height: 20px;
|
|
223
|
-
}
|
|
224
|
-
matcha-form-field[size="lg"] .matcha-form-field:has(input[type="search"])::after,
|
|
225
|
-
matcha-form-field[size="large"] .matcha-form-field:has(input[type="search"])::after,
|
|
226
|
-
matcha-form-field[size="huge"] .matcha-form-field:has(input[type="search"])::after {
|
|
227
|
-
font-size: 24px;
|
|
228
|
-
line-height: 24px;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// Hierarquia de trailing icons: loading > clear × > suffix default.
|
|
232
|
-
// Cada nível oculta os abaixo pra não empilhar ícones redundantes.
|
|
233
|
-
|
|
234
|
-
// Loading: spinner assume o suffix; oculta lupa + × juntos.
|
|
235
|
-
.matcha-form-field:has(input[type="search"]):has(.matcha-form-field-spinner)::after,
|
|
236
|
-
.matcha-form-field:has(.matcha-form-field-spinner) .matcha-clear-button {
|
|
237
|
-
display: none !important;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// Clear visível (input com valor): × toma o lugar da lupa default.
|
|
241
|
-
.matcha-form-field:has(input[type="search"]):has(.matcha-clear-button--visible)::after {
|
|
242
|
-
display: none;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// ── Structural (inputs) — sem border, sem bg (box wraps) ────────────────────
|
|
246
|
-
|
|
247
|
-
// ─── Filhos projetáveis do form-field ────────────────────────────────────
|
|
248
|
-
// Todos os tipos de input que podem ser projetados DEVEM preencher o espaço
|
|
249
|
-
// disponível e herdar padding/border/bg do wrapper externo (.matcha-form-field).
|
|
250
|
-
// O componente filho NÃO deve ter padding/border próprio quando dentro do field.
|
|
251
|
-
.matcha-form-field {
|
|
252
|
-
input,
|
|
253
|
-
input[type="text"],
|
|
254
|
-
input[type="email"],
|
|
255
|
-
input[type="tel"],
|
|
256
|
-
input[type="url"],
|
|
257
|
-
input[type="password"],
|
|
258
|
-
input[type="number"],
|
|
259
|
-
input[type="search"],
|
|
260
|
-
input[type="date"],
|
|
261
|
-
input[type="time"],
|
|
262
|
-
textarea {
|
|
263
|
-
flex: 1 1 auto;
|
|
264
|
-
width: 100%;
|
|
265
|
-
min-width: 0;
|
|
266
|
-
min-height: 0; // evita que altura natural do input expanda o container
|
|
267
|
-
background-color: transparent;
|
|
268
|
-
outline: none;
|
|
269
|
-
box-shadow: none;
|
|
270
|
-
border: none;
|
|
271
|
-
padding: 0; // wrapper fornece padding horizontal
|
|
272
|
-
margin: 0;
|
|
273
|
-
font-family: var(--matcha-font-family);
|
|
274
|
-
font-size: var(--matcha-font-size-sm, 14px); // Figma MD placeholder/value 14/400/20
|
|
275
|
-
font-weight: var(--matcha-weight-regular, 400);
|
|
276
|
-
line-height: var(--matcha-leading-body-md, 20px);
|
|
277
|
-
color: var(--matcha-color-text-primary); // Figma filled value: #E8EAED dark / #0E1116 light
|
|
278
|
-
resize: none;
|
|
279
|
-
|
|
280
|
-
// Figma: text-placeholder (#6E747A dark / #9AA0A6 light); opacity 1
|
|
281
|
-
// porque o Firefox aplica opacity < 1 no ::placeholder por default
|
|
282
|
-
&::placeholder {
|
|
283
|
-
color: var(--matcha-color-text-placeholder);
|
|
284
|
-
opacity: 1;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
&:disabled {
|
|
288
|
-
color: var(--matcha-color-interaction-disabled-fg);
|
|
289
|
-
-webkit-text-fill-color: var(--matcha-color-interaction-disabled-fg); // Safari override
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// Textarea ocupa TODA a altura disponível do wrapper (que é column mode).
|
|
294
|
-
// Quando `matchaAutoGrow` está ligado, a directive aplica `.matcha-autogrow`
|
|
295
|
-
// e controla altura via JS — o override abaixo solta o 100% forçado.
|
|
296
|
-
textarea {
|
|
297
|
-
height: 100%;
|
|
298
|
-
min-height: 100%;
|
|
299
|
-
align-self: stretch;
|
|
300
|
-
|
|
301
|
-
&.matcha-autogrow {
|
|
302
|
-
height: auto; // directive calcula e seta inline
|
|
303
|
-
min-height: 0; // flex: 1 já garante piso via wrapper min-height
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// ── Scrollbar estilizada no textarea (Webkit + Firefox) ──────────────────
|
|
308
|
-
// Usa tokens do DS em vez do scrollbar nativo cinza feio do Chrome/Windows.
|
|
309
|
-
// Aplica tanto no textarea "rows fixo" (se user passar rows pequeno + muito texto)
|
|
310
|
-
// quanto no `.matcha-autogrow` depois de atingir `maxRows`.
|
|
311
|
-
textarea {
|
|
312
|
-
scrollbar-width: thin; // Firefox
|
|
313
|
-
scrollbar-color: var(--matcha-color-text-placeholder)
|
|
314
|
-
transparent; // thumb + track
|
|
315
|
-
|
|
316
|
-
&::-webkit-scrollbar { width: 6px; height: 6px; }
|
|
317
|
-
&::-webkit-scrollbar-track { background: transparent; }
|
|
318
|
-
&::-webkit-scrollbar-thumb {
|
|
319
|
-
background: var(--matcha-color-text-placeholder);
|
|
320
|
-
border-radius: var(--matcha-radius-pill, 999px);
|
|
321
|
-
}
|
|
322
|
-
&::-webkit-scrollbar-thumb:hover { background: var(--matcha-color-text-secondary); }
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
input:focus,
|
|
326
|
-
textarea:focus {
|
|
327
|
-
outline: none;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// Truncate: quando o campo é menor que placeholder/value, corta com ellipsis
|
|
331
|
-
// Evita overflow feio em sidebars, colunas estreitas, responsive mobile.
|
|
332
|
-
input {
|
|
333
|
-
text-overflow: ellipsis;
|
|
334
|
-
overflow: hidden;
|
|
335
|
-
white-space: nowrap;
|
|
336
|
-
|
|
337
|
-
// Placeholder também trunca (Chrome/Safari precisam do ::placeholder explícito)
|
|
338
|
-
&::placeholder {
|
|
339
|
-
text-overflow: ellipsis;
|
|
340
|
-
overflow: hidden;
|
|
341
|
-
white-space: nowrap;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// ── Autofill (Chrome/Safari) — mata o azul/amarelo nativo e usa os tokens ──
|
|
346
|
-
// Browsers pintam autofill com um background-color INTERNO que ignora
|
|
347
|
-
// `background-color` normal via CSS (prioridade de UA style). O workaround
|
|
348
|
-
// padrão cobre esse fundo com um box-shadow inset opaco do tamanho da caixa —
|
|
349
|
-
// e por isso a cor do box-shadow tem que ser OPACA e igual ao fundo real por
|
|
350
|
-
// trás do input, não `transparent` (bug anterior: transparent não cobre nada,
|
|
351
|
-
// o azul nativo do Chrome continuava visível por baixo -- ilegível no tema
|
|
352
|
-
// escuro, onde o contraste com o texto claro inverte). O input em si é
|
|
353
|
-
// `background-color: transparent` (linha ~33): o que aparece por trás é o
|
|
354
|
-
// matcha-card que envolve o form-field na esmagadora maioria dos usos deste
|
|
355
|
-
// painel -- por isso surface-card, não surface-bg (fundo da PÁGINA, um tom
|
|
356
|
-
// mais escuro/mais claro que o card e que deixaria um contorno visível).
|
|
357
|
-
// `transition: ... 5000s` é o "truque dos 5000 segundos" — impede o browser de
|
|
358
|
-
// reaplicar o bg nativo antes do box-shadow cobrir.
|
|
359
|
-
input:-webkit-autofill,
|
|
360
|
-
input:-webkit-autofill:hover,
|
|
361
|
-
input:-webkit-autofill:focus,
|
|
362
|
-
input:-webkit-autofill:active,
|
|
363
|
-
textarea:-webkit-autofill {
|
|
364
|
-
-webkit-box-shadow: 0 0 0 1000px var(--matcha-color-surface-card) inset !important;
|
|
365
|
-
-webkit-text-fill-color: var(--matcha-color-text-primary) !important;
|
|
366
|
-
caret-color: var(--matcha-color-primary) !important;
|
|
367
|
-
transition: background-color 5000s ease-in-out 0s, color 5000s ease-in-out 0s;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// Caret color (cursor piscando) = primary pra match com focus border
|
|
371
|
-
input,
|
|
372
|
-
textarea {
|
|
373
|
-
caret-color: var(--matcha-color-primary);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// Selection highlight (quando user seleciona texto) — mesmo par accent do
|
|
377
|
-
// ::selection global (base/_reset.scss). Era primary-alpha aqui e azul do SO no
|
|
378
|
-
// resto da app: duas cores de seleção diferentes na mesma tela.
|
|
379
|
-
input::selection,
|
|
380
|
-
textarea::selection {
|
|
381
|
-
background-color: var(--matcha-color-accent);
|
|
382
|
-
color: var(--matcha-color-accent-text-on);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
// Componentes projetados — todos preenchem a largura e não adicionam borda/padding próprio
|
|
386
|
-
matcha-select,
|
|
387
|
-
matcha-autocomplete,
|
|
388
|
-
matcha-date,
|
|
389
|
-
matcha-field-range,
|
|
390
|
-
matcha-time,
|
|
391
|
-
matcha-phone {
|
|
392
|
-
flex: 1 1 auto;
|
|
393
|
-
width: 100%;
|
|
394
|
-
min-width: 0;
|
|
395
|
-
display: flex;
|
|
396
|
-
align-items: center;
|
|
397
|
-
background: transparent;
|
|
398
|
-
border: none;
|
|
399
|
-
padding: 0;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// matcha-phone: padding/bg próprios do componente quebram o layout dentro do field
|
|
403
|
-
matcha-phone .matcha-phone {
|
|
404
|
-
padding: 0;
|
|
405
|
-
background: transparent;
|
|
406
|
-
font-size: inherit;
|
|
407
|
-
width: 100%;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
// matcha-date/time: container do componente preenche o espaço sem padding/border próprios
|
|
411
|
-
matcha-date .matcha-date-container,
|
|
412
|
-
matcha-time .matcha-time-container {
|
|
413
|
-
width: 100%;
|
|
414
|
-
background: transparent;
|
|
415
|
-
border: none;
|
|
416
|
-
padding: 0;
|
|
417
|
-
min-width: 0;
|
|
418
|
-
gap: var(--matcha-space-100, 8px);
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// ── matchaPasswordToggle: botão do olho injetado ao lado de input[type="password"] ──
|
|
422
|
-
// Figma matcha/field/password: ícone 16/20/24 por size, cor text-placeholder (#9AA0A6)
|
|
423
|
-
.matcha-password-toggle-button {
|
|
424
|
-
flex: none;
|
|
425
|
-
display: inline-flex;
|
|
426
|
-
align-items: center;
|
|
427
|
-
justify-content: center;
|
|
428
|
-
width: 16px; // SM default
|
|
429
|
-
height: 16px;
|
|
430
|
-
padding: 0;
|
|
431
|
-
margin: 0;
|
|
432
|
-
background: transparent;
|
|
433
|
-
border: none;
|
|
434
|
-
cursor: pointer;
|
|
435
|
-
color: var(--matcha-color-text-placeholder); // #9AA0A6
|
|
436
|
-
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
437
|
-
|
|
438
|
-
&:hover:not(:disabled) {
|
|
439
|
-
color: var(--matcha-color-text-primary);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
&:disabled {
|
|
443
|
-
cursor: not-allowed;
|
|
444
|
-
color: var(--matcha-color-interaction-disabled-fg);
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
&:focus { outline: none; }
|
|
448
|
-
&:focus-visible {
|
|
449
|
-
outline: 2px solid var(--matcha-color-primary);
|
|
450
|
-
outline-offset: 2px;
|
|
451
|
-
border-radius: var(--matcha-radius-md, 4px);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
> [class^="i-matcha-"],
|
|
455
|
-
> [class*=" i-matcha-"] {
|
|
456
|
-
font-size: inherit !important;
|
|
457
|
-
width: 1em !important;
|
|
458
|
-
height: 1em !important;
|
|
459
|
-
line-height: 1 !important;
|
|
460
|
-
color: inherit !important;
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
// ── matchaQuantityStepper: wrapper flex-row + dois botões (−/+) ──────
|
|
465
|
-
// Figma matcha/field/quantity: gap 4, ícones 16px constante, cor #9AA0A6
|
|
466
|
-
.matcha-quantity-stepper {
|
|
467
|
-
flex: none;
|
|
468
|
-
display: inline-flex;
|
|
469
|
-
align-items: center;
|
|
470
|
-
gap: var(--matcha-space-050, 4px);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
.matcha-quantity-stepper-button {
|
|
474
|
-
flex: none;
|
|
475
|
-
display: inline-flex;
|
|
476
|
-
align-items: center;
|
|
477
|
-
justify-content: center;
|
|
478
|
-
width: 16px; // Figma: constante 16px em todos os sizes
|
|
479
|
-
height: 16px;
|
|
480
|
-
padding: 0;
|
|
481
|
-
margin: 0;
|
|
482
|
-
background: transparent;
|
|
483
|
-
border: none;
|
|
484
|
-
cursor: pointer;
|
|
485
|
-
color: var(--matcha-color-text-placeholder); // #9AA0A6
|
|
486
|
-
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
487
|
-
|
|
488
|
-
&:hover:not(:disabled) {
|
|
489
|
-
color: var(--matcha-color-text-primary);
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
&:disabled {
|
|
493
|
-
cursor: not-allowed;
|
|
494
|
-
color: var(--matcha-color-interaction-disabled-fg);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
&:focus { outline: none; }
|
|
498
|
-
&:focus-visible {
|
|
499
|
-
outline: 2px solid var(--matcha-color-primary);
|
|
500
|
-
outline-offset: 2px;
|
|
501
|
-
border-radius: var(--matcha-radius-md, 4px);
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
> [class^="i-matcha-"],
|
|
505
|
-
> [class*=" i-matcha-"] {
|
|
506
|
-
font-size: 16px !important;
|
|
507
|
-
width: 16px !important;
|
|
508
|
-
height: 16px !important;
|
|
509
|
-
line-height: 1 !important;
|
|
510
|
-
color: inherit !important;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
// Esconde spinner nativo (Figma usa botões customizados)
|
|
515
|
-
input[type="number"][matchaQuantityStepper] {
|
|
516
|
-
-moz-appearance: textfield;
|
|
517
|
-
appearance: textfield;
|
|
518
|
-
|
|
519
|
-
&::-webkit-outer-spin-button,
|
|
520
|
-
&::-webkit-inner-spin-button {
|
|
521
|
-
-webkit-appearance: none;
|
|
522
|
-
appearance: none;
|
|
523
|
-
margin: 0;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
// Esconde botão × nativo do Chrome/Safari em input[type="search"]
|
|
528
|
-
// (o matchaClearButton directive injeta nosso próprio — não duplicar)
|
|
529
|
-
input[type="search"] {
|
|
530
|
-
&::-webkit-search-cancel-button,
|
|
531
|
-
&::-webkit-search-decoration,
|
|
532
|
-
&::-webkit-search-results-button,
|
|
533
|
-
&::-webkit-search-results-decoration {
|
|
534
|
-
-webkit-appearance: none;
|
|
535
|
-
appearance: none;
|
|
536
|
-
display: none;
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
// ── matchaClearButton: botão × ao lado de search/text ────────────────
|
|
541
|
-
// Figma-consistent: 16/20/24 por size, cor text-placeholder
|
|
542
|
-
.matcha-clear-button {
|
|
543
|
-
flex: none;
|
|
544
|
-
display: inline-flex;
|
|
545
|
-
align-items: center;
|
|
546
|
-
justify-content: center;
|
|
547
|
-
width: 16px; height: 16px;
|
|
548
|
-
padding: 0;
|
|
549
|
-
// margin-left: auto empurra o × pro final do flex row, imune a irmãos
|
|
550
|
-
// invisíveis (ng-content placeholders, matcha-autocomplete host que
|
|
551
|
-
// acaba como sibling quando projetado via matcha-field, etc).
|
|
552
|
-
margin: 0 0 0 auto;
|
|
553
|
-
background: transparent;
|
|
554
|
-
border: none;
|
|
555
|
-
cursor: pointer;
|
|
556
|
-
color: var(--matcha-color-text-placeholder);
|
|
557
|
-
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
558
|
-
position: relative;
|
|
559
|
-
|
|
560
|
-
&:hover:not(:disabled) { color: var(--matcha-color-text-primary); }
|
|
561
|
-
|
|
562
|
-
&:focus { outline: none; }
|
|
563
|
-
&:focus-visible {
|
|
564
|
-
outline: 2px solid var(--matcha-color-primary);
|
|
565
|
-
outline-offset: 2px;
|
|
566
|
-
border-radius: var(--matcha-radius-md, 4px);
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
> [class^="i-matcha-"],
|
|
570
|
-
> [class*=" i-matcha-"] {
|
|
571
|
-
font-size: 16px !important;
|
|
572
|
-
width: 16px !important; height: 16px !important;
|
|
573
|
-
line-height: 1 !important;
|
|
574
|
-
color: inherit !important;
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
// matchaCharCounter removido daqui — agora é irmão do .matcha-form-field
|
|
579
|
-
// (vive no wrapper), estilizado fora deste bloco pra funcionar em qualquer size.
|
|
580
|
-
// Nota: estilo precisa ser GLOBAL (este arquivo) porque o span é injetado via
|
|
581
|
-
// Renderer2 sem _ngcontent — CSS scoped do Emulated não matcha.
|
|
582
|
-
|
|
583
|
-
// ── Loading spinner no suffix do field ────────────────────────────────
|
|
584
|
-
.matcha-form-field-spinner {
|
|
585
|
-
flex: none;
|
|
586
|
-
display: inline-block;
|
|
587
|
-
width: 16px; height: 16px;
|
|
588
|
-
border: 2px solid var(--matcha-color-surface-border);
|
|
589
|
-
border-top-color: var(--matcha-color-primary);
|
|
590
|
-
border-radius: 50%;
|
|
591
|
-
animation: matcha-spin 800ms linear infinite;
|
|
592
|
-
|
|
593
|
-
@media (prefers-reduced-motion: reduce) {
|
|
594
|
-
animation-duration: 2000ms;
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
// Select trigger ocupa altura E largura totais do form-field (clique abre
|
|
599
|
-
// dropdown em qualquer ponto da caixa)
|
|
600
|
-
matcha-select,
|
|
601
|
-
.matcha-select-container,
|
|
602
|
-
.matcha-select-trigger {
|
|
603
|
-
height: 100%;
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
.matcha-select-container,
|
|
607
|
-
.matcha-select-trigger {
|
|
608
|
-
width: 100%;
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
// Suffix costuma agrupar mais de uma info (contador de caracteres + ícone de
|
|
612
|
-
// status/erro) — 8px de respiro entre elas. Regra global (sem ::ng-deep): o
|
|
613
|
-
// host do <matcha-suffix> tem class .matcha-form-field-suffix e vive dentro do
|
|
614
|
-
// matcha-form-field. O display:inline-flex vem do component scss.
|
|
615
|
-
.matcha-form-field-suffix {
|
|
616
|
-
gap: var(--matcha-space-100, 8px);
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
// @deprecated `.matcha-suffix` (div avulsa) — use o componente <matcha-suffix>
|
|
620
|
-
// (host `.matcha-form-field-suffix`), que já traz o gap de 8px entre múltiplas
|
|
621
|
-
// infos. Mantido só por retrocompat; migrar consumidores e remover numa próxima major.
|
|
622
|
-
.matcha-suffix {
|
|
623
|
-
display: flex;
|
|
624
|
-
flex-wrap: nowrap;
|
|
625
|
-
align-items: center;
|
|
626
|
-
gap: var(--matcha-space-100, 8px);
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
// ─── Password toggle: tamanho do ícone por size do form-field ──────────────
|
|
631
|
-
// (Figma matcha/field/password: SM 16 · MD 20 · LG 24)
|
|
632
|
-
matcha-form-field[size="md"] .matcha-password-toggle-button,
|
|
633
|
-
matcha-form-field[size="medium"] .matcha-password-toggle-button {
|
|
634
|
-
width: 20px;
|
|
635
|
-
height: 20px;
|
|
636
|
-
font-size: 20px;
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
matcha-form-field[size="lg"] .matcha-password-toggle-button,
|
|
640
|
-
matcha-form-field[size="large"] .matcha-password-toggle-button,
|
|
641
|
-
matcha-form-field[size="huge"] .matcha-password-toggle-button {
|
|
642
|
-
width: 24px;
|
|
643
|
-
height: 24px;
|
|
644
|
-
font-size: 24px;
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
// ── Spinner keyframes ────────────────────────────────────────────────────
|
|
648
|
-
@keyframes matcha-spin {
|
|
649
|
-
to { transform: rotate(360deg); }
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
// ── Readonly state ───────────────────────────────────────────────────────
|
|
653
|
-
// Visual mais sutil que disabled: texto legível, selecionável, copiável.
|
|
654
|
-
// Diferença vs disabled: cor normal do texto (não muted) + cursor `text` no input
|
|
655
|
-
// (sinaliza "você pode selecionar e copiar"), enquanto disabled = not-allowed.
|
|
656
|
-
matcha-form-field[readonly="true"] .matcha-form-field {
|
|
657
|
-
background: var(--matcha-color-surface-bg);
|
|
658
|
-
|
|
659
|
-
input, textarea {
|
|
660
|
-
cursor: text; // nativo do input — reforça que texto é selecionável
|
|
661
|
-
user-select: text; // explícito pra evitar reset acidental
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
// Remove hover border change (não é editável, hover não deve sugerir edição)
|
|
665
|
-
&:hover { border-color: var(--matcha-color-surface-border); }
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
// ── Touch targets (WCAG 2.5.5: 44x44 mínimo em coarse pointers) ─────────
|
|
669
|
-
// Expande hit area sem mudar visual (pseudo-element overlay).
|
|
670
|
-
@media (pointer: coarse) {
|
|
671
|
-
.matcha-password-toggle-button,
|
|
672
|
-
.matcha-quantity-stepper-button,
|
|
673
|
-
.matcha-clear-button,
|
|
674
|
-
matcha-date .matcha-date-picker-button,
|
|
675
|
-
matcha-time .matcha-time-picker-button,
|
|
676
|
-
matcha-field-range .matcha-field-range-button,
|
|
677
|
-
matcha-phone .matcha-phone-country {
|
|
678
|
-
position: relative;
|
|
679
|
-
|
|
680
|
-
&::before {
|
|
681
|
-
content: '';
|
|
682
|
-
position: absolute;
|
|
683
|
-
inset: -14px; // expande 14px em cada lado = 44x44 total (16 + 14*2)
|
|
684
|
-
// invisível, mas capturavel — só expande o hit area
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
// ── Char counter (injetado via Renderer2 pelo matchaCharCounter directive) ──
|
|
690
|
-
// Figma matcha/field/textarea: body-sm 12/16, text-secondary, align right.
|
|
691
|
-
// Precisa ser global (sem ngcontent) porque o span vem de fora da view do form-field.
|
|
692
|
-
// IN-40430 (painel): a tipografia vale pra QUALQUER host do counter — quando o span
|
|
693
|
-
// caía fora do .matcha-form-field-wrapper (textarea/usos legados), ficava sem estilo
|
|
694
|
-
// e herdava fonte maior que o próprio texto do campo.
|
|
695
|
-
.matcha-char-counter {
|
|
696
|
-
font-family: var(--matcha-font-family);
|
|
697
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
698
|
-
font-weight: var(--matcha-weight-regular, 400);
|
|
699
|
-
line-height: var(--matcha-leading-body-sm, 16px);
|
|
700
|
-
color: var(--matcha-color-text-secondary);
|
|
701
|
-
text-align: right;
|
|
702
|
-
margin: 0;
|
|
703
|
-
padding: 0;
|
|
704
|
-
user-select: none;
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
.matcha-form-field-wrapper > .matcha-char-counter {
|
|
708
|
-
align-self: flex-end;
|
|
709
|
-
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
710
|
-
|
|
711
|
-
// 3 níveis visuais (0-89% = neutro, 90-99% = warn, 100%+ = danger).
|
|
712
|
-
// `is-near-limit` é aplicado a partir de 90%; `is-at-limit` sobrepõe a partir de 100%.
|
|
713
|
-
&.is-near-limit:not(.is-at-limit) {
|
|
714
|
-
color: var(--matcha-color-warn);
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
&.is-at-limit {
|
|
718
|
-
color: var(--matcha-color-danger);
|
|
719
|
-
font-weight: var(--matcha-weight-semibold, 600);
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
// ── Caps Lock hint (injetado pelo matchaCapsLockHint em input[type="password"]) ──
|
|
724
|
-
// Renderiza abaixo do field, mesmo nível do char counter. Usa cor warn (amarelo/laranja)
|
|
725
|
-
// pra sinalizar risco sem ser erro (user pode estar digitando intencionalmente).
|
|
726
|
-
.matcha-form-field-wrapper > .matcha-caps-lock-hint {
|
|
727
|
-
display: inline-flex;
|
|
728
|
-
align-items: center;
|
|
729
|
-
gap: var(--matcha-space-050, 4px);
|
|
730
|
-
align-self: flex-start;
|
|
731
|
-
font-family: var(--matcha-font-family);
|
|
732
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
733
|
-
font-weight: var(--matcha-weight-regular, 400);
|
|
734
|
-
line-height: var(--matcha-leading-body-sm, 16px);
|
|
735
|
-
color: var(--matcha-color-warn);
|
|
736
|
-
margin-top: var(--matcha-space-050, 4px);
|
|
737
|
-
user-select: none;
|
|
738
|
-
|
|
739
|
-
> [class^="i-matcha-"] {
|
|
740
|
-
font-size: 14px;
|
|
741
|
-
line-height: 14px;
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
// ── Responsive size classes (aligned with Figma SM/MD/LG) ───────────────────
|
|
746
|
-
|
|
747
|
-
@mixin generate-matcha-form-field-size-classes($helper-breakpoints) {
|
|
748
|
-
@each $breakpoint, $materialBreakpoint in $helper-breakpoints {
|
|
749
|
-
@include media-breakpoint($materialBreakpoint) {
|
|
750
|
-
$infix: if($materialBreakpoint == null, "", "-#{$breakpoint}");
|
|
751
|
-
|
|
752
|
-
&[size#{$infix}="sm"],
|
|
753
|
-
&[size#{$infix}="tiny"],
|
|
754
|
-
&[size#{$infix}="small"] {
|
|
755
|
-
.matcha-form-field input,
|
|
756
|
-
.matcha-form-field textarea {
|
|
757
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
758
|
-
line-height: var(--matcha-leading-body-sm, 16px);
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
&[size#{$infix}="md"],
|
|
763
|
-
&[size#{$infix}="medium"] {
|
|
764
|
-
.matcha-form-field input,
|
|
765
|
-
.matcha-form-field textarea {
|
|
766
|
-
font-size: var(--matcha-font-size-sm, 14px);
|
|
767
|
-
line-height: var(--matcha-leading-body-md, 20px);
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
&[size#{$infix}="lg"],
|
|
772
|
-
&[size#{$infix}="large"],
|
|
773
|
-
&[size#{$infix}="huge"] {
|
|
774
|
-
.matcha-form-field input,
|
|
775
|
-
.matcha-form-field textarea {
|
|
776
|
-
font-size: var(--matcha-font-size-md, 16px);
|
|
777
|
-
line-height: var(--matcha-leading-body-lg, 24px);
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
// ── Theme mixin ─────────────────────────────────────────────────────────────
|
|
785
|
-
|
|
786
|
-
@mixin matcha-form-field($theme) {
|
|
787
|
-
.matcha-form-field {
|
|
788
|
-
input[type="text"],
|
|
789
|
-
input[type="email"],
|
|
790
|
-
input[type="tel"],
|
|
791
|
-
input[type="url"],
|
|
792
|
-
input[type="password"],
|
|
793
|
-
input[type="number"],
|
|
794
|
-
input[type="search"],
|
|
795
|
-
input[type="date"],
|
|
796
|
-
input[type="time"],
|
|
797
|
-
textarea {
|
|
798
|
-
color: var(--matcha-color-text-primary);
|
|
799
|
-
|
|
800
|
-
&::placeholder {
|
|
801
|
-
color: var(--matcha-color-text-placeholder);
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
input:disabled,
|
|
806
|
-
textarea:disabled {
|
|
807
|
-
color: var(--matcha-color-interaction-disabled-fg);
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
// Disabled: muted text, cursor not-allowed (sinalização inequívoca de "não pode interagir").
|
|
811
|
-
// `cursor: not-allowed` vai no wrapper; `pointer-events: none` fica só no input/textarea
|
|
812
|
-
// pra herdar o cursor do parent e não bloquear eventos no wrapper (senão cursor não aparece).
|
|
813
|
-
&.matcha-form-field-disabled {
|
|
814
|
-
cursor: not-allowed;
|
|
815
|
-
|
|
816
|
-
input, textarea {
|
|
817
|
-
pointer-events: none;
|
|
818
|
-
color: var(--matcha-color-interaction-disabled-fg);
|
|
819
|
-
|
|
820
|
-
&::placeholder {
|
|
821
|
-
color: var(--matcha-color-interaction-disabled-fg);
|
|
822
|
-
opacity: 0.7;
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
matcha-form-field {
|
|
829
|
-
@include generate-matcha-form-field-size-classes($helper-breakpoints);
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
// ── Forced colors ──
|
|
834
|
-
// Field precisa border + bg explícitos pra ser visível como input.
|
|
835
|
-
@media (forced-colors: active) {
|
|
836
|
-
matcha-form-field {
|
|
837
|
-
.matcha-field-control,
|
|
838
|
-
.matcha-form-field__control {
|
|
839
|
-
border: 1px solid CanvasText !important;
|
|
840
|
-
background: Canvas !important;
|
|
841
|
-
color: CanvasText !important;
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
// Estado focused
|
|
845
|
-
&.is-focused .matcha-field-control,
|
|
846
|
-
&.is-focused .matcha-form-field__control,
|
|
847
|
-
.matcha-field-control:focus-within,
|
|
848
|
-
.matcha-form-field__control:focus-within {
|
|
849
|
-
outline: 2px solid CanvasText !important;
|
|
850
|
-
outline-offset: 2px;
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
// Estado erro/invalid
|
|
854
|
-
&.is-invalid .matcha-field-control,
|
|
855
|
-
&.has-error .matcha-form-field__control {
|
|
856
|
-
border-color: CanvasText !important;
|
|
857
|
-
border-width: 2px !important;
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
&[disabled],
|
|
861
|
-
&.is-disabled {
|
|
862
|
-
opacity: 0.5;
|
|
863
|
-
|
|
864
|
-
.matcha-field-control,
|
|
865
|
-
.matcha-form-field__control {
|
|
866
|
-
border-color: GrayText !important;
|
|
867
|
-
color: GrayText !important;
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
// ── Print ──
|
|
874
|
-
// Form fields preservam estado (form values). Sem fundo decorativo.
|
|
875
|
-
@media print {
|
|
876
|
-
matcha-form-field {
|
|
877
|
-
.matcha-field-control,
|
|
878
|
-
.matcha-form-field__control {
|
|
879
|
-
border: 1px solid currentColor !important;
|
|
880
|
-
background: transparent !important;
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
}
|
|
1
|
+
@use "../abstracts/media-breakpoint" as *;
|
|
2
|
+
@use "../tokens/breakpoints-tokens" as *;
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// matcha-form-field.scss — FONTE ÚNICA de estilo do matcha-form-field
|
|
5
|
+
// (estrutura, states, sizes, tipografia). O component SCSS é comment-only.
|
|
6
|
+
// =============================================================================
|
|
7
|
+
|
|
8
|
+
// ═══ Estrutura e states (migrado do matcha-form-field.component.scss) ═══════
|
|
9
|
+
// Histórico: estas regras viviam no SCSS do componente (ViewEncapsulation.
|
|
10
|
+
// Emulated). Seletor de host escrito como `matcha-form-field[...]` ganhava
|
|
11
|
+
// sufixo [_ngcontent-…] e virava CSS morto — caso do disabled, cuja opacity
|
|
12
|
+
// nunca aplicou. Global no tema, o que está escrito é o que vale; os antigos
|
|
13
|
+
// ::ng-deep viram seletores diretos.
|
|
14
|
+
|
|
15
|
+
// Wrapper stacked: Label → gap → Box → gap → Hint (Figma matcha/field/_base)
|
|
16
|
+
.matcha-form-field-wrapper {
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
align-items: flex-start;
|
|
20
|
+
gap: var(--matcha-space-075, 6px); // Figma matcha/field/text: gap 6px entre label/box/hint
|
|
21
|
+
width: 100%;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Box do input — onde fica o input/select/textarea
|
|
25
|
+
// Figma: align-self: stretch → ocupa toda a largura do wrapper
|
|
26
|
+
.matcha-form-field {
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-direction: row;
|
|
29
|
+
align-items: center;
|
|
30
|
+
gap: var(--matcha-space-100, 8px);
|
|
31
|
+
width: 100%; // stretch pro wrapper
|
|
32
|
+
min-height: 44px; // MD default
|
|
33
|
+
padding: 0 var(--matcha-space-150, 12px); // pad horizontal 12
|
|
34
|
+
border: var(--matcha-border-thin, 2px) solid var(--matcha-color-surface-border, #E1E7E2);
|
|
35
|
+
border-radius: var(--matcha-radius-lg, 8px);
|
|
36
|
+
background: transparent;
|
|
37
|
+
box-sizing: border-box;
|
|
38
|
+
transition: border-color var(--matcha-duration-fast, 200ms);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Slots prefix/suffix — elementos decorativos antes/depois do input
|
|
42
|
+
.matcha-form-field .matcha-form-field-prefix,
|
|
43
|
+
.matcha-form-field .matcha-form-field-suffix {
|
|
44
|
+
display: inline-flex;
|
|
45
|
+
align-items: center;
|
|
46
|
+
flex: none;
|
|
47
|
+
color: var(--matcha-color-text-label);
|
|
48
|
+
font-family: var(--matcha-font-family);
|
|
49
|
+
font-size: var(--matcha-font-size-sm, 14px);
|
|
50
|
+
font-weight: var(--matcha-weight-regular, 400);
|
|
51
|
+
line-height: var(--matcha-leading-body-md, 20px);
|
|
52
|
+
user-select: none;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.matcha-form-field .matcha-form-field-prefix:not(:empty) + * {
|
|
56
|
+
padding-left: 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Hover / focus-within (Figma matcha/field/_base State=Focus).
|
|
60
|
+
// Disabled não chega aqui (pointer-events: none nas regras de disabled abaixo);
|
|
61
|
+
// readonly neutraliza o hover na regra própria de readonly; error e data-color
|
|
62
|
+
// vencem por especificidade/ordem.
|
|
63
|
+
.matcha-form-field:hover {
|
|
64
|
+
border-color: var(--matcha-color-surface-border-strong);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.matcha-form-field:focus-within {
|
|
68
|
+
border-color: var(--matcha-color-primary, #1664C2);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Color variants via data-color — override border-color
|
|
72
|
+
.matcha-form-field[data-color="accent"] { border-color: var(--matcha-color-accent); }
|
|
73
|
+
.matcha-form-field[data-color="primary"] { border-color: var(--matcha-color-primary); }
|
|
74
|
+
.matcha-form-field[data-color="danger"] { border-color: var(--matcha-color-danger); }
|
|
75
|
+
.matcha-form-field[data-color="warn"] { border-color: var(--matcha-color-warn); }
|
|
76
|
+
.matcha-form-field[data-color="success"] { border-color: var(--matcha-color-success); }
|
|
77
|
+
.matcha-form-field[data-color="info"] { border-color: var(--matcha-color-info); }
|
|
78
|
+
|
|
79
|
+
// Sizes (Figma heights): SM 36, MD 44, LG 52.
|
|
80
|
+
// Alturas não são responsivas — a tipografia responsiva fica no mixin abaixo.
|
|
81
|
+
matcha-form-field[size="sm"] .matcha-form-field,
|
|
82
|
+
matcha-form-field[size="tiny"] .matcha-form-field,
|
|
83
|
+
matcha-form-field[size="small"] .matcha-form-field {
|
|
84
|
+
min-height: 36px;
|
|
85
|
+
padding: 0 var(--matcha-space-150, 12px);
|
|
86
|
+
}
|
|
87
|
+
matcha-form-field[size="md"] .matcha-form-field,
|
|
88
|
+
matcha-form-field[size="medium"] .matcha-form-field {
|
|
89
|
+
min-height: 44px;
|
|
90
|
+
padding: 0 var(--matcha-space-150, 12px);
|
|
91
|
+
}
|
|
92
|
+
matcha-form-field[size="lg"] .matcha-form-field,
|
|
93
|
+
matcha-form-field[size="large"] .matcha-form-field,
|
|
94
|
+
matcha-form-field[size="huge"] .matcha-form-field {
|
|
95
|
+
min-height: 52px;
|
|
96
|
+
padding: 0 var(--matcha-space-200, 16px);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Disabled — Figma aplica opacity 0.38 no WRAPPER inteiro
|
|
100
|
+
// (label, field-box e hint ficam apagados de uma vez).
|
|
101
|
+
// EXCEÇÃO: tooltip do label preserva opacity=1 e pointer-events pra manter a
|
|
102
|
+
// pergunta "por que desabilitado?" respondível (UX crítico pra forms complexos).
|
|
103
|
+
// Sem border-color especial: o token interaction-disabled-border tem MAIS
|
|
104
|
+
// contraste que a borda normal e anulava o esmaecimento — a borda fica a normal
|
|
105
|
+
// e a opacity apaga o conjunto uniformemente.
|
|
106
|
+
matcha-form-field[disabled]:not([disabled="false"]) {
|
|
107
|
+
opacity: var(--matcha-opacity-disabled, 0.38);
|
|
108
|
+
|
|
109
|
+
.matcha-form-field {
|
|
110
|
+
pointer-events: none;
|
|
111
|
+
cursor: default;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Tooltip icon continua interativo e legível mesmo com wrapper disabled
|
|
115
|
+
.matcha-label-tooltip {
|
|
116
|
+
opacity: calc(1 / var(--matcha-opacity-disabled, 0.38));
|
|
117
|
+
pointer-events: auto;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Fallback legado (classe aplicada via JS quando o input interno tem disabled);
|
|
122
|
+
// cursor/cores de texto dessa classe vivem no theme mixin mais abaixo.
|
|
123
|
+
.matcha-form-field-disabled {
|
|
124
|
+
pointer-events: none;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Error state (Figma: border danger) — via @Input() error ou data-color="danger"
|
|
128
|
+
matcha-form-field[error]:not([error="false"]) .matcha-form-field {
|
|
129
|
+
border-color: var(--matcha-color-danger);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ─── Simulação de states em docs/playgrounds ────────────────────────────
|
|
133
|
+
matcha-form-field.is-state-focus .matcha-form-field {
|
|
134
|
+
border-color: var(--matcha-color-primary) !important;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
matcha-form-field.is-state-disabled {
|
|
138
|
+
opacity: var(--matcha-opacity-disabled, 0.38);
|
|
139
|
+
pointer-events: none;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// ─── Field-range override (Figma matcha/field/range) ────────────────────
|
|
143
|
+
// Field-range renderiza DUAS caixas bordadas próprias (start/end com separador).
|
|
144
|
+
// O form-field externo NÃO deve desenhar sua box — apenas empilha label + range + hint.
|
|
145
|
+
.matcha-form-field:has(matcha-field-range) {
|
|
146
|
+
border: none;
|
|
147
|
+
background: transparent;
|
|
148
|
+
padding: 0;
|
|
149
|
+
min-height: 0;
|
|
150
|
+
gap: 0;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
matcha-form-field[size="sm"] .matcha-form-field:has(matcha-field-range),
|
|
154
|
+
matcha-form-field[size="tiny"] .matcha-form-field:has(matcha-field-range),
|
|
155
|
+
matcha-form-field[size="small"] .matcha-form-field:has(matcha-field-range),
|
|
156
|
+
matcha-form-field[size="md"] .matcha-form-field:has(matcha-field-range),
|
|
157
|
+
matcha-form-field[size="medium"] .matcha-form-field:has(matcha-field-range),
|
|
158
|
+
matcha-form-field[size="lg"] .matcha-form-field:has(matcha-field-range),
|
|
159
|
+
matcha-form-field[size="large"] .matcha-form-field:has(matcha-field-range),
|
|
160
|
+
matcha-form-field[size="huge"] .matcha-form-field:has(matcha-field-range) {
|
|
161
|
+
min-height: 0;
|
|
162
|
+
padding: 0;
|
|
163
|
+
border: none;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Erro: não mexe na borda do wrapper (já é none), a cor do erro vai para as halves
|
|
167
|
+
matcha-form-field[error]:not([error="false"]) .matcha-form-field:has(matcha-field-range) {
|
|
168
|
+
border: none;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ─── Textarea override (Figma matcha/field/textarea) ────────────────────
|
|
172
|
+
// Quando o field contém textarea, o wrapper vira column + padding all-sides
|
|
173
|
+
// Heights por size: SM 80px · MD 100px · LG 120px
|
|
174
|
+
.matcha-form-field:has(textarea) {
|
|
175
|
+
flex-direction: column;
|
|
176
|
+
align-items: flex-start;
|
|
177
|
+
padding: var(--matcha-space-150, 12px);
|
|
178
|
+
min-height: 80px; // fallback SM
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
matcha-form-field[size="sm"] .matcha-form-field:has(textarea),
|
|
182
|
+
matcha-form-field[size="tiny"] .matcha-form-field:has(textarea),
|
|
183
|
+
matcha-form-field[size="small"] .matcha-form-field:has(textarea) {
|
|
184
|
+
min-height: 80px;
|
|
185
|
+
padding: var(--matcha-space-150, 12px);
|
|
186
|
+
}
|
|
187
|
+
matcha-form-field[size="md"] .matcha-form-field:has(textarea),
|
|
188
|
+
matcha-form-field[size="medium"] .matcha-form-field:has(textarea) {
|
|
189
|
+
min-height: 100px;
|
|
190
|
+
padding: var(--matcha-space-150, 12px);
|
|
191
|
+
}
|
|
192
|
+
matcha-form-field[size="lg"] .matcha-form-field:has(textarea),
|
|
193
|
+
matcha-form-field[size="large"] .matcha-form-field:has(textarea),
|
|
194
|
+
matcha-form-field[size="huge"] .matcha-form-field:has(textarea) {
|
|
195
|
+
min-height: 120px;
|
|
196
|
+
padding: var(--matcha-space-150, 12px) var(--matcha-space-200, 16px);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// ─── Search: ícone lupa automático após o input[type=search] (Figma suffix icon) ──
|
|
200
|
+
// Mesmo padding horizontal dos outros fields. Por size: SM 16 · MD 20 · LG 24.
|
|
201
|
+
.matcha-form-field:has(input[type="search"])::after {
|
|
202
|
+
content: '\e90c'; // codepoint "search" em MatchaIcons
|
|
203
|
+
font-family: 'MatchaIcons' !important; // fonte registrada no projects/matcha-icons/matcha-icons.css
|
|
204
|
+
font-weight: normal;
|
|
205
|
+
font-style: normal;
|
|
206
|
+
font-variant: normal;
|
|
207
|
+
speak: none;
|
|
208
|
+
text-transform: none;
|
|
209
|
+
-webkit-font-smoothing: antialiased;
|
|
210
|
+
color: var(--matcha-color-text-placeholder);
|
|
211
|
+
font-size: 16px;
|
|
212
|
+
line-height: 16px;
|
|
213
|
+
flex: none;
|
|
214
|
+
pointer-events: none;
|
|
215
|
+
display: inline-flex;
|
|
216
|
+
align-items: center;
|
|
217
|
+
justify-content: center;
|
|
218
|
+
}
|
|
219
|
+
matcha-form-field[size="md"] .matcha-form-field:has(input[type="search"])::after,
|
|
220
|
+
matcha-form-field[size="medium"] .matcha-form-field:has(input[type="search"])::after {
|
|
221
|
+
font-size: 20px;
|
|
222
|
+
line-height: 20px;
|
|
223
|
+
}
|
|
224
|
+
matcha-form-field[size="lg"] .matcha-form-field:has(input[type="search"])::after,
|
|
225
|
+
matcha-form-field[size="large"] .matcha-form-field:has(input[type="search"])::after,
|
|
226
|
+
matcha-form-field[size="huge"] .matcha-form-field:has(input[type="search"])::after {
|
|
227
|
+
font-size: 24px;
|
|
228
|
+
line-height: 24px;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Hierarquia de trailing icons: loading > clear × > suffix default.
|
|
232
|
+
// Cada nível oculta os abaixo pra não empilhar ícones redundantes.
|
|
233
|
+
|
|
234
|
+
// Loading: spinner assume o suffix; oculta lupa + × juntos.
|
|
235
|
+
.matcha-form-field:has(input[type="search"]):has(.matcha-form-field-spinner)::after,
|
|
236
|
+
.matcha-form-field:has(.matcha-form-field-spinner) .matcha-clear-button {
|
|
237
|
+
display: none !important;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Clear visível (input com valor): × toma o lugar da lupa default.
|
|
241
|
+
.matcha-form-field:has(input[type="search"]):has(.matcha-clear-button--visible)::after {
|
|
242
|
+
display: none;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ── Structural (inputs) — sem border, sem bg (box wraps) ────────────────────
|
|
246
|
+
|
|
247
|
+
// ─── Filhos projetáveis do form-field ────────────────────────────────────
|
|
248
|
+
// Todos os tipos de input que podem ser projetados DEVEM preencher o espaço
|
|
249
|
+
// disponível e herdar padding/border/bg do wrapper externo (.matcha-form-field).
|
|
250
|
+
// O componente filho NÃO deve ter padding/border próprio quando dentro do field.
|
|
251
|
+
.matcha-form-field {
|
|
252
|
+
input,
|
|
253
|
+
input[type="text"],
|
|
254
|
+
input[type="email"],
|
|
255
|
+
input[type="tel"],
|
|
256
|
+
input[type="url"],
|
|
257
|
+
input[type="password"],
|
|
258
|
+
input[type="number"],
|
|
259
|
+
input[type="search"],
|
|
260
|
+
input[type="date"],
|
|
261
|
+
input[type="time"],
|
|
262
|
+
textarea {
|
|
263
|
+
flex: 1 1 auto;
|
|
264
|
+
width: 100%;
|
|
265
|
+
min-width: 0;
|
|
266
|
+
min-height: 0; // evita que altura natural do input expanda o container
|
|
267
|
+
background-color: transparent;
|
|
268
|
+
outline: none;
|
|
269
|
+
box-shadow: none;
|
|
270
|
+
border: none;
|
|
271
|
+
padding: 0; // wrapper fornece padding horizontal
|
|
272
|
+
margin: 0;
|
|
273
|
+
font-family: var(--matcha-font-family);
|
|
274
|
+
font-size: var(--matcha-font-size-sm, 14px); // Figma MD placeholder/value 14/400/20
|
|
275
|
+
font-weight: var(--matcha-weight-regular, 400);
|
|
276
|
+
line-height: var(--matcha-leading-body-md, 20px);
|
|
277
|
+
color: var(--matcha-color-text-primary); // Figma filled value: #E8EAED dark / #0E1116 light
|
|
278
|
+
resize: none;
|
|
279
|
+
|
|
280
|
+
// Figma: text-placeholder (#6E747A dark / #9AA0A6 light); opacity 1
|
|
281
|
+
// porque o Firefox aplica opacity < 1 no ::placeholder por default
|
|
282
|
+
&::placeholder {
|
|
283
|
+
color: var(--matcha-color-text-placeholder);
|
|
284
|
+
opacity: 1;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
&:disabled {
|
|
288
|
+
color: var(--matcha-color-interaction-disabled-fg);
|
|
289
|
+
-webkit-text-fill-color: var(--matcha-color-interaction-disabled-fg); // Safari override
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Textarea ocupa TODA a altura disponível do wrapper (que é column mode).
|
|
294
|
+
// Quando `matchaAutoGrow` está ligado, a directive aplica `.matcha-autogrow`
|
|
295
|
+
// e controla altura via JS — o override abaixo solta o 100% forçado.
|
|
296
|
+
textarea {
|
|
297
|
+
height: 100%;
|
|
298
|
+
min-height: 100%;
|
|
299
|
+
align-self: stretch;
|
|
300
|
+
|
|
301
|
+
&.matcha-autogrow {
|
|
302
|
+
height: auto; // directive calcula e seta inline
|
|
303
|
+
min-height: 0; // flex: 1 já garante piso via wrapper min-height
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// ── Scrollbar estilizada no textarea (Webkit + Firefox) ──────────────────
|
|
308
|
+
// Usa tokens do DS em vez do scrollbar nativo cinza feio do Chrome/Windows.
|
|
309
|
+
// Aplica tanto no textarea "rows fixo" (se user passar rows pequeno + muito texto)
|
|
310
|
+
// quanto no `.matcha-autogrow` depois de atingir `maxRows`.
|
|
311
|
+
textarea {
|
|
312
|
+
scrollbar-width: thin; // Firefox
|
|
313
|
+
scrollbar-color: var(--matcha-color-text-placeholder)
|
|
314
|
+
transparent; // thumb + track
|
|
315
|
+
|
|
316
|
+
&::-webkit-scrollbar { width: 6px; height: 6px; }
|
|
317
|
+
&::-webkit-scrollbar-track { background: transparent; }
|
|
318
|
+
&::-webkit-scrollbar-thumb {
|
|
319
|
+
background: var(--matcha-color-text-placeholder);
|
|
320
|
+
border-radius: var(--matcha-radius-pill, 999px);
|
|
321
|
+
}
|
|
322
|
+
&::-webkit-scrollbar-thumb:hover { background: var(--matcha-color-text-secondary); }
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
input:focus,
|
|
326
|
+
textarea:focus {
|
|
327
|
+
outline: none;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Truncate: quando o campo é menor que placeholder/value, corta com ellipsis
|
|
331
|
+
// Evita overflow feio em sidebars, colunas estreitas, responsive mobile.
|
|
332
|
+
input {
|
|
333
|
+
text-overflow: ellipsis;
|
|
334
|
+
overflow: hidden;
|
|
335
|
+
white-space: nowrap;
|
|
336
|
+
|
|
337
|
+
// Placeholder também trunca (Chrome/Safari precisam do ::placeholder explícito)
|
|
338
|
+
&::placeholder {
|
|
339
|
+
text-overflow: ellipsis;
|
|
340
|
+
overflow: hidden;
|
|
341
|
+
white-space: nowrap;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// ── Autofill (Chrome/Safari) — mata o azul/amarelo nativo e usa os tokens ──
|
|
346
|
+
// Browsers pintam autofill com um background-color INTERNO que ignora
|
|
347
|
+
// `background-color` normal via CSS (prioridade de UA style). O workaround
|
|
348
|
+
// padrão cobre esse fundo com um box-shadow inset opaco do tamanho da caixa —
|
|
349
|
+
// e por isso a cor do box-shadow tem que ser OPACA e igual ao fundo real por
|
|
350
|
+
// trás do input, não `transparent` (bug anterior: transparent não cobre nada,
|
|
351
|
+
// o azul nativo do Chrome continuava visível por baixo -- ilegível no tema
|
|
352
|
+
// escuro, onde o contraste com o texto claro inverte). O input em si é
|
|
353
|
+
// `background-color: transparent` (linha ~33): o que aparece por trás é o
|
|
354
|
+
// matcha-card que envolve o form-field na esmagadora maioria dos usos deste
|
|
355
|
+
// painel -- por isso surface-card, não surface-bg (fundo da PÁGINA, um tom
|
|
356
|
+
// mais escuro/mais claro que o card e que deixaria um contorno visível).
|
|
357
|
+
// `transition: ... 5000s` é o "truque dos 5000 segundos" — impede o browser de
|
|
358
|
+
// reaplicar o bg nativo antes do box-shadow cobrir.
|
|
359
|
+
input:-webkit-autofill,
|
|
360
|
+
input:-webkit-autofill:hover,
|
|
361
|
+
input:-webkit-autofill:focus,
|
|
362
|
+
input:-webkit-autofill:active,
|
|
363
|
+
textarea:-webkit-autofill {
|
|
364
|
+
-webkit-box-shadow: 0 0 0 1000px var(--matcha-color-surface-card) inset !important;
|
|
365
|
+
-webkit-text-fill-color: var(--matcha-color-text-primary) !important;
|
|
366
|
+
caret-color: var(--matcha-color-primary) !important;
|
|
367
|
+
transition: background-color 5000s ease-in-out 0s, color 5000s ease-in-out 0s;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Caret color (cursor piscando) = primary pra match com focus border
|
|
371
|
+
input,
|
|
372
|
+
textarea {
|
|
373
|
+
caret-color: var(--matcha-color-primary);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Selection highlight (quando user seleciona texto) — mesmo par accent do
|
|
377
|
+
// ::selection global (base/_reset.scss). Era primary-alpha aqui e azul do SO no
|
|
378
|
+
// resto da app: duas cores de seleção diferentes na mesma tela.
|
|
379
|
+
input::selection,
|
|
380
|
+
textarea::selection {
|
|
381
|
+
background-color: var(--matcha-color-accent);
|
|
382
|
+
color: var(--matcha-color-accent-text-on);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Componentes projetados — todos preenchem a largura e não adicionam borda/padding próprio
|
|
386
|
+
matcha-select,
|
|
387
|
+
matcha-autocomplete,
|
|
388
|
+
matcha-date,
|
|
389
|
+
matcha-field-range,
|
|
390
|
+
matcha-time,
|
|
391
|
+
matcha-phone {
|
|
392
|
+
flex: 1 1 auto;
|
|
393
|
+
width: 100%;
|
|
394
|
+
min-width: 0;
|
|
395
|
+
display: flex;
|
|
396
|
+
align-items: center;
|
|
397
|
+
background: transparent;
|
|
398
|
+
border: none;
|
|
399
|
+
padding: 0;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// matcha-phone: padding/bg próprios do componente quebram o layout dentro do field
|
|
403
|
+
matcha-phone .matcha-phone {
|
|
404
|
+
padding: 0;
|
|
405
|
+
background: transparent;
|
|
406
|
+
font-size: inherit;
|
|
407
|
+
width: 100%;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// matcha-date/time: container do componente preenche o espaço sem padding/border próprios
|
|
411
|
+
matcha-date .matcha-date-container,
|
|
412
|
+
matcha-time .matcha-time-container {
|
|
413
|
+
width: 100%;
|
|
414
|
+
background: transparent;
|
|
415
|
+
border: none;
|
|
416
|
+
padding: 0;
|
|
417
|
+
min-width: 0;
|
|
418
|
+
gap: var(--matcha-space-100, 8px);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// ── matchaPasswordToggle: botão do olho injetado ao lado de input[type="password"] ──
|
|
422
|
+
// Figma matcha/field/password: ícone 16/20/24 por size, cor text-placeholder (#9AA0A6)
|
|
423
|
+
.matcha-password-toggle-button {
|
|
424
|
+
flex: none;
|
|
425
|
+
display: inline-flex;
|
|
426
|
+
align-items: center;
|
|
427
|
+
justify-content: center;
|
|
428
|
+
width: 16px; // SM default
|
|
429
|
+
height: 16px;
|
|
430
|
+
padding: 0;
|
|
431
|
+
margin: 0;
|
|
432
|
+
background: transparent;
|
|
433
|
+
border: none;
|
|
434
|
+
cursor: pointer;
|
|
435
|
+
color: var(--matcha-color-text-placeholder); // #9AA0A6
|
|
436
|
+
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
437
|
+
|
|
438
|
+
&:hover:not(:disabled) {
|
|
439
|
+
color: var(--matcha-color-text-primary);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
&:disabled {
|
|
443
|
+
cursor: not-allowed;
|
|
444
|
+
color: var(--matcha-color-interaction-disabled-fg);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
&:focus { outline: none; }
|
|
448
|
+
&:focus-visible {
|
|
449
|
+
outline: 2px solid var(--matcha-color-primary);
|
|
450
|
+
outline-offset: 2px;
|
|
451
|
+
border-radius: var(--matcha-radius-md, 4px);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
> [class^="i-matcha-"],
|
|
455
|
+
> [class*=" i-matcha-"] {
|
|
456
|
+
font-size: inherit !important;
|
|
457
|
+
width: 1em !important;
|
|
458
|
+
height: 1em !important;
|
|
459
|
+
line-height: 1 !important;
|
|
460
|
+
color: inherit !important;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// ── matchaQuantityStepper: wrapper flex-row + dois botões (−/+) ──────
|
|
465
|
+
// Figma matcha/field/quantity: gap 4, ícones 16px constante, cor #9AA0A6
|
|
466
|
+
.matcha-quantity-stepper {
|
|
467
|
+
flex: none;
|
|
468
|
+
display: inline-flex;
|
|
469
|
+
align-items: center;
|
|
470
|
+
gap: var(--matcha-space-050, 4px);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
.matcha-quantity-stepper-button {
|
|
474
|
+
flex: none;
|
|
475
|
+
display: inline-flex;
|
|
476
|
+
align-items: center;
|
|
477
|
+
justify-content: center;
|
|
478
|
+
width: 16px; // Figma: constante 16px em todos os sizes
|
|
479
|
+
height: 16px;
|
|
480
|
+
padding: 0;
|
|
481
|
+
margin: 0;
|
|
482
|
+
background: transparent;
|
|
483
|
+
border: none;
|
|
484
|
+
cursor: pointer;
|
|
485
|
+
color: var(--matcha-color-text-placeholder); // #9AA0A6
|
|
486
|
+
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
487
|
+
|
|
488
|
+
&:hover:not(:disabled) {
|
|
489
|
+
color: var(--matcha-color-text-primary);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
&:disabled {
|
|
493
|
+
cursor: not-allowed;
|
|
494
|
+
color: var(--matcha-color-interaction-disabled-fg);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
&:focus { outline: none; }
|
|
498
|
+
&:focus-visible {
|
|
499
|
+
outline: 2px solid var(--matcha-color-primary);
|
|
500
|
+
outline-offset: 2px;
|
|
501
|
+
border-radius: var(--matcha-radius-md, 4px);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
> [class^="i-matcha-"],
|
|
505
|
+
> [class*=" i-matcha-"] {
|
|
506
|
+
font-size: 16px !important;
|
|
507
|
+
width: 16px !important;
|
|
508
|
+
height: 16px !important;
|
|
509
|
+
line-height: 1 !important;
|
|
510
|
+
color: inherit !important;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Esconde spinner nativo (Figma usa botões customizados)
|
|
515
|
+
input[type="number"][matchaQuantityStepper] {
|
|
516
|
+
-moz-appearance: textfield;
|
|
517
|
+
appearance: textfield;
|
|
518
|
+
|
|
519
|
+
&::-webkit-outer-spin-button,
|
|
520
|
+
&::-webkit-inner-spin-button {
|
|
521
|
+
-webkit-appearance: none;
|
|
522
|
+
appearance: none;
|
|
523
|
+
margin: 0;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Esconde botão × nativo do Chrome/Safari em input[type="search"]
|
|
528
|
+
// (o matchaClearButton directive injeta nosso próprio — não duplicar)
|
|
529
|
+
input[type="search"] {
|
|
530
|
+
&::-webkit-search-cancel-button,
|
|
531
|
+
&::-webkit-search-decoration,
|
|
532
|
+
&::-webkit-search-results-button,
|
|
533
|
+
&::-webkit-search-results-decoration {
|
|
534
|
+
-webkit-appearance: none;
|
|
535
|
+
appearance: none;
|
|
536
|
+
display: none;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// ── matchaClearButton: botão × ao lado de search/text ────────────────
|
|
541
|
+
// Figma-consistent: 16/20/24 por size, cor text-placeholder
|
|
542
|
+
.matcha-clear-button {
|
|
543
|
+
flex: none;
|
|
544
|
+
display: inline-flex;
|
|
545
|
+
align-items: center;
|
|
546
|
+
justify-content: center;
|
|
547
|
+
width: 16px; height: 16px;
|
|
548
|
+
padding: 0;
|
|
549
|
+
// margin-left: auto empurra o × pro final do flex row, imune a irmãos
|
|
550
|
+
// invisíveis (ng-content placeholders, matcha-autocomplete host que
|
|
551
|
+
// acaba como sibling quando projetado via matcha-field, etc).
|
|
552
|
+
margin: 0 0 0 auto;
|
|
553
|
+
background: transparent;
|
|
554
|
+
border: none;
|
|
555
|
+
cursor: pointer;
|
|
556
|
+
color: var(--matcha-color-text-placeholder);
|
|
557
|
+
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
558
|
+
position: relative;
|
|
559
|
+
|
|
560
|
+
&:hover:not(:disabled) { color: var(--matcha-color-text-primary); }
|
|
561
|
+
|
|
562
|
+
&:focus { outline: none; }
|
|
563
|
+
&:focus-visible {
|
|
564
|
+
outline: 2px solid var(--matcha-color-primary);
|
|
565
|
+
outline-offset: 2px;
|
|
566
|
+
border-radius: var(--matcha-radius-md, 4px);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
> [class^="i-matcha-"],
|
|
570
|
+
> [class*=" i-matcha-"] {
|
|
571
|
+
font-size: 16px !important;
|
|
572
|
+
width: 16px !important; height: 16px !important;
|
|
573
|
+
line-height: 1 !important;
|
|
574
|
+
color: inherit !important;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// matchaCharCounter removido daqui — agora é irmão do .matcha-form-field
|
|
579
|
+
// (vive no wrapper), estilizado fora deste bloco pra funcionar em qualquer size.
|
|
580
|
+
// Nota: estilo precisa ser GLOBAL (este arquivo) porque o span é injetado via
|
|
581
|
+
// Renderer2 sem _ngcontent — CSS scoped do Emulated não matcha.
|
|
582
|
+
|
|
583
|
+
// ── Loading spinner no suffix do field ────────────────────────────────
|
|
584
|
+
.matcha-form-field-spinner {
|
|
585
|
+
flex: none;
|
|
586
|
+
display: inline-block;
|
|
587
|
+
width: 16px; height: 16px;
|
|
588
|
+
border: 2px solid var(--matcha-color-surface-border);
|
|
589
|
+
border-top-color: var(--matcha-color-primary);
|
|
590
|
+
border-radius: 50%;
|
|
591
|
+
animation: matcha-spin 800ms linear infinite;
|
|
592
|
+
|
|
593
|
+
@media (prefers-reduced-motion: reduce) {
|
|
594
|
+
animation-duration: 2000ms;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// Select trigger ocupa altura E largura totais do form-field (clique abre
|
|
599
|
+
// dropdown em qualquer ponto da caixa)
|
|
600
|
+
matcha-select,
|
|
601
|
+
.matcha-select-container,
|
|
602
|
+
.matcha-select-trigger {
|
|
603
|
+
height: 100%;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
.matcha-select-container,
|
|
607
|
+
.matcha-select-trigger {
|
|
608
|
+
width: 100%;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// Suffix costuma agrupar mais de uma info (contador de caracteres + ícone de
|
|
612
|
+
// status/erro) — 8px de respiro entre elas. Regra global (sem ::ng-deep): o
|
|
613
|
+
// host do <matcha-suffix> tem class .matcha-form-field-suffix e vive dentro do
|
|
614
|
+
// matcha-form-field. O display:inline-flex vem do component scss.
|
|
615
|
+
.matcha-form-field-suffix {
|
|
616
|
+
gap: var(--matcha-space-100, 8px);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// @deprecated `.matcha-suffix` (div avulsa) — use o componente <matcha-suffix>
|
|
620
|
+
// (host `.matcha-form-field-suffix`), que já traz o gap de 8px entre múltiplas
|
|
621
|
+
// infos. Mantido só por retrocompat; migrar consumidores e remover numa próxima major.
|
|
622
|
+
.matcha-suffix {
|
|
623
|
+
display: flex;
|
|
624
|
+
flex-wrap: nowrap;
|
|
625
|
+
align-items: center;
|
|
626
|
+
gap: var(--matcha-space-100, 8px);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// ─── Password toggle: tamanho do ícone por size do form-field ──────────────
|
|
631
|
+
// (Figma matcha/field/password: SM 16 · MD 20 · LG 24)
|
|
632
|
+
matcha-form-field[size="md"] .matcha-password-toggle-button,
|
|
633
|
+
matcha-form-field[size="medium"] .matcha-password-toggle-button {
|
|
634
|
+
width: 20px;
|
|
635
|
+
height: 20px;
|
|
636
|
+
font-size: 20px;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
matcha-form-field[size="lg"] .matcha-password-toggle-button,
|
|
640
|
+
matcha-form-field[size="large"] .matcha-password-toggle-button,
|
|
641
|
+
matcha-form-field[size="huge"] .matcha-password-toggle-button {
|
|
642
|
+
width: 24px;
|
|
643
|
+
height: 24px;
|
|
644
|
+
font-size: 24px;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
// ── Spinner keyframes ────────────────────────────────────────────────────
|
|
648
|
+
@keyframes matcha-spin {
|
|
649
|
+
to { transform: rotate(360deg); }
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// ── Readonly state ───────────────────────────────────────────────────────
|
|
653
|
+
// Visual mais sutil que disabled: texto legível, selecionável, copiável.
|
|
654
|
+
// Diferença vs disabled: cor normal do texto (não muted) + cursor `text` no input
|
|
655
|
+
// (sinaliza "você pode selecionar e copiar"), enquanto disabled = not-allowed.
|
|
656
|
+
matcha-form-field[readonly="true"] .matcha-form-field {
|
|
657
|
+
background: var(--matcha-color-surface-bg);
|
|
658
|
+
|
|
659
|
+
input, textarea {
|
|
660
|
+
cursor: text; // nativo do input — reforça que texto é selecionável
|
|
661
|
+
user-select: text; // explícito pra evitar reset acidental
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// Remove hover border change (não é editável, hover não deve sugerir edição)
|
|
665
|
+
&:hover { border-color: var(--matcha-color-surface-border); }
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// ── Touch targets (WCAG 2.5.5: 44x44 mínimo em coarse pointers) ─────────
|
|
669
|
+
// Expande hit area sem mudar visual (pseudo-element overlay).
|
|
670
|
+
@media (pointer: coarse) {
|
|
671
|
+
.matcha-password-toggle-button,
|
|
672
|
+
.matcha-quantity-stepper-button,
|
|
673
|
+
.matcha-clear-button,
|
|
674
|
+
matcha-date .matcha-date-picker-button,
|
|
675
|
+
matcha-time .matcha-time-picker-button,
|
|
676
|
+
matcha-field-range .matcha-field-range-button,
|
|
677
|
+
matcha-phone .matcha-phone-country {
|
|
678
|
+
position: relative;
|
|
679
|
+
|
|
680
|
+
&::before {
|
|
681
|
+
content: '';
|
|
682
|
+
position: absolute;
|
|
683
|
+
inset: -14px; // expande 14px em cada lado = 44x44 total (16 + 14*2)
|
|
684
|
+
// invisível, mas capturavel — só expande o hit area
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// ── Char counter (injetado via Renderer2 pelo matchaCharCounter directive) ──
|
|
690
|
+
// Figma matcha/field/textarea: body-sm 12/16, text-secondary, align right.
|
|
691
|
+
// Precisa ser global (sem ngcontent) porque o span vem de fora da view do form-field.
|
|
692
|
+
// IN-40430 (painel): a tipografia vale pra QUALQUER host do counter — quando o span
|
|
693
|
+
// caía fora do .matcha-form-field-wrapper (textarea/usos legados), ficava sem estilo
|
|
694
|
+
// e herdava fonte maior que o próprio texto do campo.
|
|
695
|
+
.matcha-char-counter {
|
|
696
|
+
font-family: var(--matcha-font-family);
|
|
697
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
698
|
+
font-weight: var(--matcha-weight-regular, 400);
|
|
699
|
+
line-height: var(--matcha-leading-body-sm, 16px);
|
|
700
|
+
color: var(--matcha-color-text-secondary);
|
|
701
|
+
text-align: right;
|
|
702
|
+
margin: 0;
|
|
703
|
+
padding: 0;
|
|
704
|
+
user-select: none;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
.matcha-form-field-wrapper > .matcha-char-counter {
|
|
708
|
+
align-self: flex-end;
|
|
709
|
+
transition: color var(--matcha-duration-fast, 200ms) ease;
|
|
710
|
+
|
|
711
|
+
// 3 níveis visuais (0-89% = neutro, 90-99% = warn, 100%+ = danger).
|
|
712
|
+
// `is-near-limit` é aplicado a partir de 90%; `is-at-limit` sobrepõe a partir de 100%.
|
|
713
|
+
&.is-near-limit:not(.is-at-limit) {
|
|
714
|
+
color: var(--matcha-color-warn);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
&.is-at-limit {
|
|
718
|
+
color: var(--matcha-color-danger);
|
|
719
|
+
font-weight: var(--matcha-weight-semibold, 600);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
// ── Caps Lock hint (injetado pelo matchaCapsLockHint em input[type="password"]) ──
|
|
724
|
+
// Renderiza abaixo do field, mesmo nível do char counter. Usa cor warn (amarelo/laranja)
|
|
725
|
+
// pra sinalizar risco sem ser erro (user pode estar digitando intencionalmente).
|
|
726
|
+
.matcha-form-field-wrapper > .matcha-caps-lock-hint {
|
|
727
|
+
display: inline-flex;
|
|
728
|
+
align-items: center;
|
|
729
|
+
gap: var(--matcha-space-050, 4px);
|
|
730
|
+
align-self: flex-start;
|
|
731
|
+
font-family: var(--matcha-font-family);
|
|
732
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
733
|
+
font-weight: var(--matcha-weight-regular, 400);
|
|
734
|
+
line-height: var(--matcha-leading-body-sm, 16px);
|
|
735
|
+
color: var(--matcha-color-warn);
|
|
736
|
+
margin-top: var(--matcha-space-050, 4px);
|
|
737
|
+
user-select: none;
|
|
738
|
+
|
|
739
|
+
> [class^="i-matcha-"] {
|
|
740
|
+
font-size: 14px;
|
|
741
|
+
line-height: 14px;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// ── Responsive size classes (aligned with Figma SM/MD/LG) ───────────────────
|
|
746
|
+
|
|
747
|
+
@mixin generate-matcha-form-field-size-classes($helper-breakpoints) {
|
|
748
|
+
@each $breakpoint, $materialBreakpoint in $helper-breakpoints {
|
|
749
|
+
@include media-breakpoint($materialBreakpoint) {
|
|
750
|
+
$infix: if($materialBreakpoint == null, "", "-#{$breakpoint}");
|
|
751
|
+
|
|
752
|
+
&[size#{$infix}="sm"],
|
|
753
|
+
&[size#{$infix}="tiny"],
|
|
754
|
+
&[size#{$infix}="small"] {
|
|
755
|
+
.matcha-form-field input,
|
|
756
|
+
.matcha-form-field textarea {
|
|
757
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
758
|
+
line-height: var(--matcha-leading-body-sm, 16px);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
&[size#{$infix}="md"],
|
|
763
|
+
&[size#{$infix}="medium"] {
|
|
764
|
+
.matcha-form-field input,
|
|
765
|
+
.matcha-form-field textarea {
|
|
766
|
+
font-size: var(--matcha-font-size-sm, 14px);
|
|
767
|
+
line-height: var(--matcha-leading-body-md, 20px);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
&[size#{$infix}="lg"],
|
|
772
|
+
&[size#{$infix}="large"],
|
|
773
|
+
&[size#{$infix}="huge"] {
|
|
774
|
+
.matcha-form-field input,
|
|
775
|
+
.matcha-form-field textarea {
|
|
776
|
+
font-size: var(--matcha-font-size-md, 16px);
|
|
777
|
+
line-height: var(--matcha-leading-body-lg, 24px);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
// ── Theme mixin ─────────────────────────────────────────────────────────────
|
|
785
|
+
|
|
786
|
+
@mixin matcha-form-field($theme) {
|
|
787
|
+
.matcha-form-field {
|
|
788
|
+
input[type="text"],
|
|
789
|
+
input[type="email"],
|
|
790
|
+
input[type="tel"],
|
|
791
|
+
input[type="url"],
|
|
792
|
+
input[type="password"],
|
|
793
|
+
input[type="number"],
|
|
794
|
+
input[type="search"],
|
|
795
|
+
input[type="date"],
|
|
796
|
+
input[type="time"],
|
|
797
|
+
textarea {
|
|
798
|
+
color: var(--matcha-color-text-primary);
|
|
799
|
+
|
|
800
|
+
&::placeholder {
|
|
801
|
+
color: var(--matcha-color-text-placeholder);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
input:disabled,
|
|
806
|
+
textarea:disabled {
|
|
807
|
+
color: var(--matcha-color-interaction-disabled-fg);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// Disabled: muted text, cursor not-allowed (sinalização inequívoca de "não pode interagir").
|
|
811
|
+
// `cursor: not-allowed` vai no wrapper; `pointer-events: none` fica só no input/textarea
|
|
812
|
+
// pra herdar o cursor do parent e não bloquear eventos no wrapper (senão cursor não aparece).
|
|
813
|
+
&.matcha-form-field-disabled {
|
|
814
|
+
cursor: not-allowed;
|
|
815
|
+
|
|
816
|
+
input, textarea {
|
|
817
|
+
pointer-events: none;
|
|
818
|
+
color: var(--matcha-color-interaction-disabled-fg);
|
|
819
|
+
|
|
820
|
+
&::placeholder {
|
|
821
|
+
color: var(--matcha-color-interaction-disabled-fg);
|
|
822
|
+
opacity: 0.7;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
matcha-form-field {
|
|
829
|
+
@include generate-matcha-form-field-size-classes($helper-breakpoints);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
// ── Forced colors ──
|
|
834
|
+
// Field precisa border + bg explícitos pra ser visível como input.
|
|
835
|
+
@media (forced-colors: active) {
|
|
836
|
+
matcha-form-field {
|
|
837
|
+
.matcha-field-control,
|
|
838
|
+
.matcha-form-field__control {
|
|
839
|
+
border: 1px solid CanvasText !important;
|
|
840
|
+
background: Canvas !important;
|
|
841
|
+
color: CanvasText !important;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// Estado focused
|
|
845
|
+
&.is-focused .matcha-field-control,
|
|
846
|
+
&.is-focused .matcha-form-field__control,
|
|
847
|
+
.matcha-field-control:focus-within,
|
|
848
|
+
.matcha-form-field__control:focus-within {
|
|
849
|
+
outline: 2px solid CanvasText !important;
|
|
850
|
+
outline-offset: 2px;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// Estado erro/invalid
|
|
854
|
+
&.is-invalid .matcha-field-control,
|
|
855
|
+
&.has-error .matcha-form-field__control {
|
|
856
|
+
border-color: CanvasText !important;
|
|
857
|
+
border-width: 2px !important;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
&[disabled],
|
|
861
|
+
&.is-disabled {
|
|
862
|
+
opacity: 0.5;
|
|
863
|
+
|
|
864
|
+
.matcha-field-control,
|
|
865
|
+
.matcha-form-field__control {
|
|
866
|
+
border-color: GrayText !important;
|
|
867
|
+
color: GrayText !important;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
// ── Print ──
|
|
874
|
+
// Form fields preservam estado (form values). Sem fundo decorativo.
|
|
875
|
+
@media print {
|
|
876
|
+
matcha-form-field {
|
|
877
|
+
.matcha-field-control,
|
|
878
|
+
.matcha-form-field__control {
|
|
879
|
+
border: 1px solid currentColor !important;
|
|
880
|
+
background: transparent !important;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
}
|