@inchurch/matcha-theme 22.40.0 → 22.40.1

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.
Files changed (93) hide show
  1. package/abstracts/_colors.scss +291 -291
  2. package/abstracts/_elevation.scss +108 -108
  3. package/abstracts/_functions.scss +321 -321
  4. package/abstracts/_media-breakpoint.scss +26 -26
  5. package/abstracts/_theme-api.scss +224 -224
  6. package/abstracts/_typography.scss +128 -128
  7. package/base/_reset.scss +487 -487
  8. package/components/app-page-header.scss +260 -260
  9. package/components/matcha-accordion.scss +297 -297
  10. package/components/matcha-audio-player.scss +31 -31
  11. package/components/matcha-autocomplete.scss +145 -145
  12. package/components/matcha-avatar.scss +426 -426
  13. package/components/matcha-badge.scss +120 -120
  14. package/components/matcha-breadcrumb.scss +231 -231
  15. package/components/matcha-button-toggle.scss +484 -484
  16. package/components/matcha-buttons.scss +973 -973
  17. package/components/matcha-calendar.scss +253 -253
  18. package/components/matcha-cards.scss +212 -212
  19. package/components/matcha-chart-card.scss +53 -53
  20. package/components/matcha-checkbox.scss +266 -266
  21. package/components/matcha-chip.scss +311 -311
  22. package/components/matcha-color-pick.scss +34 -34
  23. package/components/matcha-command-palette.scss +316 -316
  24. package/components/matcha-crop.scss +419 -419
  25. package/components/matcha-date.scss +81 -81
  26. package/components/matcha-divider.scss +100 -100
  27. package/components/matcha-draggable.scss +23 -23
  28. package/components/matcha-drawer.scss +376 -376
  29. package/components/matcha-drop-image.scss +14 -14
  30. package/components/matcha-drop-list.scss +430 -430
  31. package/components/matcha-emoji.scss +69 -69
  32. package/components/matcha-empty-state.scss +230 -230
  33. package/components/matcha-file-uploader.scss +650 -650
  34. package/components/matcha-flag.scss +103 -103
  35. package/components/matcha-footer.scss +91 -91
  36. package/components/matcha-form-field.scss +883 -883
  37. package/components/matcha-form-section.scss +100 -100
  38. package/components/matcha-header.scss +135 -135
  39. package/components/matcha-highlight.scss +164 -164
  40. package/components/matcha-hint-text.scss +90 -90
  41. package/components/matcha-horizontal-tree.scss +247 -247
  42. package/components/matcha-icon.scss +111 -111
  43. package/components/matcha-image.scss +60 -60
  44. package/components/matcha-list.scss +211 -211
  45. package/components/matcha-menu.scss +99 -99
  46. package/components/matcha-modal.scss +210 -210
  47. package/components/matcha-nav.scss +770 -770
  48. package/components/matcha-notification.scss +417 -417
  49. package/components/matcha-option.scss +170 -170
  50. package/components/matcha-page-builder.scss +4196 -4196
  51. package/components/matcha-paginator.scss +699 -699
  52. package/components/matcha-panel.scss +216 -216
  53. package/components/matcha-period.scss +174 -174
  54. package/components/matcha-profile-card.scss +50 -50
  55. package/components/matcha-progress-bar.scss +355 -355
  56. package/components/matcha-radio.scss +325 -325
  57. package/components/matcha-ripple.scss +7 -7
  58. package/components/matcha-scrollbar.scss +33 -33
  59. package/components/matcha-scrollbox-shadow.scss +120 -120
  60. package/components/matcha-section.scss +102 -102
  61. package/components/matcha-select-multiple.scss +56 -56
  62. package/components/matcha-select.scss +643 -629
  63. package/components/matcha-skeleton.scss +182 -182
  64. package/components/matcha-slide-toggle.scss +369 -369
  65. package/components/matcha-slider.scss +285 -285
  66. package/components/matcha-snack-bar.scss +259 -259
  67. package/components/matcha-spin.scss +164 -164
  68. package/components/matcha-spinner.scss +97 -97
  69. package/components/matcha-stepper.scss +376 -376
  70. package/components/matcha-table-cell.scss +107 -107
  71. package/components/matcha-table.scss +722 -722
  72. package/components/matcha-tabs.scss +642 -642
  73. package/components/matcha-text-editor.scss +111 -111
  74. package/components/matcha-time.scss +33 -33
  75. package/components/matcha-timepicker.scss +13 -13
  76. package/components/matcha-toolbar.scss +366 -366
  77. package/components/matcha-tooltip.scss +235 -235
  78. package/components/matcha-tree-view.scss +658 -658
  79. package/layout/matcha-page-layout.scss +778 -778
  80. package/main.scss +334 -334
  81. package/package.json +1 -1
  82. package/tokens/_animations-tokens.scss +37 -37
  83. package/tokens/_breakpoints-tokens.scss +35 -35
  84. package/tokens/_color-tokens.scss +288 -288
  85. package/tokens/_elevation-tokens.scss +33 -33
  86. package/tokens/_emit-tokens.scss +329 -329
  87. package/tokens/_material-palette.scss +1149 -1149
  88. package/tokens/_primitives.scss +98 -98
  89. package/tokens/_semantic-aliases.scss +120 -120
  90. package/tokens/_spacing-tokens.scss +94 -94
  91. package/tokens/_static-tokens.scss +137 -137
  92. package/tokens/_typography-tokens.scss +65 -65
  93. package/vendors/charts.scss +90 -90
@@ -1,770 +1,770 @@
1
- @use "sass:map";
2
-
3
- // =============================================================================
4
- // matcha-nav.scss — Navigation system (nav-item, nav-rail, nav-panel, command-palette)
5
- // =============================================================================
6
-
7
- // ── Nav Item ─────────────────────────────────────────────────────────────────
8
-
9
- // Host: wrapper estrutural. Não tem padding/bg — só layout column pra empilhar
10
- // row + children. Permite que o consumer aninhe nav-items sem quebrar o layout.
11
- .matcha-nav-item {
12
- position: relative;
13
- display: flex;
14
- flex-direction: column;
15
- align-items: stretch;
16
- width: 100%;
17
- text-decoration: none;
18
- color: inherit;
19
- user-select: none;
20
- // Reset pra <button>/<a> caso o host venha como esses elementos.
21
- appearance: none;
22
- border: 0;
23
- background: transparent;
24
- font: inherit;
25
- text-align: start;
26
- outline: none;
27
-
28
- &.matcha-nav-item--disabled {
29
- pointer-events: none;
30
- cursor: default;
31
-
32
- .matcha-nav-item__row {
33
- cursor: default;
34
- }
35
- }
36
-
37
- // Focus-visible no host (keyboard) → repassa pro __row (visual).
38
- &:focus-visible .matcha-nav-item__row {
39
- outline: var(--matcha-state-focus-ring-width, 2px) solid var(--matcha-color-accent);
40
- outline-offset: calc(-1 * var(--matcha-state-focus-ring-width, 2px));
41
- }
42
- }
43
-
44
- // Row: o "botão" visível do nav-item — Figma DSV3 1:1.
45
- // Expansível: pad 8/12, gap 8, radius md (4px), body-md (14/20 regular)
46
- // Indentado: pad 6/8/24, gap 8, radius sm (2px), body-sm (12/16 regular)
47
- // Ativo: bg accent/alpha + border-inline-start 3px accent + label medium 500
48
- // Hover: bg accent/surface-hover
49
- // Expandido: bg accent/surface-pressed
50
- //
51
- // box-sizing: border-box + border-inline-start: 3px solid accent (no Ativo)
52
- // gera shift de 3px no content (Padrão @12 → Ativo @15) — literal Figma.
53
- .matcha-nav-item__row {
54
- display: flex;
55
- flex-direction: row;
56
- align-items: center;
57
- gap: var(--matcha-space-100, 8px);
58
- padding-block: var(--matcha-space-100, 8px);
59
- padding-inline: var(--matcha-space-150, 12px);
60
- border-radius: var(--matcha-radius-md, 4px);
61
- border: 0;
62
- background: transparent;
63
- cursor: pointer;
64
- // O row é <a> quando o item tem [routerLink]/[href] — sem este reset a âncora
65
- // traz sublinhado e a cor de link do browser. As demais regras já eram agnósticas
66
- // de tag (border: 0, background: transparent atendiam o <button>).
67
- text-decoration: none;
68
- color: inherit;
69
- width: 100%;
70
- box-sizing: border-box;
71
- transition: background-color var(--matcha-duration-instant, 80ms) ease,
72
- border-color var(--matcha-duration-instant, 80ms) ease;
73
- }
74
-
75
- .matcha-nav-item__icon {
76
- flex-shrink: 0;
77
- width: 20px;
78
- height: 20px;
79
- }
80
-
81
- .matcha-nav-item__label {
82
- flex: 1;
83
- font-size: var(--matcha-text-body-md, 14px);
84
- font-weight: 400;
85
- line-height: 20px;
86
- overflow: hidden;
87
- text-overflow: ellipsis;
88
- white-space: nowrap;
89
- }
90
-
91
- // Badge — Figma DSV3 spec (matcha/badge variant Label/Danger):
92
- // padding 2/8, gap 4, radius pill (9999), bg feedback/danger, caption (11/14, letter 0.3).
93
- // Em Ativo, font-weight medium 500 (Figma).
94
- .matcha-nav-item__badge {
95
- flex-shrink: 0;
96
- display: inline-flex;
97
- align-items: center;
98
- justify-content: center;
99
- padding: var(--matcha-space-025, 2px) var(--matcha-space-100, 8px);
100
- gap: var(--matcha-space-050, 4px);
101
- border-radius: var(--matcha-radius-pill, 9999px);
102
- font-family: var(--matcha-font-family);
103
- font-size: var(--matcha-text-p-tiny, 11px);
104
- line-height: var(--matcha-leading-p-tiny, 14px);
105
- letter-spacing: var(--matcha-letter-spacing-caption, 0.3px);
106
- font-weight: 400;
107
- }
108
-
109
- // Contador de itens da seção (drawer header) — número discreto à direita do label.
110
- .matcha-nav-item__count {
111
- flex-shrink: 0;
112
- font-family: var(--matcha-font-family);
113
- font-size: 11px;
114
- font-weight: 600;
115
- line-height: 16px;
116
- letter-spacing: 0.4px;
117
- color: var(--matcha-color-text-secondary);
118
- opacity: 0.7;
119
- margin-left: auto;
120
- margin-right: 4px;
121
- }
122
-
123
- // Chevron — SVG matcha-icon variant=right (fixo). Rotaciona 90° via CSS quando
124
- // item está expandido. Easing-emphasized (Material 3 spring) pra rotação smooth.
125
- .matcha-nav-item__chevron {
126
- flex-shrink: 0;
127
- width: 16px;
128
- height: 16px;
129
- opacity: 0.5;
130
- transition: transform var(--matcha-duration-fast, 200ms) var(--matcha-easing-emphasized, cubic-bezier(0.2, 0, 0, 1));
131
- transform: rotate(0deg);
132
-
133
- .matcha-nav-item--expanded & {
134
- transform: rotate(90deg);
135
- }
136
- }
137
-
138
- // Indented variant (subitem) — Figma DSV3: só label, padding 6/8/24, radius sm.
139
- .matcha-nav-item--indented .matcha-nav-item__row {
140
- padding-block: var(--matcha-space-075, 6px);
141
- padding-inline: var(--matcha-space-300, 24px) var(--matcha-space-100, 8px);
142
- border-radius: var(--matcha-radius-sm, 2px);
143
-
144
- .matcha-nav-item__label {
145
- font-size: var(--matcha-text-body-sm, 12px);
146
- line-height: 16px;
147
- }
148
-
149
- // Esconde slots não-canônicos do indentado (Figma só permite label).
150
- .matcha-nav-item__icon,
151
- .matcha-nav-item__badge,
152
- .matcha-nav-item__chevron {
153
- display: none;
154
- }
155
- }
156
-
157
- // Children container (nav-items aninhados quando pai está expandido).
158
- // Flex column garante que filhos empilhem verticalmente, NÃO inline com o row.
159
- // Gap 4px igual ao items slot do panel — mantém rítmo visual consistente.
160
- // Margin-top 4px separa o primeiro filho do row do pai.
161
- //
162
- // Animation: fade + slight slide-down ao montar (cada vez que *ngIf entra).
163
- // Duration fast 200ms easing-emphasized — entra suave, não abrupto.
164
- .matcha-nav-item__children {
165
- display: flex;
166
- flex-direction: column;
167
- align-items: stretch;
168
- gap: var(--matcha-space-050, 4px);
169
- margin-top: var(--matcha-space-050, 4px);
170
- width: 100%;
171
- animation: matcha-nav-item-children-in
172
- var(--matcha-duration-fast, 200ms)
173
- var(--matcha-easing-emphasized, cubic-bezier(0.2, 0, 0, 1));
174
- }
175
-
176
- @keyframes matcha-nav-item-children-in {
177
- from { opacity: 0; transform: translateY(-4px); }
178
- to { opacity: 1; transform: translateY(0); }
179
- }
180
-
181
- // ── Nav Rail (72px sidebar — Figma DSV3 1:1 com matcha/nav-rail) ────────────
182
-
183
- .matcha-nav-rail {
184
- // Wrapper externo: 72px wide, full height.
185
- // Bg surface/bg (1 nível abaixo do panel) — cria depth tonal sutil sem
186
- // precisar de border ou shadow. Pattern canônico de DS modernos (Slack,
187
- // VS Code, Linear): rail "recuado" + panel "elevado". Hierarquia Z via tom.
188
- display: flex;
189
- flex-direction: column;
190
- align-items: center;
191
- width: 72px;
192
- height: 100%;
193
- flex-shrink: 0;
194
- box-sizing: border-box;
195
- overflow: hidden;
196
- padding: 0;
197
- }
198
-
199
- .matcha-nav-rail__header {
200
- // Figma: 72×56, padding 4/0, flex row center.
201
- display: flex;
202
- flex-direction: row;
203
- align-items: center;
204
- justify-content: center;
205
- width: 100%;
206
- height: var(--matcha-grid-header-height, 56px);
207
- padding: var(--matcha-space-050, 4px) 0;
208
- flex-shrink: 0;
209
- box-sizing: border-box;
210
- }
211
-
212
- .matcha-nav-rail__modules {
213
- // Figma: padding 12/0, gap 4, flex column center.
214
- display: flex;
215
- flex-direction: column;
216
- align-items: center;
217
- gap: var(--matcha-space-050, 4px);
218
- padding: var(--matcha-space-150, 12px) 0;
219
- flex: 1;
220
- width: 100%;
221
- box-sizing: border-box;
222
- overflow-y: auto;
223
- overflow-x: hidden;
224
-
225
- // Hide scrollbar but keep scroll
226
- scrollbar-width: none;
227
- &::-webkit-scrollbar { display: none; }
228
- }
229
-
230
- // Module button — Figma: 44×44 (touch target), radius 12, sem padding.
231
- // Suporta tanto o atributo de slot (consumer projeta com `matcha-nav-rail-module`)
232
- // quanto a classe BEM (caso consumer use `.matcha-nav-rail__module` diretamente).
233
- [matcha-nav-rail-module],
234
- .matcha-nav-rail__module {
235
- display: flex;
236
- align-items: center;
237
- justify-content: center;
238
- width: 44px;
239
- height: 44px;
240
- padding: 0;
241
- border: 0;
242
- background: transparent;
243
- border-radius: var(--matcha-radius-xl, 12px);
244
- cursor: pointer;
245
- flex-shrink: 0;
246
- position: relative;
247
- // Reset pra <button>
248
- appearance: none;
249
- font: inherit;
250
- color: inherit;
251
- transition: background-color var(--matcha-duration-instant, 80ms) ease,
252
- color var(--matcha-duration-instant, 80ms) ease;
253
-
254
- // Focus-visible — keyboard nav.
255
- &:focus-visible {
256
- outline: var(--matcha-state-focus-ring-width, 2px) solid var(--matcha-color-accent);
257
- outline-offset: var(--matcha-state-focus-ring-offset, 2px);
258
- }
259
-
260
- // Desabilitado — irmão do .matcha-nav-item--disabled (mesma dupla
261
- // pointer-events/cursor aqui; a cor fica no mixin de tema). Cobre as 3 formas:
262
- // o `disabled` nativo do <button>, o atributo em elemento que não é button
263
- // (o slot aceita <a>) e o aria-disabled de quem precisa manter o foco.
264
- // Sem isto, um módulo desabilitado renderiza IDÊNTICO ao habilitado e o
265
- // usuário clica sem entender por que nada acontece.
266
- &:disabled,
267
- &[disabled],
268
- &[aria-disabled="true"] {
269
- cursor: default;
270
- pointer-events: none;
271
- }
272
- }
273
-
274
- // ── Nav Rail labeled (84px — nome do módulo embaixo do ícone) ───────────────
275
- // Variante ativada por `<matcha-nav-rail labeled>`. O slot do label fica oculto
276
- // por padrão, então o consumer mantém o <span> no template e só alterna a flag.
277
- // Header fica de fora do resize: o hamburger não recebe label (56px fixos).
278
-
279
- .matcha-nav-rail [matcha-nav-rail-module-label],
280
- .matcha-nav-rail .matcha-nav-rail__module-label {
281
- display: none;
282
- }
283
-
284
- .matcha-nav-rail--labeled {
285
- width: 84px;
286
-
287
- .matcha-nav-rail__modules,
288
- .matcha-nav-rail__footer {
289
- [matcha-nav-rail-module],
290
- .matcha-nav-rail__module {
291
- flex-direction: column;
292
- gap: var(--matcha-space-050, 4px);
293
- width: 76px;
294
- height: auto;
295
- min-height: 64px;
296
- padding-block: var(--matcha-space-075, 6px);
297
- padding-inline: var(--matcha-space-050, 4px);
298
- }
299
-
300
- [matcha-nav-rail-module-label],
301
- .matcha-nav-rail__module-label {
302
- // -webkit-box + line-clamp: 2 linhas máx com ellipsis. Nome longo
303
- // ("Configurações") quebra em vez de estourar os 76px do botão.
304
- display: -webkit-box;
305
- -webkit-box-orient: vertical;
306
- -webkit-line-clamp: 2;
307
- overflow: hidden;
308
- max-width: 100%;
309
- font-family: var(--matcha-font-family);
310
- font-size: var(--matcha-text-2xs, 10px);
311
- line-height: var(--matcha-leading-p-tiny, 14px);
312
- letter-spacing: var(--matcha-letter-spacing-caption, 0.3px);
313
- font-weight: 400;
314
- text-align: center;
315
- overflow-wrap: break-word;
316
- }
317
- }
318
- }
319
-
320
- .matcha-nav-rail__footer {
321
- // Figma: padding 8/0, flex column center.
322
- display: flex;
323
- flex-direction: column;
324
- align-items: center;
325
- width: 100%;
326
- padding: var(--matcha-space-100, 8px) 0;
327
- flex-shrink: 0;
328
- box-sizing: border-box;
329
- }
330
-
331
- .matcha-nav-rail__divider {
332
- // Figma: 28×1, bg surface/border (rgba(255,255,255,0.12) dark).
333
- // Sem opacity extra — token já tem 12% built-in.
334
- flex-shrink: 0;
335
- width: 28px;
336
- height: 1px;
337
- }
338
-
339
- // ── Nav Panel (216px sub-panel — Figma DSV3 1:1 com matcha/nav-panel) ───────
340
- // Estrutura: header (title-row) → divider 192×1 → items slot.
341
- // Bg surface/card · só border-right (não border completa) · width 216 fixa.
342
-
343
- .matcha-nav-panel {
344
- display: flex;
345
- flex-direction: column;
346
- align-items: stretch;
347
- width: 216px;
348
- height: 100%;
349
- box-sizing: border-box;
350
- padding: 0;
351
- overflow: hidden;
352
- }
353
-
354
- // Header — Figma: padding 20/20/16/20, gap 16.
355
- // Logical properties pra suporte RTL automático.
356
- // Aceita slot custom via [matcha-nav-panel-header] OU default title-row.
357
- .matcha-nav-panel__header {
358
- display: flex;
359
- flex-direction: column;
360
- align-items: flex-start;
361
- gap: var(--matcha-space-200, 16px);
362
- padding-block-start: var(--matcha-space-250, 20px);
363
- padding-block-end: var(--matcha-space-200, 16px);
364
- padding-inline: var(--matcha-space-250, 20px);
365
- width: 100%;
366
- box-sizing: border-box;
367
- flex-shrink: 0;
368
-
369
- // Default title-row some quando consumer projeta slot custom
370
- // (priority pro custom, sem precisar de boolean prop).
371
- &:has([matcha-nav-panel-header]) .matcha-nav-panel__title-row--default {
372
- display: none;
373
- }
374
- }
375
-
376
- // Title row — Figma: padding 0, gap 8, body-md regular 14/20.
377
- .matcha-nav-panel__title-row {
378
- display: flex;
379
- flex-direction: row;
380
- align-items: center;
381
- gap: var(--matcha-space-100, 8px);
382
- width: 100%;
383
- height: 20px;
384
- min-width: 0;
385
- }
386
-
387
- .matcha-nav-panel__title-icon {
388
- flex-shrink: 0;
389
- width: 16px;
390
- height: 16px;
391
- }
392
-
393
- .matcha-nav-panel__title {
394
- flex: 1;
395
- font-family: var(--matcha-font-family);
396
- font-size: var(--matcha-text-body-md, 14px);
397
- font-weight: 400;
398
- line-height: 20px;
399
- overflow: hidden;
400
- text-overflow: ellipsis;
401
- white-space: nowrap;
402
- }
403
-
404
- // Divider — Figma: 192×1 (= 216 - 12 - 12 padding sides), sibling do header.
405
- // Centrado via margin auto.
406
- .matcha-nav-panel__divider {
407
- flex-shrink: 0;
408
- width: 192px;
409
- height: 1px;
410
- margin: 0 auto;
411
- }
412
-
413
- // Items slot — Figma: padding 12 (todos lados), gap 4, scroll vertical.
414
- .matcha-nav-panel__items {
415
- display: flex;
416
- flex-direction: column;
417
- align-items: stretch;
418
- gap: var(--matcha-space-050, 4px);
419
- padding: var(--matcha-space-150, 12px);
420
- flex: 1;
421
- width: 100%;
422
- box-sizing: border-box;
423
- overflow-y: auto;
424
- overflow-x: hidden;
425
-
426
- // Hide scrollbar mas mantém scroll funcional.
427
- scrollbar-width: thin;
428
- }
429
-
430
- // ── Command Palette ──────────────────────────────────────────────────────────
431
- // Estilos do command-palette movidos pra matcha-command-palette.scss (canônico).
432
- // Mantido aqui só o reduced-motion das outras nav classes.
433
-
434
- @media (prefers-reduced-motion: reduce) {
435
- .matcha-nav-item,
436
- .matcha-nav-rail__module {
437
- animation: none;
438
- transition: none;
439
- }
440
- }
441
-
442
- // ── Forced colors (Windows High Contrast) ──────────────────────────────────
443
- // Bgs translúcidos (accent-surface-hover, accent-alpha) somem em high-contrast.
444
- // Usa system colors (Highlight, SelectedItem, CanvasText) sempre visíveis.
445
- @media (forced-colors: active) {
446
- // ── Nav Item ──
447
- .matcha-nav-item {
448
- forced-color-adjust: none;
449
-
450
- &.matcha-nav-item--active > .matcha-nav-item__row {
451
- background: Highlight;
452
- color: HighlightText;
453
- border-inline-start: 3px solid Highlight;
454
- }
455
-
456
- &:not(.matcha-nav-item--disabled):not(.matcha-nav-item--active) > .matcha-nav-item__row:hover,
457
- &.matcha-nav-item--expanded:not(.matcha-nav-item--active) > .matcha-nav-item__row {
458
- background: SelectedItem;
459
- color: SelectedItemText;
460
- }
461
-
462
- &:focus-visible .matcha-nav-item__row {
463
- outline-color: CanvasText;
464
- }
465
- }
466
-
467
- // ── Nav Rail ──
468
- .matcha-nav-rail {
469
- border-inline-end-color: CanvasText;
470
- }
471
-
472
- [matcha-nav-rail-module]:hover:not([aria-current]):not(.matcha-nav-rail__module--active),
473
- .matcha-nav-rail__module:hover:not([aria-current]):not(.matcha-nav-rail__module--active) {
474
- background: SelectedItem;
475
- color: SelectedItemText;
476
- }
477
-
478
- [matcha-nav-rail-module][aria-current],
479
- [matcha-nav-rail-module].matcha-nav-rail__module--active,
480
- .matcha-nav-rail__module--active {
481
- background: Highlight;
482
- color: HighlightText;
483
-
484
- matcha-icon { color: HighlightText; }
485
- }
486
-
487
- .matcha-nav-rail__divider {
488
- background-color: CanvasText;
489
- }
490
-
491
- // ── Nav Panel ──
492
- .matcha-nav-panel {
493
- border-color: CanvasText;
494
- }
495
-
496
- .matcha-nav-panel__divider {
497
- background-color: CanvasText;
498
- }
499
-
500
- // ── Command Palette: high-contrast em matcha-command-palette.scss ──
501
- }
502
-
503
- // ── Nav Drawer ───────────────────────────────────────────────────────────────
504
- // Navegação em drawer (Figma DSV3 node 19228:2014) — a forma da navegação quando
505
- // não há espaço pro par rail + panel. Compõe matcha-drawer-container +
506
- // matcha-drawer mode=over; aqui só a anatomia e o ritmo da árvore.
507
-
508
- .matcha-nav-drawer {
509
- // Cobre a viewport pra ancorar o backdrop do container (que é absolute/inset:0).
510
- // Sem isso o scrim ficaria do tamanho do pai onde o drawer foi declarado.
511
- position: fixed;
512
- inset: 0;
513
- z-index: var(--matcha-nav-drawer-z, 1000);
514
- // Fechado não pode capturar clique da página que está por baixo.
515
- pointer-events: none;
516
-
517
- &.matcha-nav-drawer--opened {
518
- pointer-events: auto;
519
- }
520
-
521
- // Contained — ancora no ancestral posicionado em vez da viewport. Preview e
522
- // embed (playground da doc dentro de um frame de phone). Mesmo cenário que o
523
- // matcha-drawer já reconhece no max-height do bottom sheet.
524
- &.matcha-nav-drawer--contained {
525
- position: absolute;
526
- }
527
-
528
- // O container tem bg opaco próprio (é feito pra envolver a app). Aqui ele é só
529
- // âncora de posicionamento — opaco cobriria a página inteira mesmo fechado.
530
- .matcha-drawer-container {
531
- height: 100%;
532
- background-color: transparent;
533
- }
534
-
535
- // Ritmo dos slots: a navegação define o próprio (Figma), não o padding 20/20
536
- // genérico do drawer. As CSS vars existem pra isso — sem !important.
537
- matcha-drawer {
538
- --drawer-pad-x: var(--matcha-space-150, 12px);
539
- --drawer-pad-y: var(--matcha-space-150, 12px);
540
- }
541
-
542
- // Header — brand à esquerda, close à direita (space-between vem do slot).
543
- .matcha-nav-drawer__brand {
544
- display: flex;
545
- align-items: center;
546
- min-width: 0;
547
- gap: var(--matcha-space-100, 8px);
548
- }
549
-
550
- // Busca — largura total, logo abaixo do header e antes da árvore.
551
- .matcha-nav-drawer__search {
552
- display: block;
553
- width: 100%;
554
- flex-shrink: 0;
555
-
556
- > * {
557
- width: 100%;
558
- }
559
- }
560
-
561
- // Árvore de navegação.
562
- .matcha-nav-drawer__items {
563
- display: flex;
564
- flex-direction: column;
565
- align-items: stretch;
566
- gap: var(--matcha-space-050, 4px);
567
- width: 100%;
568
- }
569
-
570
- // Hierarquia de 3 níveis. O matcha-nav-item só tem UM flag de indentação
571
- // (`indented`), reservado ao nível 3 — que também é o único que o Figma
572
- // permite sem ícone/chevron. O recuo do nível 2 vem daqui, do container,
573
- // pra não sobrecarregar o contrato público do nav-item nem mexer no desktop.
574
- //
575
- // 24px = ícone (16) + gap (8) do row do módulo. Isso alinha o label do filho
576
- // com o label do pai, formando uma coluna de texto. Com menos que isso o filho
577
- // renderiza à ESQUERDA do label do pai (o pai tem ícone, o filho não) e a
578
- // hierarquia lê invertida. O nível 3 soma os 24 do `indented` por cima.
579
- .matcha-nav-drawer__items > .matcha-nav-item > .matcha-nav-item__children {
580
- padding-inline-start: var(--matcha-space-300, 24px);
581
- }
582
-
583
- // Footer — lista de itens empilhada. O slot do drawer é feito pra botões de
584
- // ação (row, alinhado à direita); a navegação precisa do oposto.
585
- .matcha-drawer__slot--footer > * {
586
- flex-direction: column;
587
- align-items: stretch;
588
- justify-content: flex-start;
589
- gap: var(--matcha-space-025, 2px);
590
- }
591
-
592
- .matcha-nav-drawer__footer {
593
- display: flex;
594
- flex-direction: column;
595
- align-items: stretch;
596
- gap: var(--matcha-space-025, 2px);
597
- width: 100%;
598
- }
599
-
600
- // O wrapper do slot existe sempre (é do template), então o :has() do drawer
601
- // não consegue esconder o footer vazio sozinho — a checagem real é esta.
602
- .matcha-drawer__slot--footer:not(:has(matcha-nav-drawer-footer)) {
603
- display: none;
604
- }
605
- }
606
-
607
- // ── Print ──────────────────────────────────────────────────────────────────
608
- // Convenção DS: chrome de navegação some em impressão — conteúdo full-page.
609
- @media print {
610
- .matcha-nav-rail,
611
- .matcha-nav-panel,
612
- .matcha-nav-drawer {
613
- display: none !important;
614
- }
615
- }
616
-
617
- // =============================================================================
618
- // Theme mixin
619
- // =============================================================================
620
-
621
- @mixin matcha-nav-theme($theme) {
622
- // ── Nav Item ── Figma DSV3 (node 14998:10045) — tokens accent diretos
623
- // Bg/border/etc aplicados no .matcha-nav-item__row (não no host) — assim
624
- // os filhos aninhados não herdam o bg do pai expandido/ativo.
625
- .matcha-nav-item {
626
- color: var(--matcha-color-text-primary);
627
-
628
- .matcha-nav-item__label {
629
- color: var(--matcha-color-text-primary);
630
- }
631
-
632
- .matcha-nav-item__icon,
633
- .matcha-nav-item__chevron {
634
- color: var(--matcha-color-text-secondary);
635
- }
636
-
637
- // Hover — bg accent/surface-hover direto (Figma usa este token, não state-layer).
638
- &:not(.matcha-nav-item--disabled):not(.matcha-nav-item--active) > .matcha-nav-item__row:hover {
639
- background-color: var(--matcha-color-accent-surface-hover);
640
- }
641
-
642
- // Ativo — bg accent/alpha + border-inline-start 3px accent + label medium.
643
- // 1:1 literal Figma. Aplicado no __row (não host) pra não vazar pros filhos.
644
- &.matcha-nav-item--active > .matcha-nav-item__row {
645
- background-color: var(--matcha-color-accent-alpha);
646
- border-inline-start: 3px solid var(--matcha-color-accent);
647
-
648
- .matcha-nav-item__label {
649
- font-weight: var(--matcha-weight-medium, 500);
650
- }
651
-
652
- .matcha-nav-item__badge {
653
- font-weight: var(--matcha-weight-medium, 500);
654
- color: var(--matcha-color-text-inverse, #1a1d21);
655
- }
656
- }
657
-
658
- // Expandido — pai com filhos abertos: bg accent/surface-pressed.
659
- &.matcha-nav-item--expanded:not(.matcha-nav-item--active) > .matcha-nav-item__row {
660
- background-color: var(--matcha-color-accent-surface-pressed);
661
- }
662
-
663
- // Badge — Figma DSV3 feedback/danger bg + danger-contrast fg (Padrão).
664
- .matcha-nav-item__badge {
665
- background: var(--matcha-color-feedback-danger);
666
- color: var(--matcha-color-feedback-danger-contrast, rgba(0, 0, 0, 0.87));
667
- }
668
-
669
- // Disabled — texto/ícone caem pra disabled-fg.
670
- &.matcha-nav-item--disabled {
671
- .matcha-nav-item__label,
672
- .matcha-nav-item__icon,
673
- .matcha-nav-item__chevron {
674
- color: var(--matcha-color-interaction-disabled-fg);
675
- }
676
- }
677
- }
678
-
679
- // Indented — placeholder pra futuras diferenças de tema (border já no base).
680
-
681
- // ── Nav Rail (depth sutil — light/dark adaptativo) ──
682
- // Bg = surface-bg (page layer) + 4% foreground overlay via color-mix.
683
- // Cria tonal step VISIBLE em ambos modes:
684
- // - Light: surface-bg #f1f4f1 + 4% fg #2a2d33 → ~#e8ebe7 (recesso vs page brighter)
685
- // - Dark: surface-bg #111318 + 4% fg #e8eaed → ~#1a1c20 (peak vs page darker)
686
- // Antes usava surface-card 85% transparente, que em light ficava imperceptível
687
- // (surface-card ≈ surface-bg no zona do branco — humano não distingue ~7 units).
688
- .matcha-nav-rail {
689
- background-color: color-mix(
690
- in srgb,
691
- var(--matcha-color-surface-bg) 96%,
692
- var(--matcha-color-fg) 4%
693
- );
694
- }
695
-
696
- [matcha-nav-rail-module],
697
- .matcha-nav-rail__module {
698
- // Inactive: text-secondary no button + override no matcha-icon filho
699
- // (matcha-icon tem regra global no theme com mesma especificidade,
700
- // então precisa target explícito pra vencer no cascade).
701
- color: var(--matcha-color-text-secondary);
702
-
703
- matcha-icon {
704
- color: var(--matcha-color-text-secondary);
705
- }
706
-
707
- // Hover (inactive): bg accent/surface-hover (state-layer canon Figma).
708
- &:hover:not(.matcha-nav-rail__module--active):not([aria-current]) {
709
- background-color: var(--matcha-color-accent-surface-hover);
710
- }
711
-
712
- // Active: bg accent/surface-hover + icon accent.
713
- // Figma usa #161E12 (accent/surface-hover token), não accent/alpha.
714
- // Aceita .--active class OU aria-current (pattern ARIA canônico).
715
- &.matcha-nav-rail__module--active,
716
- &[aria-current] {
717
- background-color: var(--matcha-color-accent-surface-hover);
718
- color: var(--matcha-color-accent);
719
-
720
- matcha-icon {
721
- color: var(--matcha-color-accent);
722
- }
723
-
724
- // Labeled: ícone E label sobem pra accent (color herdado) + label medium,
725
- // espelhando o nav-item ativo.
726
- [matcha-nav-rail-module-label],
727
- .matcha-nav-rail__module-label {
728
- font-weight: var(--matcha-weight-medium, 500);
729
- }
730
- }
731
-
732
- // Desabilitado — mesmo token de cor do nav-item disabled, pra os dois
733
- // estados lerem igual. Depois do bloco ativo de propósito: um módulo
734
- // desabilitado não deve ficar com a cor de ativo.
735
- &:disabled,
736
- &[disabled],
737
- &[aria-disabled="true"] {
738
- color: var(--matcha-color-interaction-disabled-fg);
739
-
740
- matcha-icon {
741
- color: var(--matcha-color-interaction-disabled-fg);
742
- }
743
- }
744
- }
745
-
746
- .matcha-nav-rail__divider {
747
- background-color: var(--matcha-color-surface-border);
748
- }
749
-
750
- // ── Nav Panel (Figma DSV3 1:1) ──
751
- // bg surface/card (1 step acima do rail). Sem shadow — só tonal hierarchy.
752
- .matcha-nav-panel {
753
- background-color: var(--matcha-color-surface-card);
754
- border-right: var(--matcha-border-hairline, 1px) solid var(--matcha-color-surface-border);
755
- }
756
-
757
- .matcha-nav-panel__divider {
758
- background-color: var(--matcha-color-surface-border);
759
- }
760
-
761
- .matcha-nav-panel__title {
762
- color: var(--matcha-color-text-primary);
763
- }
764
-
765
- .matcha-nav-panel__title-icon {
766
- color: var(--matcha-color-text-secondary);
767
- }
768
-
769
- // ── Command Palette theme em matcha-command-palette.scss (canônico) ──
770
- }
1
+ @use "sass:map";
2
+
3
+ // =============================================================================
4
+ // matcha-nav.scss — Navigation system (nav-item, nav-rail, nav-panel, command-palette)
5
+ // =============================================================================
6
+
7
+ // ── Nav Item ─────────────────────────────────────────────────────────────────
8
+
9
+ // Host: wrapper estrutural. Não tem padding/bg — só layout column pra empilhar
10
+ // row + children. Permite que o consumer aninhe nav-items sem quebrar o layout.
11
+ .matcha-nav-item {
12
+ position: relative;
13
+ display: flex;
14
+ flex-direction: column;
15
+ align-items: stretch;
16
+ width: 100%;
17
+ text-decoration: none;
18
+ color: inherit;
19
+ user-select: none;
20
+ // Reset pra <button>/<a> caso o host venha como esses elementos.
21
+ appearance: none;
22
+ border: 0;
23
+ background: transparent;
24
+ font: inherit;
25
+ text-align: start;
26
+ outline: none;
27
+
28
+ &.matcha-nav-item--disabled {
29
+ pointer-events: none;
30
+ cursor: default;
31
+
32
+ .matcha-nav-item__row {
33
+ cursor: default;
34
+ }
35
+ }
36
+
37
+ // Focus-visible no host (keyboard) → repassa pro __row (visual).
38
+ &:focus-visible .matcha-nav-item__row {
39
+ outline: var(--matcha-state-focus-ring-width, 2px) solid var(--matcha-color-accent);
40
+ outline-offset: calc(-1 * var(--matcha-state-focus-ring-width, 2px));
41
+ }
42
+ }
43
+
44
+ // Row: o "botão" visível do nav-item — Figma DSV3 1:1.
45
+ // Expansível: pad 8/12, gap 8, radius md (4px), body-md (14/20 regular)
46
+ // Indentado: pad 6/8/24, gap 8, radius sm (2px), body-sm (12/16 regular)
47
+ // Ativo: bg accent/alpha + border-inline-start 3px accent + label medium 500
48
+ // Hover: bg accent/surface-hover
49
+ // Expandido: bg accent/surface-pressed
50
+ //
51
+ // box-sizing: border-box + border-inline-start: 3px solid accent (no Ativo)
52
+ // gera shift de 3px no content (Padrão @12 → Ativo @15) — literal Figma.
53
+ .matcha-nav-item__row {
54
+ display: flex;
55
+ flex-direction: row;
56
+ align-items: center;
57
+ gap: var(--matcha-space-100, 8px);
58
+ padding-block: var(--matcha-space-100, 8px);
59
+ padding-inline: var(--matcha-space-150, 12px);
60
+ border-radius: var(--matcha-radius-md, 4px);
61
+ border: 0;
62
+ background: transparent;
63
+ cursor: pointer;
64
+ // O row é <a> quando o item tem [routerLink]/[href] — sem este reset a âncora
65
+ // traz sublinhado e a cor de link do browser. As demais regras já eram agnósticas
66
+ // de tag (border: 0, background: transparent atendiam o <button>).
67
+ text-decoration: none;
68
+ color: inherit;
69
+ width: 100%;
70
+ box-sizing: border-box;
71
+ transition: background-color var(--matcha-duration-instant, 80ms) ease,
72
+ border-color var(--matcha-duration-instant, 80ms) ease;
73
+ }
74
+
75
+ .matcha-nav-item__icon {
76
+ flex-shrink: 0;
77
+ width: 20px;
78
+ height: 20px;
79
+ }
80
+
81
+ .matcha-nav-item__label {
82
+ flex: 1;
83
+ font-size: var(--matcha-text-body-md, 14px);
84
+ font-weight: 400;
85
+ line-height: 20px;
86
+ overflow: hidden;
87
+ text-overflow: ellipsis;
88
+ white-space: nowrap;
89
+ }
90
+
91
+ // Badge — Figma DSV3 spec (matcha/badge variant Label/Danger):
92
+ // padding 2/8, gap 4, radius pill (9999), bg feedback/danger, caption (11/14, letter 0.3).
93
+ // Em Ativo, font-weight medium 500 (Figma).
94
+ .matcha-nav-item__badge {
95
+ flex-shrink: 0;
96
+ display: inline-flex;
97
+ align-items: center;
98
+ justify-content: center;
99
+ padding: var(--matcha-space-025, 2px) var(--matcha-space-100, 8px);
100
+ gap: var(--matcha-space-050, 4px);
101
+ border-radius: var(--matcha-radius-pill, 9999px);
102
+ font-family: var(--matcha-font-family);
103
+ font-size: var(--matcha-text-p-tiny, 11px);
104
+ line-height: var(--matcha-leading-p-tiny, 14px);
105
+ letter-spacing: var(--matcha-letter-spacing-caption, 0.3px);
106
+ font-weight: 400;
107
+ }
108
+
109
+ // Contador de itens da seção (drawer header) — número discreto à direita do label.
110
+ .matcha-nav-item__count {
111
+ flex-shrink: 0;
112
+ font-family: var(--matcha-font-family);
113
+ font-size: 11px;
114
+ font-weight: 600;
115
+ line-height: 16px;
116
+ letter-spacing: 0.4px;
117
+ color: var(--matcha-color-text-secondary);
118
+ opacity: 0.7;
119
+ margin-left: auto;
120
+ margin-right: 4px;
121
+ }
122
+
123
+ // Chevron — SVG matcha-icon variant=right (fixo). Rotaciona 90° via CSS quando
124
+ // item está expandido. Easing-emphasized (Material 3 spring) pra rotação smooth.
125
+ .matcha-nav-item__chevron {
126
+ flex-shrink: 0;
127
+ width: 16px;
128
+ height: 16px;
129
+ opacity: 0.5;
130
+ transition: transform var(--matcha-duration-fast, 200ms) var(--matcha-easing-emphasized, cubic-bezier(0.2, 0, 0, 1));
131
+ transform: rotate(0deg);
132
+
133
+ .matcha-nav-item--expanded & {
134
+ transform: rotate(90deg);
135
+ }
136
+ }
137
+
138
+ // Indented variant (subitem) — Figma DSV3: só label, padding 6/8/24, radius sm.
139
+ .matcha-nav-item--indented .matcha-nav-item__row {
140
+ padding-block: var(--matcha-space-075, 6px);
141
+ padding-inline: var(--matcha-space-300, 24px) var(--matcha-space-100, 8px);
142
+ border-radius: var(--matcha-radius-sm, 2px);
143
+
144
+ .matcha-nav-item__label {
145
+ font-size: var(--matcha-text-body-sm, 12px);
146
+ line-height: 16px;
147
+ }
148
+
149
+ // Esconde slots não-canônicos do indentado (Figma só permite label).
150
+ .matcha-nav-item__icon,
151
+ .matcha-nav-item__badge,
152
+ .matcha-nav-item__chevron {
153
+ display: none;
154
+ }
155
+ }
156
+
157
+ // Children container (nav-items aninhados quando pai está expandido).
158
+ // Flex column garante que filhos empilhem verticalmente, NÃO inline com o row.
159
+ // Gap 4px igual ao items slot do panel — mantém rítmo visual consistente.
160
+ // Margin-top 4px separa o primeiro filho do row do pai.
161
+ //
162
+ // Animation: fade + slight slide-down ao montar (cada vez que *ngIf entra).
163
+ // Duration fast 200ms easing-emphasized — entra suave, não abrupto.
164
+ .matcha-nav-item__children {
165
+ display: flex;
166
+ flex-direction: column;
167
+ align-items: stretch;
168
+ gap: var(--matcha-space-050, 4px);
169
+ margin-top: var(--matcha-space-050, 4px);
170
+ width: 100%;
171
+ animation: matcha-nav-item-children-in
172
+ var(--matcha-duration-fast, 200ms)
173
+ var(--matcha-easing-emphasized, cubic-bezier(0.2, 0, 0, 1));
174
+ }
175
+
176
+ @keyframes matcha-nav-item-children-in {
177
+ from { opacity: 0; transform: translateY(-4px); }
178
+ to { opacity: 1; transform: translateY(0); }
179
+ }
180
+
181
+ // ── Nav Rail (72px sidebar — Figma DSV3 1:1 com matcha/nav-rail) ────────────
182
+
183
+ .matcha-nav-rail {
184
+ // Wrapper externo: 72px wide, full height.
185
+ // Bg surface/bg (1 nível abaixo do panel) — cria depth tonal sutil sem
186
+ // precisar de border ou shadow. Pattern canônico de DS modernos (Slack,
187
+ // VS Code, Linear): rail "recuado" + panel "elevado". Hierarquia Z via tom.
188
+ display: flex;
189
+ flex-direction: column;
190
+ align-items: center;
191
+ width: 72px;
192
+ height: 100%;
193
+ flex-shrink: 0;
194
+ box-sizing: border-box;
195
+ overflow: hidden;
196
+ padding: 0;
197
+ }
198
+
199
+ .matcha-nav-rail__header {
200
+ // Figma: 72×56, padding 4/0, flex row center.
201
+ display: flex;
202
+ flex-direction: row;
203
+ align-items: center;
204
+ justify-content: center;
205
+ width: 100%;
206
+ height: var(--matcha-grid-header-height, 56px);
207
+ padding: var(--matcha-space-050, 4px) 0;
208
+ flex-shrink: 0;
209
+ box-sizing: border-box;
210
+ }
211
+
212
+ .matcha-nav-rail__modules {
213
+ // Figma: padding 12/0, gap 4, flex column center.
214
+ display: flex;
215
+ flex-direction: column;
216
+ align-items: center;
217
+ gap: var(--matcha-space-050, 4px);
218
+ padding: var(--matcha-space-150, 12px) 0;
219
+ flex: 1;
220
+ width: 100%;
221
+ box-sizing: border-box;
222
+ overflow-y: auto;
223
+ overflow-x: hidden;
224
+
225
+ // Hide scrollbar but keep scroll
226
+ scrollbar-width: none;
227
+ &::-webkit-scrollbar { display: none; }
228
+ }
229
+
230
+ // Module button — Figma: 44×44 (touch target), radius 12, sem padding.
231
+ // Suporta tanto o atributo de slot (consumer projeta com `matcha-nav-rail-module`)
232
+ // quanto a classe BEM (caso consumer use `.matcha-nav-rail__module` diretamente).
233
+ [matcha-nav-rail-module],
234
+ .matcha-nav-rail__module {
235
+ display: flex;
236
+ align-items: center;
237
+ justify-content: center;
238
+ width: 44px;
239
+ height: 44px;
240
+ padding: 0;
241
+ border: 0;
242
+ background: transparent;
243
+ border-radius: var(--matcha-radius-xl, 12px);
244
+ cursor: pointer;
245
+ flex-shrink: 0;
246
+ position: relative;
247
+ // Reset pra <button>
248
+ appearance: none;
249
+ font: inherit;
250
+ color: inherit;
251
+ transition: background-color var(--matcha-duration-instant, 80ms) ease,
252
+ color var(--matcha-duration-instant, 80ms) ease;
253
+
254
+ // Focus-visible — keyboard nav.
255
+ &:focus-visible {
256
+ outline: var(--matcha-state-focus-ring-width, 2px) solid var(--matcha-color-accent);
257
+ outline-offset: var(--matcha-state-focus-ring-offset, 2px);
258
+ }
259
+
260
+ // Desabilitado — irmão do .matcha-nav-item--disabled (mesma dupla
261
+ // pointer-events/cursor aqui; a cor fica no mixin de tema). Cobre as 3 formas:
262
+ // o `disabled` nativo do <button>, o atributo em elemento que não é button
263
+ // (o slot aceita <a>) e o aria-disabled de quem precisa manter o foco.
264
+ // Sem isto, um módulo desabilitado renderiza IDÊNTICO ao habilitado e o
265
+ // usuário clica sem entender por que nada acontece.
266
+ &:disabled,
267
+ &[disabled],
268
+ &[aria-disabled="true"] {
269
+ cursor: default;
270
+ pointer-events: none;
271
+ }
272
+ }
273
+
274
+ // ── Nav Rail labeled (84px — nome do módulo embaixo do ícone) ───────────────
275
+ // Variante ativada por `<matcha-nav-rail labeled>`. O slot do label fica oculto
276
+ // por padrão, então o consumer mantém o <span> no template e só alterna a flag.
277
+ // Header fica de fora do resize: o hamburger não recebe label (56px fixos).
278
+
279
+ .matcha-nav-rail [matcha-nav-rail-module-label],
280
+ .matcha-nav-rail .matcha-nav-rail__module-label {
281
+ display: none;
282
+ }
283
+
284
+ .matcha-nav-rail--labeled {
285
+ width: 84px;
286
+
287
+ .matcha-nav-rail__modules,
288
+ .matcha-nav-rail__footer {
289
+ [matcha-nav-rail-module],
290
+ .matcha-nav-rail__module {
291
+ flex-direction: column;
292
+ gap: var(--matcha-space-050, 4px);
293
+ width: 76px;
294
+ height: auto;
295
+ min-height: 64px;
296
+ padding-block: var(--matcha-space-075, 6px);
297
+ padding-inline: var(--matcha-space-050, 4px);
298
+ }
299
+
300
+ [matcha-nav-rail-module-label],
301
+ .matcha-nav-rail__module-label {
302
+ // -webkit-box + line-clamp: 2 linhas máx com ellipsis. Nome longo
303
+ // ("Configurações") quebra em vez de estourar os 76px do botão.
304
+ display: -webkit-box;
305
+ -webkit-box-orient: vertical;
306
+ -webkit-line-clamp: 2;
307
+ overflow: hidden;
308
+ max-width: 100%;
309
+ font-family: var(--matcha-font-family);
310
+ font-size: var(--matcha-text-2xs, 10px);
311
+ line-height: var(--matcha-leading-p-tiny, 14px);
312
+ letter-spacing: var(--matcha-letter-spacing-caption, 0.3px);
313
+ font-weight: 400;
314
+ text-align: center;
315
+ overflow-wrap: break-word;
316
+ }
317
+ }
318
+ }
319
+
320
+ .matcha-nav-rail__footer {
321
+ // Figma: padding 8/0, flex column center.
322
+ display: flex;
323
+ flex-direction: column;
324
+ align-items: center;
325
+ width: 100%;
326
+ padding: var(--matcha-space-100, 8px) 0;
327
+ flex-shrink: 0;
328
+ box-sizing: border-box;
329
+ }
330
+
331
+ .matcha-nav-rail__divider {
332
+ // Figma: 28×1, bg surface/border (rgba(255,255,255,0.12) dark).
333
+ // Sem opacity extra — token já tem 12% built-in.
334
+ flex-shrink: 0;
335
+ width: 28px;
336
+ height: 1px;
337
+ }
338
+
339
+ // ── Nav Panel (216px sub-panel — Figma DSV3 1:1 com matcha/nav-panel) ───────
340
+ // Estrutura: header (title-row) → divider 192×1 → items slot.
341
+ // Bg surface/card · só border-right (não border completa) · width 216 fixa.
342
+
343
+ .matcha-nav-panel {
344
+ display: flex;
345
+ flex-direction: column;
346
+ align-items: stretch;
347
+ width: 216px;
348
+ height: 100%;
349
+ box-sizing: border-box;
350
+ padding: 0;
351
+ overflow: hidden;
352
+ }
353
+
354
+ // Header — Figma: padding 20/20/16/20, gap 16.
355
+ // Logical properties pra suporte RTL automático.
356
+ // Aceita slot custom via [matcha-nav-panel-header] OU default title-row.
357
+ .matcha-nav-panel__header {
358
+ display: flex;
359
+ flex-direction: column;
360
+ align-items: flex-start;
361
+ gap: var(--matcha-space-200, 16px);
362
+ padding-block-start: var(--matcha-space-250, 20px);
363
+ padding-block-end: var(--matcha-space-200, 16px);
364
+ padding-inline: var(--matcha-space-250, 20px);
365
+ width: 100%;
366
+ box-sizing: border-box;
367
+ flex-shrink: 0;
368
+
369
+ // Default title-row some quando consumer projeta slot custom
370
+ // (priority pro custom, sem precisar de boolean prop).
371
+ &:has([matcha-nav-panel-header]) .matcha-nav-panel__title-row--default {
372
+ display: none;
373
+ }
374
+ }
375
+
376
+ // Title row — Figma: padding 0, gap 8, body-md regular 14/20.
377
+ .matcha-nav-panel__title-row {
378
+ display: flex;
379
+ flex-direction: row;
380
+ align-items: center;
381
+ gap: var(--matcha-space-100, 8px);
382
+ width: 100%;
383
+ height: 20px;
384
+ min-width: 0;
385
+ }
386
+
387
+ .matcha-nav-panel__title-icon {
388
+ flex-shrink: 0;
389
+ width: 16px;
390
+ height: 16px;
391
+ }
392
+
393
+ .matcha-nav-panel__title {
394
+ flex: 1;
395
+ font-family: var(--matcha-font-family);
396
+ font-size: var(--matcha-text-body-md, 14px);
397
+ font-weight: 400;
398
+ line-height: 20px;
399
+ overflow: hidden;
400
+ text-overflow: ellipsis;
401
+ white-space: nowrap;
402
+ }
403
+
404
+ // Divider — Figma: 192×1 (= 216 - 12 - 12 padding sides), sibling do header.
405
+ // Centrado via margin auto.
406
+ .matcha-nav-panel__divider {
407
+ flex-shrink: 0;
408
+ width: 192px;
409
+ height: 1px;
410
+ margin: 0 auto;
411
+ }
412
+
413
+ // Items slot — Figma: padding 12 (todos lados), gap 4, scroll vertical.
414
+ .matcha-nav-panel__items {
415
+ display: flex;
416
+ flex-direction: column;
417
+ align-items: stretch;
418
+ gap: var(--matcha-space-050, 4px);
419
+ padding: var(--matcha-space-150, 12px);
420
+ flex: 1;
421
+ width: 100%;
422
+ box-sizing: border-box;
423
+ overflow-y: auto;
424
+ overflow-x: hidden;
425
+
426
+ // Hide scrollbar mas mantém scroll funcional.
427
+ scrollbar-width: thin;
428
+ }
429
+
430
+ // ── Command Palette ──────────────────────────────────────────────────────────
431
+ // Estilos do command-palette movidos pra matcha-command-palette.scss (canônico).
432
+ // Mantido aqui só o reduced-motion das outras nav classes.
433
+
434
+ @media (prefers-reduced-motion: reduce) {
435
+ .matcha-nav-item,
436
+ .matcha-nav-rail__module {
437
+ animation: none;
438
+ transition: none;
439
+ }
440
+ }
441
+
442
+ // ── Forced colors (Windows High Contrast) ──────────────────────────────────
443
+ // Bgs translúcidos (accent-surface-hover, accent-alpha) somem em high-contrast.
444
+ // Usa system colors (Highlight, SelectedItem, CanvasText) sempre visíveis.
445
+ @media (forced-colors: active) {
446
+ // ── Nav Item ──
447
+ .matcha-nav-item {
448
+ forced-color-adjust: none;
449
+
450
+ &.matcha-nav-item--active > .matcha-nav-item__row {
451
+ background: Highlight;
452
+ color: HighlightText;
453
+ border-inline-start: 3px solid Highlight;
454
+ }
455
+
456
+ &:not(.matcha-nav-item--disabled):not(.matcha-nav-item--active) > .matcha-nav-item__row:hover,
457
+ &.matcha-nav-item--expanded:not(.matcha-nav-item--active) > .matcha-nav-item__row {
458
+ background: SelectedItem;
459
+ color: SelectedItemText;
460
+ }
461
+
462
+ &:focus-visible .matcha-nav-item__row {
463
+ outline-color: CanvasText;
464
+ }
465
+ }
466
+
467
+ // ── Nav Rail ──
468
+ .matcha-nav-rail {
469
+ border-inline-end-color: CanvasText;
470
+ }
471
+
472
+ [matcha-nav-rail-module]:hover:not([aria-current]):not(.matcha-nav-rail__module--active),
473
+ .matcha-nav-rail__module:hover:not([aria-current]):not(.matcha-nav-rail__module--active) {
474
+ background: SelectedItem;
475
+ color: SelectedItemText;
476
+ }
477
+
478
+ [matcha-nav-rail-module][aria-current],
479
+ [matcha-nav-rail-module].matcha-nav-rail__module--active,
480
+ .matcha-nav-rail__module--active {
481
+ background: Highlight;
482
+ color: HighlightText;
483
+
484
+ matcha-icon { color: HighlightText; }
485
+ }
486
+
487
+ .matcha-nav-rail__divider {
488
+ background-color: CanvasText;
489
+ }
490
+
491
+ // ── Nav Panel ──
492
+ .matcha-nav-panel {
493
+ border-color: CanvasText;
494
+ }
495
+
496
+ .matcha-nav-panel__divider {
497
+ background-color: CanvasText;
498
+ }
499
+
500
+ // ── Command Palette: high-contrast em matcha-command-palette.scss ──
501
+ }
502
+
503
+ // ── Nav Drawer ───────────────────────────────────────────────────────────────
504
+ // Navegação em drawer (Figma DSV3 node 19228:2014) — a forma da navegação quando
505
+ // não há espaço pro par rail + panel. Compõe matcha-drawer-container +
506
+ // matcha-drawer mode=over; aqui só a anatomia e o ritmo da árvore.
507
+
508
+ .matcha-nav-drawer {
509
+ // Cobre a viewport pra ancorar o backdrop do container (que é absolute/inset:0).
510
+ // Sem isso o scrim ficaria do tamanho do pai onde o drawer foi declarado.
511
+ position: fixed;
512
+ inset: 0;
513
+ z-index: var(--matcha-nav-drawer-z, 1000);
514
+ // Fechado não pode capturar clique da página que está por baixo.
515
+ pointer-events: none;
516
+
517
+ &.matcha-nav-drawer--opened {
518
+ pointer-events: auto;
519
+ }
520
+
521
+ // Contained — ancora no ancestral posicionado em vez da viewport. Preview e
522
+ // embed (playground da doc dentro de um frame de phone). Mesmo cenário que o
523
+ // matcha-drawer já reconhece no max-height do bottom sheet.
524
+ &.matcha-nav-drawer--contained {
525
+ position: absolute;
526
+ }
527
+
528
+ // O container tem bg opaco próprio (é feito pra envolver a app). Aqui ele é só
529
+ // âncora de posicionamento — opaco cobriria a página inteira mesmo fechado.
530
+ .matcha-drawer-container {
531
+ height: 100%;
532
+ background-color: transparent;
533
+ }
534
+
535
+ // Ritmo dos slots: a navegação define o próprio (Figma), não o padding 20/20
536
+ // genérico do drawer. As CSS vars existem pra isso — sem !important.
537
+ matcha-drawer {
538
+ --drawer-pad-x: var(--matcha-space-150, 12px);
539
+ --drawer-pad-y: var(--matcha-space-150, 12px);
540
+ }
541
+
542
+ // Header — brand à esquerda, close à direita (space-between vem do slot).
543
+ .matcha-nav-drawer__brand {
544
+ display: flex;
545
+ align-items: center;
546
+ min-width: 0;
547
+ gap: var(--matcha-space-100, 8px);
548
+ }
549
+
550
+ // Busca — largura total, logo abaixo do header e antes da árvore.
551
+ .matcha-nav-drawer__search {
552
+ display: block;
553
+ width: 100%;
554
+ flex-shrink: 0;
555
+
556
+ > * {
557
+ width: 100%;
558
+ }
559
+ }
560
+
561
+ // Árvore de navegação.
562
+ .matcha-nav-drawer__items {
563
+ display: flex;
564
+ flex-direction: column;
565
+ align-items: stretch;
566
+ gap: var(--matcha-space-050, 4px);
567
+ width: 100%;
568
+ }
569
+
570
+ // Hierarquia de 3 níveis. O matcha-nav-item só tem UM flag de indentação
571
+ // (`indented`), reservado ao nível 3 — que também é o único que o Figma
572
+ // permite sem ícone/chevron. O recuo do nível 2 vem daqui, do container,
573
+ // pra não sobrecarregar o contrato público do nav-item nem mexer no desktop.
574
+ //
575
+ // 24px = ícone (16) + gap (8) do row do módulo. Isso alinha o label do filho
576
+ // com o label do pai, formando uma coluna de texto. Com menos que isso o filho
577
+ // renderiza à ESQUERDA do label do pai (o pai tem ícone, o filho não) e a
578
+ // hierarquia lê invertida. O nível 3 soma os 24 do `indented` por cima.
579
+ .matcha-nav-drawer__items > .matcha-nav-item > .matcha-nav-item__children {
580
+ padding-inline-start: var(--matcha-space-300, 24px);
581
+ }
582
+
583
+ // Footer — lista de itens empilhada. O slot do drawer é feito pra botões de
584
+ // ação (row, alinhado à direita); a navegação precisa do oposto.
585
+ .matcha-drawer__slot--footer > * {
586
+ flex-direction: column;
587
+ align-items: stretch;
588
+ justify-content: flex-start;
589
+ gap: var(--matcha-space-025, 2px);
590
+ }
591
+
592
+ .matcha-nav-drawer__footer {
593
+ display: flex;
594
+ flex-direction: column;
595
+ align-items: stretch;
596
+ gap: var(--matcha-space-025, 2px);
597
+ width: 100%;
598
+ }
599
+
600
+ // O wrapper do slot existe sempre (é do template), então o :has() do drawer
601
+ // não consegue esconder o footer vazio sozinho — a checagem real é esta.
602
+ .matcha-drawer__slot--footer:not(:has(matcha-nav-drawer-footer)) {
603
+ display: none;
604
+ }
605
+ }
606
+
607
+ // ── Print ──────────────────────────────────────────────────────────────────
608
+ // Convenção DS: chrome de navegação some em impressão — conteúdo full-page.
609
+ @media print {
610
+ .matcha-nav-rail,
611
+ .matcha-nav-panel,
612
+ .matcha-nav-drawer {
613
+ display: none !important;
614
+ }
615
+ }
616
+
617
+ // =============================================================================
618
+ // Theme mixin
619
+ // =============================================================================
620
+
621
+ @mixin matcha-nav-theme($theme) {
622
+ // ── Nav Item ── Figma DSV3 (node 14998:10045) — tokens accent diretos
623
+ // Bg/border/etc aplicados no .matcha-nav-item__row (não no host) — assim
624
+ // os filhos aninhados não herdam o bg do pai expandido/ativo.
625
+ .matcha-nav-item {
626
+ color: var(--matcha-color-text-primary);
627
+
628
+ .matcha-nav-item__label {
629
+ color: var(--matcha-color-text-primary);
630
+ }
631
+
632
+ .matcha-nav-item__icon,
633
+ .matcha-nav-item__chevron {
634
+ color: var(--matcha-color-text-secondary);
635
+ }
636
+
637
+ // Hover — bg accent/surface-hover direto (Figma usa este token, não state-layer).
638
+ &:not(.matcha-nav-item--disabled):not(.matcha-nav-item--active) > .matcha-nav-item__row:hover {
639
+ background-color: var(--matcha-color-accent-surface-hover);
640
+ }
641
+
642
+ // Ativo — bg accent/alpha + border-inline-start 3px accent + label medium.
643
+ // 1:1 literal Figma. Aplicado no __row (não host) pra não vazar pros filhos.
644
+ &.matcha-nav-item--active > .matcha-nav-item__row {
645
+ background-color: var(--matcha-color-accent-alpha);
646
+ border-inline-start: 3px solid var(--matcha-color-accent);
647
+
648
+ .matcha-nav-item__label {
649
+ font-weight: var(--matcha-weight-medium, 500);
650
+ }
651
+
652
+ .matcha-nav-item__badge {
653
+ font-weight: var(--matcha-weight-medium, 500);
654
+ color: var(--matcha-color-text-inverse, #1a1d21);
655
+ }
656
+ }
657
+
658
+ // Expandido — pai com filhos abertos: bg accent/surface-pressed.
659
+ &.matcha-nav-item--expanded:not(.matcha-nav-item--active) > .matcha-nav-item__row {
660
+ background-color: var(--matcha-color-accent-surface-pressed);
661
+ }
662
+
663
+ // Badge — Figma DSV3 feedback/danger bg + danger-contrast fg (Padrão).
664
+ .matcha-nav-item__badge {
665
+ background: var(--matcha-color-feedback-danger);
666
+ color: var(--matcha-color-feedback-danger-contrast, rgba(0, 0, 0, 0.87));
667
+ }
668
+
669
+ // Disabled — texto/ícone caem pra disabled-fg.
670
+ &.matcha-nav-item--disabled {
671
+ .matcha-nav-item__label,
672
+ .matcha-nav-item__icon,
673
+ .matcha-nav-item__chevron {
674
+ color: var(--matcha-color-interaction-disabled-fg);
675
+ }
676
+ }
677
+ }
678
+
679
+ // Indented — placeholder pra futuras diferenças de tema (border já no base).
680
+
681
+ // ── Nav Rail (depth sutil — light/dark adaptativo) ──
682
+ // Bg = surface-bg (page layer) + 4% foreground overlay via color-mix.
683
+ // Cria tonal step VISIBLE em ambos modes:
684
+ // - Light: surface-bg #f1f4f1 + 4% fg #2a2d33 → ~#e8ebe7 (recesso vs page brighter)
685
+ // - Dark: surface-bg #111318 + 4% fg #e8eaed → ~#1a1c20 (peak vs page darker)
686
+ // Antes usava surface-card 85% transparente, que em light ficava imperceptível
687
+ // (surface-card ≈ surface-bg no zona do branco — humano não distingue ~7 units).
688
+ .matcha-nav-rail {
689
+ background-color: color-mix(
690
+ in srgb,
691
+ var(--matcha-color-surface-bg) 96%,
692
+ var(--matcha-color-fg) 4%
693
+ );
694
+ }
695
+
696
+ [matcha-nav-rail-module],
697
+ .matcha-nav-rail__module {
698
+ // Inactive: text-secondary no button + override no matcha-icon filho
699
+ // (matcha-icon tem regra global no theme com mesma especificidade,
700
+ // então precisa target explícito pra vencer no cascade).
701
+ color: var(--matcha-color-text-secondary);
702
+
703
+ matcha-icon {
704
+ color: var(--matcha-color-text-secondary);
705
+ }
706
+
707
+ // Hover (inactive): bg accent/surface-hover (state-layer canon Figma).
708
+ &:hover:not(.matcha-nav-rail__module--active):not([aria-current]) {
709
+ background-color: var(--matcha-color-accent-surface-hover);
710
+ }
711
+
712
+ // Active: bg accent/surface-hover + icon accent.
713
+ // Figma usa #161E12 (accent/surface-hover token), não accent/alpha.
714
+ // Aceita .--active class OU aria-current (pattern ARIA canônico).
715
+ &.matcha-nav-rail__module--active,
716
+ &[aria-current] {
717
+ background-color: var(--matcha-color-accent-surface-hover);
718
+ color: var(--matcha-color-accent);
719
+
720
+ matcha-icon {
721
+ color: var(--matcha-color-accent);
722
+ }
723
+
724
+ // Labeled: ícone E label sobem pra accent (color herdado) + label medium,
725
+ // espelhando o nav-item ativo.
726
+ [matcha-nav-rail-module-label],
727
+ .matcha-nav-rail__module-label {
728
+ font-weight: var(--matcha-weight-medium, 500);
729
+ }
730
+ }
731
+
732
+ // Desabilitado — mesmo token de cor do nav-item disabled, pra os dois
733
+ // estados lerem igual. Depois do bloco ativo de propósito: um módulo
734
+ // desabilitado não deve ficar com a cor de ativo.
735
+ &:disabled,
736
+ &[disabled],
737
+ &[aria-disabled="true"] {
738
+ color: var(--matcha-color-interaction-disabled-fg);
739
+
740
+ matcha-icon {
741
+ color: var(--matcha-color-interaction-disabled-fg);
742
+ }
743
+ }
744
+ }
745
+
746
+ .matcha-nav-rail__divider {
747
+ background-color: var(--matcha-color-surface-border);
748
+ }
749
+
750
+ // ── Nav Panel (Figma DSV3 1:1) ──
751
+ // bg surface/card (1 step acima do rail). Sem shadow — só tonal hierarchy.
752
+ .matcha-nav-panel {
753
+ background-color: var(--matcha-color-surface-card);
754
+ border-right: var(--matcha-border-hairline, 1px) solid var(--matcha-color-surface-border);
755
+ }
756
+
757
+ .matcha-nav-panel__divider {
758
+ background-color: var(--matcha-color-surface-border);
759
+ }
760
+
761
+ .matcha-nav-panel__title {
762
+ color: var(--matcha-color-text-primary);
763
+ }
764
+
765
+ .matcha-nav-panel__title-icon {
766
+ color: var(--matcha-color-text-secondary);
767
+ }
768
+
769
+ // ── Command Palette theme em matcha-command-palette.scss (canônico) ──
770
+ }