@inchurch/matcha-theme 22.38.2 → 22.38.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/abstracts/_colors.scss +291 -291
- package/abstracts/_elevation.scss +108 -108
- package/abstracts/_functions.scss +321 -321
- package/abstracts/_media-breakpoint.scss +26 -26
- package/abstracts/_theme-api.scss +224 -224
- package/abstracts/_typography.scss +128 -128
- package/base/_reset.scss +487 -487
- package/components/app-page-header.scss +260 -260
- package/components/matcha-accordion.scss +297 -297
- package/components/matcha-audio-player.scss +31 -31
- package/components/matcha-autocomplete.scss +145 -145
- package/components/matcha-avatar.scss +426 -426
- package/components/matcha-badge.scss +120 -120
- package/components/matcha-breadcrumb.scss +231 -231
- package/components/matcha-button-toggle.scss +484 -484
- package/components/matcha-buttons.scss +973 -973
- package/components/matcha-calendar.scss +253 -253
- package/components/matcha-cards.scss +212 -212
- package/components/matcha-chart-card.scss +53 -53
- package/components/matcha-checkbox.scss +266 -266
- package/components/matcha-chip.scss +311 -311
- package/components/matcha-color-pick.scss +34 -34
- package/components/matcha-command-palette.scss +316 -316
- package/components/matcha-crop.scss +419 -419
- package/components/matcha-date.scss +81 -81
- package/components/matcha-divider.scss +100 -100
- package/components/matcha-draggable.scss +23 -23
- package/components/matcha-drawer.scss +376 -376
- package/components/matcha-drop-image.scss +14 -14
- package/components/matcha-drop-list.scss +430 -430
- package/components/matcha-emoji.scss +69 -69
- package/components/matcha-empty-state.scss +230 -230
- package/components/matcha-file-uploader.scss +650 -637
- package/components/matcha-flag.scss +103 -103
- package/components/matcha-footer.scss +91 -91
- package/components/matcha-form-field.scss +883 -883
- package/components/matcha-form-section.scss +100 -100
- package/components/matcha-header.scss +135 -135
- package/components/matcha-highlight.scss +164 -164
- package/components/matcha-hint-text.scss +90 -90
- package/components/matcha-horizontal-tree.scss +247 -247
- package/components/matcha-icon.scss +111 -111
- package/components/matcha-image.scss +60 -60
- package/components/matcha-list.scss +211 -211
- package/components/matcha-menu.scss +99 -99
- package/components/matcha-modal.scss +210 -210
- package/components/matcha-nav.scss +770 -770
- package/components/matcha-notification.scss +417 -417
- package/components/matcha-option.scss +170 -170
- package/components/matcha-page-builder.scss +4196 -4196
- package/components/matcha-paginator.scss +699 -699
- package/components/matcha-panel.scss +216 -216
- package/components/matcha-period.scss +174 -174
- package/components/matcha-profile-card.scss +50 -50
- package/components/matcha-progress-bar.scss +355 -355
- package/components/matcha-radio.scss +325 -325
- package/components/matcha-ripple.scss +7 -7
- package/components/matcha-scrollbar.scss +33 -33
- package/components/matcha-scrollbox-shadow.scss +120 -120
- package/components/matcha-section.scss +102 -102
- package/components/matcha-select-multiple.scss +56 -56
- package/components/matcha-select.scss +629 -629
- package/components/matcha-skeleton.scss +182 -182
- package/components/matcha-slide-toggle.scss +369 -369
- package/components/matcha-slider.scss +285 -285
- package/components/matcha-snack-bar.scss +259 -259
- package/components/matcha-spin.scss +164 -164
- package/components/matcha-spinner.scss +97 -97
- package/components/matcha-stepper.scss +376 -376
- package/components/matcha-table-cell.scss +107 -107
- package/components/matcha-table.scss +722 -722
- package/components/matcha-tabs.scss +642 -642
- package/components/matcha-text-editor.scss +111 -111
- package/components/matcha-time.scss +33 -33
- package/components/matcha-timepicker.scss +13 -13
- package/components/matcha-toolbar.scss +366 -366
- package/components/matcha-tooltip.scss +235 -235
- package/components/matcha-tree-view.scss +636 -636
- package/layout/matcha-page-layout.scss +778 -778
- package/main.scss +334 -334
- package/package.json +1 -1
- package/tokens/_animations-tokens.scss +37 -37
- package/tokens/_breakpoints-tokens.scss +35 -35
- package/tokens/_color-tokens.scss +288 -288
- package/tokens/_elevation-tokens.scss +33 -33
- package/tokens/_emit-tokens.scss +329 -329
- package/tokens/_material-palette.scss +1149 -1149
- package/tokens/_primitives.scss +98 -98
- package/tokens/_semantic-aliases.scss +120 -120
- package/tokens/_spacing-tokens.scss +94 -94
- package/tokens/_static-tokens.scss +137 -137
- package/tokens/_typography-tokens.scss +65 -65
- package/vendors/charts.scss +90 -90
|
@@ -1,636 +1,636 @@
|
|
|
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
|
-
min-height: 2px; // alvo de drop mínimo quando o branch está vazio
|
|
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) ─────────────────────────────────────────
|
|
147
|
-
.matcha-tree-view__node {
|
|
148
|
-
display: block;
|
|
149
|
-
outline: none;
|
|
150
|
-
}
|
|
151
|
-
|
|
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;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// ── Item host ───────────────────────────────────────────────────────────────
|
|
193
|
-
matcha-tree-view-item {
|
|
194
|
-
display: flex;
|
|
195
|
-
flex-direction: row;
|
|
196
|
-
align-items: stretch;
|
|
197
|
-
width: 100%;
|
|
198
|
-
box-sizing: border-box;
|
|
199
|
-
outline: none;
|
|
200
|
-
|
|
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.
|
|
203
|
-
&[disabled] {
|
|
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; }
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
&[clickable]:not([disabled]) {
|
|
213
|
-
cursor: pointer;
|
|
214
|
-
|
|
215
|
-
&:focus-visible .matcha-tree-view-item__row {
|
|
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);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// ── Indent liso (fora do container) — width inline = (level-1) × indentStep ──
|
|
241
|
-
.matcha-tree-view-item__indent {
|
|
242
|
-
flex: none;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// ── Row ─────────────────────────────────────────────────────────────────────
|
|
246
|
-
.matcha-tree-view-item__row {
|
|
247
|
-
position: relative; // contexto do pé da guia e da barra de seleção
|
|
248
|
-
flex: 1;
|
|
249
|
-
display: flex;
|
|
250
|
-
flex-direction: row;
|
|
251
|
-
align-items: center;
|
|
252
|
-
gap: var(--matcha-space-100, 8px);
|
|
253
|
-
min-height: 48px;
|
|
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;
|
|
257
|
-
background: transparent;
|
|
258
|
-
border-radius: var(--matcha-radius-md, 4px);
|
|
259
|
-
box-sizing: border-box;
|
|
260
|
-
min-width: 0;
|
|
261
|
-
transition: background-color var(--matcha-duration-instant, 80ms) ease;
|
|
262
|
-
flex-wrap: var(--matcha-tree-view-item-wrap, nowrap);
|
|
263
|
-
}
|
|
264
|
-
|
|
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);
|
|
270
|
-
}
|
|
271
|
-
|
|
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.
|
|
274
|
-
matcha-tree-view-item:not([disabled]):hover .matcha-tree-view-item__row {
|
|
275
|
-
background: var(--matcha-color-surface-hover);
|
|
276
|
-
}
|
|
277
|
-
|
|
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.
|
|
288
|
-
.matcha-tree-view-item__grip {
|
|
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);
|
|
295
|
-
--matcha-icon-color: var(--matcha-color-text-muted);
|
|
296
|
-
cursor: grab;
|
|
297
|
-
opacity: 0;
|
|
298
|
-
transition: opacity var(--matcha-duration-instant, 80ms) ease;
|
|
299
|
-
|
|
300
|
-
&:active { cursor: grabbing; }
|
|
301
|
-
}
|
|
302
|
-
|
|
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;
|
|
313
|
-
}
|
|
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;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// Alvo de drop de um branch VAZIO — nó expandido sem filhos, lazy-load, árvore
|
|
326
|
-
// vazia. Renderizado durante todo o drag (não só quando já está sob o cursor):
|
|
327
|
-
// sem altura própria o branch tem ~2px e é impossível mirar pra soltar/reparentar
|
|
328
|
-
// dentro do nó. (IN-42506)
|
|
329
|
-
.matcha-tree-view .matcha-drop-list-empty-placeholder {
|
|
330
|
-
display: flex;
|
|
331
|
-
align-items: center;
|
|
332
|
-
justify-content: center;
|
|
333
|
-
min-height: 40px;
|
|
334
|
-
margin: var(--matcha-space-050, 4px) 0;
|
|
335
|
-
padding: var(--matcha-space-150, 12px);
|
|
336
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
337
|
-
color: var(--matcha-color-text-muted);
|
|
338
|
-
border: 2px dashed var(--matcha-color-surface-border);
|
|
339
|
-
border-radius: var(--matcha-radius-md, 4px);
|
|
340
|
-
background: transparent;
|
|
341
|
-
// Sem transição: o feedback de aceite/rejeição precisa ser imediato durante o
|
|
342
|
-
// drag (o estado alterna a cada mousemove perto de uma borda de validação).
|
|
343
|
-
|
|
344
|
-
// Drag ativo mas o cursor ainda não chegou / chegou e o drop é válido.
|
|
345
|
-
&.can-accept {
|
|
346
|
-
border-color: var(--matcha-color-accent);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// Cursor sobre o alvo e o drop é rejeitado (profundidade, ciclo, tipo).
|
|
350
|
-
&.cannot-accept {
|
|
351
|
-
border-color: var(--matcha-color-danger);
|
|
352
|
-
background: var(--matcha-color-danger-alpha, transparent);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
// Em ponteiro grosso (toque) não existe hover: grip e ações ficam visíveis.
|
|
357
|
-
@media (hover: none) {
|
|
358
|
-
.matcha-tree-view-item__grip,
|
|
359
|
-
.matcha-tree-view-item__actions { opacity: 1; }
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// Navegar (›): o trailing do drill-down mobile. Sempre visível; substitui as
|
|
363
|
-
// ações quando a linha inteira navega.
|
|
364
|
-
.matcha-tree-view-item__navigate {
|
|
365
|
-
flex: none;
|
|
366
|
-
display: inline-flex;
|
|
367
|
-
align-items: center;
|
|
368
|
-
justify-content: center;
|
|
369
|
-
width: var(--matcha-tree-view-control-size, 32px);
|
|
370
|
-
height: var(--matcha-tree-view-control-size, 32px);
|
|
371
|
-
--matcha-icon-color: var(--matcha-color-text-muted);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// Disclosure: 32px, reserva o slot mesmo na folha (use a classe num <span>
|
|
375
|
-
// vazio) pra a identidade alinhar entre irmãos. Um único chevron-right que o
|
|
376
|
-
// tema gira em 150ms quando o item está [expanded]; caption em repouso, texto
|
|
377
|
-
// no hover/focus.
|
|
378
|
-
matcha-tree-view-item .matcha-tree-view-item__disclosure {
|
|
379
|
-
flex: none;
|
|
380
|
-
display: inline-flex;
|
|
381
|
-
align-items: center;
|
|
382
|
-
justify-content: center;
|
|
383
|
-
width: var(--matcha-tree-view-control-size, 32px);
|
|
384
|
-
height: var(--matcha-tree-view-control-size, 32px);
|
|
385
|
-
--matcha-icon-color: var(--matcha-color-text-muted);
|
|
386
|
-
|
|
387
|
-
matcha-icon {
|
|
388
|
-
transition: transform 150ms var(--matcha-easing-standard, ease);
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
matcha-tree-view-item[expanded] .matcha-tree-view-item__disclosure matcha-icon {
|
|
393
|
-
transform: rotate(90deg);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
matcha-tree-view-item:hover .matcha-tree-view-item__disclosure,
|
|
397
|
-
matcha-tree-view-item:focus-within .matcha-tree-view-item__disclosure,
|
|
398
|
-
.matcha-tree-view__node:focus-visible > matcha-tree-view-item .matcha-tree-view-item__disclosure {
|
|
399
|
-
--matcha-icon-color: var(--matcha-color-text-primary);
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// Identidade (dot|avatar + textos). Fica com o espaço que sobra e é a ÚLTIMA a
|
|
403
|
-
// ceder: sem isso o flex encolhe na ordem do DOM e, em tela estreita, o NOME
|
|
404
|
-
// chegava a zero enquanto cargo e contador ficavam intactos.
|
|
405
|
-
.matcha-tree-view-item__identity {
|
|
406
|
-
flex: 1 1 auto;
|
|
407
|
-
min-width: 4ch; // piso: sempre sobra o começo do nome
|
|
408
|
-
display: flex;
|
|
409
|
-
align-items: center;
|
|
410
|
-
gap: var(--matcha-space-100, 8px);
|
|
411
|
-
// SEM overflow:hidden. Quem trunca é o texto (min-width:0 + text-overflow
|
|
412
|
-
// no __name/__secondary), e recortar aqui comia os 2px do anel de nível do
|
|
413
|
-
// avatar — que ficava com as beiradas retas — e comeria também o anel de
|
|
414
|
-
// foco de qualquer controle projetado na identidade.
|
|
415
|
-
overflow: visible;
|
|
416
|
-
|
|
417
|
-
> * { min-width: 0; }
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
// Cor de nível: no dot (6px + anel a 20%) ou no anel do avatar. O consumer
|
|
421
|
-
// informa a cor em --matcha-tree-view-level-color; sem ela, herda o texto.
|
|
422
|
-
.matcha-tree-view-item__dot {
|
|
423
|
-
flex: none;
|
|
424
|
-
width: 6px;
|
|
425
|
-
height: 6px;
|
|
426
|
-
margin: var(--matcha-border-thin, 2px);
|
|
427
|
-
border-radius: var(--matcha-radius-pill, 9999px);
|
|
428
|
-
background: var(--matcha-tree-view-level-color, currentColor);
|
|
429
|
-
box-shadow: 0 0 0 var(--matcha-border-thin, 2px)
|
|
430
|
-
color-mix(in srgb, var(--matcha-tree-view-level-color, currentColor) 20%, transparent);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
.matcha-tree-view-item__avatar {
|
|
434
|
-
flex: none;
|
|
435
|
-
display: inline-flex;
|
|
436
|
-
|
|
437
|
-
.matcha-avatar {
|
|
438
|
-
border-radius: var(--matcha-radius-pill, 9999px);
|
|
439
|
-
box-shadow: 0 0 0 var(--matcha-border-thin, 2px) var(--matcha-tree-view-level-color, transparent);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
// Textos: nome (label-medium) e linha secundária opcional (p-small, caption).
|
|
444
|
-
// Com linha secundária a row cresce pra 64px sozinha.
|
|
445
|
-
.matcha-tree-view-item__text {
|
|
446
|
-
flex: 1 1 auto;
|
|
447
|
-
min-width: 0;
|
|
448
|
-
display: flex;
|
|
449
|
-
flex-direction: column;
|
|
450
|
-
gap: var(--matcha-border-thin, 2px);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
.matcha-tree-view-item__name {
|
|
454
|
-
display: block;
|
|
455
|
-
min-width: 0;
|
|
456
|
-
overflow: hidden;
|
|
457
|
-
text-overflow: ellipsis;
|
|
458
|
-
white-space: nowrap;
|
|
459
|
-
font-size: var(--matcha-text-label-md, 14px);
|
|
460
|
-
font-weight: var(--matcha-font-weight-medium, 500);
|
|
461
|
-
line-height: 20px;
|
|
462
|
-
color: var(--matcha-color-text-primary);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
.matcha-tree-view-item__secondary {
|
|
466
|
-
display: block;
|
|
467
|
-
min-width: 0;
|
|
468
|
-
overflow: hidden;
|
|
469
|
-
text-overflow: ellipsis;
|
|
470
|
-
white-space: nowrap;
|
|
471
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
472
|
-
line-height: 16px;
|
|
473
|
-
color: var(--matcha-color-text-muted);
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
// Meta (cargo + contadores). Cede ANTES do nome e, quando não cabe, sai de cena.
|
|
477
|
-
.matcha-tree-view-item__meta {
|
|
478
|
-
flex: 0 1 auto;
|
|
479
|
-
min-width: 0;
|
|
480
|
-
margin-inline-start: auto;
|
|
481
|
-
display: flex;
|
|
482
|
-
align-items: center;
|
|
483
|
-
gap: var(--matcha-space-100, 8px);
|
|
484
|
-
overflow: hidden;
|
|
485
|
-
color: var(--matcha-color-text-muted);
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
// Cargo é TEXTO, não pílula: pílula em toda linha é peso repetido 30 vezes na
|
|
489
|
-
// tela. Pílula (matcha-badge) fica pra ESTADO (Inativo, Pendente).
|
|
490
|
-
.matcha-tree-view-item__cargo {
|
|
491
|
-
flex: none;
|
|
492
|
-
font-size: var(--matcha-text-label-sm, 12px);
|
|
493
|
-
font-weight: var(--matcha-font-weight-medium, 500);
|
|
494
|
-
line-height: 16px;
|
|
495
|
-
color: var(--matcha-color-text-muted);
|
|
496
|
-
white-space: nowrap;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
// Contadores: números tabulares (alinham à direita sem parecer relatório) e
|
|
500
|
-
// sem zero à esquerda — isso é do dado, não do CSS: "2 células", não "02".
|
|
501
|
-
.matcha-tree-view-item__counters {
|
|
502
|
-
flex: none;
|
|
503
|
-
display: inline-flex;
|
|
504
|
-
align-items: baseline;
|
|
505
|
-
gap: var(--matcha-space-050, 4px);
|
|
506
|
-
font-variant-numeric: tabular-nums;
|
|
507
|
-
white-space: nowrap;
|
|
508
|
-
|
|
509
|
-
strong {
|
|
510
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
511
|
-
font-weight: var(--matcha-font-weight-medium, 500);
|
|
512
|
-
color: var(--matcha-color-text-primary);
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
small {
|
|
516
|
-
font-size: var(--matcha-text-p-tiny, 11px);
|
|
517
|
-
letter-spacing: 0.3px;
|
|
518
|
-
color: var(--matcha-color-text-muted);
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
// Só some quando não há mesmo onde caber. Entre 360 e 480 o flex encolhe o
|
|
523
|
-
// meta antes do nome.
|
|
524
|
-
@container matcha-tree-view (max-width: 360px) {
|
|
525
|
-
.matcha-tree-view-item__meta { display: none; }
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
@container matcha-tree-view (max-width: 480px) {
|
|
529
|
-
.matcha-tree-view-item__indent {
|
|
530
|
-
transform: scaleX(0.6);
|
|
531
|
-
transform-origin: left center;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
.matcha-tree-view-item__row {
|
|
535
|
-
gap: var(--matcha-space-050, 4px);
|
|
536
|
-
min-height: 44px; // alvo de toque WCAG 2.5.5 em mobile
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
// ── Drag-and-drop (compõe com o motor do matcha-drop-list) ──────────────────
|
|
541
|
-
|
|
542
|
-
// Dragging = o FANTASMA na origem. O motor do drop-list aplica isso INLINE no
|
|
543
|
-
// wrapper arrastado (opacidade + translate dos irmãos) — não há classe pra
|
|
544
|
-
// estilizar aqui; o que o tema garante é que o wrapper não ganhe fundo, sombra
|
|
545
|
-
// ou escala de "card solto" (ver as regras do wrapper acima).
|
|
546
|
-
|
|
547
|
-
// Levantado = a cópia que acompanha o cursor: SÓ a linha, com superfície e
|
|
548
|
-
// elevação level-2. O motor clona o wrapper inteiro (a subárvore junto);
|
|
549
|
-
// esconder os filhos no clone deixa a cópia do tamanho de uma linha.
|
|
550
|
-
.matcha-drag-ghost {
|
|
551
|
-
box-shadow: none; // a elevação é da row, não da caixa do clone
|
|
552
|
-
|
|
553
|
-
.matcha-tree-view__children-host { display: none; }
|
|
554
|
-
|
|
555
|
-
.matcha-tree-view-item__row {
|
|
556
|
-
background: var(--matcha-color-surface);
|
|
557
|
-
box-shadow: var(--matcha-shadow-2);
|
|
558
|
-
border-radius: var(--matcha-radius-md, 4px);
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
.matcha-tree-view-item__grip { opacity: 1; }
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
// Região do aria-live: só pra leitor de tela.
|
|
565
|
-
.matcha-tree-view__live {
|
|
566
|
-
position: absolute;
|
|
567
|
-
width: 1px;
|
|
568
|
-
height: 1px;
|
|
569
|
-
margin: -1px;
|
|
570
|
-
padding: 0;
|
|
571
|
-
overflow: hidden;
|
|
572
|
-
clip: rect(0 0 0 0);
|
|
573
|
-
white-space: nowrap;
|
|
574
|
-
border: 0;
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
// Recebendo = o PAI que vai receber o drop dentro: tinta accent + hairline
|
|
578
|
-
// accent na linha dele. O motor marca o branch dos filhos; a linha do pai é a
|
|
579
|
-
// irmã anterior do bloco, daí o :has() com filhos diretos.
|
|
580
|
-
.matcha-tree-view .matcha-tree-view__node:has(
|
|
581
|
-
> .matcha-tree-view__children-host > .matcha-tree-view__children > matcha-tree-branch.matcha-drop-list-receiving
|
|
582
|
-
) > matcha-tree-view-item .matcha-tree-view-item__row {
|
|
583
|
-
background: var(--matcha-color-accent-surface-hover, var(--matcha-color-accent-alpha));
|
|
584
|
-
box-shadow: inset 0 0 0 var(--matcha-border-hairline, 1px) var(--matcha-color-accent);
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
// Recusado = destino inválido por TIPO: tracejado danger na linha do pai. A
|
|
588
|
-
// zona em si não ganha moldura, e a subárvore de quem está sendo arrastado
|
|
589
|
-
// (.matcha-drop-zone-self) não é pintada: rejeitar a si mesmo é óbvio.
|
|
590
|
-
.matcha-tree-view .matcha-tree-view__node:has(
|
|
591
|
-
> .matcha-tree-view__children-host > .matcha-drop-zone-cannot-accept:not(.matcha-drop-zone-self)
|
|
592
|
-
) > matcha-tree-view-item .matcha-tree-view-item__row {
|
|
593
|
-
outline: var(--matcha-border-hairline, 1px) dashed var(--matcha-color-danger);
|
|
594
|
-
outline-offset: calc(-1 * var(--matcha-border-hairline, 1px));
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
// A moldura listrada/tracejada que o drop-list dá à zona não vale na árvore.
|
|
598
|
-
.matcha-tree-view .matcha-tree-view__children.matcha-drop-zone-cannot-accept {
|
|
599
|
-
outline: none;
|
|
600
|
-
background: transparent;
|
|
601
|
-
border: 0;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
// O branch NÃO herda a moldura listrada do drop-list plano.
|
|
605
|
-
.matcha-tree-view matcha-tree-branch.matcha-drop-list-receiving,
|
|
606
|
-
.matcha-tree-view matcha-tree-branch.matcha-drop-list-can-accept,
|
|
607
|
-
.matcha-tree-view matcha-tree-branch.matcha-drop-list-cannot-accept {
|
|
608
|
-
background: transparent;
|
|
609
|
-
border: 0;
|
|
610
|
-
padding: 0;
|
|
611
|
-
|
|
612
|
-
&::before { content: none; }
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
// Entre irmãos NÃO há linha indicadora: o motor abre o espaço do item arrastado
|
|
616
|
-
// (translateY nos irmãos, 150ms) e deixa o fantasma na origem. É o "indicador"
|
|
617
|
-
// do código; o bloco drop-indicator do Figma é a representação estática disso.
|
|
618
|
-
|
|
619
|
-
// Respeita preferência de redução de movimento
|
|
620
|
-
@media (prefers-reduced-motion: reduce) {
|
|
621
|
-
matcha-tree-view-item,
|
|
622
|
-
matcha-tree-view-item:not(.matcha-drag-dragging),
|
|
623
|
-
.matcha-tree-view__children,
|
|
624
|
-
.matcha-tree-view-item__disclosure matcha-icon,
|
|
625
|
-
.matcha-tree-view-item__row,
|
|
626
|
-
.matcha-tree-view-item__grip,
|
|
627
|
-
.matcha-tree-view-item__actions {
|
|
628
|
-
animation: none !important;
|
|
629
|
-
transition: none !important;
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
// ── Theme mixin ─────────────────────────────────────────────────────────────
|
|
634
|
-
@mixin matcha-tree-view-theme($theme) {
|
|
635
|
-
// Tudo via CSS vars — sem theme-specific overrides.
|
|
636
|
-
}
|
|
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
|
+
min-height: 2px; // alvo de drop mínimo quando o branch está vazio
|
|
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) ─────────────────────────────────────────
|
|
147
|
+
.matcha-tree-view__node {
|
|
148
|
+
display: block;
|
|
149
|
+
outline: none;
|
|
150
|
+
}
|
|
151
|
+
|
|
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;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ── Item host ───────────────────────────────────────────────────────────────
|
|
193
|
+
matcha-tree-view-item {
|
|
194
|
+
display: flex;
|
|
195
|
+
flex-direction: row;
|
|
196
|
+
align-items: stretch;
|
|
197
|
+
width: 100%;
|
|
198
|
+
box-sizing: border-box;
|
|
199
|
+
outline: none;
|
|
200
|
+
|
|
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.
|
|
203
|
+
&[disabled] {
|
|
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; }
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
&[clickable]:not([disabled]) {
|
|
213
|
+
cursor: pointer;
|
|
214
|
+
|
|
215
|
+
&:focus-visible .matcha-tree-view-item__row {
|
|
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);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// ── Indent liso (fora do container) — width inline = (level-1) × indentStep ──
|
|
241
|
+
.matcha-tree-view-item__indent {
|
|
242
|
+
flex: none;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ── Row ─────────────────────────────────────────────────────────────────────
|
|
246
|
+
.matcha-tree-view-item__row {
|
|
247
|
+
position: relative; // contexto do pé da guia e da barra de seleção
|
|
248
|
+
flex: 1;
|
|
249
|
+
display: flex;
|
|
250
|
+
flex-direction: row;
|
|
251
|
+
align-items: center;
|
|
252
|
+
gap: var(--matcha-space-100, 8px);
|
|
253
|
+
min-height: 48px;
|
|
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;
|
|
257
|
+
background: transparent;
|
|
258
|
+
border-radius: var(--matcha-radius-md, 4px);
|
|
259
|
+
box-sizing: border-box;
|
|
260
|
+
min-width: 0;
|
|
261
|
+
transition: background-color var(--matcha-duration-instant, 80ms) ease;
|
|
262
|
+
flex-wrap: var(--matcha-tree-view-item-wrap, nowrap);
|
|
263
|
+
}
|
|
264
|
+
|
|
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);
|
|
270
|
+
}
|
|
271
|
+
|
|
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.
|
|
274
|
+
matcha-tree-view-item:not([disabled]):hover .matcha-tree-view-item__row {
|
|
275
|
+
background: var(--matcha-color-surface-hover);
|
|
276
|
+
}
|
|
277
|
+
|
|
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.
|
|
288
|
+
.matcha-tree-view-item__grip {
|
|
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);
|
|
295
|
+
--matcha-icon-color: var(--matcha-color-text-muted);
|
|
296
|
+
cursor: grab;
|
|
297
|
+
opacity: 0;
|
|
298
|
+
transition: opacity var(--matcha-duration-instant, 80ms) ease;
|
|
299
|
+
|
|
300
|
+
&:active { cursor: grabbing; }
|
|
301
|
+
}
|
|
302
|
+
|
|
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;
|
|
313
|
+
}
|
|
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;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Alvo de drop de um branch VAZIO — nó expandido sem filhos, lazy-load, árvore
|
|
326
|
+
// vazia. Renderizado durante todo o drag (não só quando já está sob o cursor):
|
|
327
|
+
// sem altura própria o branch tem ~2px e é impossível mirar pra soltar/reparentar
|
|
328
|
+
// dentro do nó. (IN-42506)
|
|
329
|
+
.matcha-tree-view .matcha-drop-list-empty-placeholder {
|
|
330
|
+
display: flex;
|
|
331
|
+
align-items: center;
|
|
332
|
+
justify-content: center;
|
|
333
|
+
min-height: 40px;
|
|
334
|
+
margin: var(--matcha-space-050, 4px) 0;
|
|
335
|
+
padding: var(--matcha-space-150, 12px);
|
|
336
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
337
|
+
color: var(--matcha-color-text-muted);
|
|
338
|
+
border: 2px dashed var(--matcha-color-surface-border);
|
|
339
|
+
border-radius: var(--matcha-radius-md, 4px);
|
|
340
|
+
background: transparent;
|
|
341
|
+
// Sem transição: o feedback de aceite/rejeição precisa ser imediato durante o
|
|
342
|
+
// drag (o estado alterna a cada mousemove perto de uma borda de validação).
|
|
343
|
+
|
|
344
|
+
// Drag ativo mas o cursor ainda não chegou / chegou e o drop é válido.
|
|
345
|
+
&.can-accept {
|
|
346
|
+
border-color: var(--matcha-color-accent);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Cursor sobre o alvo e o drop é rejeitado (profundidade, ciclo, tipo).
|
|
350
|
+
&.cannot-accept {
|
|
351
|
+
border-color: var(--matcha-color-danger);
|
|
352
|
+
background: var(--matcha-color-danger-alpha, transparent);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Em ponteiro grosso (toque) não existe hover: grip e ações ficam visíveis.
|
|
357
|
+
@media (hover: none) {
|
|
358
|
+
.matcha-tree-view-item__grip,
|
|
359
|
+
.matcha-tree-view-item__actions { opacity: 1; }
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Navegar (›): o trailing do drill-down mobile. Sempre visível; substitui as
|
|
363
|
+
// ações quando a linha inteira navega.
|
|
364
|
+
.matcha-tree-view-item__navigate {
|
|
365
|
+
flex: none;
|
|
366
|
+
display: inline-flex;
|
|
367
|
+
align-items: center;
|
|
368
|
+
justify-content: center;
|
|
369
|
+
width: var(--matcha-tree-view-control-size, 32px);
|
|
370
|
+
height: var(--matcha-tree-view-control-size, 32px);
|
|
371
|
+
--matcha-icon-color: var(--matcha-color-text-muted);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Disclosure: 32px, reserva o slot mesmo na folha (use a classe num <span>
|
|
375
|
+
// vazio) pra a identidade alinhar entre irmãos. Um único chevron-right que o
|
|
376
|
+
// tema gira em 150ms quando o item está [expanded]; caption em repouso, texto
|
|
377
|
+
// no hover/focus.
|
|
378
|
+
matcha-tree-view-item .matcha-tree-view-item__disclosure {
|
|
379
|
+
flex: none;
|
|
380
|
+
display: inline-flex;
|
|
381
|
+
align-items: center;
|
|
382
|
+
justify-content: center;
|
|
383
|
+
width: var(--matcha-tree-view-control-size, 32px);
|
|
384
|
+
height: var(--matcha-tree-view-control-size, 32px);
|
|
385
|
+
--matcha-icon-color: var(--matcha-color-text-muted);
|
|
386
|
+
|
|
387
|
+
matcha-icon {
|
|
388
|
+
transition: transform 150ms var(--matcha-easing-standard, ease);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
matcha-tree-view-item[expanded] .matcha-tree-view-item__disclosure matcha-icon {
|
|
393
|
+
transform: rotate(90deg);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
matcha-tree-view-item:hover .matcha-tree-view-item__disclosure,
|
|
397
|
+
matcha-tree-view-item:focus-within .matcha-tree-view-item__disclosure,
|
|
398
|
+
.matcha-tree-view__node:focus-visible > matcha-tree-view-item .matcha-tree-view-item__disclosure {
|
|
399
|
+
--matcha-icon-color: var(--matcha-color-text-primary);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Identidade (dot|avatar + textos). Fica com o espaço que sobra e é a ÚLTIMA a
|
|
403
|
+
// ceder: sem isso o flex encolhe na ordem do DOM e, em tela estreita, o NOME
|
|
404
|
+
// chegava a zero enquanto cargo e contador ficavam intactos.
|
|
405
|
+
.matcha-tree-view-item__identity {
|
|
406
|
+
flex: 1 1 auto;
|
|
407
|
+
min-width: 4ch; // piso: sempre sobra o começo do nome
|
|
408
|
+
display: flex;
|
|
409
|
+
align-items: center;
|
|
410
|
+
gap: var(--matcha-space-100, 8px);
|
|
411
|
+
// SEM overflow:hidden. Quem trunca é o texto (min-width:0 + text-overflow
|
|
412
|
+
// no __name/__secondary), e recortar aqui comia os 2px do anel de nível do
|
|
413
|
+
// avatar — que ficava com as beiradas retas — e comeria também o anel de
|
|
414
|
+
// foco de qualquer controle projetado na identidade.
|
|
415
|
+
overflow: visible;
|
|
416
|
+
|
|
417
|
+
> * { min-width: 0; }
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Cor de nível: no dot (6px + anel a 20%) ou no anel do avatar. O consumer
|
|
421
|
+
// informa a cor em --matcha-tree-view-level-color; sem ela, herda o texto.
|
|
422
|
+
.matcha-tree-view-item__dot {
|
|
423
|
+
flex: none;
|
|
424
|
+
width: 6px;
|
|
425
|
+
height: 6px;
|
|
426
|
+
margin: var(--matcha-border-thin, 2px);
|
|
427
|
+
border-radius: var(--matcha-radius-pill, 9999px);
|
|
428
|
+
background: var(--matcha-tree-view-level-color, currentColor);
|
|
429
|
+
box-shadow: 0 0 0 var(--matcha-border-thin, 2px)
|
|
430
|
+
color-mix(in srgb, var(--matcha-tree-view-level-color, currentColor) 20%, transparent);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
.matcha-tree-view-item__avatar {
|
|
434
|
+
flex: none;
|
|
435
|
+
display: inline-flex;
|
|
436
|
+
|
|
437
|
+
.matcha-avatar {
|
|
438
|
+
border-radius: var(--matcha-radius-pill, 9999px);
|
|
439
|
+
box-shadow: 0 0 0 var(--matcha-border-thin, 2px) var(--matcha-tree-view-level-color, transparent);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Textos: nome (label-medium) e linha secundária opcional (p-small, caption).
|
|
444
|
+
// Com linha secundária a row cresce pra 64px sozinha.
|
|
445
|
+
.matcha-tree-view-item__text {
|
|
446
|
+
flex: 1 1 auto;
|
|
447
|
+
min-width: 0;
|
|
448
|
+
display: flex;
|
|
449
|
+
flex-direction: column;
|
|
450
|
+
gap: var(--matcha-border-thin, 2px);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
.matcha-tree-view-item__name {
|
|
454
|
+
display: block;
|
|
455
|
+
min-width: 0;
|
|
456
|
+
overflow: hidden;
|
|
457
|
+
text-overflow: ellipsis;
|
|
458
|
+
white-space: nowrap;
|
|
459
|
+
font-size: var(--matcha-text-label-md, 14px);
|
|
460
|
+
font-weight: var(--matcha-font-weight-medium, 500);
|
|
461
|
+
line-height: 20px;
|
|
462
|
+
color: var(--matcha-color-text-primary);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
.matcha-tree-view-item__secondary {
|
|
466
|
+
display: block;
|
|
467
|
+
min-width: 0;
|
|
468
|
+
overflow: hidden;
|
|
469
|
+
text-overflow: ellipsis;
|
|
470
|
+
white-space: nowrap;
|
|
471
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
472
|
+
line-height: 16px;
|
|
473
|
+
color: var(--matcha-color-text-muted);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// Meta (cargo + contadores). Cede ANTES do nome e, quando não cabe, sai de cena.
|
|
477
|
+
.matcha-tree-view-item__meta {
|
|
478
|
+
flex: 0 1 auto;
|
|
479
|
+
min-width: 0;
|
|
480
|
+
margin-inline-start: auto;
|
|
481
|
+
display: flex;
|
|
482
|
+
align-items: center;
|
|
483
|
+
gap: var(--matcha-space-100, 8px);
|
|
484
|
+
overflow: hidden;
|
|
485
|
+
color: var(--matcha-color-text-muted);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// Cargo é TEXTO, não pílula: pílula em toda linha é peso repetido 30 vezes na
|
|
489
|
+
// tela. Pílula (matcha-badge) fica pra ESTADO (Inativo, Pendente).
|
|
490
|
+
.matcha-tree-view-item__cargo {
|
|
491
|
+
flex: none;
|
|
492
|
+
font-size: var(--matcha-text-label-sm, 12px);
|
|
493
|
+
font-weight: var(--matcha-font-weight-medium, 500);
|
|
494
|
+
line-height: 16px;
|
|
495
|
+
color: var(--matcha-color-text-muted);
|
|
496
|
+
white-space: nowrap;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// Contadores: números tabulares (alinham à direita sem parecer relatório) e
|
|
500
|
+
// sem zero à esquerda — isso é do dado, não do CSS: "2 células", não "02".
|
|
501
|
+
.matcha-tree-view-item__counters {
|
|
502
|
+
flex: none;
|
|
503
|
+
display: inline-flex;
|
|
504
|
+
align-items: baseline;
|
|
505
|
+
gap: var(--matcha-space-050, 4px);
|
|
506
|
+
font-variant-numeric: tabular-nums;
|
|
507
|
+
white-space: nowrap;
|
|
508
|
+
|
|
509
|
+
strong {
|
|
510
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
511
|
+
font-weight: var(--matcha-font-weight-medium, 500);
|
|
512
|
+
color: var(--matcha-color-text-primary);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
small {
|
|
516
|
+
font-size: var(--matcha-text-p-tiny, 11px);
|
|
517
|
+
letter-spacing: 0.3px;
|
|
518
|
+
color: var(--matcha-color-text-muted);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Só some quando não há mesmo onde caber. Entre 360 e 480 o flex encolhe o
|
|
523
|
+
// meta antes do nome.
|
|
524
|
+
@container matcha-tree-view (max-width: 360px) {
|
|
525
|
+
.matcha-tree-view-item__meta { display: none; }
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
@container matcha-tree-view (max-width: 480px) {
|
|
529
|
+
.matcha-tree-view-item__indent {
|
|
530
|
+
transform: scaleX(0.6);
|
|
531
|
+
transform-origin: left center;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
.matcha-tree-view-item__row {
|
|
535
|
+
gap: var(--matcha-space-050, 4px);
|
|
536
|
+
min-height: 44px; // alvo de toque WCAG 2.5.5 em mobile
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// ── Drag-and-drop (compõe com o motor do matcha-drop-list) ──────────────────
|
|
541
|
+
|
|
542
|
+
// Dragging = o FANTASMA na origem. O motor do drop-list aplica isso INLINE no
|
|
543
|
+
// wrapper arrastado (opacidade + translate dos irmãos) — não há classe pra
|
|
544
|
+
// estilizar aqui; o que o tema garante é que o wrapper não ganhe fundo, sombra
|
|
545
|
+
// ou escala de "card solto" (ver as regras do wrapper acima).
|
|
546
|
+
|
|
547
|
+
// Levantado = a cópia que acompanha o cursor: SÓ a linha, com superfície e
|
|
548
|
+
// elevação level-2. O motor clona o wrapper inteiro (a subárvore junto);
|
|
549
|
+
// esconder os filhos no clone deixa a cópia do tamanho de uma linha.
|
|
550
|
+
.matcha-drag-ghost {
|
|
551
|
+
box-shadow: none; // a elevação é da row, não da caixa do clone
|
|
552
|
+
|
|
553
|
+
.matcha-tree-view__children-host { display: none; }
|
|
554
|
+
|
|
555
|
+
.matcha-tree-view-item__row {
|
|
556
|
+
background: var(--matcha-color-surface);
|
|
557
|
+
box-shadow: var(--matcha-shadow-2);
|
|
558
|
+
border-radius: var(--matcha-radius-md, 4px);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.matcha-tree-view-item__grip { opacity: 1; }
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// Região do aria-live: só pra leitor de tela.
|
|
565
|
+
.matcha-tree-view__live {
|
|
566
|
+
position: absolute;
|
|
567
|
+
width: 1px;
|
|
568
|
+
height: 1px;
|
|
569
|
+
margin: -1px;
|
|
570
|
+
padding: 0;
|
|
571
|
+
overflow: hidden;
|
|
572
|
+
clip: rect(0 0 0 0);
|
|
573
|
+
white-space: nowrap;
|
|
574
|
+
border: 0;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// Recebendo = o PAI que vai receber o drop dentro: tinta accent + hairline
|
|
578
|
+
// accent na linha dele. O motor marca o branch dos filhos; a linha do pai é a
|
|
579
|
+
// irmã anterior do bloco, daí o :has() com filhos diretos.
|
|
580
|
+
.matcha-tree-view .matcha-tree-view__node:has(
|
|
581
|
+
> .matcha-tree-view__children-host > .matcha-tree-view__children > matcha-tree-branch.matcha-drop-list-receiving
|
|
582
|
+
) > matcha-tree-view-item .matcha-tree-view-item__row {
|
|
583
|
+
background: var(--matcha-color-accent-surface-hover, var(--matcha-color-accent-alpha));
|
|
584
|
+
box-shadow: inset 0 0 0 var(--matcha-border-hairline, 1px) var(--matcha-color-accent);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// Recusado = destino inválido por TIPO: tracejado danger na linha do pai. A
|
|
588
|
+
// zona em si não ganha moldura, e a subárvore de quem está sendo arrastado
|
|
589
|
+
// (.matcha-drop-zone-self) não é pintada: rejeitar a si mesmo é óbvio.
|
|
590
|
+
.matcha-tree-view .matcha-tree-view__node:has(
|
|
591
|
+
> .matcha-tree-view__children-host > .matcha-drop-zone-cannot-accept:not(.matcha-drop-zone-self)
|
|
592
|
+
) > matcha-tree-view-item .matcha-tree-view-item__row {
|
|
593
|
+
outline: var(--matcha-border-hairline, 1px) dashed var(--matcha-color-danger);
|
|
594
|
+
outline-offset: calc(-1 * var(--matcha-border-hairline, 1px));
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// A moldura listrada/tracejada que o drop-list dá à zona não vale na árvore.
|
|
598
|
+
.matcha-tree-view .matcha-tree-view__children.matcha-drop-zone-cannot-accept {
|
|
599
|
+
outline: none;
|
|
600
|
+
background: transparent;
|
|
601
|
+
border: 0;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// O branch NÃO herda a moldura listrada do drop-list plano.
|
|
605
|
+
.matcha-tree-view matcha-tree-branch.matcha-drop-list-receiving,
|
|
606
|
+
.matcha-tree-view matcha-tree-branch.matcha-drop-list-can-accept,
|
|
607
|
+
.matcha-tree-view matcha-tree-branch.matcha-drop-list-cannot-accept {
|
|
608
|
+
background: transparent;
|
|
609
|
+
border: 0;
|
|
610
|
+
padding: 0;
|
|
611
|
+
|
|
612
|
+
&::before { content: none; }
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// Entre irmãos NÃO há linha indicadora: o motor abre o espaço do item arrastado
|
|
616
|
+
// (translateY nos irmãos, 150ms) e deixa o fantasma na origem. É o "indicador"
|
|
617
|
+
// do código; o bloco drop-indicator do Figma é a representação estática disso.
|
|
618
|
+
|
|
619
|
+
// Respeita preferência de redução de movimento
|
|
620
|
+
@media (prefers-reduced-motion: reduce) {
|
|
621
|
+
matcha-tree-view-item,
|
|
622
|
+
matcha-tree-view-item:not(.matcha-drag-dragging),
|
|
623
|
+
.matcha-tree-view__children,
|
|
624
|
+
.matcha-tree-view-item__disclosure matcha-icon,
|
|
625
|
+
.matcha-tree-view-item__row,
|
|
626
|
+
.matcha-tree-view-item__grip,
|
|
627
|
+
.matcha-tree-view-item__actions {
|
|
628
|
+
animation: none !important;
|
|
629
|
+
transition: none !important;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// ── Theme mixin ─────────────────────────────────────────────────────────────
|
|
634
|
+
@mixin matcha-tree-view-theme($theme) {
|
|
635
|
+
// Tudo via CSS vars — sem theme-specific overrides.
|
|
636
|
+
}
|