@inchurch/matcha-theme 21.3.3 → 22.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/abstracts/_colors.scss +236 -229
  2. package/abstracts/_elevation.scss +108 -108
  3. package/abstracts/_functions.scss +321 -321
  4. package/abstracts/_media-breakpoint.scss +26 -26
  5. package/abstracts/_theme-api.scss +219 -219
  6. package/abstracts/_typography.scss +128 -128
  7. package/base/_reset.scss +445 -432
  8. package/components/app-page-header.scss +260 -260
  9. package/components/matcha-accordion.scss +293 -293
  10. package/components/matcha-audio-player.scss +31 -31
  11. package/components/matcha-autocomplete.scss +145 -145
  12. package/components/matcha-avatar.scss +440 -301
  13. package/components/matcha-badge.scss +120 -120
  14. package/components/matcha-breadcrumb.scss +231 -231
  15. package/components/matcha-button-toggle.scss +384 -384
  16. package/components/matcha-buttons.scss +913 -913
  17. package/components/matcha-calendar.scss +218 -218
  18. package/components/matcha-cards.scss +230 -230
  19. package/components/matcha-chart-card.scss +53 -53
  20. package/components/matcha-checkbox.scss +255 -255
  21. package/components/matcha-chip.scss +292 -292
  22. package/components/matcha-color-pick.scss +34 -34
  23. package/components/matcha-command-palette.scss +316 -316
  24. package/components/matcha-crop.scss +406 -406
  25. package/components/matcha-date.scss +81 -81
  26. package/components/matcha-divider.scss +100 -100
  27. package/components/matcha-draggable.scss +23 -23
  28. package/components/matcha-drawer.scss +376 -376
  29. package/components/matcha-drop-image.scss +14 -14
  30. package/components/matcha-drop-list.scss +430 -430
  31. package/components/matcha-emoji.scss +69 -69
  32. package/components/matcha-empty-state.scss +230 -230
  33. package/components/matcha-file-uploader.scss +471 -471
  34. package/components/matcha-flag.scss +103 -103
  35. package/components/matcha-footer.scss +91 -91
  36. package/components/matcha-form-field.scss +606 -606
  37. package/components/matcha-form-section.scss +100 -100
  38. package/components/matcha-header.scss +135 -135
  39. package/components/matcha-highlight.scss +164 -164
  40. package/components/matcha-hint-text.scss +90 -90
  41. package/components/matcha-horizontal-tree.scss +316 -316
  42. package/components/matcha-icon.scss +98 -98
  43. package/components/matcha-image.scss +61 -61
  44. package/components/matcha-list.scss +211 -211
  45. package/components/matcha-menu.scss +99 -99
  46. package/components/matcha-modal.scss +210 -210
  47. package/components/matcha-nav.scss +581 -581
  48. package/components/matcha-notification.scss +413 -413
  49. package/components/matcha-option.scss +170 -170
  50. package/components/matcha-page-builder.scss +4196 -4196
  51. package/components/matcha-paginator.scss +689 -689
  52. package/components/matcha-panel.scss +194 -194
  53. package/components/matcha-profile-card.scss +50 -50
  54. package/components/matcha-progress-bar.scss +313 -313
  55. package/components/matcha-radio.scss +320 -320
  56. package/components/matcha-ripple.scss +7 -7
  57. package/components/matcha-scrollbar.scss +33 -33
  58. package/components/matcha-scrollbox-shadow.scss +120 -120
  59. package/components/matcha-section.scss +102 -102
  60. package/components/matcha-select-multiple.scss +56 -56
  61. package/components/matcha-select.scss +667 -667
  62. package/components/matcha-skeleton.scss +155 -155
  63. package/components/matcha-slide-toggle.scss +369 -369
  64. package/components/matcha-slider.scss +285 -285
  65. package/components/matcha-snack-bar.scss +259 -259
  66. package/components/matcha-spin.scss +164 -164
  67. package/components/matcha-spinner.scss +97 -97
  68. package/components/matcha-status-pill.scss +38 -18
  69. package/components/matcha-stepper.scss +376 -376
  70. package/components/matcha-table-cell.scss +74 -41
  71. package/components/matcha-table.scss +579 -578
  72. package/components/matcha-tabs.scss +600 -600
  73. package/components/matcha-text-editor.scss +105 -105
  74. package/components/matcha-time.scss +33 -33
  75. package/components/matcha-timepicker.scss +13 -13
  76. package/components/matcha-toolbar.scss +359 -359
  77. package/components/matcha-tooltip.scss +224 -224
  78. package/components/matcha-tree-view.scss +257 -212
  79. package/layout/matcha-page-layout.scss +778 -778
  80. package/main.scss +329 -329
  81. package/package.json +1 -1
  82. package/tokens/_animations-tokens.scss +37 -37
  83. package/tokens/_breakpoints-tokens.scss +35 -35
  84. package/tokens/_color-tokens.scss +274 -261
  85. package/tokens/_elevation-tokens.scss +33 -33
  86. package/tokens/_emit-tokens.scss +324 -324
  87. package/tokens/_material-palette.scss +1149 -1149
  88. package/tokens/_primitives.scss +98 -98
  89. package/tokens/_semantic-aliases.scss +120 -120
  90. package/tokens/_spacing-tokens.scss +94 -94
  91. package/tokens/_static-tokens.scss +137 -137
  92. package/tokens/_typography-tokens.scss +65 -65
  93. package/vendors/charts.scss +90 -90
@@ -1,578 +1,579 @@
1
- @use "sass:map";
2
-
3
- // =============================================================================
4
- // matcha-table — `<table matcha-table>` directive (1:1 Figma DSV3 15641:275)
5
- //
6
- // API canon:
7
- // <table matcha-table size="comfortable" striped hover bordered stickyHeader
8
- // [stickyStart]="N" [stickyEnd]="N" [loading]="isLoading">
9
- // <thead><tr><th>...</th></tr></thead>
10
- // <tbody><tr><td>...</td></tr></tbody>
11
- // </table>
12
- //
13
- // Companion directives (a11y automática):
14
- // [matcha-table-sortable] em <th> — aria-sort + tabindex + keyboard
15
- // [matcha-table-clickable] em <tr> — tabindex + Enter/Space + (rowClick)
16
- //
17
- // Helpers CSS-only:
18
- // td.numeric → tabular-nums
19
- // td.truncate → ellipsis (text overflow)
20
- // td[data-alinhamento] / td.text-{center,right} → alinhamento
21
- // tr.equal/.plus/.minus → variant semantic accent (cor via CSS var)
22
- // tr.child-item → indent + accent esmaecido
23
- // tr.is-selected → highlight
24
- // =============================================================================
25
-
26
- @mixin matcha-table-modern($theme) {
27
-
28
- // ═══════════════════════════════════════════════════════════════════════
29
- // CSS vars do componente — única fonte de verdade. ZERO literal hardcoded
30
- // fora deste bloco. Consumer override qualquer um no escopo do <table>.
31
- // ═══════════════════════════════════════════════════════════════════════
32
- table.matcha-table {
33
- // ── Dimensions ────────────────────────────────────────────────────────
34
- // Calibrado pra density moderna (Stripe/Linear/Notion). Comfortable era 52
35
- // antes — apertado em telas wide. 58px equilibra densidade × respiro.
36
- --matcha-table-cell-height-compact: var(--matcha-space-500, 40px);
37
- --matcha-table-cell-height-comfortable: 58px;
38
- --matcha-table-cell-height-spacious: var(--matcha-space-800, 64px);
39
- // Padding uniforme L/R — assimétrico cria sensação de "primeira coluna
40
- // afastada do resto". 16px ambos lados é canon moderno.
41
- --matcha-table-cell-padding-x-left: var(--matcha-space-200, 16px);
42
- --matcha-table-cell-padding-x-right: var(--matcha-space-200, 16px);
43
- --matcha-table-cell-min-width: var(--matcha-space-1500, 120px);
44
- --matcha-table-paginator-spacing: var(--matcha-space-300, 24px);
45
-
46
- // ── Typography (modern density Stripe/Linear) ─────────────────────────
47
- --matcha-table-font-size: 13px;
48
- --matcha-table-font-line-height: 18px;
49
- --matcha-table-header-font-size: var(--matcha-text-body-sm, 12px);
50
- --matcha-table-header-font-line-height: var(--matcha-leading-body-sm, 16px);
51
- --matcha-table-header-letter-spacing: 0.04em;
52
-
53
- // ── Borders / radius ──────────────────────────────────────────────────
54
- --matcha-table-border-color: var(--matcha-color-interaction-disabled-border);
55
- --matcha-table-border-header: var(--matcha-border-thin, 2px);
56
- --matcha-table-border-row: var(--matcha-border-hairline, 1px);
57
- --matcha-table-bordered-radius: var(--matcha-radius-md, 4px);
58
-
59
- // ── Surface colors ────────────────────────────────────────────────────
60
- --matcha-table-cell-bg: var(--matcha-color-surface-card);
61
- --matcha-table-row-bg-selected: var(--matcha-color-accent-alpha-12,
62
- rgba(var(--matcha-color-accent), 0.12));
63
- --matcha-table-row-bg-striped: var(--matcha-color-surface-card-alt,
64
- rgba(var(--matcha-color-fg), 0.02));
65
- // Hover NÃO usa surface-table-row-hover token (tá próximo demais de surface-card
66
- // em dark e fica imperceptível). Calibrado pra delta visível mesmo sobre stripe.
67
- // CSS custom property values são TEXTO LITERAL pro Sass — fn calls Sass
68
- // dentro NÃO são avaliadas. Precisa interpolação `#{}` pra forçar Sass a
69
- // evaluar `var(--matcha-color-fg)` ANTES do output. Sem isso, o valor sai
70
- // literal no bundle (ex: `rgba(var(--matcha-color-fg), 0.12)`) e o browser
71
- // descarta como invalid CSS (= chevron invisível, hover sem cor, etc).
72
- --matcha-table-row-bg-hover: rgba(var(--matcha-color-fg), 0.12);
73
- --matcha-table-row-bg-hover-striped: rgba(var(--matcha-color-fg), 0.18);
74
- --matcha-table-header-bg-hover: rgba(var(--matcha-color-fg), 0.10);
75
-
76
- // ── Sort indicator colors ─────────────────────────────────────────────
77
- // Inactive usa alpha 0.45 no foreground — claramente VISÍVEL como "ali tem
78
- // sort", sem competir com texto do header. Hover/ativo passa pra accent full.
79
- --matcha-table-sort-icon-color: rgba(var(--matcha-color-fg), 0.45);
80
- --matcha-table-sort-icon-color-active: var(--matcha-color-accent);
81
- --matcha-table-sort-icon-size: var(--matcha-space-250, 20px);
82
-
83
- // ── Empty cell placeholder ────────────────────────────────────────────
84
- --matcha-table-empty-cell-text: var(--matcha-color-text-muted,
85
- rgba(var(--matcha-color-fg), 0.5));
86
-
87
- // ── Variant accent (semantic row) ─────────────────────────────────────
88
- --matcha-table-variant-accent-width: var(--matcha-space-050, 4px);
89
- --matcha-table-row-accent-child-opacity: 0.5;
90
- --matcha-table-selected-accent-width: var(--matcha-border-thin, 2px);
91
- --matcha-table-selected-accent-color: var(--matcha-color-accent);
92
-
93
- // ── Column width hints (utility classes col-*) ────────────────────────
94
- --matcha-table-col-checkbox-width: var(--matcha-space-600, 48px);
95
- --matcha-table-col-id-width: var(--matcha-space-1000, 80px);
96
- --matcha-table-col-narrow-width: var(--matcha-space-1500, 120px);
97
- --matcha-table-col-medium-width: var(--matcha-space-2500, 200px);
98
-
99
- // ── States / animations ───────────────────────────────────────────────
100
- --matcha-table-disabled-opacity: var(--matcha-state-disabled-opacity, 0.5);
101
- --matcha-table-loading-pulse-duration: var(--matcha-duration-slow, 1500ms);
102
- --matcha-table-loading-pulse-opacity-min: 0.5;
103
- --matcha-table-transition-duration: var(--matcha-duration-instant, 80ms);
104
- --matcha-table-focus-ring-width: var(--matcha-state-focus-ring-width, 2px);
105
- --matcha-table-focus-ring-color: var(--matcha-color-accent);
106
-
107
- // ── Empty state row (matcha-table-empty directive) ────────────────────
108
- --matcha-table-empty-padding-y: var(--matcha-space-500, 40px);
109
- --matcha-table-empty-padding-x: var(--matcha-space-300, 24px);
110
-
111
- // ── Resize handle (matcha-table-resizable directive) ──────────────────
112
- --matcha-table-resize-handle-width: var(--matcha-space-100, 8px);
113
- --matcha-table-resize-indicator-width: var(--matcha-border-hairline, 1px);
114
- --matcha-table-resize-indicator-height: 50%;
115
- --matcha-table-resize-indicator-top: 25%;
116
-
117
- // ── Sticky cols shadow ────────────────────────────────────────────────
118
- --matcha-table-sticky-shadow-offset: var(--matcha-space-100, 8px);
119
- --matcha-table-sticky-shadow-blur: var(--matcha-space-200, 16px);
120
- --matcha-table-sticky-shadow-color: var(--matcha-color-elevation-shadow, #000);
121
- --matcha-table-sticky-shadow-alpha: 16%;
122
- }
123
-
124
- // ── Base — display table nativo + typography via vars ─────────────────
125
- table.matcha-table {
126
- display: table;
127
- width: 100%;
128
- border-collapse: collapse;
129
- border-spacing: 0;
130
- font-family: var(--matcha-font-family);
131
- font-size: var(--matcha-table-font-size);
132
- line-height: var(--matcha-table-font-line-height);
133
- font-weight: var(--matcha-weight-regular, 400);
134
- color: var(--matcha-color-text-secondary,
135
- color-mix(in srgb, var(--matcha-color-fg) 70%, transparent));
136
-
137
- // ── Header cells (text/primary, border-bottom 2px, height 64) ────────
138
- thead th {
139
- box-sizing: border-box;
140
- height: var(--matcha-table-cell-height-comfortable);
141
- min-width: var(--matcha-table-cell-min-width);
142
- padding: 0
143
- var(--matcha-table-cell-padding-x-right)
144
- 0
145
- var(--matcha-table-cell-padding-x-left);
146
- background: var(--matcha-table-cell-bg);
147
- color: var(--matcha-color-text-primary,
148
- var(--matcha-color-fg));
149
- // Header menor que body — hierarquia "metadado" vs "conteúdo".
150
- font-size: var(--matcha-table-header-font-size);
151
- line-height: var(--matcha-table-header-font-line-height);
152
- font-weight: var(--matcha-weight-semibold, 600);
153
- letter-spacing: var(--matcha-table-header-letter-spacing);
154
- text-align: left;
155
- vertical-align: middle;
156
- border-bottom: var(--matcha-table-border-header) solid
157
- var(--matcha-table-border-color);
158
-
159
- // Alinhamento — aceita data-attr canon DSV3 + utility classes legacy
160
- &[data-alinhamento="center"], &.text-center { text-align: center; }
161
- &[data-alinhamento="right"], &.text-right { text-align: right; }
162
-
163
- // ── Sortable hint ([matcha-table-sortable] directive seta os attrs) ──
164
- &[data-sortable] {
165
- cursor: pointer;
166
- user-select: none;
167
- // SEMPRE reserva espaço pro chevron (mesmo inativo) — chevron entra/sai
168
- // via opacity. Sem padding condicional texto NÃO desloca no hover.
169
- padding-right: calc(var(--matcha-table-cell-padding-x-right) +
170
- var(--matcha-table-sort-icon-size));
171
- position: relative;
172
-
173
- // Hover NÃO muda bg do header — bg-change era o que fazia o user
174
- // perceber "movimento" quando o chevron entrava ao mesmo tempo.
175
- // Manter header estático no hover, chevron aparece com opacity.
176
- // Cursor pointer + chevron fade comunicam interatividade.
177
-
178
- // Sort indicators — SVG 1:1 com `matcha/icon/arrow` (figma-icons.ts).
179
- // Estado inativo (none) = INVISÍVEL (opacity 0). Aparece no hover do header
180
- // com opacity faded, full quando ativo (asc/desc). Pattern canon Stripe/Linear:
181
- // sortable em todas as colunas, mas indicador na que ordenando.
182
- &::after {
183
- content: '';
184
- position: absolute;
185
- right: var(--matcha-table-cell-padding-x-right);
186
- top: 50%;
187
- transform: translateY(-50%);
188
- width: var(--matcha-table-sort-icon-size);
189
- height: var(--matcha-table-sort-icon-size);
190
- background: var(--matcha-table-sort-icon-color);
191
- transition: background-color var(--matcha-table-transition-duration) linear;
192
- mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 7.82499L6.1 12.725C5.9 12.925 5.66667 13.0208 5.4 13.0125C5.13333 13.0042 4.9 12.9 4.7 12.7C4.51667 12.5 4.42083 12.2667 4.4125 12C4.40417 11.7333 4.5 11.5 4.7 11.3L11.3 4.69999C11.4 4.59999 11.5083 4.52915 11.625 4.48749C11.7417 4.44582 11.8667 4.42499 12 4.42499C12.1333 4.42499 12.2583 4.44582 12.375 4.48749C12.4917 4.52915 12.6 4.59999 12.7 4.69999L19.3 11.3C19.4833 11.4833 19.575 11.7125 19.575 11.9875C19.575 12.2625 19.4833 12.5 19.3 12.7C19.1 12.9 18.8625 13 18.5875 13C18.3125 13 18.075 12.9 17.875 12.7L13 7.82499V19C13 19.2833 12.9042 19.5208 12.7125 19.7125C12.5208 19.9042 12.2833 20 12 20C11.7167 20 11.4792 19.9042 11.2875 19.7125C11.0958 19.5208 11 19.2833 11 19V7.82499Z'/></svg>")
193
- center/contain no-repeat;
194
- }
195
-
196
- // Hover no header — chevron escurece pra foreground full (já visível
197
- // muted antes via alpha 0.45). Reforça que interativo.
198
- &:hover::after {
199
- background: var(--matcha-color-text-primary,
200
- var(--matcha-color-fg));
201
- }
202
-
203
- // Padding-right SEMPRE reserva espaço pro chevron. Antes ajustava
204
- // condicionalmente (sem padding extra no inativo) causava text
205
- // "dançar" 20px ao hover quando padding crescia pra acomodar arrow.
206
- // Mantém estável: chevron entra via opacity, sem reflow do texto.
207
-
208
- &[data-sort-direction="asc"]::after {
209
- mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 7.82499L6.1 12.725C5.9 12.925 5.66667 13.0208 5.4 13.0125C5.13333 13.0042 4.9 12.9 4.7 12.7C4.51667 12.5 4.42083 12.2667 4.4125 12C4.40417 11.7333 4.5 11.5 4.7 11.3L11.3 4.69999C11.4 4.59999 11.5083 4.52915 11.625 4.48749C11.7417 4.44582 11.8667 4.42499 12 4.42499C12.1333 4.42499 12.2583 4.44582 12.375 4.48749C12.4917 4.52915 12.6 4.59999 12.7 4.69999L19.3 11.3C19.4833 11.4833 19.575 11.7125 19.575 11.9875C19.575 12.2625 19.4833 12.5 19.3 12.7C19.1 12.9 18.8625 13 18.5875 13C18.3125 13 18.075 12.9 17.875 12.7L13 7.82499V19C13 19.2833 12.9042 19.5208 12.7125 19.7125C12.5208 19.9042 12.2833 20 12 20C11.7167 20 11.4792 19.9042 11.2875 19.7125C11.0958 19.5208 11 19.2833 11 19V7.82499Z'/></svg>")
210
- center/contain no-repeat;
211
- background: var(--matcha-table-sort-icon-color-active);
212
- }
213
-
214
- &[data-sort-direction="desc"]::after {
215
- mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 16.175V5C11 4.71667 11.0958 4.47917 11.2875 4.2875C11.4792 4.09583 11.7167 4 12 4C12.2833 4 12.5208 4.09583 12.7125 4.2875C12.9042 4.47917 13 4.71667 13 5V16.175L17.9 11.275C18.1 11.075 18.3333 10.9792 18.6 10.9875C18.8667 10.9958 19.1 11.1 19.3 11.3C19.4833 11.5 19.5792 11.7333 19.5875 12C19.5958 12.2667 19.5 12.5 19.3 12.7L12.7 19.3C12.6 19.4 12.4917 19.4708 12.375 19.5125C12.2583 19.5542 12.1333 19.575 12 19.575C11.8667 19.575 11.7417 19.5542 11.625 19.5125C11.5083 19.4708 11.4 19.4 11.3 19.3L4.7 12.7C4.51667 12.5167 4.425 12.2875 4.425 12.0125C4.425 11.7375 4.51667 11.5 4.7 11.3C4.9 11.1 5.1375 11 5.4125 11C5.6875 11 5.925 11.1 6.125 11.3L11 16.175Z'/></svg>")
216
- center/contain no-repeat;
217
- background: var(--matcha-table-sort-icon-color-active);
218
- }
219
-
220
- // Header right-aligned com sort — chevron vem ANTES do texto (canon).
221
- &[data-alinhamento="right"], &.text-right {
222
- padding-right: var(--matcha-table-cell-padding-x-right);
223
- padding-left: calc(var(--matcha-table-cell-padding-x-left) +
224
- var(--matcha-table-sort-icon-size));
225
-
226
- &::after {
227
- right: auto;
228
- left: var(--matcha-table-cell-padding-x-left);
229
- }
230
- }
231
-
232
- // Focus ring quando keyboard-navigated (tabindex via directive).
233
- &:focus-visible {
234
- outline: var(--matcha-table-focus-ring-width) solid
235
- var(--matcha-table-focus-ring-color);
236
- outline-offset: calc(-1 * var(--matcha-table-focus-ring-width));
237
- }
238
- }
239
- }
240
-
241
- // ── Body cells ────────────────────────────────────────────────────────
242
- tbody td {
243
- box-sizing: border-box;
244
- height: var(--matcha-table-cell-height-comfortable);
245
- min-width: var(--matcha-table-cell-min-width);
246
- padding: 0
247
- var(--matcha-table-cell-padding-x-right)
248
- 0
249
- var(--matcha-table-cell-padding-x-left);
250
- background: var(--matcha-table-cell-bg);
251
- color: var(--matcha-color-text-secondary,
252
- color-mix(in srgb, var(--matcha-color-fg) 70%, transparent));
253
- vertical-align: middle;
254
- border-bottom: var(--matcha-table-border-row) solid
255
- var(--matcha-table-border-color);
256
- transition: background-color var(--matcha-table-transition-duration) linear;
257
-
258
- &[data-alinhamento="center"], &.text-center { text-align: center; }
259
- &[data-alinhamento="right"], &.text-right { text-align: right; }
260
-
261
- // Helper: tabular-nums (alinha decimais)
262
- &[data-numeric], &.numeric {
263
- font-variant-numeric: tabular-nums;
264
- font-feature-settings: 'tnum';
265
- }
266
-
267
- // Helper: ellipsis (texto longo)
268
- &[data-truncate], &.truncate {
269
- max-width: 0;
270
- white-space: nowrap;
271
- overflow: hidden;
272
- text-overflow: ellipsis;
273
- }
274
-
275
- // Helper: cells vazias preenchidas com "—" muted (canon moderno).
276
- &:empty::after {
277
- content: '—';
278
- color: var(--matcha-table-empty-cell-text);
279
- }
280
- }
281
-
282
- // ── Column width hints (aplicar em <th> — <td> herda pela coluna) ─────
283
- thead th,
284
- tbody td {
285
- &.col-checkbox { width: var(--matcha-table-col-checkbox-width); text-align: center; }
286
- &.col-id { width: var(--matcha-table-col-id-width); }
287
- &.col-narrow { width: var(--matcha-table-col-narrow-width); }
288
- &.col-medium { width: var(--matcha-table-col-medium-width); }
289
- // Actions / icon-buttons shrink-to-content (1% truque de table layout).
290
- // Children inline horizontal right-aligned (canon Figma: edit/delete lado a
291
- // lado, não stackados).
292
- //
293
- // Importante: `.matcha-button` tem `display: flex` (block-level) que faria
294
- // os icon-buttons empilharem verticalmente. Override via selector descendant
295
- // com specificity maior pra forçar inline-flex no contexto de actions cell.
296
- //
297
- // Padding-right ZERO no body — icon-button já tem click target padding
298
- // interno; somar padding ao td empurraria os botões pra ESQUERDA do edge
299
- // do header "Ações". Alinhamento perfeito: button box-right = cell-right.
300
- // Actions / icon-buttons shrink-to-content (1% truque de table layout).
301
- // Children inline horizontal LEFT-aligned (header text "Ações" alinha
302
- // naturalmente acima do primeiro ícone). Padding uniforme L/R com resto
303
- // da table.
304
- &.col-actions {
305
- width: 1%;
306
- white-space: nowrap;
307
- text-align: left;
308
-
309
- > .matcha-button,
310
- > button[matcha-icon-button],
311
- > * {
312
- display: inline-flex;
313
- vertical-align: middle;
314
- }
315
- > * + * {
316
- margin-left: var(--matcha-space-050, 4px);
317
- }
318
- }
319
- // Greedy = espaço residual (default, classe explícita pra documentação).
320
- &.col-greedy { width: auto; }
321
- }
322
-
323
- // ── Paginator alinhado após table (convention) ────────────────────────
324
- // Sem margin-top paginator gruda no border-bottom da última row.
325
- // Spacing visual vem dos paddings internos do próprio matcha-paginator.
326
- .matcha-table-paginator,
327
- & + matcha-paginator {
328
- display: block;
329
- margin-top: 0;
330
- }
331
-
332
- // ── Row clickable ([matcha-table-clickable] directive seta tabindex) ─
333
- tbody tr.is-clickable {
334
- cursor: pointer;
335
-
336
- &:hover td {
337
- --matcha-table-cell-bg: var(--matcha-table-row-bg-hover);
338
- }
339
-
340
- &:focus-visible {
341
- outline: var(--matcha-table-focus-ring-width) solid
342
- var(--matcha-table-focus-ring-color);
343
- outline-offset: calc(-1 * var(--matcha-table-focus-ring-width));
344
- }
345
- }
346
-
347
- // ── Modifiers via host classes (Angular bind quando striped/hover/etc) ─
348
- // Striped usa :where() pra dropar specificity do :nth-child hover vence.
349
- &.matcha-table-striped tbody tr:where(:nth-child(even)) td {
350
- --matcha-table-cell-bg: var(--matcha-table-row-bg-striped);
351
- }
352
-
353
- &.matcha-table-hover tbody tr:hover td {
354
- --matcha-table-cell-bg: var(--matcha-table-row-bg-hover);
355
- }
356
-
357
- // Stripe-aware hover: row PAR ganha alpha mais forte pra preservar stripe.
358
- &.matcha-table-striped tbody tr:where(:nth-child(even)).is-clickable:hover td,
359
- &.matcha-table-striped.matcha-table-hover tbody tr:where(:nth-child(even)):hover td {
360
- --matcha-table-cell-bg: var(--matcha-table-row-bg-hover-striped);
361
- }
362
-
363
- // Variante de hover accent (input `rowHover="accent"` → classe host
364
- // `matcha-table-hover-accent`). Rebinda a var de hover no PRÓPRIO `<table>`,
365
- // com especificidade acima do default dispensa o consumer de furar o
366
- // encapsulamento com `::ng-deep`. Substitui o override manual repetido em
367
- // members/visitors/history/datas-comemorativas.
368
- &.matcha-table-hover-accent {
369
- --matcha-table-row-bg-hover: var(--matcha-color-accent-surface-hover);
370
- --matcha-table-row-bg-hover-striped: var(--matcha-color-accent-surface-hover);
371
- }
372
-
373
- tbody tr.is-selected td {
374
- --matcha-table-cell-bg: var(--matcha-table-row-bg-selected);
375
- }
376
- // Selected row ganha border-left accent — affordance canon Linear/Notion.
377
- // No <tr> não some com stickyStart. Usa ::after pra coexistir com
378
- // ::before do variant accent sem conflito.
379
- tbody tr.is-selected {
380
- position: relative;
381
-
382
- &::after {
383
- content: '';
384
- position: absolute;
385
- top: 0;
386
- left: 0;
387
- width: var(--matcha-table-selected-accent-width);
388
- height: 100%;
389
- background: var(--matcha-table-selected-accent-color);
390
- pointer-events: none;
391
- z-index: 2; // acima do variant accent (z-index 1)
392
- }
393
- }
394
-
395
- // Bordered — box-shadow inset em vez de border real (não clipa shadows
396
- // externos das sticky cols, que projetam pra fora da <table>).
397
- &.matcha-table-bordered {
398
- box-shadow: inset 0 0 0 var(--matcha-table-border-row)
399
- var(--matcha-table-border-color);
400
- border-radius: var(--matcha-table-bordered-radius);
401
- }
402
-
403
- // Sticky header (vertical scroll)
404
- &.matcha-table-sticky-header thead th {
405
- position: sticky;
406
- top: 0;
407
- z-index: 1;
408
- }
409
-
410
- // Size variants (data-size cascateia altura)
411
- &[data-size="compact"] thead th,
412
- &[data-size="compact"] tbody td { height: var(--matcha-table-cell-height-compact); }
413
- &[data-size="spacious"] thead th,
414
- &[data-size="spacious"] tbody td { height: var(--matcha-table-cell-height-spacious); }
415
-
416
- // ── Sticky columns (start/end) — canon scroll horizontal ──────────────
417
- // Shadow scroll-edge via color-mix() pra tokenizar funciona em light
418
- // E dark. Offsets/blur/cor todos via var.
419
- @for $i from 1 through 4 {
420
- &[data-sticky-start="#{$i}"] {
421
- thead th:nth-child(-n+#{$i}),
422
- tbody tr td:nth-child(-n+#{$i}) {
423
- position: sticky;
424
- z-index: 2;
425
- background: var(--matcha-table-cell-bg);
426
- }
427
- // Última cell do grupo sticky-start projeta shadow scroll-edge.
428
- thead th:nth-child(#{$i}),
429
- tbody tr td:nth-child(#{$i}) {
430
- box-shadow: var(--matcha-table-sticky-shadow-offset) 0
431
- var(--matcha-table-sticky-shadow-blur)
432
- calc(-1 * var(--matcha-table-sticky-shadow-offset))
433
- color-mix(in srgb, var(--matcha-table-sticky-shadow-color)
434
- var(--matcha-table-sticky-shadow-alpha), transparent);
435
- }
436
- }
437
-
438
- &[data-sticky-end="#{$i}"] {
439
- thead th:nth-last-child(-n+#{$i}),
440
- tbody tr td:nth-last-child(-n+#{$i}) {
441
- position: sticky;
442
- z-index: 2;
443
- background: var(--matcha-table-cell-bg);
444
- }
445
- thead th:nth-last-child(#{$i}),
446
- tbody tr td:nth-last-child(#{$i}) {
447
- box-shadow: calc(-1 * var(--matcha-table-sticky-shadow-offset)) 0
448
- var(--matcha-table-sticky-shadow-blur)
449
- calc(-1 * var(--matcha-table-sticky-shadow-offset))
450
- color-mix(in srgb, var(--matcha-table-sticky-shadow-color)
451
- var(--matcha-table-sticky-shadow-alpha), transparent);
452
- }
453
- }
454
- }
455
-
456
- &[data-sticky-start] thead th:first-child,
457
- &[data-sticky-start] tbody tr td:first-child { left: 0; }
458
- &[data-sticky-end] thead th:last-child,
459
- &[data-sticky-end] tbody tr td:last-child { right: 0; }
460
-
461
- // ── Variant accent (semantic row coloring) ────────────────────────────
462
- // Defaults canon Figma DSV3: equal=info, plus=success, minus=danger.
463
- // Accent vive no <tr> NÃO some com stickyStart.
464
- // `position: relative` em <tr> suportado em Chrome 80+, FF 87+, Safari 14+.
465
- tr.equal { --matcha-table-row-accent-color: var(--matcha-color-info); }
466
- tr.plus { --matcha-table-row-accent-color: var(--matcha-color-success); }
467
- tr.minus { --matcha-table-row-accent-color: var(--matcha-color-danger); }
468
-
469
- tbody tr[data-variant],
470
- tbody tr.equal,
471
- tbody tr.plus,
472
- tbody tr.minus {
473
- position: relative;
474
-
475
- &::before {
476
- content: '';
477
- position: absolute;
478
- top: 0;
479
- left: 0;
480
- width: var(--matcha-table-variant-accent-width);
481
- height: 100%;
482
- background: var(--matcha-table-row-accent-color, transparent);
483
- pointer-events: none;
484
- z-index: 1; // acima do bg da cell, abaixo do sticky shadow
485
- }
486
- }
487
-
488
- // Child row (indent + accent esmaecido) — pattern tree/hierarquia.
489
- tbody tr.child-item::before {
490
- opacity: var(--matcha-table-row-accent-child-opacity);
491
- }
492
- tbody tr.child-item td:first-child {
493
- padding-left: calc(var(--matcha-table-cell-padding-x-left) +
494
- var(--matcha-space-200, 16px));
495
- }
496
-
497
- // ── Loading state global — pulse + aria-busy ─────────────────────────
498
- &.matcha-table-loading tbody tr {
499
- animation: matcha-table-loading-pulse
500
- var(--matcha-table-loading-pulse-duration)
501
- ease-in-out infinite;
502
- pointer-events: none;
503
- }
504
-
505
- // ── Disabled state — row/cell ─────────────────────────────────────────
506
- // Pattern canon Material/Polaris. A11y: também aplicar aria-disabled.
507
- tbody tr[disabled], tbody tr.is-disabled,
508
- tbody td[disabled], tbody td.is-disabled {
509
- opacity: var(--matcha-table-disabled-opacity);
510
- pointer-events: none;
511
- cursor: not-allowed;
512
- }
513
-
514
- // ── Per-row loading (matcha-table-loading directive) ─────────────────
515
- // Pulse só naquela row optimistic save/delete sem bloquear a tabela.
516
- tbody tr.is-loading {
517
- animation: matcha-table-loading-pulse
518
- var(--matcha-table-loading-pulse-duration)
519
- ease-in-out infinite;
520
- pointer-events: none;
521
- }
522
-
523
- // ── Empty state row (matcha-table-empty directive) ────────────────────
524
- // Container pra <matcha-empty-state>. Directive seta colspan automático.
525
- tbody tr.is-empty td {
526
- padding: var(--matcha-table-empty-padding-y) var(--matcha-table-empty-padding-x);
527
- text-align: center;
528
- background: var(--matcha-table-cell-bg);
529
- }
530
-
531
- // ── Resizable column (matcha-table-resizable directive) ───────────────
532
- // Handle invisível na borda direita. Hover mostra cursor + barra discreta.
533
- thead th.is-resizable {
534
- position: relative;
535
-
536
- &::before {
537
- content: '';
538
- position: absolute;
539
- top: var(--matcha-table-resize-indicator-top);
540
- right: 0;
541
- width: var(--matcha-table-resize-indicator-width);
542
- height: var(--matcha-table-resize-indicator-height);
543
- background: var(--matcha-table-border-color);
544
- opacity: 0;
545
- transition: opacity var(--matcha-table-transition-duration) linear;
546
- }
547
- &:hover::before { opacity: 1; }
548
- }
549
- thead th.is-resizable::after {
550
- // Override do ::after do sort-indicator: handle de resize ocupa a borda.
551
- // Col sortable + resizable é raro consumer escolhe uma.
552
- content: '';
553
- position: absolute;
554
- top: 0;
555
- right: calc(-1 * var(--matcha-table-resize-handle-width) / 2);
556
- width: var(--matcha-table-resize-handle-width);
557
- height: 100%;
558
- cursor: col-resize;
559
- z-index: 3;
560
- background: transparent;
561
- mask: none;
562
- }
563
- }
564
-
565
- @keyframes matcha-table-loading-pulse {
566
- 0%, 100% { opacity: 1; }
567
- 50% { opacity: var(--matcha-table-loading-pulse-opacity-min); }
568
- }
569
-
570
- // ── Reduced motion ────────────────────────────────────────────────────
571
- @media (prefers-reduced-motion: reduce) {
572
- table.matcha-table tbody td,
573
- table.matcha-table.matcha-table-loading tbody tr {
574
- transition: none;
575
- animation: none;
576
- }
577
- }
578
- }
1
+ @use "sass:map";
2
+
3
+ // =============================================================================
4
+ // matcha-table — `<table matcha-table>` directive (1:1 Figma DSV3 15641:275)
5
+ //
6
+ // API canon:
7
+ // <table matcha-table size="comfortable" striped hover bordered stickyHeader
8
+ // [stickyStart]="N" [stickyEnd]="N" [loading]="isLoading">
9
+ // <thead><tr><th>...</th></tr></thead>
10
+ // <tbody><tr><td>...</td></tr></tbody>
11
+ // </table>
12
+ //
13
+ // Companion directives (a11y automática):
14
+ // [matcha-table-sortable] em <th> — aria-sort + tabindex + keyboard
15
+ // [matcha-table-clickable] em <tr> — tabindex + Enter/Space + (rowClick)
16
+ //
17
+ // Helpers CSS-only:
18
+ // td.numeric → tabular-nums
19
+ // td.truncate → ellipsis (text overflow)
20
+ // td[data-align] → alinhamento (data-alinhamento / td.text-{center,right} deprecated)
21
+ // tr.equal/.plus/.minus → variant semantic accent (cor via CSS var)
22
+ // tr.child-item → indent + accent esmaecido
23
+ // tr.is-selected → highlight
24
+ // =============================================================================
25
+
26
+ @mixin matcha-table-modern($theme) {
27
+
28
+ // ═══════════════════════════════════════════════════════════════════════
29
+ // CSS vars do componente — única fonte de verdade. ZERO literal hardcoded
30
+ // fora deste bloco. Consumer override qualquer um no escopo do <table>.
31
+ // ═══════════════════════════════════════════════════════════════════════
32
+ table.matcha-table {
33
+ // ── Dimensions ────────────────────────────────────────────────────────
34
+ // Calibrado pra density moderna (Stripe/Linear/Notion). Comfortable era 52
35
+ // antes — apertado em telas wide. 58px equilibra densidade × respiro.
36
+ --matcha-table-cell-height-compact: var(--matcha-space-500, 40px);
37
+ --matcha-table-cell-height-comfortable: 58px;
38
+ --matcha-table-cell-height-spacious: var(--matcha-space-800, 64px);
39
+ // Padding uniforme L/R — assimétrico cria sensação de "primeira coluna
40
+ // afastada do resto". 16px ambos lados é canon moderno.
41
+ --matcha-table-cell-padding-x-left: var(--matcha-space-200, 16px);
42
+ --matcha-table-cell-padding-x-right: var(--matcha-space-200, 16px);
43
+ --matcha-table-cell-min-width: var(--matcha-space-1500, 120px);
44
+ --matcha-table-paginator-spacing: var(--matcha-space-300, 24px);
45
+
46
+ // ── Typography (modern density Stripe/Linear) ─────────────────────────
47
+ --matcha-table-font-size: 13px;
48
+ --matcha-table-font-line-height: 18px;
49
+ --matcha-table-header-font-size: var(--matcha-text-body-sm, 12px);
50
+ --matcha-table-header-font-line-height: var(--matcha-leading-body-sm, 16px);
51
+ --matcha-table-header-letter-spacing: 0.04em;
52
+
53
+ // ── Borders / radius ──────────────────────────────────────────────────
54
+ --matcha-table-border-color: var(--matcha-color-interaction-disabled-border);
55
+ --matcha-table-border-header: var(--matcha-border-thin, 2px);
56
+ --matcha-table-border-row: var(--matcha-border-hairline, 1px);
57
+ --matcha-table-bordered-radius: var(--matcha-radius-md, 4px);
58
+
59
+ // ── Surface colors ────────────────────────────────────────────────────
60
+ --matcha-table-cell-bg: var(--matcha-color-surface-card);
61
+ --matcha-table-row-bg-selected: var(--matcha-color-accent-alpha-12,
62
+ rgba(var(--matcha-color-accent), 0.12));
63
+ --matcha-table-row-bg-striped: var(--matcha-color-surface-card-alt,
64
+ rgba(var(--matcha-color-fg), 0.02));
65
+ // Hover NÃO usa surface-table-row-hover token (tá próximo demais de surface-card
66
+ // em dark e fica imperceptível). Calibrado pra delta visível mesmo sobre stripe.
67
+ // CSS custom property values são TEXTO LITERAL pro Sass — fn calls Sass
68
+ // dentro NÃO são avaliadas. Precisa interpolação `#{}` pra forçar Sass a
69
+ // evaluar `var(--matcha-color-fg)` ANTES do output. Sem isso, o valor sai
70
+ // literal no bundle (ex: `rgba(var(--matcha-color-fg), 0.12)`) e o browser
71
+ // descarta como invalid CSS (= chevron invisível, hover sem cor, etc).
72
+ --matcha-table-row-bg-hover: rgba(var(--matcha-color-fg), 0.12);
73
+ --matcha-table-row-bg-hover-striped: rgba(var(--matcha-color-fg), 0.18);
74
+ --matcha-table-header-bg-hover: rgba(var(--matcha-color-fg), 0.10);
75
+
76
+ // ── Sort indicator colors ─────────────────────────────────────────────
77
+ // Inactive usa alpha 0.45 no foreground — claramente VISÍVEL como "ali tem
78
+ // sort", sem competir com texto do header. Hover/ativo passa pra accent full.
79
+ --matcha-table-sort-icon-color: rgba(var(--matcha-color-fg), 0.45);
80
+ --matcha-table-sort-icon-color-active: var(--matcha-color-accent);
81
+ --matcha-table-sort-icon-size: var(--matcha-space-250, 20px);
82
+
83
+ // ── Empty cell placeholder ────────────────────────────────────────────
84
+ --matcha-table-empty-cell-text: var(--matcha-color-text-muted,
85
+ rgba(var(--matcha-color-fg), 0.5));
86
+
87
+ // ── Variant accent (semantic row) ─────────────────────────────────────
88
+ --matcha-table-variant-accent-width: var(--matcha-space-050, 4px);
89
+ --matcha-table-row-accent-child-opacity: 0.5;
90
+ --matcha-table-selected-accent-width: var(--matcha-border-thin, 2px);
91
+ --matcha-table-selected-accent-color: var(--matcha-color-accent);
92
+
93
+ // ── Column width hints (utility classes col-*) ────────────────────────
94
+ --matcha-table-col-checkbox-width: var(--matcha-space-600, 48px);
95
+ --matcha-table-col-id-width: var(--matcha-space-1000, 80px);
96
+ --matcha-table-col-narrow-width: var(--matcha-space-1500, 120px);
97
+ --matcha-table-col-medium-width: var(--matcha-space-2500, 200px);
98
+
99
+ // ── States / animations ───────────────────────────────────────────────
100
+ --matcha-table-disabled-opacity: var(--matcha-state-disabled-opacity, 0.5);
101
+ --matcha-table-loading-pulse-duration: var(--matcha-duration-slow, 1500ms);
102
+ --matcha-table-loading-pulse-opacity-min: 0.5;
103
+ --matcha-table-transition-duration: var(--matcha-duration-instant, 80ms);
104
+ --matcha-table-focus-ring-width: var(--matcha-state-focus-ring-width, 2px);
105
+ --matcha-table-focus-ring-color: var(--matcha-color-accent);
106
+
107
+ // ── Empty state row (matcha-table-empty directive) ────────────────────
108
+ --matcha-table-empty-padding-y: var(--matcha-space-500, 40px);
109
+ --matcha-table-empty-padding-x: var(--matcha-space-300, 24px);
110
+
111
+ // ── Resize handle (matcha-table-resizable directive) ──────────────────
112
+ --matcha-table-resize-handle-width: var(--matcha-space-100, 8px);
113
+ --matcha-table-resize-indicator-width: var(--matcha-border-hairline, 1px);
114
+ --matcha-table-resize-indicator-height: 50%;
115
+ --matcha-table-resize-indicator-top: 25%;
116
+
117
+ // ── Sticky cols shadow ────────────────────────────────────────────────
118
+ --matcha-table-sticky-shadow-offset: var(--matcha-space-100, 8px);
119
+ --matcha-table-sticky-shadow-blur: var(--matcha-space-200, 16px);
120
+ --matcha-table-sticky-shadow-color: var(--matcha-color-elevation-shadow, #000);
121
+ --matcha-table-sticky-shadow-alpha: 16%;
122
+ }
123
+
124
+ // ── Base — display table nativo + typography via vars ─────────────────
125
+ table.matcha-table {
126
+ display: table;
127
+ width: 100%;
128
+ border-collapse: collapse;
129
+ border-spacing: 0;
130
+ font-family: var(--matcha-font-family);
131
+ font-size: var(--matcha-table-font-size);
132
+ line-height: var(--matcha-table-font-line-height);
133
+ font-weight: var(--matcha-weight-regular, 400);
134
+ color: var(--matcha-color-text-secondary,
135
+ color-mix(in srgb, var(--matcha-color-fg) 70%, transparent));
136
+
137
+ // ── Header cells (text/primary, border-bottom 2px, height 64) ────────
138
+ thead th {
139
+ box-sizing: border-box;
140
+ height: var(--matcha-table-cell-height-comfortable);
141
+ min-width: var(--matcha-table-cell-min-width);
142
+ padding: 0
143
+ var(--matcha-table-cell-padding-x-right)
144
+ 0
145
+ var(--matcha-table-cell-padding-x-left);
146
+ background: var(--matcha-table-cell-bg);
147
+ color: var(--matcha-color-text-primary,
148
+ var(--matcha-color-fg));
149
+ // Header menor que body — hierarquia "metadado" vs "conteúdo".
150
+ font-size: var(--matcha-table-header-font-size);
151
+ line-height: var(--matcha-table-header-font-line-height);
152
+ font-weight: var(--matcha-weight-semibold, 600);
153
+ letter-spacing: var(--matcha-table-header-letter-spacing);
154
+ text-align: left;
155
+ vertical-align: middle;
156
+ border-bottom: var(--matcha-table-border-header) solid
157
+ var(--matcha-table-border-color);
158
+
159
+ // Alinhamento — data-align é o canon DSV3; data-alinhamento + utility
160
+ // classes seguem aceitos (deprecated, remoção em ciclo futuro)
161
+ &[data-align="center"], &[data-alinhamento="center"], &.text-center { text-align: center; }
162
+ &[data-align="right"], &[data-alinhamento="right"], &.text-right { text-align: right; }
163
+
164
+ // ── Sortable hint ([matcha-table-sortable] directive seta os attrs) ──
165
+ &[data-sortable] {
166
+ cursor: pointer;
167
+ user-select: none;
168
+ // SEMPRE reserva espaço pro chevron (mesmo inativo) chevron entra/sai
169
+ // só via opacity. Sem padding condicional → texto NÃO desloca no hover.
170
+ padding-right: calc(var(--matcha-table-cell-padding-x-right) +
171
+ var(--matcha-table-sort-icon-size));
172
+ position: relative;
173
+
174
+ // Hover NÃO muda bg do header — bg-change era o que fazia o user
175
+ // perceber "movimento" quando o chevron entrava ao mesmo tempo.
176
+ // Manter header estático no hover, só chevron aparece com opacity.
177
+ // Cursor pointer + chevron fade já comunicam interatividade.
178
+
179
+ // Sort indicators SVG 1:1 com `matcha/icon/arrow` (figma-icons.ts).
180
+ // Estado inativo (none) = INVISÍVEL (opacity 0). Aparece no hover do header
181
+ // com opacity faded, full quando ativo (asc/desc). Pattern canon Stripe/Linear:
182
+ // sortable em todas as colunas, mas indicador só na que tá ordenando.
183
+ &::after {
184
+ content: '';
185
+ position: absolute;
186
+ right: var(--matcha-table-cell-padding-x-right);
187
+ top: 50%;
188
+ transform: translateY(-50%);
189
+ width: var(--matcha-table-sort-icon-size);
190
+ height: var(--matcha-table-sort-icon-size);
191
+ background: var(--matcha-table-sort-icon-color);
192
+ transition: background-color var(--matcha-table-transition-duration) linear;
193
+ mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 7.82499L6.1 12.725C5.9 12.925 5.66667 13.0208 5.4 13.0125C5.13333 13.0042 4.9 12.9 4.7 12.7C4.51667 12.5 4.42083 12.2667 4.4125 12C4.40417 11.7333 4.5 11.5 4.7 11.3L11.3 4.69999C11.4 4.59999 11.5083 4.52915 11.625 4.48749C11.7417 4.44582 11.8667 4.42499 12 4.42499C12.1333 4.42499 12.2583 4.44582 12.375 4.48749C12.4917 4.52915 12.6 4.59999 12.7 4.69999L19.3 11.3C19.4833 11.4833 19.575 11.7125 19.575 11.9875C19.575 12.2625 19.4833 12.5 19.3 12.7C19.1 12.9 18.8625 13 18.5875 13C18.3125 13 18.075 12.9 17.875 12.7L13 7.82499V19C13 19.2833 12.9042 19.5208 12.7125 19.7125C12.5208 19.9042 12.2833 20 12 20C11.7167 20 11.4792 19.9042 11.2875 19.7125C11.0958 19.5208 11 19.2833 11 19V7.82499Z'/></svg>")
194
+ center/contain no-repeat;
195
+ }
196
+
197
+ // Hover no header chevron escurece pra foreground full (já visível
198
+ // muted antes via alpha 0.45). Reforça que tá interativo.
199
+ &:hover::after {
200
+ background: var(--matcha-color-text-primary,
201
+ var(--matcha-color-fg));
202
+ }
203
+
204
+ // Padding-right SEMPRE reserva espaço pro chevron. Antes ajustava
205
+ // condicionalmente (sem padding extra no inativo) causava text
206
+ // "dançar" 20px ao hover quando padding crescia pra acomodar arrow.
207
+ // Mantém estável: chevron entra via opacity, sem reflow do texto.
208
+
209
+ &[data-sort-direction="asc"]::after {
210
+ mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 7.82499L6.1 12.725C5.9 12.925 5.66667 13.0208 5.4 13.0125C5.13333 13.0042 4.9 12.9 4.7 12.7C4.51667 12.5 4.42083 12.2667 4.4125 12C4.40417 11.7333 4.5 11.5 4.7 11.3L11.3 4.69999C11.4 4.59999 11.5083 4.52915 11.625 4.48749C11.7417 4.44582 11.8667 4.42499 12 4.42499C12.1333 4.42499 12.2583 4.44582 12.375 4.48749C12.4917 4.52915 12.6 4.59999 12.7 4.69999L19.3 11.3C19.4833 11.4833 19.575 11.7125 19.575 11.9875C19.575 12.2625 19.4833 12.5 19.3 12.7C19.1 12.9 18.8625 13 18.5875 13C18.3125 13 18.075 12.9 17.875 12.7L13 7.82499V19C13 19.2833 12.9042 19.5208 12.7125 19.7125C12.5208 19.9042 12.2833 20 12 20C11.7167 20 11.4792 19.9042 11.2875 19.7125C11.0958 19.5208 11 19.2833 11 19V7.82499Z'/></svg>")
211
+ center/contain no-repeat;
212
+ background: var(--matcha-table-sort-icon-color-active);
213
+ }
214
+
215
+ &[data-sort-direction="desc"]::after {
216
+ mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 16.175V5C11 4.71667 11.0958 4.47917 11.2875 4.2875C11.4792 4.09583 11.7167 4 12 4C12.2833 4 12.5208 4.09583 12.7125 4.2875C12.9042 4.47917 13 4.71667 13 5V16.175L17.9 11.275C18.1 11.075 18.3333 10.9792 18.6 10.9875C18.8667 10.9958 19.1 11.1 19.3 11.3C19.4833 11.5 19.5792 11.7333 19.5875 12C19.5958 12.2667 19.5 12.5 19.3 12.7L12.7 19.3C12.6 19.4 12.4917 19.4708 12.375 19.5125C12.2583 19.5542 12.1333 19.575 12 19.575C11.8667 19.575 11.7417 19.5542 11.625 19.5125C11.5083 19.4708 11.4 19.4 11.3 19.3L4.7 12.7C4.51667 12.5167 4.425 12.2875 4.425 12.0125C4.425 11.7375 4.51667 11.5 4.7 11.3C4.9 11.1 5.1375 11 5.4125 11C5.6875 11 5.925 11.1 6.125 11.3L11 16.175Z'/></svg>")
217
+ center/contain no-repeat;
218
+ background: var(--matcha-table-sort-icon-color-active);
219
+ }
220
+
221
+ // Header right-aligned com sort — chevron vem ANTES do texto (canon).
222
+ &[data-align="right"], &[data-alinhamento="right"], &.text-right {
223
+ padding-right: var(--matcha-table-cell-padding-x-right);
224
+ padding-left: calc(var(--matcha-table-cell-padding-x-left) +
225
+ var(--matcha-table-sort-icon-size));
226
+
227
+ &::after {
228
+ right: auto;
229
+ left: var(--matcha-table-cell-padding-x-left);
230
+ }
231
+ }
232
+
233
+ // Focus ring quando keyboard-navigated (tabindex via directive).
234
+ &:focus-visible {
235
+ outline: var(--matcha-table-focus-ring-width) solid
236
+ var(--matcha-table-focus-ring-color);
237
+ outline-offset: calc(-1 * var(--matcha-table-focus-ring-width));
238
+ }
239
+ }
240
+ }
241
+
242
+ // ── Body cells ────────────────────────────────────────────────────────
243
+ tbody td {
244
+ box-sizing: border-box;
245
+ height: var(--matcha-table-cell-height-comfortable);
246
+ min-width: var(--matcha-table-cell-min-width);
247
+ padding: 0
248
+ var(--matcha-table-cell-padding-x-right)
249
+ 0
250
+ var(--matcha-table-cell-padding-x-left);
251
+ background: var(--matcha-table-cell-bg);
252
+ color: var(--matcha-color-text-secondary,
253
+ color-mix(in srgb, var(--matcha-color-fg) 70%, transparent));
254
+ vertical-align: middle;
255
+ border-bottom: var(--matcha-table-border-row) solid
256
+ var(--matcha-table-border-color);
257
+ transition: background-color var(--matcha-table-transition-duration) linear;
258
+
259
+ &[data-align="center"], &[data-alinhamento="center"], &.text-center { text-align: center; }
260
+ &[data-align="right"], &[data-alinhamento="right"], &.text-right { text-align: right; }
261
+
262
+ // Helper: tabular-nums (alinha decimais)
263
+ &[data-numeric], &.numeric {
264
+ font-variant-numeric: tabular-nums;
265
+ font-feature-settings: 'tnum';
266
+ }
267
+
268
+ // Helper: ellipsis (texto longo)
269
+ &[data-truncate], &.truncate {
270
+ max-width: 0;
271
+ white-space: nowrap;
272
+ overflow: hidden;
273
+ text-overflow: ellipsis;
274
+ }
275
+
276
+ // Helper: cells vazias preenchidas com "—" muted (canon moderno).
277
+ &:empty::after {
278
+ content: '—';
279
+ color: var(--matcha-table-empty-cell-text);
280
+ }
281
+ }
282
+
283
+ // ── Column width hints (aplicar em <th> — <td> herda pela coluna) ─────
284
+ thead th,
285
+ tbody td {
286
+ &.col-checkbox { width: var(--matcha-table-col-checkbox-width); text-align: center; }
287
+ &.col-id { width: var(--matcha-table-col-id-width); }
288
+ &.col-narrow { width: var(--matcha-table-col-narrow-width); }
289
+ &.col-medium { width: var(--matcha-table-col-medium-width); }
290
+ // Actions / icon-buttons — shrink-to-content (1% truque de table layout).
291
+ // Children inline horizontal right-aligned (canon Figma: edit/delete lado a
292
+ // lado, não stackados).
293
+ //
294
+ // Importante: `.matcha-button` tem `display: flex` (block-level) que faria
295
+ // os icon-buttons empilharem verticalmente. Override via selector descendant
296
+ // com specificity maior pra forçar inline-flex no contexto de actions cell.
297
+ //
298
+ // Padding-right ZERO no body icon-button tem click target padding
299
+ // interno; somar padding ao td empurraria os botões pra ESQUERDA do edge
300
+ // do header "Ações". Alinhamento perfeito: button box-right = cell-right.
301
+ // Actions / icon-buttons — shrink-to-content (1% truque de table layout).
302
+ // Children inline horizontal LEFT-aligned (header text "Ações" alinha
303
+ // naturalmente acima do primeiro ícone). Padding uniforme L/R com resto
304
+ // da table.
305
+ &.col-actions {
306
+ width: 1%;
307
+ white-space: nowrap;
308
+ text-align: left;
309
+
310
+ > .matcha-button,
311
+ > button[matcha-icon-button],
312
+ > * {
313
+ display: inline-flex;
314
+ vertical-align: middle;
315
+ }
316
+ > * + * {
317
+ margin-left: var(--matcha-space-050, 4px);
318
+ }
319
+ }
320
+ // Greedy = espaço residual (default, classe explícita pra documentação).
321
+ &.col-greedy { width: auto; }
322
+ }
323
+
324
+ // ── Paginator alinhado após table (convention) ────────────────────────
325
+ // Sem margin-top paginator gruda no border-bottom da última row.
326
+ // Spacing visual vem dos paddings internos do próprio matcha-paginator.
327
+ .matcha-table-paginator,
328
+ & + matcha-paginator {
329
+ display: block;
330
+ margin-top: 0;
331
+ }
332
+
333
+ // ── Row clickable ([matcha-table-clickable] directive seta tabindex) ─
334
+ tbody tr.is-clickable {
335
+ cursor: pointer;
336
+
337
+ &:hover td {
338
+ --matcha-table-cell-bg: var(--matcha-table-row-bg-hover);
339
+ }
340
+
341
+ &:focus-visible {
342
+ outline: var(--matcha-table-focus-ring-width) solid
343
+ var(--matcha-table-focus-ring-color);
344
+ outline-offset: calc(-1 * var(--matcha-table-focus-ring-width));
345
+ }
346
+ }
347
+
348
+ // ── Modifiers via host classes (Angular bind quando striped/hover/etc)
349
+ // Striped usa :where() pra dropar specificity do :nth-child hover vence.
350
+ &.matcha-table-striped tbody tr:where(:nth-child(even)) td {
351
+ --matcha-table-cell-bg: var(--matcha-table-row-bg-striped);
352
+ }
353
+
354
+ &.matcha-table-hover tbody tr:hover td {
355
+ --matcha-table-cell-bg: var(--matcha-table-row-bg-hover);
356
+ }
357
+
358
+ // Stripe-aware hover: row PAR ganha alpha mais forte pra preservar stripe.
359
+ &.matcha-table-striped tbody tr:where(:nth-child(even)).is-clickable:hover td,
360
+ &.matcha-table-striped.matcha-table-hover tbody tr:where(:nth-child(even)):hover td {
361
+ --matcha-table-cell-bg: var(--matcha-table-row-bg-hover-striped);
362
+ }
363
+
364
+ // Variante de hover accent (input `rowHover="accent"` classe host
365
+ // `matcha-table-hover-accent`). Rebinda a var de hover no PRÓPRIO `<table>`,
366
+ // com especificidade acima do default — dispensa o consumer de furar o
367
+ // encapsulamento com `::ng-deep`. Substitui o override manual repetido em
368
+ // members/visitors/history/datas-comemorativas.
369
+ &.matcha-table-hover-accent {
370
+ --matcha-table-row-bg-hover: var(--matcha-color-accent-surface-hover);
371
+ --matcha-table-row-bg-hover-striped: var(--matcha-color-accent-surface-hover);
372
+ }
373
+
374
+ tbody tr.is-selected td {
375
+ --matcha-table-cell-bg: var(--matcha-table-row-bg-selected);
376
+ }
377
+ // Selected row ganha border-left accent affordance canon Linear/Notion.
378
+ // No <tr> não some com stickyStart. Usa ::after pra coexistir com
379
+ // ::before do variant accent sem conflito.
380
+ tbody tr.is-selected {
381
+ position: relative;
382
+
383
+ &::after {
384
+ content: '';
385
+ position: absolute;
386
+ top: 0;
387
+ left: 0;
388
+ width: var(--matcha-table-selected-accent-width);
389
+ height: 100%;
390
+ background: var(--matcha-table-selected-accent-color);
391
+ pointer-events: none;
392
+ z-index: 2; // acima do variant accent (z-index 1)
393
+ }
394
+ }
395
+
396
+ // Bordered box-shadow inset em vez de border real (não clipa shadows
397
+ // externos das sticky cols, que projetam pra fora da <table>).
398
+ &.matcha-table-bordered {
399
+ box-shadow: inset 0 0 0 var(--matcha-table-border-row)
400
+ var(--matcha-table-border-color);
401
+ border-radius: var(--matcha-table-bordered-radius);
402
+ }
403
+
404
+ // Sticky header (vertical scroll)
405
+ &.matcha-table-sticky-header thead th {
406
+ position: sticky;
407
+ top: 0;
408
+ z-index: 1;
409
+ }
410
+
411
+ // Size variants (data-size cascateia altura)
412
+ &[data-size="compact"] thead th,
413
+ &[data-size="compact"] tbody td { height: var(--matcha-table-cell-height-compact); }
414
+ &[data-size="spacious"] thead th,
415
+ &[data-size="spacious"] tbody td { height: var(--matcha-table-cell-height-spacious); }
416
+
417
+ // ── Sticky columns (start/end) canon scroll horizontal ──────────────
418
+ // Shadow scroll-edge via color-mix() pra tokenizar — funciona em light
419
+ // E dark. Offsets/blur/cor todos via var.
420
+ @for $i from 1 through 4 {
421
+ &[data-sticky-start="#{$i}"] {
422
+ thead th:nth-child(-n+#{$i}),
423
+ tbody tr td:nth-child(-n+#{$i}) {
424
+ position: sticky;
425
+ z-index: 2;
426
+ background: var(--matcha-table-cell-bg);
427
+ }
428
+ // Última cell do grupo sticky-start projeta shadow scroll-edge.
429
+ thead th:nth-child(#{$i}),
430
+ tbody tr td:nth-child(#{$i}) {
431
+ box-shadow: var(--matcha-table-sticky-shadow-offset) 0
432
+ var(--matcha-table-sticky-shadow-blur)
433
+ calc(-1 * var(--matcha-table-sticky-shadow-offset))
434
+ color-mix(in srgb, var(--matcha-table-sticky-shadow-color)
435
+ var(--matcha-table-sticky-shadow-alpha), transparent);
436
+ }
437
+ }
438
+
439
+ &[data-sticky-end="#{$i}"] {
440
+ thead th:nth-last-child(-n+#{$i}),
441
+ tbody tr td:nth-last-child(-n+#{$i}) {
442
+ position: sticky;
443
+ z-index: 2;
444
+ background: var(--matcha-table-cell-bg);
445
+ }
446
+ thead th:nth-last-child(#{$i}),
447
+ tbody tr td:nth-last-child(#{$i}) {
448
+ box-shadow: calc(-1 * var(--matcha-table-sticky-shadow-offset)) 0
449
+ var(--matcha-table-sticky-shadow-blur)
450
+ calc(-1 * var(--matcha-table-sticky-shadow-offset))
451
+ color-mix(in srgb, var(--matcha-table-sticky-shadow-color)
452
+ var(--matcha-table-sticky-shadow-alpha), transparent);
453
+ }
454
+ }
455
+ }
456
+
457
+ &[data-sticky-start] thead th:first-child,
458
+ &[data-sticky-start] tbody tr td:first-child { left: 0; }
459
+ &[data-sticky-end] thead th:last-child,
460
+ &[data-sticky-end] tbody tr td:last-child { right: 0; }
461
+
462
+ // ── Variant accent (semantic row coloring) ────────────────────────────
463
+ // Defaults canon Figma DSV3: equal=info, plus=success, minus=danger.
464
+ // Accent vive no <tr> NÃO some com stickyStart.
465
+ // `position: relative` em <tr> suportado em Chrome 80+, FF 87+, Safari 14+.
466
+ tr.equal { --matcha-table-row-accent-color: var(--matcha-color-info); }
467
+ tr.plus { --matcha-table-row-accent-color: var(--matcha-color-success); }
468
+ tr.minus { --matcha-table-row-accent-color: var(--matcha-color-danger); }
469
+
470
+ tbody tr[data-variant],
471
+ tbody tr.equal,
472
+ tbody tr.plus,
473
+ tbody tr.minus {
474
+ position: relative;
475
+
476
+ &::before {
477
+ content: '';
478
+ position: absolute;
479
+ top: 0;
480
+ left: 0;
481
+ width: var(--matcha-table-variant-accent-width);
482
+ height: 100%;
483
+ background: var(--matcha-table-row-accent-color, transparent);
484
+ pointer-events: none;
485
+ z-index: 1; // acima do bg da cell, abaixo do sticky shadow
486
+ }
487
+ }
488
+
489
+ // Child row (indent + accent esmaecido) — pattern tree/hierarquia.
490
+ tbody tr.child-item::before {
491
+ opacity: var(--matcha-table-row-accent-child-opacity);
492
+ }
493
+ tbody tr.child-item td:first-child {
494
+ padding-left: calc(var(--matcha-table-cell-padding-x-left) +
495
+ var(--matcha-space-200, 16px));
496
+ }
497
+
498
+ // ── Loading state global — pulse + aria-busy ─────────────────────────
499
+ &.matcha-table-loading tbody tr {
500
+ animation: matcha-table-loading-pulse
501
+ var(--matcha-table-loading-pulse-duration)
502
+ ease-in-out infinite;
503
+ pointer-events: none;
504
+ }
505
+
506
+ // ── Disabled state row/cell ─────────────────────────────────────────
507
+ // Pattern canon Material/Polaris. A11y: também aplicar aria-disabled.
508
+ tbody tr[disabled], tbody tr.is-disabled,
509
+ tbody td[disabled], tbody td.is-disabled {
510
+ opacity: var(--matcha-table-disabled-opacity);
511
+ pointer-events: none;
512
+ cursor: not-allowed;
513
+ }
514
+
515
+ // ── Per-row loading (matcha-table-loading directive) ─────────────────
516
+ // Pulse só naquela row — optimistic save/delete sem bloquear a tabela.
517
+ tbody tr.is-loading {
518
+ animation: matcha-table-loading-pulse
519
+ var(--matcha-table-loading-pulse-duration)
520
+ ease-in-out infinite;
521
+ pointer-events: none;
522
+ }
523
+
524
+ // ── Empty state row (matcha-table-empty directive) ────────────────────
525
+ // Container pra <matcha-empty-state>. Directive seta colspan automático.
526
+ tbody tr.is-empty td {
527
+ padding: var(--matcha-table-empty-padding-y) var(--matcha-table-empty-padding-x);
528
+ text-align: center;
529
+ background: var(--matcha-table-cell-bg);
530
+ }
531
+
532
+ // ── Resizable column (matcha-table-resizable directive) ───────────────
533
+ // Handle invisível na borda direita. Hover mostra cursor + barra discreta.
534
+ thead th.is-resizable {
535
+ position: relative;
536
+
537
+ &::before {
538
+ content: '';
539
+ position: absolute;
540
+ top: var(--matcha-table-resize-indicator-top);
541
+ right: 0;
542
+ width: var(--matcha-table-resize-indicator-width);
543
+ height: var(--matcha-table-resize-indicator-height);
544
+ background: var(--matcha-table-border-color);
545
+ opacity: 0;
546
+ transition: opacity var(--matcha-table-transition-duration) linear;
547
+ }
548
+ &:hover::before { opacity: 1; }
549
+ }
550
+ thead th.is-resizable::after {
551
+ // Override do ::after do sort-indicator: handle de resize ocupa a borda.
552
+ // Col sortable + resizable é raro — consumer escolhe uma.
553
+ content: '';
554
+ position: absolute;
555
+ top: 0;
556
+ right: calc(-1 * var(--matcha-table-resize-handle-width) / 2);
557
+ width: var(--matcha-table-resize-handle-width);
558
+ height: 100%;
559
+ cursor: col-resize;
560
+ z-index: 3;
561
+ background: transparent;
562
+ mask: none;
563
+ }
564
+ }
565
+
566
+ @keyframes matcha-table-loading-pulse {
567
+ 0%, 100% { opacity: 1; }
568
+ 50% { opacity: var(--matcha-table-loading-pulse-opacity-min); }
569
+ }
570
+
571
+ // ── Reduced motion ────────────────────────────────────────────────────
572
+ @media (prefers-reduced-motion: reduce) {
573
+ table.matcha-table tbody td,
574
+ table.matcha-table.matcha-table-loading tbody tr {
575
+ transition: none;
576
+ animation: none;
577
+ }
578
+ }
579
+ }