@inchurch/matcha-theme 22.40.1 → 22.40.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/abstracts/_colors.scss +291 -291
- package/abstracts/_elevation.scss +108 -108
- package/abstracts/_functions.scss +321 -321
- package/abstracts/_media-breakpoint.scss +26 -26
- package/abstracts/_theme-api.scss +224 -224
- package/abstracts/_typography.scss +128 -128
- package/base/_reset.scss +487 -487
- package/components/app-page-header.scss +260 -260
- package/components/matcha-accordion.scss +297 -297
- package/components/matcha-audio-player.scss +31 -31
- package/components/matcha-autocomplete.scss +145 -145
- package/components/matcha-avatar.scss +426 -426
- package/components/matcha-badge.scss +120 -120
- package/components/matcha-breadcrumb.scss +231 -231
- package/components/matcha-button-toggle.scss +484 -484
- package/components/matcha-buttons.scss +973 -973
- package/components/matcha-calendar.scss +253 -253
- package/components/matcha-cards.scss +212 -212
- package/components/matcha-chart-card.scss +53 -53
- package/components/matcha-checkbox.scss +266 -266
- package/components/matcha-chip.scss +311 -311
- package/components/matcha-color-pick.scss +34 -34
- package/components/matcha-command-palette.scss +316 -316
- package/components/matcha-crop.scss +419 -419
- package/components/matcha-date.scss +81 -81
- package/components/matcha-divider.scss +100 -100
- package/components/matcha-draggable.scss +23 -23
- package/components/matcha-drawer.scss +376 -376
- package/components/matcha-drop-image.scss +14 -14
- package/components/matcha-drop-list.scss +430 -430
- package/components/matcha-emoji.scss +69 -69
- package/components/matcha-empty-state.scss +230 -230
- package/components/matcha-file-uploader.scss +650 -650
- package/components/matcha-flag.scss +103 -103
- package/components/matcha-footer.scss +91 -91
- package/components/matcha-form-field.scss +883 -883
- package/components/matcha-form-section.scss +100 -100
- package/components/matcha-header.scss +135 -135
- package/components/matcha-highlight.scss +164 -164
- package/components/matcha-hint-text.scss +90 -90
- package/components/matcha-horizontal-tree.scss +247 -247
- package/components/matcha-icon.scss +111 -111
- package/components/matcha-image.scss +60 -60
- package/components/matcha-list.scss +211 -211
- package/components/matcha-menu.scss +99 -99
- package/components/matcha-modal.scss +210 -210
- package/components/matcha-nav.scss +770 -770
- package/components/matcha-notification.scss +417 -417
- package/components/matcha-option.scss +170 -170
- package/components/matcha-page-builder.scss +4196 -4196
- package/components/matcha-paginator.scss +699 -699
- package/components/matcha-panel.scss +216 -216
- package/components/matcha-period.scss +174 -174
- package/components/matcha-profile-card.scss +50 -50
- package/components/matcha-progress-bar.scss +355 -355
- package/components/matcha-radio.scss +325 -325
- package/components/matcha-ripple.scss +7 -7
- package/components/matcha-scrollbar.scss +33 -33
- package/components/matcha-scrollbox-shadow.scss +120 -120
- package/components/matcha-section.scss +102 -102
- package/components/matcha-select-multiple.scss +56 -56
- package/components/matcha-select.scss +643 -643
- package/components/matcha-skeleton.scss +182 -182
- package/components/matcha-slide-toggle.scss +369 -369
- package/components/matcha-slider.scss +285 -285
- package/components/matcha-snack-bar.scss +259 -259
- package/components/matcha-spin.scss +164 -164
- package/components/matcha-spinner.scss +97 -97
- package/components/matcha-stepper.scss +376 -376
- package/components/matcha-table-cell.scss +107 -107
- package/components/matcha-table.scss +722 -722
- package/components/matcha-tabs.scss +642 -642
- package/components/matcha-text-editor.scss +111 -111
- package/components/matcha-time.scss +33 -33
- package/components/matcha-timepicker.scss +13 -13
- package/components/matcha-toolbar.scss +366 -366
- package/components/matcha-tooltip.scss +235 -235
- package/components/matcha-tree-view.scss +658 -658
- package/layout/matcha-page-layout.scss +778 -778
- package/main.scss +334 -334
- package/package.json +1 -1
- package/tokens/_animations-tokens.scss +37 -37
- package/tokens/_breakpoints-tokens.scss +35 -35
- package/tokens/_color-tokens.scss +288 -288
- package/tokens/_elevation-tokens.scss +33 -33
- package/tokens/_emit-tokens.scss +329 -329
- package/tokens/_material-palette.scss +1149 -1149
- package/tokens/_primitives.scss +98 -98
- package/tokens/_semantic-aliases.scss +120 -120
- package/tokens/_spacing-tokens.scss +94 -94
- package/tokens/_static-tokens.scss +137 -137
- package/tokens/_typography-tokens.scss +65 -65
- package/vendors/charts.scss +90 -90
|
@@ -1,658 +1,658 @@
|
|
|
1
|
-
// =============================================================================
|
|
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.
|
|
9
|
-
// =============================================================================
|
|
10
|
-
|
|
11
|
-
// ── Container ───────────────────────────────────────────────────────────────
|
|
12
|
-
.matcha-tree-view {
|
|
13
|
-
display: flex;
|
|
14
|
-
flex-direction: column;
|
|
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;
|
|
22
|
-
|
|
23
|
-
container-type: inline-size;
|
|
24
|
-
container-name: matcha-tree-view;
|
|
25
|
-
|
|
26
|
-
.matcha-drop-list-container {
|
|
27
|
-
display: flex;
|
|
28
|
-
flex-direction: column;
|
|
29
|
-
gap: 0;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
matcha-tree-branch,
|
|
34
|
-
.matcha-tree-view__children {
|
|
35
|
-
display: flex;
|
|
36
|
-
flex-direction: column;
|
|
37
|
-
gap: 0;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// ── Recuo (bloco de filhos) ────────────────────────────────────────────────
|
|
41
|
-
// O recuo é do BLOCO, não de cada linha: o item dentro do container não recua
|
|
42
|
-
// sozinho, e a guia vira UM traço por nível, contínuo por estrutura.
|
|
43
|
-
.matcha-tree-view__children {
|
|
44
|
-
position: relative;
|
|
45
|
-
// Motion do Figma: filhos entram em 200ms, desacelerando.
|
|
46
|
-
animation: matcha-tree-view-children-in var(--matcha-duration-fast, 200ms) var(--matcha-easing-decelerated, ease-out) both;
|
|
47
|
-
|
|
48
|
-
// O padding mora no BRANCH, não no bloco: a faixa do recuo (onde passa a
|
|
49
|
-
// guia) é da lista de filhos no hit-test do arraste. No bloco, o cursor
|
|
50
|
-
// sobre a guia caía na lista de fora, e o destino mostrado era outro.
|
|
51
|
-
> matcha-tree-branch {
|
|
52
|
-
padding-inline-start: var(--matcha-tree-view-indent-step, 32px);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
@keyframes matcha-tree-view-children-in {
|
|
57
|
-
from { opacity: 0; transform: translateY(-4px); }
|
|
58
|
-
to { opacity: 1; transform: translateY(0); }
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// O wrapper do nó é um .matcha-drag-item, e o drop-list desenha nele um state
|
|
62
|
-
// layer (::before, currentColor a 8% no hover). Como o wrapper CONTÉM a
|
|
63
|
-
// subárvore, passar o mouse num neto pintava a árvore inteira de cinza. Sem
|
|
64
|
-
// state layer aqui: o hover é da ROW. Fica ANTES das regras da guia de
|
|
65
|
-
// propósito — elas reutilizam o ::before com a mesma especificidade e vencem
|
|
66
|
-
// por ordem.
|
|
67
|
-
.matcha-tree-view .matcha-tree-view__node.matcha-drag-item::before {
|
|
68
|
-
content: none;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// ── Guia de recuo ───────────────────────────────────────────────────────────
|
|
72
|
-
// Vive no WRAPPER de cada nó filho, não no bloco: no bloco a vertical iria até
|
|
73
|
-
// o fim dele, e quando o último filho tem subárvore a guia do pai desceria ao
|
|
74
|
-
// lado dos netos sugerindo irmãos que não existem.
|
|
75
|
-
//
|
|
76
|
-
// X = centro da PRIMEIRA coluna da linha do pai (16px): o chevron quando a
|
|
77
|
-
// árvore não arrasta, o gutter do grip quando arrasta. Medido a partir da
|
|
78
|
-
// origem do wrapper do filho, isso é `meio controle - passo do recuo`,
|
|
79
|
-
// negativo de propósito. A guia no centro do CHEVRON cairia em cima da coluna
|
|
80
|
-
// do grip dos filhos, que é a mesma coluna deslocada um nível.
|
|
81
|
-
.matcha-tree-view--guides .matcha-tree-view__node {
|
|
82
|
-
position: relative;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
.matcha-tree-view--guides .matcha-tree-view__children .matcha-tree-view__node::before {
|
|
86
|
-
content: "";
|
|
87
|
-
position: absolute;
|
|
88
|
-
inset-block: 0;
|
|
89
|
-
inset-inline-start: calc(
|
|
90
|
-
var(--matcha-tree-view-control-size, 32px) / 2
|
|
91
|
-
- var(--matcha-tree-view-indent-step, 32px)
|
|
92
|
-
);
|
|
93
|
-
width: var(--matcha-border-hairline, 1px);
|
|
94
|
-
background: var(--matcha-tree-view-guide-color, currentColor);
|
|
95
|
-
// Estrutura de leitura, não moldura: matcha/opacity/secondary (0.54) dá
|
|
96
|
-
// ~2.9:1 no light e ~4.2:1 no dark, que num traço de 1px lê como fio.
|
|
97
|
-
opacity: var(--matcha-opacity-secondary, 0.54);
|
|
98
|
-
pointer-events: none;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// O state layer do drop-list (.matcha-drag-item:hover::before, opacidade 8%)
|
|
102
|
-
// empata em especificidade com a regra acima e apagava a guia da linha sob o
|
|
103
|
-
// mouse. Uma regra com :hover/:active vence e mantém a opacidade da guia.
|
|
104
|
-
.matcha-tree-view--guides .matcha-tree-view__children .matcha-tree-view__node:hover::before,
|
|
105
|
-
.matcha-tree-view--guides .matcha-tree-view__children .matcha-tree-view__node:active::before {
|
|
106
|
-
opacity: var(--matcha-opacity-secondary, 0.54);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Último irmão: a guia para no CENTRO da linha dele. Mora na row porque só ela
|
|
110
|
-
// conhece a própria altura, então o pé fica no centro mesmo com linha secundária.
|
|
111
|
-
.matcha-tree-view--guides .matcha-tree-view__children .matcha-tree-view__node.is-last::before {
|
|
112
|
-
content: none;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
.matcha-tree-view--guides .matcha-tree-view__children .matcha-tree-view__node.is-last
|
|
116
|
-
.matcha-tree-view-item__row::before {
|
|
117
|
-
content: "";
|
|
118
|
-
position: absolute;
|
|
119
|
-
inset-inline-start: calc(
|
|
120
|
-
var(--matcha-tree-view-control-size, 32px) / 2
|
|
121
|
-
- var(--matcha-tree-view-indent-step, 32px)
|
|
122
|
-
);
|
|
123
|
-
top: 0;
|
|
124
|
-
height: 50%;
|
|
125
|
-
width: var(--matcha-border-hairline, 1px);
|
|
126
|
-
background: var(--matcha-tree-view-guide-color, currentColor);
|
|
127
|
-
opacity: var(--matcha-opacity-secondary, 0.54);
|
|
128
|
-
pointer-events: none;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Recuo travado ([maxIndentLevel]): o bloco não recua nem desenha guia; a linha
|
|
132
|
-
// fica no recuo do pai e o contexto entrega `clamped` pra ela sinalizar (L5+).
|
|
133
|
-
.matcha-tree-view .matcha-tree-view__children.is-clamped > matcha-tree-branch {
|
|
134
|
-
padding-inline-start: 0;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
.matcha-tree-view--guides .matcha-tree-view__children.is-clamped > matcha-tree-branch > .matcha-tree-view__node::before,
|
|
138
|
-
.matcha-tree-view--guides .matcha-tree-view__children.is-clamped > matcha-tree-branch > .matcha-tree-view__node.is-last
|
|
139
|
-
.matcha-tree-view-item__row::before {
|
|
140
|
-
content: none;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Telas estreitas: metade do passo. Sem isso, 4 níveis comem metade da largura
|
|
144
|
-
// e o nome do nó (a informação) fica sem espaço.
|
|
145
|
-
@container matcha-tree-view (max-width: 480px) {
|
|
146
|
-
.matcha-tree-view__children {
|
|
147
|
-
--matcha-tree-view-indent-step: var(--matcha-space-200, 16px);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// ── Wrapper do nó (o treeitem ARIA) ─────────────────────────────────────────
|
|
152
|
-
.matcha-tree-view__node {
|
|
153
|
-
display: block;
|
|
154
|
-
outline: none;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// A row e a subárvore dela são IRMÃS dentro do wrapper, porque a recursão
|
|
158
|
-
// (<matcha-tree-children>) mora no template da row. O wrapper também é o
|
|
159
|
-
// .matcha-drag-item, que o drop-list declara `display: flex` em linha: sem
|
|
160
|
-
// forçar coluna, os filhos renderizam à DIREITA da row.
|
|
161
|
-
.matcha-tree-view .matcha-tree-view__node {
|
|
162
|
-
display: flex;
|
|
163
|
-
flex-direction: column;
|
|
164
|
-
align-items: stretch;
|
|
165
|
-
// Padding ZERO: o respiro é da row (48px de min-height). Somar aqui levava
|
|
166
|
-
// o ritmo a 72px por linha e recuava TODOS os descendentes a cada nível.
|
|
167
|
-
padding: 0;
|
|
168
|
-
// E não pinta fundo: o wrapper CONTÉM a subárvore, e a parte que a row não
|
|
169
|
-
// cobre virava uma faixa de tom diferente a cada nível.
|
|
170
|
-
background: transparent;
|
|
171
|
-
box-shadow: none;
|
|
172
|
-
border-radius: 0;
|
|
173
|
-
overflow: visible;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Focus (teclado) na LINHA do nó focado — roving tabindex do container. O anel
|
|
177
|
-
// do drop-list (no wrapper, com offset) contornaria a subárvore inteira.
|
|
178
|
-
.matcha-tree-view .matcha-tree-view__node.matcha-drag-item:focus-visible {
|
|
179
|
-
outline: none;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
.matcha-tree-view .matcha-tree-view__node:focus-visible > matcha-tree-view-item .matcha-tree-view-item__row {
|
|
183
|
-
outline: var(--matcha-border-thin, 2px) solid var(--matcha-color-accent);
|
|
184
|
-
outline-offset: calc(-1 * var(--matcha-border-thin, 2px));
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// "Não arrastável" num nó de árvore NÃO é "desabilitado". O drop-list marca a
|
|
188
|
-
// row com .matcha-drag-disabled (pointer-events:none + cores de disabled), regra
|
|
189
|
-
// pensada pra um card FOLHA. Aqui a row CONTÉM a própria subárvore e
|
|
190
|
-
// pointer-events é herdado: apagaria os filhos do hit-test. Restaura.
|
|
191
|
-
.matcha-tree-view .matcha-tree-view__node.matcha-drag-disabled {
|
|
192
|
-
pointer-events: auto;
|
|
193
|
-
color: inherit;
|
|
194
|
-
background-color: transparent;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// ── Item host ───────────────────────────────────────────────────────────────
|
|
198
|
-
matcha-tree-view-item {
|
|
199
|
-
display: flex;
|
|
200
|
-
flex-direction: row;
|
|
201
|
-
align-items: stretch;
|
|
202
|
-
width: 100%;
|
|
203
|
-
box-sizing: border-box;
|
|
204
|
-
outline: none;
|
|
205
|
-
|
|
206
|
-
// Disabled por TOKEN, sem opacidade no wrapper (padrão do Matcha): texto e
|
|
207
|
-
// ícones em disabled/fg, e a linha sai do hit-test.
|
|
208
|
-
&[disabled] {
|
|
209
|
-
color: var(--matcha-color-disabled-fg);
|
|
210
|
-
--matcha-icon-color: var(--matcha-color-disabled-fg);
|
|
211
|
-
pointer-events: none;
|
|
212
|
-
|
|
213
|
-
.matcha-tree-view-item__name,
|
|
214
|
-
.matcha-tree-view-item__counters strong { color: inherit; }
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
&[clickable]:not([disabled]) {
|
|
218
|
-
cursor: pointer;
|
|
219
|
-
|
|
220
|
-
&:focus-visible .matcha-tree-view-item__row {
|
|
221
|
-
outline: var(--matcha-border-thin, 2px) solid var(--matcha-color-accent);
|
|
222
|
-
outline-offset: calc(-1 * var(--matcha-border-thin, 2px));
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Selected = barra de 2px accent à esquerda + tinta neutra. O preenchimento
|
|
227
|
-
// cheio competia com o painel do nó-célula, que também é um fundo. Vale
|
|
228
|
-
// pelo [selected] do item e pelo treeitem selecionado no container.
|
|
229
|
-
&[selected] .matcha-tree-view-item__row,
|
|
230
|
-
.matcha-tree-view__node.is-selected > & .matcha-tree-view-item__row {
|
|
231
|
-
background: var(--matcha-color-surface-hover);
|
|
232
|
-
|
|
233
|
-
&::after {
|
|
234
|
-
content: "";
|
|
235
|
-
position: absolute;
|
|
236
|
-
inset-block: 0;
|
|
237
|
-
inset-inline-start: 0;
|
|
238
|
-
width: var(--matcha-border-thin, 2px);
|
|
239
|
-
border-radius: var(--matcha-border-hairline, 1px);
|
|
240
|
-
background: var(--matcha-color-accent);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// ── Indent liso (fora do container) — width inline = (level-1) × indentStep ──
|
|
246
|
-
.matcha-tree-view-item__indent {
|
|
247
|
-
flex: none;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// ── Row ─────────────────────────────────────────────────────────────────────
|
|
251
|
-
.matcha-tree-view-item__row {
|
|
252
|
-
position: relative; // contexto do pé da guia e da barra de seleção
|
|
253
|
-
flex: 1;
|
|
254
|
-
display: flex;
|
|
255
|
-
flex-direction: row;
|
|
256
|
-
align-items: center;
|
|
257
|
-
gap: var(--matcha-space-100, 8px);
|
|
258
|
-
min-height: 48px;
|
|
259
|
-
// Sem padding à esquerda: a primeira coluna (grip ou disclosure) começa na
|
|
260
|
-
// origem da linha, e é o centro dela (16px) que a guia do próximo nível usa.
|
|
261
|
-
padding: var(--matcha-space-100, 8px) var(--matcha-space-150, 12px) var(--matcha-space-100, 8px) 0;
|
|
262
|
-
background: transparent;
|
|
263
|
-
border-radius: var(--matcha-radius-md, 4px);
|
|
264
|
-
box-sizing: border-box;
|
|
265
|
-
min-width: 0;
|
|
266
|
-
transition: background-color var(--matcha-duration-instant, 80ms) ease;
|
|
267
|
-
flex-wrap: var(--matcha-tree-view-item-wrap, nowrap);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// Sem primeira coluna (nem grip nem disclosure: o drill-down mobile, uma lista
|
|
271
|
-
// achatada), a identidade colava na borda e o hover encostava no dot. A row
|
|
272
|
-
// recupera o respiro lateral que a coluna de 32px dava de graça.
|
|
273
|
-
.matcha-tree-view-item__row:not(:has(> .matcha-tree-view-item__grip, > .matcha-tree-view-item__disclosure)) {
|
|
274
|
-
padding-inline-start: var(--matcha-space-150, 12px);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// Hover é o ÚNICO fundo que a row ganha fora de selected: transparente, a guia
|
|
278
|
-
// passa por trás sem ser recortada a cada linha.
|
|
279
|
-
matcha-tree-view-item:not([disabled]):hover .matcha-tree-view-item__row {
|
|
280
|
-
background: var(--matcha-color-surface-hover);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// ── Prioridade de encolhimento — a identidade nunca cede primeiro ───────────
|
|
284
|
-
.matcha-tree-view-item__row > * {
|
|
285
|
-
min-width: 0; // permite truncar em vez de transbordar
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// ── Slots da linha (classes que o consumer aplica no conteúdo projetado) ────
|
|
289
|
-
|
|
290
|
-
// Grip: primeira coluna, 32px, NO FLUXO. Reserva o espaço só quando existe
|
|
291
|
-
// (árvore arrastável) e revela o ícone em hover/focus. Em árvore arrastável,
|
|
292
|
-
// projete o grip em TODAS as linhas, raiz inclusive, pra as colunas alinharem.
|
|
293
|
-
.matcha-tree-view-item__grip {
|
|
294
|
-
flex: none;
|
|
295
|
-
display: inline-flex;
|
|
296
|
-
align-items: center;
|
|
297
|
-
justify-content: center;
|
|
298
|
-
width: var(--matcha-tree-view-control-size, 32px);
|
|
299
|
-
height: var(--matcha-tree-view-control-size, 32px);
|
|
300
|
-
--matcha-icon-color: var(--matcha-color-text-muted);
|
|
301
|
-
cursor: grab;
|
|
302
|
-
opacity: 0;
|
|
303
|
-
transition: opacity var(--matcha-duration-instant, 80ms) ease;
|
|
304
|
-
|
|
305
|
-
&:active { cursor: grabbing; }
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
// Ações (kebab): slot reservado, ícone só em hover/focus. 11 kebabs sempre
|
|
309
|
-
// visíveis eram uma coluna de ruído; o slot fica pra os contadores não pularem.
|
|
310
|
-
.matcha-tree-view-item__actions {
|
|
311
|
-
flex: none;
|
|
312
|
-
display: flex;
|
|
313
|
-
align-items: center;
|
|
314
|
-
gap: var(--matcha-space-050, 4px);
|
|
315
|
-
min-width: var(--matcha-tree-view-control-size, 32px);
|
|
316
|
-
opacity: 0;
|
|
317
|
-
transition: opacity var(--matcha-duration-instant, 80ms) ease;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
matcha-tree-view-item:hover .matcha-tree-view-item__grip,
|
|
321
|
-
matcha-tree-view-item:focus-within .matcha-tree-view-item__grip,
|
|
322
|
-
.matcha-tree-view__node:focus-visible > matcha-tree-view-item .matcha-tree-view-item__grip,
|
|
323
|
-
.matcha-drag-ghost .matcha-tree-view-item__grip,
|
|
324
|
-
matcha-tree-view-item:hover .matcha-tree-view-item__actions,
|
|
325
|
-
matcha-tree-view-item:focus-within .matcha-tree-view-item__actions,
|
|
326
|
-
.matcha-tree-view__node:focus-visible > matcha-tree-view-item .matcha-tree-view-item__actions {
|
|
327
|
-
opacity: 1;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// "Solte aqui para tornar filho" — o alvo de uma pasta ABERTA e VAZIA que aceita
|
|
331
|
-
// o item (Figma: filhos · vazio). Aparece durante todo o arraste pra dar onde
|
|
332
|
-
// mirar (IN-42506), mas só onde o drop é possível: nunca numa página, nunca na
|
|
333
|
-
// outra árvore. É sempre neutro: quando o cursor chega nele (`.is-target`), o
|
|
334
|
-
// destaque é o Recebendo na linha do PAI — um sinal só, como no Figma.
|
|
335
|
-
.matcha-tree-view .matcha-drop-list-empty-placeholder {
|
|
336
|
-
display: flex;
|
|
337
|
-
align-items: center;
|
|
338
|
-
justify-content: center;
|
|
339
|
-
min-height: 48px;
|
|
340
|
-
margin: var(--matcha-space-050, 4px) 0;
|
|
341
|
-
padding: var(--matcha-space-100, 8px) var(--matcha-space-150, 12px);
|
|
342
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
343
|
-
line-height: 16px;
|
|
344
|
-
color: var(--matcha-color-text-muted);
|
|
345
|
-
border: var(--matcha-border-hairline, 1px) dashed var(--matcha-color-surface-border);
|
|
346
|
-
border-radius: var(--matcha-radius-md, 4px);
|
|
347
|
-
background: transparent;
|
|
348
|
-
box-sizing: border-box;
|
|
349
|
-
pointer-events: auto;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// Em ponteiro grosso (toque) não existe hover: grip e ações ficam visíveis.
|
|
353
|
-
@media (hover: none) {
|
|
354
|
-
.matcha-tree-view-item__grip,
|
|
355
|
-
.matcha-tree-view-item__actions { opacity: 1; }
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
// Navegar (›): o trailing do drill-down mobile. Sempre visível; substitui as
|
|
359
|
-
// ações quando a linha inteira navega.
|
|
360
|
-
.matcha-tree-view-item__navigate {
|
|
361
|
-
flex: none;
|
|
362
|
-
display: inline-flex;
|
|
363
|
-
align-items: center;
|
|
364
|
-
justify-content: center;
|
|
365
|
-
width: var(--matcha-tree-view-control-size, 32px);
|
|
366
|
-
height: var(--matcha-tree-view-control-size, 32px);
|
|
367
|
-
--matcha-icon-color: var(--matcha-color-text-muted);
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// Disclosure: 32px, reserva o slot mesmo na folha (use a classe num <span>
|
|
371
|
-
// vazio) pra a identidade alinhar entre irmãos. Um único chevron-right que o
|
|
372
|
-
// tema gira em 150ms quando o item está [expanded]; caption em repouso, texto
|
|
373
|
-
// no hover/focus.
|
|
374
|
-
matcha-tree-view-item .matcha-tree-view-item__disclosure {
|
|
375
|
-
flex: none;
|
|
376
|
-
display: inline-flex;
|
|
377
|
-
align-items: center;
|
|
378
|
-
justify-content: center;
|
|
379
|
-
width: var(--matcha-tree-view-control-size, 32px);
|
|
380
|
-
height: var(--matcha-tree-view-control-size, 32px);
|
|
381
|
-
--matcha-icon-color: var(--matcha-color-text-muted);
|
|
382
|
-
|
|
383
|
-
matcha-icon {
|
|
384
|
-
transition: transform 150ms var(--matcha-easing-standard, ease);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
matcha-tree-view-item[expanded] .matcha-tree-view-item__disclosure matcha-icon {
|
|
389
|
-
transform: rotate(90deg);
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
matcha-tree-view-item:hover .matcha-tree-view-item__disclosure,
|
|
393
|
-
matcha-tree-view-item:focus-within .matcha-tree-view-item__disclosure,
|
|
394
|
-
.matcha-tree-view__node:focus-visible > matcha-tree-view-item .matcha-tree-view-item__disclosure {
|
|
395
|
-
--matcha-icon-color: var(--matcha-color-text-primary);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// Identidade (dot|avatar + textos). Fica com o espaço que sobra e é a ÚLTIMA a
|
|
399
|
-
// ceder: sem isso o flex encolhe na ordem do DOM e, em tela estreita, o NOME
|
|
400
|
-
// chegava a zero enquanto cargo e contador ficavam intactos.
|
|
401
|
-
.matcha-tree-view-item__identity {
|
|
402
|
-
flex: 1 1 auto;
|
|
403
|
-
min-width: 4ch; // piso: sempre sobra o começo do nome
|
|
404
|
-
display: flex;
|
|
405
|
-
align-items: center;
|
|
406
|
-
gap: var(--matcha-space-100, 8px);
|
|
407
|
-
// SEM overflow:hidden. Quem trunca é o texto (min-width:0 + text-overflow
|
|
408
|
-
// no __name/__secondary), e recortar aqui comia os 2px do anel de nível do
|
|
409
|
-
// avatar — que ficava com as beiradas retas — e comeria também o anel de
|
|
410
|
-
// foco de qualquer controle projetado na identidade.
|
|
411
|
-
overflow: visible;
|
|
412
|
-
|
|
413
|
-
> * { min-width: 0; }
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// Cor de nível: no dot (6px + anel a 20%) ou no anel do avatar. O consumer
|
|
417
|
-
// informa a cor em --matcha-tree-view-level-color; sem ela, herda o texto.
|
|
418
|
-
.matcha-tree-view-item__dot {
|
|
419
|
-
flex: none;
|
|
420
|
-
width: 6px;
|
|
421
|
-
height: 6px;
|
|
422
|
-
margin: var(--matcha-border-thin, 2px);
|
|
423
|
-
border-radius: var(--matcha-radius-pill, 9999px);
|
|
424
|
-
background: var(--matcha-tree-view-level-color, currentColor);
|
|
425
|
-
box-shadow: 0 0 0 var(--matcha-border-thin, 2px)
|
|
426
|
-
color-mix(in srgb, var(--matcha-tree-view-level-color, currentColor) 20%, transparent);
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
.matcha-tree-view-item__avatar {
|
|
430
|
-
flex: none;
|
|
431
|
-
display: inline-flex;
|
|
432
|
-
|
|
433
|
-
.matcha-avatar {
|
|
434
|
-
border-radius: var(--matcha-radius-pill, 9999px);
|
|
435
|
-
box-shadow: 0 0 0 var(--matcha-border-thin, 2px) var(--matcha-tree-view-level-color, transparent);
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
// Textos: nome (label-medium) e linha secundária opcional (p-small, caption).
|
|
440
|
-
// Com linha secundária a row cresce pra 64px sozinha.
|
|
441
|
-
.matcha-tree-view-item__text {
|
|
442
|
-
flex: 1 1 auto;
|
|
443
|
-
min-width: 0;
|
|
444
|
-
display: flex;
|
|
445
|
-
flex-direction: column;
|
|
446
|
-
gap: var(--matcha-border-thin, 2px);
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
.matcha-tree-view-item__name {
|
|
450
|
-
display: block;
|
|
451
|
-
min-width: 0;
|
|
452
|
-
overflow: hidden;
|
|
453
|
-
text-overflow: ellipsis;
|
|
454
|
-
white-space: nowrap;
|
|
455
|
-
font-size: var(--matcha-text-label-md, 14px);
|
|
456
|
-
font-weight: var(--matcha-font-weight-medium, 500);
|
|
457
|
-
line-height: 20px;
|
|
458
|
-
color: var(--matcha-color-text-primary);
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
.matcha-tree-view-item__secondary {
|
|
462
|
-
display: block;
|
|
463
|
-
min-width: 0;
|
|
464
|
-
overflow: hidden;
|
|
465
|
-
text-overflow: ellipsis;
|
|
466
|
-
white-space: nowrap;
|
|
467
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
468
|
-
line-height: 16px;
|
|
469
|
-
color: var(--matcha-color-text-muted);
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
// Meta (cargo + contadores). Cede ANTES do nome e, quando não cabe, sai de cena.
|
|
473
|
-
.matcha-tree-view-item__meta {
|
|
474
|
-
flex: 0 1 auto;
|
|
475
|
-
min-width: 0;
|
|
476
|
-
margin-inline-start: auto;
|
|
477
|
-
display: flex;
|
|
478
|
-
align-items: center;
|
|
479
|
-
gap: var(--matcha-space-100, 8px);
|
|
480
|
-
overflow: hidden;
|
|
481
|
-
color: var(--matcha-color-text-muted);
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// Cargo é TEXTO, não pílula: pílula em toda linha é peso repetido 30 vezes na
|
|
485
|
-
// tela. Pílula (matcha-badge) fica pra ESTADO (Inativo, Pendente).
|
|
486
|
-
.matcha-tree-view-item__cargo {
|
|
487
|
-
flex: none;
|
|
488
|
-
font-size: var(--matcha-text-label-sm, 12px);
|
|
489
|
-
font-weight: var(--matcha-font-weight-medium, 500);
|
|
490
|
-
line-height: 16px;
|
|
491
|
-
color: var(--matcha-color-text-muted);
|
|
492
|
-
white-space: nowrap;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
// Contadores: números tabulares (alinham à direita sem parecer relatório) e
|
|
496
|
-
// sem zero à esquerda — isso é do dado, não do CSS: "2 células", não "02".
|
|
497
|
-
.matcha-tree-view-item__counters {
|
|
498
|
-
flex: none;
|
|
499
|
-
display: inline-flex;
|
|
500
|
-
align-items: baseline;
|
|
501
|
-
gap: var(--matcha-space-050, 4px);
|
|
502
|
-
font-variant-numeric: tabular-nums;
|
|
503
|
-
white-space: nowrap;
|
|
504
|
-
|
|
505
|
-
strong {
|
|
506
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
507
|
-
font-weight: var(--matcha-font-weight-medium, 500);
|
|
508
|
-
color: var(--matcha-color-text-primary);
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
small {
|
|
512
|
-
font-size: var(--matcha-text-p-tiny, 11px);
|
|
513
|
-
letter-spacing: 0.3px;
|
|
514
|
-
color: var(--matcha-color-text-muted);
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
// Só some quando não há mesmo onde caber. Entre 360 e 480 o flex encolhe o
|
|
519
|
-
// meta antes do nome.
|
|
520
|
-
@container matcha-tree-view (max-width: 360px) {
|
|
521
|
-
.matcha-tree-view-item__meta { display: none; }
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
@container matcha-tree-view (max-width: 480px) {
|
|
525
|
-
.matcha-tree-view-item__indent {
|
|
526
|
-
transform: scaleX(0.6);
|
|
527
|
-
transform-origin: left center;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
.matcha-tree-view-item__row {
|
|
531
|
-
gap: var(--matcha-space-050, 4px);
|
|
532
|
-
min-height: 44px; // alvo de toque WCAG 2.5.5 em mobile
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// ── Drag-and-drop (compõe com o motor do matcha-drop-list) ──────────────────
|
|
537
|
-
// Um alvo por vez: a árvore resolve o destino sob o cursor e pinta UMA coisa —
|
|
538
|
-
// Recebendo na pasta que vai receber, Recusado na linha que não aceita, ou a
|
|
539
|
-
// linha do Figma entre irmãos. As classes vêm do branch (estado da árvore).
|
|
540
|
-
|
|
541
|
-
// Dragging = o FANTASMA na origem, durante o arraste inteiro (Figma:
|
|
542
|
-
// opacity/disabled). Esmaece o bloco todo: a subárvore vai junto com o nó.
|
|
543
|
-
.matcha-tree-view .matcha-tree-view__node.is-dragging {
|
|
544
|
-
opacity: var(--matcha-opacity-disabled, 0.38);
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
// Durante o arraste o hover das linhas sai de cena: um fundo de hover sob o
|
|
548
|
-
// cursor parecia um segundo alvo ao lado do Recebendo, e o grip e o kebab
|
|
549
|
-
// revelados na linha de destino eram ruído (ela é destino, não alvo de clique).
|
|
550
|
-
.matcha-tree-view--dragging matcha-tree-view-item:not([disabled]):hover .matcha-tree-view-item__row {
|
|
551
|
-
background: transparent;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
.matcha-tree-view--dragging matcha-tree-view-item:hover .matcha-tree-view-item__grip,
|
|
555
|
-
.matcha-tree-view--dragging matcha-tree-view-item:hover .matcha-tree-view-item__actions {
|
|
556
|
-
opacity: 0;
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
// Recebendo = a pasta que vai receber o item como filho: tinta accent + hairline
|
|
560
|
-
// accent. Mesma especificidade da regra acima e declarada depois: vence o hover
|
|
561
|
-
// suprimido e o selected.
|
|
562
|
-
.matcha-tree-view .matcha-tree-view__node.is-drop-into > matcha-tree-view-item .matcha-tree-view-item__row {
|
|
563
|
-
background: var(--matcha-color-accent-surface-hover, var(--matcha-color-accent-alpha));
|
|
564
|
-
box-shadow: inset 0 0 0 var(--matcha-border-hairline, 1px) var(--matcha-color-accent);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
// Recusado = destino inválido (tipo ou profundidade), só na linha sob o cursor:
|
|
568
|
-
// tracejado danger de 2px (Figma: border/thin).
|
|
569
|
-
.matcha-tree-view .matcha-tree-view__node.is-drop-rejected > matcha-tree-view-item .matcha-tree-view-item__row {
|
|
570
|
-
outline: var(--matcha-border-thin, 2px) dashed var(--matcha-color-danger);
|
|
571
|
-
outline-offset: calc(-1 * var(--matcha-border-thin, 2px));
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
// Entre irmãos = a linha do Figma (matcha/tree-view/drop-indicator): 2px accent
|
|
575
|
-
// com uma bolinha no começo, na borda do nó e no recuo do nível dele.
|
|
576
|
-
.matcha-tree-view__drop-line {
|
|
577
|
-
position: absolute;
|
|
578
|
-
inset-inline: 0;
|
|
579
|
-
top: calc(-1 * var(--matcha-border-thin, 2px) / 2);
|
|
580
|
-
height: var(--matcha-border-thin, 2px);
|
|
581
|
-
border-radius: var(--matcha-radius-pill, 9999px);
|
|
582
|
-
background: var(--matcha-color-accent);
|
|
583
|
-
pointer-events: none;
|
|
584
|
-
z-index: 1;
|
|
585
|
-
|
|
586
|
-
&::before {
|
|
587
|
-
content: "";
|
|
588
|
-
position: absolute;
|
|
589
|
-
inset-inline-start: 0;
|
|
590
|
-
top: 50%;
|
|
591
|
-
width: var(--matcha-space-075, 6px);
|
|
592
|
-
height: var(--matcha-space-075, 6px);
|
|
593
|
-
border-radius: var(--matcha-radius-pill, 9999px);
|
|
594
|
-
background: var(--matcha-color-accent);
|
|
595
|
-
transform: translateY(-50%);
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
&--after {
|
|
599
|
-
top: auto;
|
|
600
|
-
bottom: calc(-1 * var(--matcha-border-thin, 2px) / 2);
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
// Levantado = a cópia que acompanha o cursor: SÓ a linha, com superfície e
|
|
605
|
-
// elevação level-2 — a sombra é da row, não da caixa do clone. Escopado no
|
|
606
|
-
// clone de nó da árvore: o ghost das listas planas segue com a opacidade e a
|
|
607
|
-
// sombra do drop-list.
|
|
608
|
-
.matcha-drag-ghost:has(> .matcha-tree-view__node) {
|
|
609
|
-
opacity: 1;
|
|
610
|
-
box-shadow: none;
|
|
611
|
-
border-radius: 0;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
// O motor clona o wrapper inteiro (a subárvore junto); esconder os filhos no
|
|
615
|
-
// clone deixa a cópia do tamanho de uma linha.
|
|
616
|
-
.matcha-drag-ghost {
|
|
617
|
-
.matcha-tree-view__children-host { display: none; }
|
|
618
|
-
|
|
619
|
-
.matcha-tree-view-item__row {
|
|
620
|
-
background: var(--matcha-color-surface);
|
|
621
|
-
box-shadow: var(--matcha-shadow-2);
|
|
622
|
-
border-radius: var(--matcha-radius-md, 4px);
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
.matcha-tree-view-item__grip { opacity: 1; }
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
// Região do aria-live: só pra leitor de tela.
|
|
629
|
-
.matcha-tree-view__live {
|
|
630
|
-
position: absolute;
|
|
631
|
-
width: 1px;
|
|
632
|
-
height: 1px;
|
|
633
|
-
margin: -1px;
|
|
634
|
-
padding: 0;
|
|
635
|
-
overflow: hidden;
|
|
636
|
-
clip: rect(0 0 0 0);
|
|
637
|
-
white-space: nowrap;
|
|
638
|
-
border: 0;
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
// Respeita preferência de redução de movimento
|
|
642
|
-
@media (prefers-reduced-motion: reduce) {
|
|
643
|
-
matcha-tree-view-item,
|
|
644
|
-
matcha-tree-view-item:not(.matcha-drag-dragging),
|
|
645
|
-
.matcha-tree-view__children,
|
|
646
|
-
.matcha-tree-view-item__disclosure matcha-icon,
|
|
647
|
-
.matcha-tree-view-item__row,
|
|
648
|
-
.matcha-tree-view-item__grip,
|
|
649
|
-
.matcha-tree-view-item__actions {
|
|
650
|
-
animation: none !important;
|
|
651
|
-
transition: none !important;
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
// ── Theme mixin ─────────────────────────────────────────────────────────────
|
|
656
|
-
@mixin matcha-tree-view-theme($theme) {
|
|
657
|
-
// Tudo via CSS vars — sem theme-specific overrides.
|
|
658
|
-
}
|
|
1
|
+
// =============================================================================
|
|
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.
|
|
9
|
+
// =============================================================================
|
|
10
|
+
|
|
11
|
+
// ── Container ───────────────────────────────────────────────────────────────
|
|
12
|
+
.matcha-tree-view {
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
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;
|
|
22
|
+
|
|
23
|
+
container-type: inline-size;
|
|
24
|
+
container-name: matcha-tree-view;
|
|
25
|
+
|
|
26
|
+
.matcha-drop-list-container {
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-direction: column;
|
|
29
|
+
gap: 0;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
matcha-tree-branch,
|
|
34
|
+
.matcha-tree-view__children {
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
gap: 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ── Recuo (bloco de filhos) ────────────────────────────────────────────────
|
|
41
|
+
// O recuo é do BLOCO, não de cada linha: o item dentro do container não recua
|
|
42
|
+
// sozinho, e a guia vira UM traço por nível, contínuo por estrutura.
|
|
43
|
+
.matcha-tree-view__children {
|
|
44
|
+
position: relative;
|
|
45
|
+
// Motion do Figma: filhos entram em 200ms, desacelerando.
|
|
46
|
+
animation: matcha-tree-view-children-in var(--matcha-duration-fast, 200ms) var(--matcha-easing-decelerated, ease-out) both;
|
|
47
|
+
|
|
48
|
+
// O padding mora no BRANCH, não no bloco: a faixa do recuo (onde passa a
|
|
49
|
+
// guia) é da lista de filhos no hit-test do arraste. No bloco, o cursor
|
|
50
|
+
// sobre a guia caía na lista de fora, e o destino mostrado era outro.
|
|
51
|
+
> matcha-tree-branch {
|
|
52
|
+
padding-inline-start: var(--matcha-tree-view-indent-step, 32px);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@keyframes matcha-tree-view-children-in {
|
|
57
|
+
from { opacity: 0; transform: translateY(-4px); }
|
|
58
|
+
to { opacity: 1; transform: translateY(0); }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// O wrapper do nó é um .matcha-drag-item, e o drop-list desenha nele um state
|
|
62
|
+
// layer (::before, currentColor a 8% no hover). Como o wrapper CONTÉM a
|
|
63
|
+
// subárvore, passar o mouse num neto pintava a árvore inteira de cinza. Sem
|
|
64
|
+
// state layer aqui: o hover é da ROW. Fica ANTES das regras da guia de
|
|
65
|
+
// propósito — elas reutilizam o ::before com a mesma especificidade e vencem
|
|
66
|
+
// por ordem.
|
|
67
|
+
.matcha-tree-view .matcha-tree-view__node.matcha-drag-item::before {
|
|
68
|
+
content: none;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ── Guia de recuo ───────────────────────────────────────────────────────────
|
|
72
|
+
// Vive no WRAPPER de cada nó filho, não no bloco: no bloco a vertical iria até
|
|
73
|
+
// o fim dele, e quando o último filho tem subárvore a guia do pai desceria ao
|
|
74
|
+
// lado dos netos sugerindo irmãos que não existem.
|
|
75
|
+
//
|
|
76
|
+
// X = centro da PRIMEIRA coluna da linha do pai (16px): o chevron quando a
|
|
77
|
+
// árvore não arrasta, o gutter do grip quando arrasta. Medido a partir da
|
|
78
|
+
// origem do wrapper do filho, isso é `meio controle - passo do recuo`,
|
|
79
|
+
// negativo de propósito. A guia no centro do CHEVRON cairia em cima da coluna
|
|
80
|
+
// do grip dos filhos, que é a mesma coluna deslocada um nível.
|
|
81
|
+
.matcha-tree-view--guides .matcha-tree-view__node {
|
|
82
|
+
position: relative;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.matcha-tree-view--guides .matcha-tree-view__children .matcha-tree-view__node::before {
|
|
86
|
+
content: "";
|
|
87
|
+
position: absolute;
|
|
88
|
+
inset-block: 0;
|
|
89
|
+
inset-inline-start: calc(
|
|
90
|
+
var(--matcha-tree-view-control-size, 32px) / 2
|
|
91
|
+
- var(--matcha-tree-view-indent-step, 32px)
|
|
92
|
+
);
|
|
93
|
+
width: var(--matcha-border-hairline, 1px);
|
|
94
|
+
background: var(--matcha-tree-view-guide-color, currentColor);
|
|
95
|
+
// Estrutura de leitura, não moldura: matcha/opacity/secondary (0.54) dá
|
|
96
|
+
// ~2.9:1 no light e ~4.2:1 no dark, que num traço de 1px lê como fio.
|
|
97
|
+
opacity: var(--matcha-opacity-secondary, 0.54);
|
|
98
|
+
pointer-events: none;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// O state layer do drop-list (.matcha-drag-item:hover::before, opacidade 8%)
|
|
102
|
+
// empata em especificidade com a regra acima e apagava a guia da linha sob o
|
|
103
|
+
// mouse. Uma regra com :hover/:active vence e mantém a opacidade da guia.
|
|
104
|
+
.matcha-tree-view--guides .matcha-tree-view__children .matcha-tree-view__node:hover::before,
|
|
105
|
+
.matcha-tree-view--guides .matcha-tree-view__children .matcha-tree-view__node:active::before {
|
|
106
|
+
opacity: var(--matcha-opacity-secondary, 0.54);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Último irmão: a guia para no CENTRO da linha dele. Mora na row porque só ela
|
|
110
|
+
// conhece a própria altura, então o pé fica no centro mesmo com linha secundária.
|
|
111
|
+
.matcha-tree-view--guides .matcha-tree-view__children .matcha-tree-view__node.is-last::before {
|
|
112
|
+
content: none;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.matcha-tree-view--guides .matcha-tree-view__children .matcha-tree-view__node.is-last
|
|
116
|
+
.matcha-tree-view-item__row::before {
|
|
117
|
+
content: "";
|
|
118
|
+
position: absolute;
|
|
119
|
+
inset-inline-start: calc(
|
|
120
|
+
var(--matcha-tree-view-control-size, 32px) / 2
|
|
121
|
+
- var(--matcha-tree-view-indent-step, 32px)
|
|
122
|
+
);
|
|
123
|
+
top: 0;
|
|
124
|
+
height: 50%;
|
|
125
|
+
width: var(--matcha-border-hairline, 1px);
|
|
126
|
+
background: var(--matcha-tree-view-guide-color, currentColor);
|
|
127
|
+
opacity: var(--matcha-opacity-secondary, 0.54);
|
|
128
|
+
pointer-events: none;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Recuo travado ([maxIndentLevel]): o bloco não recua nem desenha guia; a linha
|
|
132
|
+
// fica no recuo do pai e o contexto entrega `clamped` pra ela sinalizar (L5+).
|
|
133
|
+
.matcha-tree-view .matcha-tree-view__children.is-clamped > matcha-tree-branch {
|
|
134
|
+
padding-inline-start: 0;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.matcha-tree-view--guides .matcha-tree-view__children.is-clamped > matcha-tree-branch > .matcha-tree-view__node::before,
|
|
138
|
+
.matcha-tree-view--guides .matcha-tree-view__children.is-clamped > matcha-tree-branch > .matcha-tree-view__node.is-last
|
|
139
|
+
.matcha-tree-view-item__row::before {
|
|
140
|
+
content: none;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Telas estreitas: metade do passo. Sem isso, 4 níveis comem metade da largura
|
|
144
|
+
// e o nome do nó (a informação) fica sem espaço.
|
|
145
|
+
@container matcha-tree-view (max-width: 480px) {
|
|
146
|
+
.matcha-tree-view__children {
|
|
147
|
+
--matcha-tree-view-indent-step: var(--matcha-space-200, 16px);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ── Wrapper do nó (o treeitem ARIA) ─────────────────────────────────────────
|
|
152
|
+
.matcha-tree-view__node {
|
|
153
|
+
display: block;
|
|
154
|
+
outline: none;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// A row e a subárvore dela são IRMÃS dentro do wrapper, porque a recursão
|
|
158
|
+
// (<matcha-tree-children>) mora no template da row. O wrapper também é o
|
|
159
|
+
// .matcha-drag-item, que o drop-list declara `display: flex` em linha: sem
|
|
160
|
+
// forçar coluna, os filhos renderizam à DIREITA da row.
|
|
161
|
+
.matcha-tree-view .matcha-tree-view__node {
|
|
162
|
+
display: flex;
|
|
163
|
+
flex-direction: column;
|
|
164
|
+
align-items: stretch;
|
|
165
|
+
// Padding ZERO: o respiro é da row (48px de min-height). Somar aqui levava
|
|
166
|
+
// o ritmo a 72px por linha e recuava TODOS os descendentes a cada nível.
|
|
167
|
+
padding: 0;
|
|
168
|
+
// E não pinta fundo: o wrapper CONTÉM a subárvore, e a parte que a row não
|
|
169
|
+
// cobre virava uma faixa de tom diferente a cada nível.
|
|
170
|
+
background: transparent;
|
|
171
|
+
box-shadow: none;
|
|
172
|
+
border-radius: 0;
|
|
173
|
+
overflow: visible;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Focus (teclado) na LINHA do nó focado — roving tabindex do container. O anel
|
|
177
|
+
// do drop-list (no wrapper, com offset) contornaria a subárvore inteira.
|
|
178
|
+
.matcha-tree-view .matcha-tree-view__node.matcha-drag-item:focus-visible {
|
|
179
|
+
outline: none;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.matcha-tree-view .matcha-tree-view__node:focus-visible > matcha-tree-view-item .matcha-tree-view-item__row {
|
|
183
|
+
outline: var(--matcha-border-thin, 2px) solid var(--matcha-color-accent);
|
|
184
|
+
outline-offset: calc(-1 * var(--matcha-border-thin, 2px));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// "Não arrastável" num nó de árvore NÃO é "desabilitado". O drop-list marca a
|
|
188
|
+
// row com .matcha-drag-disabled (pointer-events:none + cores de disabled), regra
|
|
189
|
+
// pensada pra um card FOLHA. Aqui a row CONTÉM a própria subárvore e
|
|
190
|
+
// pointer-events é herdado: apagaria os filhos do hit-test. Restaura.
|
|
191
|
+
.matcha-tree-view .matcha-tree-view__node.matcha-drag-disabled {
|
|
192
|
+
pointer-events: auto;
|
|
193
|
+
color: inherit;
|
|
194
|
+
background-color: transparent;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// ── Item host ───────────────────────────────────────────────────────────────
|
|
198
|
+
matcha-tree-view-item {
|
|
199
|
+
display: flex;
|
|
200
|
+
flex-direction: row;
|
|
201
|
+
align-items: stretch;
|
|
202
|
+
width: 100%;
|
|
203
|
+
box-sizing: border-box;
|
|
204
|
+
outline: none;
|
|
205
|
+
|
|
206
|
+
// Disabled por TOKEN, sem opacidade no wrapper (padrão do Matcha): texto e
|
|
207
|
+
// ícones em disabled/fg, e a linha sai do hit-test.
|
|
208
|
+
&[disabled] {
|
|
209
|
+
color: var(--matcha-color-disabled-fg);
|
|
210
|
+
--matcha-icon-color: var(--matcha-color-disabled-fg);
|
|
211
|
+
pointer-events: none;
|
|
212
|
+
|
|
213
|
+
.matcha-tree-view-item__name,
|
|
214
|
+
.matcha-tree-view-item__counters strong { color: inherit; }
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
&[clickable]:not([disabled]) {
|
|
218
|
+
cursor: pointer;
|
|
219
|
+
|
|
220
|
+
&:focus-visible .matcha-tree-view-item__row {
|
|
221
|
+
outline: var(--matcha-border-thin, 2px) solid var(--matcha-color-accent);
|
|
222
|
+
outline-offset: calc(-1 * var(--matcha-border-thin, 2px));
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Selected = barra de 2px accent à esquerda + tinta neutra. O preenchimento
|
|
227
|
+
// cheio competia com o painel do nó-célula, que também é um fundo. Vale
|
|
228
|
+
// pelo [selected] do item e pelo treeitem selecionado no container.
|
|
229
|
+
&[selected] .matcha-tree-view-item__row,
|
|
230
|
+
.matcha-tree-view__node.is-selected > & .matcha-tree-view-item__row {
|
|
231
|
+
background: var(--matcha-color-surface-hover);
|
|
232
|
+
|
|
233
|
+
&::after {
|
|
234
|
+
content: "";
|
|
235
|
+
position: absolute;
|
|
236
|
+
inset-block: 0;
|
|
237
|
+
inset-inline-start: 0;
|
|
238
|
+
width: var(--matcha-border-thin, 2px);
|
|
239
|
+
border-radius: var(--matcha-border-hairline, 1px);
|
|
240
|
+
background: var(--matcha-color-accent);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ── Indent liso (fora do container) — width inline = (level-1) × indentStep ──
|
|
246
|
+
.matcha-tree-view-item__indent {
|
|
247
|
+
flex: none;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// ── Row ─────────────────────────────────────────────────────────────────────
|
|
251
|
+
.matcha-tree-view-item__row {
|
|
252
|
+
position: relative; // contexto do pé da guia e da barra de seleção
|
|
253
|
+
flex: 1;
|
|
254
|
+
display: flex;
|
|
255
|
+
flex-direction: row;
|
|
256
|
+
align-items: center;
|
|
257
|
+
gap: var(--matcha-space-100, 8px);
|
|
258
|
+
min-height: 48px;
|
|
259
|
+
// Sem padding à esquerda: a primeira coluna (grip ou disclosure) começa na
|
|
260
|
+
// origem da linha, e é o centro dela (16px) que a guia do próximo nível usa.
|
|
261
|
+
padding: var(--matcha-space-100, 8px) var(--matcha-space-150, 12px) var(--matcha-space-100, 8px) 0;
|
|
262
|
+
background: transparent;
|
|
263
|
+
border-radius: var(--matcha-radius-md, 4px);
|
|
264
|
+
box-sizing: border-box;
|
|
265
|
+
min-width: 0;
|
|
266
|
+
transition: background-color var(--matcha-duration-instant, 80ms) ease;
|
|
267
|
+
flex-wrap: var(--matcha-tree-view-item-wrap, nowrap);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Sem primeira coluna (nem grip nem disclosure: o drill-down mobile, uma lista
|
|
271
|
+
// achatada), a identidade colava na borda e o hover encostava no dot. A row
|
|
272
|
+
// recupera o respiro lateral que a coluna de 32px dava de graça.
|
|
273
|
+
.matcha-tree-view-item__row:not(:has(> .matcha-tree-view-item__grip, > .matcha-tree-view-item__disclosure)) {
|
|
274
|
+
padding-inline-start: var(--matcha-space-150, 12px);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Hover é o ÚNICO fundo que a row ganha fora de selected: transparente, a guia
|
|
278
|
+
// passa por trás sem ser recortada a cada linha.
|
|
279
|
+
matcha-tree-view-item:not([disabled]):hover .matcha-tree-view-item__row {
|
|
280
|
+
background: var(--matcha-color-surface-hover);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// ── Prioridade de encolhimento — a identidade nunca cede primeiro ───────────
|
|
284
|
+
.matcha-tree-view-item__row > * {
|
|
285
|
+
min-width: 0; // permite truncar em vez de transbordar
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// ── Slots da linha (classes que o consumer aplica no conteúdo projetado) ────
|
|
289
|
+
|
|
290
|
+
// Grip: primeira coluna, 32px, NO FLUXO. Reserva o espaço só quando existe
|
|
291
|
+
// (árvore arrastável) e revela o ícone em hover/focus. Em árvore arrastável,
|
|
292
|
+
// projete o grip em TODAS as linhas, raiz inclusive, pra as colunas alinharem.
|
|
293
|
+
.matcha-tree-view-item__grip {
|
|
294
|
+
flex: none;
|
|
295
|
+
display: inline-flex;
|
|
296
|
+
align-items: center;
|
|
297
|
+
justify-content: center;
|
|
298
|
+
width: var(--matcha-tree-view-control-size, 32px);
|
|
299
|
+
height: var(--matcha-tree-view-control-size, 32px);
|
|
300
|
+
--matcha-icon-color: var(--matcha-color-text-muted);
|
|
301
|
+
cursor: grab;
|
|
302
|
+
opacity: 0;
|
|
303
|
+
transition: opacity var(--matcha-duration-instant, 80ms) ease;
|
|
304
|
+
|
|
305
|
+
&:active { cursor: grabbing; }
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Ações (kebab): slot reservado, ícone só em hover/focus. 11 kebabs sempre
|
|
309
|
+
// visíveis eram uma coluna de ruído; o slot fica pra os contadores não pularem.
|
|
310
|
+
.matcha-tree-view-item__actions {
|
|
311
|
+
flex: none;
|
|
312
|
+
display: flex;
|
|
313
|
+
align-items: center;
|
|
314
|
+
gap: var(--matcha-space-050, 4px);
|
|
315
|
+
min-width: var(--matcha-tree-view-control-size, 32px);
|
|
316
|
+
opacity: 0;
|
|
317
|
+
transition: opacity var(--matcha-duration-instant, 80ms) ease;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
matcha-tree-view-item:hover .matcha-tree-view-item__grip,
|
|
321
|
+
matcha-tree-view-item:focus-within .matcha-tree-view-item__grip,
|
|
322
|
+
.matcha-tree-view__node:focus-visible > matcha-tree-view-item .matcha-tree-view-item__grip,
|
|
323
|
+
.matcha-drag-ghost .matcha-tree-view-item__grip,
|
|
324
|
+
matcha-tree-view-item:hover .matcha-tree-view-item__actions,
|
|
325
|
+
matcha-tree-view-item:focus-within .matcha-tree-view-item__actions,
|
|
326
|
+
.matcha-tree-view__node:focus-visible > matcha-tree-view-item .matcha-tree-view-item__actions {
|
|
327
|
+
opacity: 1;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// "Solte aqui para tornar filho" — o alvo de uma pasta ABERTA e VAZIA que aceita
|
|
331
|
+
// o item (Figma: filhos · vazio). Aparece durante todo o arraste pra dar onde
|
|
332
|
+
// mirar (IN-42506), mas só onde o drop é possível: nunca numa página, nunca na
|
|
333
|
+
// outra árvore. É sempre neutro: quando o cursor chega nele (`.is-target`), o
|
|
334
|
+
// destaque é o Recebendo na linha do PAI — um sinal só, como no Figma.
|
|
335
|
+
.matcha-tree-view .matcha-drop-list-empty-placeholder {
|
|
336
|
+
display: flex;
|
|
337
|
+
align-items: center;
|
|
338
|
+
justify-content: center;
|
|
339
|
+
min-height: 48px;
|
|
340
|
+
margin: var(--matcha-space-050, 4px) 0;
|
|
341
|
+
padding: var(--matcha-space-100, 8px) var(--matcha-space-150, 12px);
|
|
342
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
343
|
+
line-height: 16px;
|
|
344
|
+
color: var(--matcha-color-text-muted);
|
|
345
|
+
border: var(--matcha-border-hairline, 1px) dashed var(--matcha-color-surface-border);
|
|
346
|
+
border-radius: var(--matcha-radius-md, 4px);
|
|
347
|
+
background: transparent;
|
|
348
|
+
box-sizing: border-box;
|
|
349
|
+
pointer-events: auto;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Em ponteiro grosso (toque) não existe hover: grip e ações ficam visíveis.
|
|
353
|
+
@media (hover: none) {
|
|
354
|
+
.matcha-tree-view-item__grip,
|
|
355
|
+
.matcha-tree-view-item__actions { opacity: 1; }
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Navegar (›): o trailing do drill-down mobile. Sempre visível; substitui as
|
|
359
|
+
// ações quando a linha inteira navega.
|
|
360
|
+
.matcha-tree-view-item__navigate {
|
|
361
|
+
flex: none;
|
|
362
|
+
display: inline-flex;
|
|
363
|
+
align-items: center;
|
|
364
|
+
justify-content: center;
|
|
365
|
+
width: var(--matcha-tree-view-control-size, 32px);
|
|
366
|
+
height: var(--matcha-tree-view-control-size, 32px);
|
|
367
|
+
--matcha-icon-color: var(--matcha-color-text-muted);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Disclosure: 32px, reserva o slot mesmo na folha (use a classe num <span>
|
|
371
|
+
// vazio) pra a identidade alinhar entre irmãos. Um único chevron-right que o
|
|
372
|
+
// tema gira em 150ms quando o item está [expanded]; caption em repouso, texto
|
|
373
|
+
// no hover/focus.
|
|
374
|
+
matcha-tree-view-item .matcha-tree-view-item__disclosure {
|
|
375
|
+
flex: none;
|
|
376
|
+
display: inline-flex;
|
|
377
|
+
align-items: center;
|
|
378
|
+
justify-content: center;
|
|
379
|
+
width: var(--matcha-tree-view-control-size, 32px);
|
|
380
|
+
height: var(--matcha-tree-view-control-size, 32px);
|
|
381
|
+
--matcha-icon-color: var(--matcha-color-text-muted);
|
|
382
|
+
|
|
383
|
+
matcha-icon {
|
|
384
|
+
transition: transform 150ms var(--matcha-easing-standard, ease);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
matcha-tree-view-item[expanded] .matcha-tree-view-item__disclosure matcha-icon {
|
|
389
|
+
transform: rotate(90deg);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
matcha-tree-view-item:hover .matcha-tree-view-item__disclosure,
|
|
393
|
+
matcha-tree-view-item:focus-within .matcha-tree-view-item__disclosure,
|
|
394
|
+
.matcha-tree-view__node:focus-visible > matcha-tree-view-item .matcha-tree-view-item__disclosure {
|
|
395
|
+
--matcha-icon-color: var(--matcha-color-text-primary);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Identidade (dot|avatar + textos). Fica com o espaço que sobra e é a ÚLTIMA a
|
|
399
|
+
// ceder: sem isso o flex encolhe na ordem do DOM e, em tela estreita, o NOME
|
|
400
|
+
// chegava a zero enquanto cargo e contador ficavam intactos.
|
|
401
|
+
.matcha-tree-view-item__identity {
|
|
402
|
+
flex: 1 1 auto;
|
|
403
|
+
min-width: 4ch; // piso: sempre sobra o começo do nome
|
|
404
|
+
display: flex;
|
|
405
|
+
align-items: center;
|
|
406
|
+
gap: var(--matcha-space-100, 8px);
|
|
407
|
+
// SEM overflow:hidden. Quem trunca é o texto (min-width:0 + text-overflow
|
|
408
|
+
// no __name/__secondary), e recortar aqui comia os 2px do anel de nível do
|
|
409
|
+
// avatar — que ficava com as beiradas retas — e comeria também o anel de
|
|
410
|
+
// foco de qualquer controle projetado na identidade.
|
|
411
|
+
overflow: visible;
|
|
412
|
+
|
|
413
|
+
> * { min-width: 0; }
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Cor de nível: no dot (6px + anel a 20%) ou no anel do avatar. O consumer
|
|
417
|
+
// informa a cor em --matcha-tree-view-level-color; sem ela, herda o texto.
|
|
418
|
+
.matcha-tree-view-item__dot {
|
|
419
|
+
flex: none;
|
|
420
|
+
width: 6px;
|
|
421
|
+
height: 6px;
|
|
422
|
+
margin: var(--matcha-border-thin, 2px);
|
|
423
|
+
border-radius: var(--matcha-radius-pill, 9999px);
|
|
424
|
+
background: var(--matcha-tree-view-level-color, currentColor);
|
|
425
|
+
box-shadow: 0 0 0 var(--matcha-border-thin, 2px)
|
|
426
|
+
color-mix(in srgb, var(--matcha-tree-view-level-color, currentColor) 20%, transparent);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.matcha-tree-view-item__avatar {
|
|
430
|
+
flex: none;
|
|
431
|
+
display: inline-flex;
|
|
432
|
+
|
|
433
|
+
.matcha-avatar {
|
|
434
|
+
border-radius: var(--matcha-radius-pill, 9999px);
|
|
435
|
+
box-shadow: 0 0 0 var(--matcha-border-thin, 2px) var(--matcha-tree-view-level-color, transparent);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// Textos: nome (label-medium) e linha secundária opcional (p-small, caption).
|
|
440
|
+
// Com linha secundária a row cresce pra 64px sozinha.
|
|
441
|
+
.matcha-tree-view-item__text {
|
|
442
|
+
flex: 1 1 auto;
|
|
443
|
+
min-width: 0;
|
|
444
|
+
display: flex;
|
|
445
|
+
flex-direction: column;
|
|
446
|
+
gap: var(--matcha-border-thin, 2px);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.matcha-tree-view-item__name {
|
|
450
|
+
display: block;
|
|
451
|
+
min-width: 0;
|
|
452
|
+
overflow: hidden;
|
|
453
|
+
text-overflow: ellipsis;
|
|
454
|
+
white-space: nowrap;
|
|
455
|
+
font-size: var(--matcha-text-label-md, 14px);
|
|
456
|
+
font-weight: var(--matcha-font-weight-medium, 500);
|
|
457
|
+
line-height: 20px;
|
|
458
|
+
color: var(--matcha-color-text-primary);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
.matcha-tree-view-item__secondary {
|
|
462
|
+
display: block;
|
|
463
|
+
min-width: 0;
|
|
464
|
+
overflow: hidden;
|
|
465
|
+
text-overflow: ellipsis;
|
|
466
|
+
white-space: nowrap;
|
|
467
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
468
|
+
line-height: 16px;
|
|
469
|
+
color: var(--matcha-color-text-muted);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Meta (cargo + contadores). Cede ANTES do nome e, quando não cabe, sai de cena.
|
|
473
|
+
.matcha-tree-view-item__meta {
|
|
474
|
+
flex: 0 1 auto;
|
|
475
|
+
min-width: 0;
|
|
476
|
+
margin-inline-start: auto;
|
|
477
|
+
display: flex;
|
|
478
|
+
align-items: center;
|
|
479
|
+
gap: var(--matcha-space-100, 8px);
|
|
480
|
+
overflow: hidden;
|
|
481
|
+
color: var(--matcha-color-text-muted);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Cargo é TEXTO, não pílula: pílula em toda linha é peso repetido 30 vezes na
|
|
485
|
+
// tela. Pílula (matcha-badge) fica pra ESTADO (Inativo, Pendente).
|
|
486
|
+
.matcha-tree-view-item__cargo {
|
|
487
|
+
flex: none;
|
|
488
|
+
font-size: var(--matcha-text-label-sm, 12px);
|
|
489
|
+
font-weight: var(--matcha-font-weight-medium, 500);
|
|
490
|
+
line-height: 16px;
|
|
491
|
+
color: var(--matcha-color-text-muted);
|
|
492
|
+
white-space: nowrap;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Contadores: números tabulares (alinham à direita sem parecer relatório) e
|
|
496
|
+
// sem zero à esquerda — isso é do dado, não do CSS: "2 células", não "02".
|
|
497
|
+
.matcha-tree-view-item__counters {
|
|
498
|
+
flex: none;
|
|
499
|
+
display: inline-flex;
|
|
500
|
+
align-items: baseline;
|
|
501
|
+
gap: var(--matcha-space-050, 4px);
|
|
502
|
+
font-variant-numeric: tabular-nums;
|
|
503
|
+
white-space: nowrap;
|
|
504
|
+
|
|
505
|
+
strong {
|
|
506
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
507
|
+
font-weight: var(--matcha-font-weight-medium, 500);
|
|
508
|
+
color: var(--matcha-color-text-primary);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
small {
|
|
512
|
+
font-size: var(--matcha-text-p-tiny, 11px);
|
|
513
|
+
letter-spacing: 0.3px;
|
|
514
|
+
color: var(--matcha-color-text-muted);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Só some quando não há mesmo onde caber. Entre 360 e 480 o flex encolhe o
|
|
519
|
+
// meta antes do nome.
|
|
520
|
+
@container matcha-tree-view (max-width: 360px) {
|
|
521
|
+
.matcha-tree-view-item__meta { display: none; }
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
@container matcha-tree-view (max-width: 480px) {
|
|
525
|
+
.matcha-tree-view-item__indent {
|
|
526
|
+
transform: scaleX(0.6);
|
|
527
|
+
transform-origin: left center;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
.matcha-tree-view-item__row {
|
|
531
|
+
gap: var(--matcha-space-050, 4px);
|
|
532
|
+
min-height: 44px; // alvo de toque WCAG 2.5.5 em mobile
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// ── Drag-and-drop (compõe com o motor do matcha-drop-list) ──────────────────
|
|
537
|
+
// Um alvo por vez: a árvore resolve o destino sob o cursor e pinta UMA coisa —
|
|
538
|
+
// Recebendo na pasta que vai receber, Recusado na linha que não aceita, ou a
|
|
539
|
+
// linha do Figma entre irmãos. As classes vêm do branch (estado da árvore).
|
|
540
|
+
|
|
541
|
+
// Dragging = o FANTASMA na origem, durante o arraste inteiro (Figma:
|
|
542
|
+
// opacity/disabled). Esmaece o bloco todo: a subárvore vai junto com o nó.
|
|
543
|
+
.matcha-tree-view .matcha-tree-view__node.is-dragging {
|
|
544
|
+
opacity: var(--matcha-opacity-disabled, 0.38);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Durante o arraste o hover das linhas sai de cena: um fundo de hover sob o
|
|
548
|
+
// cursor parecia um segundo alvo ao lado do Recebendo, e o grip e o kebab
|
|
549
|
+
// revelados na linha de destino eram ruído (ela é destino, não alvo de clique).
|
|
550
|
+
.matcha-tree-view--dragging matcha-tree-view-item:not([disabled]):hover .matcha-tree-view-item__row {
|
|
551
|
+
background: transparent;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
.matcha-tree-view--dragging matcha-tree-view-item:hover .matcha-tree-view-item__grip,
|
|
555
|
+
.matcha-tree-view--dragging matcha-tree-view-item:hover .matcha-tree-view-item__actions {
|
|
556
|
+
opacity: 0;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// Recebendo = a pasta que vai receber o item como filho: tinta accent + hairline
|
|
560
|
+
// accent. Mesma especificidade da regra acima e declarada depois: vence o hover
|
|
561
|
+
// suprimido e o selected.
|
|
562
|
+
.matcha-tree-view .matcha-tree-view__node.is-drop-into > matcha-tree-view-item .matcha-tree-view-item__row {
|
|
563
|
+
background: var(--matcha-color-accent-surface-hover, var(--matcha-color-accent-alpha));
|
|
564
|
+
box-shadow: inset 0 0 0 var(--matcha-border-hairline, 1px) var(--matcha-color-accent);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// Recusado = destino inválido (tipo ou profundidade), só na linha sob o cursor:
|
|
568
|
+
// tracejado danger de 2px (Figma: border/thin).
|
|
569
|
+
.matcha-tree-view .matcha-tree-view__node.is-drop-rejected > matcha-tree-view-item .matcha-tree-view-item__row {
|
|
570
|
+
outline: var(--matcha-border-thin, 2px) dashed var(--matcha-color-danger);
|
|
571
|
+
outline-offset: calc(-1 * var(--matcha-border-thin, 2px));
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// Entre irmãos = a linha do Figma (matcha/tree-view/drop-indicator): 2px accent
|
|
575
|
+
// com uma bolinha no começo, na borda do nó e no recuo do nível dele.
|
|
576
|
+
.matcha-tree-view__drop-line {
|
|
577
|
+
position: absolute;
|
|
578
|
+
inset-inline: 0;
|
|
579
|
+
top: calc(-1 * var(--matcha-border-thin, 2px) / 2);
|
|
580
|
+
height: var(--matcha-border-thin, 2px);
|
|
581
|
+
border-radius: var(--matcha-radius-pill, 9999px);
|
|
582
|
+
background: var(--matcha-color-accent);
|
|
583
|
+
pointer-events: none;
|
|
584
|
+
z-index: 1;
|
|
585
|
+
|
|
586
|
+
&::before {
|
|
587
|
+
content: "";
|
|
588
|
+
position: absolute;
|
|
589
|
+
inset-inline-start: 0;
|
|
590
|
+
top: 50%;
|
|
591
|
+
width: var(--matcha-space-075, 6px);
|
|
592
|
+
height: var(--matcha-space-075, 6px);
|
|
593
|
+
border-radius: var(--matcha-radius-pill, 9999px);
|
|
594
|
+
background: var(--matcha-color-accent);
|
|
595
|
+
transform: translateY(-50%);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
&--after {
|
|
599
|
+
top: auto;
|
|
600
|
+
bottom: calc(-1 * var(--matcha-border-thin, 2px) / 2);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// Levantado = a cópia que acompanha o cursor: SÓ a linha, com superfície e
|
|
605
|
+
// elevação level-2 — a sombra é da row, não da caixa do clone. Escopado no
|
|
606
|
+
// clone de nó da árvore: o ghost das listas planas segue com a opacidade e a
|
|
607
|
+
// sombra do drop-list.
|
|
608
|
+
.matcha-drag-ghost:has(> .matcha-tree-view__node) {
|
|
609
|
+
opacity: 1;
|
|
610
|
+
box-shadow: none;
|
|
611
|
+
border-radius: 0;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
// O motor clona o wrapper inteiro (a subárvore junto); esconder os filhos no
|
|
615
|
+
// clone deixa a cópia do tamanho de uma linha.
|
|
616
|
+
.matcha-drag-ghost {
|
|
617
|
+
.matcha-tree-view__children-host { display: none; }
|
|
618
|
+
|
|
619
|
+
.matcha-tree-view-item__row {
|
|
620
|
+
background: var(--matcha-color-surface);
|
|
621
|
+
box-shadow: var(--matcha-shadow-2);
|
|
622
|
+
border-radius: var(--matcha-radius-md, 4px);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
.matcha-tree-view-item__grip { opacity: 1; }
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Região do aria-live: só pra leitor de tela.
|
|
629
|
+
.matcha-tree-view__live {
|
|
630
|
+
position: absolute;
|
|
631
|
+
width: 1px;
|
|
632
|
+
height: 1px;
|
|
633
|
+
margin: -1px;
|
|
634
|
+
padding: 0;
|
|
635
|
+
overflow: hidden;
|
|
636
|
+
clip: rect(0 0 0 0);
|
|
637
|
+
white-space: nowrap;
|
|
638
|
+
border: 0;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// Respeita preferência de redução de movimento
|
|
642
|
+
@media (prefers-reduced-motion: reduce) {
|
|
643
|
+
matcha-tree-view-item,
|
|
644
|
+
matcha-tree-view-item:not(.matcha-drag-dragging),
|
|
645
|
+
.matcha-tree-view__children,
|
|
646
|
+
.matcha-tree-view-item__disclosure matcha-icon,
|
|
647
|
+
.matcha-tree-view-item__row,
|
|
648
|
+
.matcha-tree-view-item__grip,
|
|
649
|
+
.matcha-tree-view-item__actions {
|
|
650
|
+
animation: none !important;
|
|
651
|
+
transition: none !important;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// ── Theme mixin ─────────────────────────────────────────────────────────────
|
|
656
|
+
@mixin matcha-tree-view-theme($theme) {
|
|
657
|
+
// Tudo via CSS vars — sem theme-specific overrides.
|
|
658
|
+
}
|