@inchurch/matcha-theme 22.36.2 → 22.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -14,6 +14,29 @@
|
|
|
14
14
|
|
|
15
15
|
@mixin matcha-file-uploader-theme($theme) {
|
|
16
16
|
|
|
17
|
+
// ── Shell (modo múltiplo: moldura única em volta de dropzone + lista) ──
|
|
18
|
+
// Recebe o mesmo tratamento visual da dropzone porque é ELE que passa a ser
|
|
19
|
+
// a "área de upload" quando a lista mora dentro — inclusive o realce de
|
|
20
|
+
// dragover, já que os handlers de drag vivem aqui.
|
|
21
|
+
.matcha-file-uploader-shell {
|
|
22
|
+
background: var(--matcha-color-surface-background, var(--matcha-color-surface-bg));
|
|
23
|
+
border-color: var(--matcha-color-surface-border);
|
|
24
|
+
|
|
25
|
+
&.matcha-file-uploader-dragover {
|
|
26
|
+
background: var(--matcha-color-accent-alpha);
|
|
27
|
+
border-color: var(--matcha-color-accent);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&.matcha-file-uploader-disabled {
|
|
31
|
+
opacity: 0.5;
|
|
32
|
+
// pointer-events + cursor default, não `not-allowed`: constraint #14 do
|
|
33
|
+
// INTERACTION-SYSTEM (o lint de CSS avisa). A dropzone legada abaixo ainda
|
|
34
|
+
// usa not-allowed — rastreado no backlog, fora do escopo desta mudança.
|
|
35
|
+
pointer-events: none;
|
|
36
|
+
cursor: default;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
17
40
|
// ── Dropzone ──
|
|
18
41
|
.matcha-file-uploader-dropzone {
|
|
19
42
|
background: var(--matcha-color-surface-background, var(--matcha-color-surface-bg));
|
|
@@ -29,6 +52,14 @@
|
|
|
29
52
|
cursor: not-allowed;
|
|
30
53
|
pointer-events: none;
|
|
31
54
|
}
|
|
55
|
+
|
|
56
|
+
// Dentro do shell a moldura e o fundo são do shell — a dropzone é só a
|
|
57
|
+
// afordância de clique. Duas classes de propósito: precisa vencer o bloco
|
|
58
|
+
// acima, que tem a mesma especificidade.
|
|
59
|
+
&.matcha-file-uploader-dropzone--inset {
|
|
60
|
+
background: transparent;
|
|
61
|
+
border-color: transparent;
|
|
62
|
+
}
|
|
32
63
|
}
|
|
33
64
|
|
|
34
65
|
.matcha-file-uploader-dropzone__icon-pill {
|
|
@@ -94,8 +125,27 @@
|
|
|
94
125
|
color: var(--matcha-color-text-primary);
|
|
95
126
|
}
|
|
96
127
|
|
|
97
|
-
|
|
128
|
+
// Apagar é vermelho EM REPOUSO, não só no hover: remover arquivo é
|
|
129
|
+
// destrutivo e irreversível, e num modo múltiplo com vários itens
|
|
130
|
+
// empilhados a ação precisa ser distinguível antes de o ponteiro chegar
|
|
131
|
+
// nela (em touch não há hover nenhum). `danger` é papel, não hue —
|
|
132
|
+
// o tema pode remapear.
|
|
133
|
+
//
|
|
134
|
+
// `--matcha-icon-color` é obrigatório, e não redundante com o `color`: o
|
|
135
|
+
// matcha-icon resolve o glyph por `var(--matcha-icon-color, …-icon-default)`
|
|
136
|
+
// (matcha-icon.scss:97) e NÃO herda o `color` do pai. Era por isso que o
|
|
137
|
+
// vermelho antigo de hover nunca chegou a pintar a lixeira.
|
|
138
|
+
&.matcha-file-uploader-file__action--delete {
|
|
98
139
|
color: var(--matcha-color-danger);
|
|
140
|
+
--matcha-icon-color: var(--matcha-color-danger);
|
|
141
|
+
|
|
142
|
+
// Fundo tinted em vez de surface-hover neutro, e a cor é reafirmada
|
|
143
|
+
// porque o :hover genérico acima empurraria text-primary.
|
|
144
|
+
&:hover {
|
|
145
|
+
background: var(--matcha-color-danger-alpha);
|
|
146
|
+
color: var(--matcha-color-danger);
|
|
147
|
+
--matcha-icon-color: var(--matcha-color-danger);
|
|
148
|
+
}
|
|
99
149
|
}
|
|
100
150
|
}
|
|
101
151
|
|
|
@@ -116,6 +166,15 @@
|
|
|
116
166
|
&:hover {
|
|
117
167
|
background: var(--matcha-color-surface-card);
|
|
118
168
|
}
|
|
169
|
+
|
|
170
|
+
// Mesma regra do delete na linha. Aqui só o GLYPH vira danger: o fundo
|
|
171
|
+
// continua sendo a pastilha de surface-card, que é o que garante contraste
|
|
172
|
+
// do ícone sobre uma imagem qualquer — trocá-lo por danger-alpha (10%)
|
|
173
|
+
// deixaria o vermelho competir com a foto atrás.
|
|
174
|
+
&.matcha-file-uploader-card__action--delete {
|
|
175
|
+
color: var(--matcha-color-danger);
|
|
176
|
+
--matcha-icon-color: var(--matcha-color-danger);
|
|
177
|
+
}
|
|
119
178
|
}
|
|
120
179
|
}
|
|
121
180
|
|
|
@@ -137,6 +196,75 @@
|
|
|
137
196
|
width: 100%;
|
|
138
197
|
}
|
|
139
198
|
|
|
199
|
+
// ── Shell (modo múltiplo) ────────────────────────────────────────────────────
|
|
200
|
+
// A "área de upload" quando a lista mora dentro: uma moldura tracejada só,
|
|
201
|
+
// com a dropzone no topo e a lista rolável embaixo. Sem arquivo nenhum o
|
|
202
|
+
// resultado é visualmente idêntico à dropzone solta — só a moldura mudou de
|
|
203
|
+
// dono, do filho para o pai.
|
|
204
|
+
.matcha-file-uploader-shell {
|
|
205
|
+
display: flex;
|
|
206
|
+
flex-direction: column;
|
|
207
|
+
width: 100%;
|
|
208
|
+
box-sizing: border-box;
|
|
209
|
+
border: var(--matcha-border-thin, 2px) dashed transparent;
|
|
210
|
+
border-radius: var(--matcha-radius-lg, 8px);
|
|
211
|
+
overflow: hidden; // o radius precisa cortar a lista que rola por dentro
|
|
212
|
+
transition: background-color var(--matcha-duration-instant, 80ms) linear,
|
|
213
|
+
border-color var(--matcha-duration-instant, 80ms) linear;
|
|
214
|
+
|
|
215
|
+
// Classe de dimensionamento posta NO HOST tem que alcancar o shell — mesmo
|
|
216
|
+
// padrao (e mesmo racional) do matcha-grid, grid.component.scss:11-18. Sem
|
|
217
|
+
// isto, `<matcha-file-uploader class="h-400">` esticaria o host e deixaria o
|
|
218
|
+
// shell na altura do conteudo, e a area continuaria crescendo por dentro.
|
|
219
|
+
//
|
|
220
|
+
// `height: 100%` contra host de altura auto resolve pra `auto`: e no-op para
|
|
221
|
+
// quem nao define altura, portanto value-preserving nos usos existentes.
|
|
222
|
+
height: 100%;
|
|
223
|
+
|
|
224
|
+
// O foco visível é da dropzone interna (o elemento focável), não do shell.
|
|
225
|
+
&:focus-within {
|
|
226
|
+
outline: none;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Com altura definida no host, e a DROPZONE que absorve a sobra: com 1 arquivo
|
|
230
|
+
// ela fica grande e a area nao tem buraco; conforme a lista cresce, cede
|
|
231
|
+
// espaco ate o proprio conteudo (pill + dois textos), que o min-height auto
|
|
232
|
+
// do flex protege de ser esmagado. Sem altura definida, nao ha sobra para
|
|
233
|
+
// distribuir e o resultado e o mesmo de antes.
|
|
234
|
+
.matcha-file-uploader-dropzone--inset {
|
|
235
|
+
flex: 1 1 auto;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// ── Lista de arquivos rolável (dentro do shell) ──────────────────────────────
|
|
240
|
+
// max-height em custom property com fallback, igual --matcha-panel-max-height
|
|
241
|
+
// (280px é o mesmo teto que select/autocomplete/panel já usam para "lista com
|
|
242
|
+
// mais conteúdo abaixo"). Passar `none` devolve o crescimento ilimitado antigo.
|
|
243
|
+
.matcha-file-uploader-list {
|
|
244
|
+
display: flex;
|
|
245
|
+
flex-direction: column;
|
|
246
|
+
gap: var(--matcha-space-100, 8px);
|
|
247
|
+
min-height: 0; // sem isso o floor de min-content impede o scroll no flex
|
|
248
|
+
// Pede o tamanho do conteudo e ENCOLHE quando falta espaco — e ai o scroll
|
|
249
|
+
// interno assume. E o que faz a lista caber quando o host tem altura definida
|
|
250
|
+
// e o teto de 280px seria maior do que sobrou.
|
|
251
|
+
flex: 0 1 auto;
|
|
252
|
+
max-height: var(--matcha-file-uploader-list-max-height, 280px);
|
|
253
|
+
overflow-y: auto;
|
|
254
|
+
overflow-x: hidden; // scrollbar vertical + nowrap gera barra horizontal fantasma
|
|
255
|
+
overscroll-behavior: contain; // o scroll não vaza pra página ao chegar no fim
|
|
256
|
+
-webkit-overflow-scrolling: touch;
|
|
257
|
+
padding: 0 var(--matcha-space-100, 8px) var(--matcha-space-100, 8px);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Dentro da lista o espaçamento é do `gap` — o margin-top do item rolaria
|
|
261
|
+
// junto e daria um respiro fantasma no topo do scroll.
|
|
262
|
+
.matcha-file-uploader-list > .matcha-file-uploader-file,
|
|
263
|
+
.matcha-file-uploader-list > .matcha-file-uploader-card {
|
|
264
|
+
margin-top: 0;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
|
|
140
268
|
// ── Dropzone box (Estado=Dropzone — Figma 16152:209) — a zona INTEIRA é o alvo
|
|
141
269
|
.matcha-file-uploader-dropzone {
|
|
142
270
|
display: flex;
|
|
@@ -157,6 +285,24 @@
|
|
|
157
285
|
}
|
|
158
286
|
}
|
|
159
287
|
|
|
288
|
+
// Dropzone dentro do shell: sem moldura própria (é do shell) e sem o radius
|
|
289
|
+
// que arredondaria um canto interno. Mantém padding, cursor e foco.
|
|
290
|
+
// Precisa vir DEPOIS do bloco base: mesma especificidade (uma classe), então é
|
|
291
|
+
// a ordem que decide — declarado antes, o `border: 2px dashed` do base vencia e
|
|
292
|
+
// sobravam 2px de borda transparente dentro do shell.
|
|
293
|
+
.matcha-file-uploader-dropzone--inset {
|
|
294
|
+
border-width: 0;
|
|
295
|
+
border-radius: 0;
|
|
296
|
+
|
|
297
|
+
// Anel de foco PARA DENTRO. A dropzone inset ocupa a largura toda do shell,
|
|
298
|
+
// que tem `overflow: hidden` (o radius precisa cortar a lista rolável): com o
|
|
299
|
+
// `outline-offset: 2px` do bloco base o anel cai fora da caixa e é ceifado,
|
|
300
|
+
// deixando o alvo de teclado sem indicação visível nas laterais.
|
|
301
|
+
&:focus-visible {
|
|
302
|
+
outline-offset: -2px;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
160
306
|
// layout="card": dropzone vazio compartilha a proporção do card preenchido
|
|
161
307
|
// (aspect-ratio aplicado inline via previewRatio) pra empty e filled terem a
|
|
162
308
|
// MESMA altura lado a lado. Sem isso, vazio é dimensionado por padding/conteúdo
|
|
@@ -369,6 +515,14 @@
|
|
|
369
515
|
width: 20px;
|
|
370
516
|
height: 20px;
|
|
371
517
|
}
|
|
518
|
+
// Com o uploader desabilitado a linha continua legivel, mas as acoes saem de
|
|
519
|
+
// operacao. `pointer-events: none` + `cursor: default` em vez de
|
|
520
|
+
// `not-allowed`: constraint #14 do INTERACTION-SYSTEM.
|
|
521
|
+
&:disabled {
|
|
522
|
+
opacity: var(--matcha-opacity-disabled, 0.38);
|
|
523
|
+
pointer-events: none;
|
|
524
|
+
cursor: default;
|
|
525
|
+
}
|
|
372
526
|
}
|
|
373
527
|
|
|
374
528
|
// ── Card layout — preview preenchido 16:9 + ações no hover (Estado=Drop filled) ──
|
|
@@ -429,6 +583,14 @@
|
|
|
429
583
|
width: 18px;
|
|
430
584
|
height: 18px;
|
|
431
585
|
}
|
|
586
|
+
|
|
587
|
+
// Mesma regra da acao da linha: desabilitado sai de operacao sem virar
|
|
588
|
+
// `not-allowed` (constraint #14 do INTERACTION-SYSTEM).
|
|
589
|
+
&:disabled {
|
|
590
|
+
opacity: var(--matcha-opacity-disabled, 0.38);
|
|
591
|
+
pointer-events: none;
|
|
592
|
+
cursor: default;
|
|
593
|
+
}
|
|
432
594
|
}
|
|
433
595
|
|
|
434
596
|
// ── Cropper inline (modo crop: imagem única) ──────────────────────────────
|
|
@@ -464,6 +626,7 @@
|
|
|
464
626
|
|
|
465
627
|
// ── Reduced motion ───────────────────────────────────────────────────────────
|
|
466
628
|
@media (prefers-reduced-motion: reduce) {
|
|
629
|
+
.matcha-file-uploader-shell,
|
|
467
630
|
.matcha-file-uploader-dropzone,
|
|
468
631
|
.matcha-file-uploader-file__progress-fill,
|
|
469
632
|
.matcha-file-uploader-file__action,
|
|
@@ -424,6 +424,33 @@
|
|
|
424
424
|
--matcha-table-cell-bg: var(--matcha-table-row-bg-hover-accent);
|
|
425
425
|
}
|
|
426
426
|
|
|
427
|
+
// O ALVO é a CÉLULA inteira, não só o texto do nome.
|
|
428
|
+
//
|
|
429
|
+
// A âncora envolve o nome, e em título curto isso vira um alvo de poucos pixels —
|
|
430
|
+
// reclamação de quem usa, medida em séries. O `::after` esticado resolve sem trocar
|
|
431
|
+
// a âncora por handler de clique: o href continua existindo, então ctrl+clique,
|
|
432
|
+
// clique do meio e "abrir em nova aba" seguem funcionando, e o foco de teclado
|
|
433
|
+
// continua sendo o do link.
|
|
434
|
+
//
|
|
435
|
+
// De quebra conserta o hover: a regra acima só pinta a linha quando o mouse está
|
|
436
|
+
// sobre o TEXTO. Com a área esticada, pinta ao entrar na célula — que é o que faz
|
|
437
|
+
// a linha parecer clicável.
|
|
438
|
+
//
|
|
439
|
+
// Escopado em `.matcha-table td` de propósito: `a[matcha-cell-link]` também aparece
|
|
440
|
+
// em card de listagem, fora de tabela, e lá o link deve seguir do tamanho do texto.
|
|
441
|
+
//
|
|
442
|
+
// O custo é a seleção de texto DENTRO desta célula. No resto da linha continua
|
|
443
|
+
// funcionando, que é a diferença para a linha toda clicável.
|
|
444
|
+
td:has(a[matcha-cell-link]) {
|
|
445
|
+
position: relative;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
td a[matcha-cell-link]::after {
|
|
449
|
+
content: '';
|
|
450
|
+
position: absolute;
|
|
451
|
+
inset: 0;
|
|
452
|
+
}
|
|
453
|
+
|
|
427
454
|
tbody tr.is-selected td {
|
|
428
455
|
--matcha-table-cell-bg: var(--matcha-table-row-bg-selected);
|
|
429
456
|
}
|
|
@@ -1,54 +1,195 @@
|
|
|
1
1
|
// =============================================================================
|
|
2
|
-
// matcha-tree-view.scss —
|
|
3
|
-
//
|
|
4
|
-
//
|
|
2
|
+
// matcha-tree-view.scss — árvore hierárquica do painel (Figma DSV3 matcha/tree-view)
|
|
3
|
+
//
|
|
4
|
+
// UMA anatomia de linha pra qualquer nó:
|
|
5
|
+
// [grip 32 · disclosure 32 · identidade (dot|avatar + nome, linha secundária) · meta (cargo + contadores) · ações]
|
|
6
|
+
// Nível NÃO é variante: é o recuo do bloco de filhos (32px) + uma guia vertical
|
|
7
|
+
// alinhada ao centro da primeira coluna da linha do pai. O consumer compõe a
|
|
8
|
+
// linha com as classes de slot abaixo; o componente não impõe conteúdo.
|
|
5
9
|
// =============================================================================
|
|
6
10
|
|
|
7
|
-
// ── Container
|
|
8
|
-
// Provê: bg "tray" Figma + gap entre rows + propagação de gap dentro de drop-list.
|
|
11
|
+
// ── Container ───────────────────────────────────────────────────────────────
|
|
9
12
|
.matcha-tree-view {
|
|
10
13
|
display: flex;
|
|
11
14
|
flex-direction: column;
|
|
12
|
-
gap:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
// Sem tray e sem gap. A árvore vive na superfície da página: fundo próprio
|
|
16
|
+
// + rows-card + respiro entre elas transformavam a hierarquia numa pilha de
|
|
17
|
+
// chips, e o card opaco de cada row cobria a guia, que saía tracejada.
|
|
18
|
+
gap: 0;
|
|
19
|
+
padding: 0;
|
|
20
|
+
background: transparent;
|
|
21
|
+
border-radius: 0;
|
|
16
22
|
|
|
17
|
-
// Container queries — base pra responsivo dos filhos
|
|
18
23
|
container-type: inline-size;
|
|
19
24
|
container-name: matcha-tree-view;
|
|
20
25
|
|
|
21
26
|
.matcha-drop-list-container {
|
|
22
27
|
display: flex;
|
|
23
28
|
flex-direction: column;
|
|
24
|
-
gap:
|
|
29
|
+
gap: 0;
|
|
25
30
|
}
|
|
26
31
|
}
|
|
27
32
|
|
|
28
|
-
// ── Container data-driven (matcha-tree-view) + branches recursivos ──────────
|
|
29
|
-
// O host <matcha-tree-view> reusa a classe .matcha-tree-view acima (tray + gap).
|
|
30
|
-
// Cada nível é um <matcha-tree-branch> (drop container); a indentação é por item
|
|
31
|
-
// (via [level] do tree-view-item), então os wrappers NÃO adicionam indent.
|
|
32
33
|
matcha-tree-branch,
|
|
33
34
|
.matcha-tree-view__children {
|
|
34
35
|
display: flex;
|
|
35
36
|
flex-direction: column;
|
|
36
|
-
gap:
|
|
37
|
+
gap: 0;
|
|
37
38
|
min-height: 2px; // alvo de drop mínimo quando o branch está vazio
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
// ── Recuo (bloco de filhos) ────────────────────────────────────────────────
|
|
42
|
+
// O recuo é do BLOCO, não de cada linha: o item dentro do container não recua
|
|
43
|
+
// sozinho, e a guia vira UM traço por nível, contínuo por estrutura.
|
|
44
|
+
.matcha-tree-view__children {
|
|
45
|
+
position: relative;
|
|
46
|
+
padding-inline-start: var(--matcha-tree-view-indent-step, 32px);
|
|
47
|
+
// Motion do Figma: filhos entram em 200ms, desacelerando.
|
|
48
|
+
animation: matcha-tree-view-children-in var(--matcha-duration-fast, 200ms) var(--matcha-easing-decelerated, ease-out) both;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@keyframes matcha-tree-view-children-in {
|
|
52
|
+
from { opacity: 0; transform: translateY(-4px); }
|
|
53
|
+
to { opacity: 1; transform: translateY(0); }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// O wrapper do nó é um .matcha-drag-item, e o drop-list desenha nele um state
|
|
57
|
+
// layer (::before, currentColor a 8% no hover). Como o wrapper CONTÉM a
|
|
58
|
+
// subárvore, passar o mouse num neto pintava a árvore inteira de cinza. Sem
|
|
59
|
+
// state layer aqui: o hover é da ROW. Fica ANTES das regras da guia de
|
|
60
|
+
// propósito — elas reutilizam o ::before com a mesma especificidade e vencem
|
|
61
|
+
// por ordem.
|
|
62
|
+
.matcha-tree-view .matcha-tree-view__node.matcha-drag-item::before {
|
|
63
|
+
content: none;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ── Guia de recuo ───────────────────────────────────────────────────────────
|
|
67
|
+
// Vive no WRAPPER de cada nó filho, não no bloco: no bloco a vertical iria até
|
|
68
|
+
// o fim dele, e quando o último filho tem subárvore a guia do pai desceria ao
|
|
69
|
+
// lado dos netos sugerindo irmãos que não existem.
|
|
70
|
+
//
|
|
71
|
+
// X = centro da PRIMEIRA coluna da linha do pai (16px): o chevron quando a
|
|
72
|
+
// árvore não arrasta, o gutter do grip quando arrasta. Medido a partir da
|
|
73
|
+
// origem do wrapper do filho, isso é `meio controle - passo do recuo`,
|
|
74
|
+
// negativo de propósito. A guia no centro do CHEVRON cairia em cima da coluna
|
|
75
|
+
// do grip dos filhos, que é a mesma coluna deslocada um nível.
|
|
76
|
+
.matcha-tree-view--guides .matcha-tree-view__node {
|
|
77
|
+
position: relative;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.matcha-tree-view--guides .matcha-tree-view__children .matcha-tree-view__node::before {
|
|
81
|
+
content: "";
|
|
82
|
+
position: absolute;
|
|
83
|
+
inset-block: 0;
|
|
84
|
+
inset-inline-start: calc(
|
|
85
|
+
var(--matcha-tree-view-control-size, 32px) / 2
|
|
86
|
+
- var(--matcha-tree-view-indent-step, 32px)
|
|
87
|
+
);
|
|
88
|
+
width: var(--matcha-border-hairline, 1px);
|
|
89
|
+
background: var(--matcha-tree-view-guide-color, currentColor);
|
|
90
|
+
// Estrutura de leitura, não moldura: matcha/opacity/secondary (0.54) dá
|
|
91
|
+
// ~2.9:1 no light e ~4.2:1 no dark, que num traço de 1px lê como fio.
|
|
92
|
+
opacity: var(--matcha-opacity-secondary, 0.54);
|
|
93
|
+
pointer-events: none;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// O state layer do drop-list (.matcha-drag-item:hover::before, opacidade 8%)
|
|
97
|
+
// empata em especificidade com a regra acima e apagava a guia da linha sob o
|
|
98
|
+
// mouse. Uma regra com :hover/:active vence e mantém a opacidade da guia.
|
|
99
|
+
.matcha-tree-view--guides .matcha-tree-view__children .matcha-tree-view__node:hover::before,
|
|
100
|
+
.matcha-tree-view--guides .matcha-tree-view__children .matcha-tree-view__node:active::before {
|
|
101
|
+
opacity: var(--matcha-opacity-secondary, 0.54);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Último irmão: a guia para no CENTRO da linha dele. Mora na row porque só ela
|
|
105
|
+
// conhece a própria altura, então o pé fica no centro mesmo com linha secundária.
|
|
106
|
+
.matcha-tree-view--guides .matcha-tree-view__children .matcha-tree-view__node.is-last::before {
|
|
107
|
+
content: none;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.matcha-tree-view--guides .matcha-tree-view__children .matcha-tree-view__node.is-last
|
|
111
|
+
.matcha-tree-view-item__row::before {
|
|
112
|
+
content: "";
|
|
113
|
+
position: absolute;
|
|
114
|
+
inset-inline-start: calc(
|
|
115
|
+
var(--matcha-tree-view-control-size, 32px) / 2
|
|
116
|
+
- var(--matcha-tree-view-indent-step, 32px)
|
|
117
|
+
);
|
|
118
|
+
top: 0;
|
|
119
|
+
height: 50%;
|
|
120
|
+
width: var(--matcha-border-hairline, 1px);
|
|
121
|
+
background: var(--matcha-tree-view-guide-color, currentColor);
|
|
122
|
+
opacity: var(--matcha-opacity-secondary, 0.54);
|
|
123
|
+
pointer-events: none;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Recuo travado ([maxIndentLevel]): o bloco não recua nem desenha guia; a linha
|
|
127
|
+
// fica no recuo do pai e o contexto entrega `clamped` pra ela sinalizar (L5+).
|
|
128
|
+
.matcha-tree-view .matcha-tree-view__children.is-clamped {
|
|
129
|
+
padding-inline-start: 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.matcha-tree-view--guides .matcha-tree-view__children.is-clamped > matcha-tree-branch > .matcha-tree-view__node::before,
|
|
133
|
+
.matcha-tree-view--guides .matcha-tree-view__children.is-clamped > matcha-tree-branch > .matcha-tree-view__node.is-last
|
|
134
|
+
.matcha-tree-view-item__row::before {
|
|
135
|
+
content: none;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Telas estreitas: metade do passo. Sem isso, 4 níveis comem metade da largura
|
|
139
|
+
// e o nome do nó (a informação) fica sem espaço.
|
|
140
|
+
@container matcha-tree-view (max-width: 480px) {
|
|
141
|
+
.matcha-tree-view__children {
|
|
142
|
+
--matcha-tree-view-indent-step: var(--matcha-space-200, 16px);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ── Wrapper do nó (o treeitem ARIA) ─────────────────────────────────────────
|
|
40
147
|
.matcha-tree-view__node {
|
|
41
148
|
display: block;
|
|
149
|
+
outline: none;
|
|
42
150
|
}
|
|
43
151
|
|
|
44
|
-
//
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
152
|
+
// A row e a subárvore dela são IRMÃS dentro do wrapper, porque a recursão
|
|
153
|
+
// (<matcha-tree-children>) mora no template da row. O wrapper também é o
|
|
154
|
+
// .matcha-drag-item, que o drop-list declara `display: flex` em linha: sem
|
|
155
|
+
// forçar coluna, os filhos renderizam à DIREITA da row.
|
|
156
|
+
.matcha-tree-view .matcha-tree-view__node {
|
|
157
|
+
display: flex;
|
|
158
|
+
flex-direction: column;
|
|
159
|
+
align-items: stretch;
|
|
160
|
+
// Padding ZERO: o respiro é da row (48px de min-height). Somar aqui levava
|
|
161
|
+
// o ritmo a 72px por linha e recuava TODOS os descendentes a cada nível.
|
|
162
|
+
padding: 0;
|
|
163
|
+
// E não pinta fundo: o wrapper CONTÉM a subárvore, e a parte que a row não
|
|
164
|
+
// cobre virava uma faixa de tom diferente a cada nível.
|
|
165
|
+
background: transparent;
|
|
166
|
+
box-shadow: none;
|
|
167
|
+
border-radius: 0;
|
|
168
|
+
overflow: visible;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Focus (teclado) na LINHA do nó focado — roving tabindex do container. O anel
|
|
172
|
+
// do drop-list (no wrapper, com offset) contornaria a subárvore inteira.
|
|
173
|
+
.matcha-tree-view .matcha-tree-view__node.matcha-drag-item:focus-visible {
|
|
174
|
+
outline: none;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.matcha-tree-view .matcha-tree-view__node:focus-visible > matcha-tree-view-item .matcha-tree-view-item__row {
|
|
178
|
+
outline: var(--matcha-border-thin, 2px) solid var(--matcha-color-accent);
|
|
179
|
+
outline-offset: calc(-1 * var(--matcha-border-thin, 2px));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// "Não arrastável" num nó de árvore NÃO é "desabilitado". O drop-list marca a
|
|
183
|
+
// row com .matcha-drag-disabled (pointer-events:none + cores de disabled), regra
|
|
184
|
+
// pensada pra um card FOLHA. Aqui a row CONTÉM a própria subárvore e
|
|
185
|
+
// pointer-events é herdado: apagaria os filhos do hit-test. Restaura.
|
|
186
|
+
.matcha-tree-view .matcha-tree-view__node.matcha-drag-disabled {
|
|
187
|
+
pointer-events: auto;
|
|
188
|
+
color: inherit;
|
|
189
|
+
background-color: transparent;
|
|
49
190
|
}
|
|
50
191
|
|
|
51
|
-
// ── Item host
|
|
192
|
+
// ── Item host ───────────────────────────────────────────────────────────────
|
|
52
193
|
matcha-tree-view-item {
|
|
53
194
|
display: flex;
|
|
54
195
|
flex-direction: row;
|
|
@@ -57,195 +198,414 @@ matcha-tree-view-item {
|
|
|
57
198
|
box-sizing: border-box;
|
|
58
199
|
outline: none;
|
|
59
200
|
|
|
60
|
-
// Disabled
|
|
201
|
+
// Disabled por TOKEN, sem opacidade no wrapper (padrão do Matcha): texto e
|
|
202
|
+
// ícones em disabled/fg, e a linha sai do hit-test.
|
|
61
203
|
&[disabled] {
|
|
62
|
-
|
|
63
|
-
|
|
204
|
+
color: var(--matcha-color-disabled-fg);
|
|
205
|
+
--matcha-icon-color: var(--matcha-color-disabled-fg);
|
|
206
|
+
pointer-events: none;
|
|
207
|
+
|
|
208
|
+
.matcha-tree-view-item__name,
|
|
209
|
+
.matcha-tree-view-item__counters strong { color: inherit; }
|
|
64
210
|
}
|
|
65
211
|
|
|
66
|
-
// Clickable
|
|
67
212
|
&[clickable]:not([disabled]) {
|
|
68
213
|
cursor: pointer;
|
|
69
214
|
|
|
70
215
|
&:focus-visible .matcha-tree-view-item__row {
|
|
71
|
-
outline: 2px solid var(--matcha-color-accent);
|
|
72
|
-
outline-offset: -2px;
|
|
216
|
+
outline: var(--matcha-border-thin, 2px) solid var(--matcha-color-accent);
|
|
217
|
+
outline-offset: calc(-1 * var(--matcha-border-thin, 2px));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Selected = barra de 2px accent à esquerda + tinta neutra. O preenchimento
|
|
222
|
+
// cheio competia com o painel do nó-célula, que também é um fundo. Vale
|
|
223
|
+
// pelo [selected] do item e pelo treeitem selecionado no container.
|
|
224
|
+
&[selected] .matcha-tree-view-item__row,
|
|
225
|
+
.matcha-tree-view__node.is-selected > & .matcha-tree-view-item__row {
|
|
226
|
+
background: var(--matcha-color-surface-hover);
|
|
227
|
+
|
|
228
|
+
&::after {
|
|
229
|
+
content: "";
|
|
230
|
+
position: absolute;
|
|
231
|
+
inset-block: 0;
|
|
232
|
+
inset-inline-start: 0;
|
|
233
|
+
width: var(--matcha-border-thin, 2px);
|
|
234
|
+
border-radius: var(--matcha-border-hairline, 1px);
|
|
235
|
+
background: var(--matcha-color-accent);
|
|
73
236
|
}
|
|
74
237
|
}
|
|
75
238
|
}
|
|
76
239
|
|
|
77
|
-
// ── Indent (
|
|
240
|
+
// ── Indent liso (fora do container) — width inline = (level-1) × indentStep ──
|
|
78
241
|
.matcha-tree-view-item__indent {
|
|
79
|
-
flex:
|
|
80
|
-
// height auto — se ajusta ao row
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// ── Guias de conector (modo organograma) — render quando [guides] é passado ──
|
|
84
|
-
// Cada célula (largura = indentStep, inline) desenha a linha vertical do ancestral
|
|
85
|
-
// (data-guide=line|tee) e/ou o cotovelo do nó (tee ├ / ell └). Linha via
|
|
86
|
-
// --matcha-tree-view-guide-color (theme-aware, default = surface-border). As
|
|
87
|
-
// verticais transbordam o padding-block da row (--_pad) p/ emendar entre rows —
|
|
88
|
-
// use gap:0 no container quando quiser linhas 100% contínuas.
|
|
89
|
-
.matcha-tree-view-item__guides {
|
|
90
|
-
flex: none;
|
|
91
|
-
align-self: stretch;
|
|
92
|
-
display: flex;
|
|
93
|
-
}
|
|
94
|
-
.matcha-tree-view-item__guide {
|
|
95
|
-
--_guide: var(--matcha-tree-view-guide-color, var(--matcha-color-surface-border));
|
|
96
|
-
--_pad: var(--matcha-space-100, 8px);
|
|
97
|
-
position: relative;
|
|
98
|
-
flex: none;
|
|
99
|
-
|
|
100
|
-
// Linha vertical no centro — 'line'/'tee' atravessam; 'ell' (último) para no centro.
|
|
101
|
-
&[data-guide="line"]::before,
|
|
102
|
-
&[data-guide="tee"]::before,
|
|
103
|
-
&[data-guide="ell"]::before {
|
|
104
|
-
content: "";
|
|
105
|
-
position: absolute;
|
|
106
|
-
left: 50%;
|
|
107
|
-
top: calc(-1 * var(--_pad));
|
|
108
|
-
width: 1px;
|
|
109
|
-
background: var(--_guide);
|
|
110
|
-
}
|
|
111
|
-
&[data-guide="line"]::before,
|
|
112
|
-
&[data-guide="tee"]::before { bottom: calc(-1 * var(--_pad)); }
|
|
113
|
-
&[data-guide="ell"]::before { height: calc(50% + var(--_pad)); }
|
|
114
|
-
|
|
115
|
-
// Cotovelo horizontal (centro → direita, na metade da altura) — 'tee'/'ell'.
|
|
116
|
-
&[data-guide="tee"]::after,
|
|
117
|
-
&[data-guide="ell"]::after {
|
|
118
|
-
content: "";
|
|
119
|
-
position: absolute;
|
|
120
|
-
top: 50%;
|
|
121
|
-
left: 50%;
|
|
122
|
-
right: 0;
|
|
123
|
-
height: 1px;
|
|
124
|
-
background: var(--_guide);
|
|
125
|
-
}
|
|
242
|
+
flex: none;
|
|
126
243
|
}
|
|
127
244
|
|
|
128
|
-
// ── Row
|
|
245
|
+
// ── Row ─────────────────────────────────────────────────────────────────────
|
|
129
246
|
.matcha-tree-view-item__row {
|
|
247
|
+
position: relative; // contexto do pé da guia e da barra de seleção
|
|
130
248
|
flex: 1;
|
|
131
249
|
display: flex;
|
|
132
250
|
flex-direction: row;
|
|
133
251
|
align-items: center;
|
|
134
252
|
gap: var(--matcha-space-100, 8px);
|
|
135
253
|
min-height: 48px;
|
|
136
|
-
padding:
|
|
254
|
+
// Sem padding à esquerda: a primeira coluna (grip ou disclosure) começa na
|
|
255
|
+
// origem da linha, e é o centro dela (16px) que a guia do próximo nível usa.
|
|
256
|
+
padding: var(--matcha-space-100, 8px) var(--matcha-space-150, 12px) var(--matcha-space-100, 8px) 0;
|
|
137
257
|
background: transparent;
|
|
138
|
-
border-bottom: 1px solid var(--matcha-color-surface-border);
|
|
139
258
|
border-radius: var(--matcha-radius-md, 4px);
|
|
140
259
|
box-sizing: border-box;
|
|
141
260
|
min-width: 0;
|
|
142
261
|
transition: background-color var(--matcha-duration-instant, 80ms) ease;
|
|
262
|
+
flex-wrap: var(--matcha-tree-view-item-wrap, nowrap);
|
|
263
|
+
}
|
|
143
264
|
|
|
144
|
-
|
|
145
|
-
|
|
265
|
+
// Sem primeira coluna (nem grip nem disclosure: o drill-down mobile, uma lista
|
|
266
|
+
// achatada), a identidade colava na borda e o hover encostava no dot. A row
|
|
267
|
+
// recupera o respiro lateral que a coluna de 32px dava de graça.
|
|
268
|
+
.matcha-tree-view-item__row:not(:has(> .matcha-tree-view-item__grip, > .matcha-tree-view-item__disclosure)) {
|
|
269
|
+
padding-inline-start: var(--matcha-space-150, 12px);
|
|
146
270
|
}
|
|
147
271
|
|
|
148
|
-
// Hover
|
|
272
|
+
// Hover é o ÚNICO fundo que a row ganha fora de selected: transparente, a guia
|
|
273
|
+
// passa por trás sem ser recortada a cada linha.
|
|
149
274
|
matcha-tree-view-item:not([disabled]):hover .matcha-tree-view-item__row {
|
|
150
275
|
background: var(--matcha-color-surface-hover);
|
|
151
276
|
}
|
|
152
277
|
|
|
153
|
-
// ──
|
|
154
|
-
|
|
155
|
-
//
|
|
278
|
+
// ── Prioridade de encolhimento — a identidade nunca cede primeiro ───────────
|
|
279
|
+
.matcha-tree-view-item__row > * {
|
|
280
|
+
min-width: 0; // permite truncar em vez de transbordar
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// ── Slots da linha (classes que o consumer aplica no conteúdo projetado) ────
|
|
284
|
+
|
|
285
|
+
// Grip: primeira coluna, 32px, NO FLUXO. Reserva o espaço só quando existe
|
|
286
|
+
// (árvore arrastável) e revela o ícone em hover/focus. Em árvore arrastável,
|
|
287
|
+
// projete o grip em TODAS as linhas, raiz inclusive, pra as colunas alinharem.
|
|
156
288
|
.matcha-tree-view-item__grip {
|
|
157
|
-
flex:
|
|
158
|
-
display:
|
|
159
|
-
align-items:
|
|
160
|
-
justify-content:
|
|
161
|
-
width:
|
|
162
|
-
height:
|
|
289
|
+
flex: none;
|
|
290
|
+
display: inline-flex;
|
|
291
|
+
align-items: center;
|
|
292
|
+
justify-content: center;
|
|
293
|
+
width: var(--matcha-tree-view-control-size, 32px);
|
|
294
|
+
height: var(--matcha-tree-view-control-size, 32px);
|
|
163
295
|
--matcha-icon-color: var(--matcha-color-text-muted);
|
|
164
|
-
cursor:
|
|
165
|
-
|
|
296
|
+
cursor: grab;
|
|
297
|
+
opacity: 0;
|
|
298
|
+
transition: opacity var(--matcha-duration-instant, 80ms) ease;
|
|
166
299
|
|
|
167
|
-
&:hover { --matcha-icon-color: var(--matcha-color-text-primary); }
|
|
168
300
|
&:active { cursor: grabbing; }
|
|
169
301
|
}
|
|
170
302
|
|
|
171
|
-
//
|
|
172
|
-
|
|
173
|
-
|
|
303
|
+
// Ações (kebab): slot reservado, ícone só em hover/focus. 11 kebabs sempre
|
|
304
|
+
// visíveis eram uma coluna de ruído; o slot fica pra os contadores não pularem.
|
|
305
|
+
.matcha-tree-view-item__actions {
|
|
306
|
+
flex: none;
|
|
307
|
+
display: flex;
|
|
308
|
+
align-items: center;
|
|
309
|
+
gap: var(--matcha-space-050, 4px);
|
|
310
|
+
min-width: var(--matcha-tree-view-control-size, 32px);
|
|
311
|
+
opacity: 0;
|
|
312
|
+
transition: opacity var(--matcha-duration-instant, 80ms) ease;
|
|
174
313
|
}
|
|
175
|
-
|
|
176
|
-
|
|
314
|
+
|
|
315
|
+
matcha-tree-view-item:hover .matcha-tree-view-item__grip,
|
|
316
|
+
matcha-tree-view-item:focus-within .matcha-tree-view-item__grip,
|
|
317
|
+
.matcha-tree-view__node:focus-visible > matcha-tree-view-item .matcha-tree-view-item__grip,
|
|
318
|
+
.matcha-drag-ghost .matcha-tree-view-item__grip,
|
|
319
|
+
matcha-tree-view-item:hover .matcha-tree-view-item__actions,
|
|
320
|
+
matcha-tree-view-item:focus-within .matcha-tree-view-item__actions,
|
|
321
|
+
.matcha-tree-view__node:focus-visible > matcha-tree-view-item .matcha-tree-view-item__actions {
|
|
322
|
+
opacity: 1;
|
|
177
323
|
}
|
|
178
324
|
|
|
179
|
-
//
|
|
180
|
-
|
|
181
|
-
|
|
325
|
+
// Em ponteiro grosso (toque) não existe hover: grip e ações ficam visíveis.
|
|
326
|
+
@media (hover: none) {
|
|
327
|
+
.matcha-tree-view-item__grip,
|
|
328
|
+
.matcha-tree-view-item__actions { opacity: 1; }
|
|
329
|
+
}
|
|
182
330
|
|
|
183
|
-
|
|
331
|
+
// Navegar (›): o trailing do drill-down mobile. Sempre visível; substitui as
|
|
332
|
+
// ações quando a linha inteira navega.
|
|
333
|
+
.matcha-tree-view-item__navigate {
|
|
334
|
+
flex: none;
|
|
335
|
+
display: inline-flex;
|
|
336
|
+
align-items: center;
|
|
337
|
+
justify-content: center;
|
|
338
|
+
width: var(--matcha-tree-view-control-size, 32px);
|
|
339
|
+
height: var(--matcha-tree-view-control-size, 32px);
|
|
340
|
+
--matcha-icon-color: var(--matcha-color-text-muted);
|
|
184
341
|
}
|
|
185
342
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
343
|
+
// Disclosure: 32px, reserva o slot mesmo na folha (use a classe num <span>
|
|
344
|
+
// vazio) pra a identidade alinhar entre irmãos. Um único chevron-right que o
|
|
345
|
+
// tema gira em 150ms quando o item está [expanded]; caption em repouso, texto
|
|
346
|
+
// no hover/focus.
|
|
347
|
+
matcha-tree-view-item .matcha-tree-view-item__disclosure {
|
|
348
|
+
flex: none;
|
|
349
|
+
display: inline-flex;
|
|
350
|
+
align-items: center;
|
|
351
|
+
justify-content: center;
|
|
352
|
+
width: var(--matcha-tree-view-control-size, 32px);
|
|
353
|
+
height: var(--matcha-tree-view-control-size, 32px);
|
|
354
|
+
--matcha-icon-color: var(--matcha-color-text-muted);
|
|
355
|
+
|
|
356
|
+
matcha-icon {
|
|
357
|
+
transition: transform 150ms var(--matcha-easing-standard, ease);
|
|
358
|
+
}
|
|
194
359
|
}
|
|
195
360
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
to { opacity: 1; }
|
|
361
|
+
matcha-tree-view-item[expanded] .matcha-tree-view-item__disclosure matcha-icon {
|
|
362
|
+
transform: rotate(90deg);
|
|
199
363
|
}
|
|
200
364
|
|
|
201
|
-
|
|
365
|
+
matcha-tree-view-item:hover .matcha-tree-view-item__disclosure,
|
|
366
|
+
matcha-tree-view-item:focus-within .matcha-tree-view-item__disclosure,
|
|
367
|
+
.matcha-tree-view__node:focus-visible > matcha-tree-view-item .matcha-tree-view-item__disclosure {
|
|
368
|
+
--matcha-icon-color: var(--matcha-color-text-primary);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Identidade (dot|avatar + textos). Fica com o espaço que sobra e é a ÚLTIMA a
|
|
372
|
+
// ceder: sem isso o flex encolhe na ordem do DOM e, em tela estreita, o NOME
|
|
373
|
+
// chegava a zero enquanto cargo e contador ficavam intactos.
|
|
374
|
+
.matcha-tree-view-item__identity {
|
|
375
|
+
flex: 1 1 auto;
|
|
376
|
+
min-width: 4ch; // piso: sempre sobra o começo do nome
|
|
377
|
+
display: flex;
|
|
378
|
+
align-items: center;
|
|
379
|
+
gap: var(--matcha-space-100, 8px);
|
|
380
|
+
// SEM overflow:hidden. Quem trunca é o texto (min-width:0 + text-overflow
|
|
381
|
+
// no __name/__secondary), e recortar aqui comia os 2px do anel de nível do
|
|
382
|
+
// avatar — que ficava com as beiradas retas — e comeria também o anel de
|
|
383
|
+
// foco de qualquer controle projetado na identidade.
|
|
384
|
+
overflow: visible;
|
|
385
|
+
|
|
386
|
+
> * { min-width: 0; }
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Cor de nível: no dot (6px + anel a 20%) ou no anel do avatar. O consumer
|
|
390
|
+
// informa a cor em --matcha-tree-view-level-color; sem ela, herda o texto.
|
|
391
|
+
.matcha-tree-view-item__dot {
|
|
392
|
+
flex: none;
|
|
393
|
+
width: 6px;
|
|
394
|
+
height: 6px;
|
|
395
|
+
margin: var(--matcha-border-thin, 2px);
|
|
396
|
+
border-radius: var(--matcha-radius-pill, 9999px);
|
|
397
|
+
background: var(--matcha-tree-view-level-color, currentColor);
|
|
398
|
+
box-shadow: 0 0 0 var(--matcha-border-thin, 2px)
|
|
399
|
+
color-mix(in srgb, var(--matcha-tree-view-level-color, currentColor) 20%, transparent);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.matcha-tree-view-item__avatar {
|
|
403
|
+
flex: none;
|
|
404
|
+
display: inline-flex;
|
|
405
|
+
|
|
406
|
+
.matcha-avatar {
|
|
407
|
+
border-radius: var(--matcha-radius-pill, 9999px);
|
|
408
|
+
box-shadow: 0 0 0 var(--matcha-border-thin, 2px) var(--matcha-tree-view-level-color, transparent);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// Textos: nome (label-medium) e linha secundária opcional (p-small, caption).
|
|
413
|
+
// Com linha secundária a row cresce pra 64px sozinha.
|
|
414
|
+
.matcha-tree-view-item__text {
|
|
415
|
+
flex: 1 1 auto;
|
|
416
|
+
min-width: 0;
|
|
202
417
|
display: flex;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
padding: var(--matcha-space-400, 32px);
|
|
206
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
207
|
-
color: var(--matcha-color-text-muted);
|
|
208
|
-
border: 2px dashed var(--matcha-color-surface-border);
|
|
209
|
-
border-radius: var(--matcha-radius-md, 4px);
|
|
210
|
-
background: transparent;
|
|
418
|
+
flex-direction: column;
|
|
419
|
+
gap: var(--matcha-border-thin, 2px);
|
|
211
420
|
}
|
|
212
421
|
|
|
213
|
-
.matcha-
|
|
422
|
+
.matcha-tree-view-item__name {
|
|
423
|
+
display: block;
|
|
424
|
+
min-width: 0;
|
|
425
|
+
overflow: hidden;
|
|
426
|
+
text-overflow: ellipsis;
|
|
427
|
+
white-space: nowrap;
|
|
428
|
+
font-size: var(--matcha-text-label-md, 14px);
|
|
429
|
+
font-weight: var(--matcha-font-weight-medium, 500);
|
|
430
|
+
line-height: 20px;
|
|
431
|
+
color: var(--matcha-color-text-primary);
|
|
432
|
+
}
|
|
214
433
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
434
|
+
.matcha-tree-view-item__secondary {
|
|
435
|
+
display: block;
|
|
436
|
+
min-width: 0;
|
|
437
|
+
overflow: hidden;
|
|
438
|
+
text-overflow: ellipsis;
|
|
439
|
+
white-space: nowrap;
|
|
440
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
441
|
+
line-height: 16px;
|
|
442
|
+
color: var(--matcha-color-text-muted);
|
|
218
443
|
}
|
|
219
444
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
445
|
+
// Meta (cargo + contadores). Cede ANTES do nome e, quando não cabe, sai de cena.
|
|
446
|
+
.matcha-tree-view-item__meta {
|
|
447
|
+
flex: 0 1 auto;
|
|
448
|
+
min-width: 0;
|
|
449
|
+
margin-inline-start: auto;
|
|
450
|
+
display: flex;
|
|
451
|
+
align-items: center;
|
|
452
|
+
gap: var(--matcha-space-100, 8px);
|
|
453
|
+
overflow: hidden;
|
|
454
|
+
color: var(--matcha-color-text-muted);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Cargo é TEXTO, não pílula: pílula em toda linha é peso repetido 30 vezes na
|
|
458
|
+
// tela. Pílula (matcha-badge) fica pra ESTADO (Inativo, Pendente).
|
|
459
|
+
.matcha-tree-view-item__cargo {
|
|
460
|
+
flex: none;
|
|
461
|
+
font-size: var(--matcha-text-label-sm, 12px);
|
|
462
|
+
font-weight: var(--matcha-font-weight-medium, 500);
|
|
463
|
+
line-height: 16px;
|
|
464
|
+
color: var(--matcha-color-text-muted);
|
|
465
|
+
white-space: nowrap;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Contadores: números tabulares (alinham à direita sem parecer relatório) e
|
|
469
|
+
// sem zero à esquerda — isso é do dado, não do CSS: "2 células", não "02".
|
|
470
|
+
.matcha-tree-view-item__counters {
|
|
471
|
+
flex: none;
|
|
472
|
+
display: inline-flex;
|
|
473
|
+
align-items: baseline;
|
|
474
|
+
gap: var(--matcha-space-050, 4px);
|
|
475
|
+
font-variant-numeric: tabular-nums;
|
|
476
|
+
white-space: nowrap;
|
|
477
|
+
|
|
478
|
+
strong {
|
|
479
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
480
|
+
font-weight: var(--matcha-font-weight-medium, 500);
|
|
481
|
+
color: var(--matcha-color-text-primary);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
small {
|
|
485
|
+
font-size: var(--matcha-text-p-tiny, 11px);
|
|
486
|
+
letter-spacing: 0.3px;
|
|
487
|
+
color: var(--matcha-color-text-muted);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// Só some quando não há mesmo onde caber. Entre 360 e 480 o flex encolhe o
|
|
492
|
+
// meta antes do nome.
|
|
493
|
+
@container matcha-tree-view (max-width: 360px) {
|
|
494
|
+
.matcha-tree-view-item__meta { display: none; }
|
|
223
495
|
}
|
|
224
496
|
|
|
225
|
-
// ── Responsividade — container query baseada no .matcha-tree-view container
|
|
226
|
-
// Em containers estreitos (< 480px), reduz indent visual pra preservar espaço útil.
|
|
227
|
-
// Indent visual = padding-left implícito via --matcha-tree-view-item-indent setado
|
|
228
|
-
// inline pelo componente. Container query NÃO consegue overridar inline style
|
|
229
|
-
// diretamente, então usamos uma estratégia diferente: scale do indent div.
|
|
230
497
|
@container matcha-tree-view (max-width: 480px) {
|
|
231
498
|
.matcha-tree-view-item__indent {
|
|
232
|
-
// Reduz 50% do width inline — preserva indent visual sem perder hierarquia
|
|
233
499
|
transform: scaleX(0.6);
|
|
234
500
|
transform-origin: left center;
|
|
235
501
|
}
|
|
236
502
|
|
|
237
503
|
.matcha-tree-view-item__row {
|
|
238
504
|
gap: var(--matcha-space-050, 4px);
|
|
239
|
-
|
|
240
|
-
|
|
505
|
+
min-height: 44px; // alvo de toque WCAG 2.5.5 em mobile
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// ── Drag-and-drop (compõe com o motor do matcha-drop-list) ──────────────────
|
|
510
|
+
|
|
511
|
+
// Dragging = o FANTASMA na origem. O motor do drop-list aplica isso INLINE no
|
|
512
|
+
// wrapper arrastado (opacidade + translate dos irmãos) — não há classe pra
|
|
513
|
+
// estilizar aqui; o que o tema garante é que o wrapper não ganhe fundo, sombra
|
|
514
|
+
// ou escala de "card solto" (ver as regras do wrapper acima).
|
|
515
|
+
|
|
516
|
+
// Levantado = a cópia que acompanha o cursor: SÓ a linha, com superfície e
|
|
517
|
+
// elevação level-2. O motor clona o wrapper inteiro (a subárvore junto);
|
|
518
|
+
// esconder os filhos no clone deixa a cópia do tamanho de uma linha.
|
|
519
|
+
.matcha-drag-ghost {
|
|
520
|
+
box-shadow: none; // a elevação é da row, não da caixa do clone
|
|
521
|
+
|
|
522
|
+
.matcha-tree-view__children-host { display: none; }
|
|
523
|
+
|
|
524
|
+
.matcha-tree-view-item__row {
|
|
525
|
+
background: var(--matcha-color-surface);
|
|
526
|
+
box-shadow: var(--matcha-shadow-2);
|
|
527
|
+
border-radius: var(--matcha-radius-md, 4px);
|
|
241
528
|
}
|
|
529
|
+
|
|
530
|
+
.matcha-tree-view-item__grip { opacity: 1; }
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// Região do aria-live: só pra leitor de tela.
|
|
534
|
+
.matcha-tree-view__live {
|
|
535
|
+
position: absolute;
|
|
536
|
+
width: 1px;
|
|
537
|
+
height: 1px;
|
|
538
|
+
margin: -1px;
|
|
539
|
+
padding: 0;
|
|
540
|
+
overflow: hidden;
|
|
541
|
+
clip: rect(0 0 0 0);
|
|
542
|
+
white-space: nowrap;
|
|
543
|
+
border: 0;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// Recebendo = o PAI que vai receber o drop dentro: tinta accent + hairline
|
|
547
|
+
// accent na linha dele. O motor marca o branch dos filhos; a linha do pai é a
|
|
548
|
+
// irmã anterior do bloco, daí o :has() com filhos diretos.
|
|
549
|
+
.matcha-tree-view .matcha-tree-view__node:has(
|
|
550
|
+
> .matcha-tree-view__children-host > .matcha-tree-view__children > matcha-tree-branch.matcha-drop-list-receiving
|
|
551
|
+
) > matcha-tree-view-item .matcha-tree-view-item__row {
|
|
552
|
+
background: var(--matcha-color-accent-surface-hover, var(--matcha-color-accent-alpha));
|
|
553
|
+
box-shadow: inset 0 0 0 var(--matcha-border-hairline, 1px) var(--matcha-color-accent);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// Recusado = destino inválido por TIPO: tracejado danger na linha do pai. A
|
|
557
|
+
// zona em si não ganha moldura, e a subárvore de quem está sendo arrastado
|
|
558
|
+
// (.matcha-drop-zone-self) não é pintada: rejeitar a si mesmo é óbvio.
|
|
559
|
+
.matcha-tree-view .matcha-tree-view__node:has(
|
|
560
|
+
> .matcha-tree-view__children-host > .matcha-drop-zone-cannot-accept:not(.matcha-drop-zone-self)
|
|
561
|
+
) > matcha-tree-view-item .matcha-tree-view-item__row {
|
|
562
|
+
outline: var(--matcha-border-hairline, 1px) dashed var(--matcha-color-danger);
|
|
563
|
+
outline-offset: calc(-1 * var(--matcha-border-hairline, 1px));
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// A moldura listrada/tracejada que o drop-list dá à zona não vale na árvore.
|
|
567
|
+
.matcha-tree-view .matcha-tree-view__children.matcha-drop-zone-cannot-accept {
|
|
568
|
+
outline: none;
|
|
569
|
+
background: transparent;
|
|
570
|
+
border: 0;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// O branch NÃO herda a moldura listrada do drop-list plano.
|
|
574
|
+
.matcha-tree-view matcha-tree-branch.matcha-drop-list-receiving,
|
|
575
|
+
.matcha-tree-view matcha-tree-branch.matcha-drop-list-can-accept,
|
|
576
|
+
.matcha-tree-view matcha-tree-branch.matcha-drop-list-cannot-accept {
|
|
577
|
+
background: transparent;
|
|
578
|
+
border: 0;
|
|
579
|
+
padding: 0;
|
|
580
|
+
|
|
581
|
+
&::before { content: none; }
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// Entre irmãos NÃO há linha indicadora: o motor abre o espaço do item arrastado
|
|
585
|
+
// (translateY nos irmãos, 150ms) e deixa o fantasma na origem. É o "indicador"
|
|
586
|
+
// do código; o bloco drop-indicator do Figma é a representação estática disso.
|
|
587
|
+
|
|
588
|
+
// Alvo "Solte aqui" quando o pai ainda não tem filhos.
|
|
589
|
+
.matcha-tree-view .matcha-drop-list-empty-placeholder {
|
|
590
|
+
display: flex;
|
|
591
|
+
align-items: center;
|
|
592
|
+
justify-content: center;
|
|
593
|
+
min-height: 48px;
|
|
594
|
+
padding: var(--matcha-space-150, 12px);
|
|
595
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
596
|
+
color: var(--matcha-color-text-muted);
|
|
597
|
+
border: var(--matcha-border-hairline, 1px) dashed var(--matcha-color-surface-border);
|
|
598
|
+
border-radius: var(--matcha-radius-md, 4px);
|
|
599
|
+
background: transparent;
|
|
242
600
|
}
|
|
243
601
|
|
|
244
602
|
// Respeita preferência de redução de movimento
|
|
245
603
|
@media (prefers-reduced-motion: reduce) {
|
|
246
|
-
matcha-tree-
|
|
247
|
-
matcha-tree-view-
|
|
248
|
-
.matcha-tree-view
|
|
604
|
+
.matcha-tree-view__children,
|
|
605
|
+
.matcha-tree-view-item__disclosure matcha-icon,
|
|
606
|
+
.matcha-tree-view-item__row,
|
|
607
|
+
.matcha-tree-view-item__grip,
|
|
608
|
+
.matcha-tree-view-item__actions {
|
|
249
609
|
animation: none !important;
|
|
250
610
|
transition: none !important;
|
|
251
611
|
}
|