@inchurch/matcha-theme 22.2.0 → 22.4.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.
@@ -29,7 +29,7 @@
29
29
  // CSS vars do componente — única fonte de verdade. ZERO literal hardcoded
30
30
  // fora deste bloco. Consumer override qualquer um no escopo do <table>.
31
31
  // ═══════════════════════════════════════════════════════════════════════
32
- table.matcha-table {
32
+ .matcha-table {
33
33
  // ── Dimensions ────────────────────────────────────────────────────────
34
34
  // Calibrado pra density moderna (Stripe/Linear/Notion). Comfortable era 52
35
35
  // antes — apertado em telas wide. 58px equilibra densidade × respiro.
@@ -55,6 +55,9 @@
55
55
  --matcha-table-border-header: var(--matcha-border-thin, 2px);
56
56
  --matcha-table-border-row: var(--matcha-border-hairline, 1px);
57
57
  --matcha-table-bordered-radius: var(--matcha-radius-md, 4px);
58
+ // Escala de card (não a mesma de --matcha-table-bordered-radius, que é só
59
+ // pro inset border fino) — roundedTop arredonda o CONTAINER inteiro.
60
+ --matcha-table-rounded-top-radius: var(--matcha-radius-xl, 16px);
58
61
 
59
62
  // ── Surface colors ────────────────────────────────────────────────────
60
63
  --matcha-table-cell-bg: var(--matcha-color-surface-card);
@@ -113,19 +116,19 @@
113
116
  --matcha-table-resize-indicator-width: var(--matcha-border-hairline, 1px);
114
117
  --matcha-table-resize-indicator-height: 50%;
115
118
  --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
119
  }
123
120
 
124
121
  // ── Base — display table nativo + typography via vars ─────────────────
125
- table.matcha-table {
122
+ .matcha-table {
126
123
  display: table;
127
124
  width: 100%;
128
- border-collapse: collapse;
125
+ // separate (não collapse) + spacing 0 → visualmente idêntico (zero gap
126
+ // entre cells), mas `border-collapse: collapse` é conhecido por quebrar
127
+ // `position: sticky` em <th>/<td> em vários browsers — especialmente
128
+ // quando a cell precisa ficar sticky nos DOIS eixos ao mesmo tempo (linha
129
+ // + coluna, o canto stickyHeader × stickyStart/stickyEnd). Só existe
130
+ // border-bottom no arquivo (nenhum border-top) — sem risco de borda dupla.
131
+ border-collapse: separate;
129
132
  border-spacing: 0;
130
133
  font-family: var(--matcha-font-family);
131
134
  font-size: var(--matcha-table-font-size);
@@ -345,28 +348,39 @@
345
348
  }
346
349
  }
347
350
 
348
- // ── Modifiers via host classes (Angular bind quando striped/hover/etc) ─
351
+ // ── Modifiers via atributo no host (Angular @HostBinding, ver
352
+ // table.component.ts) ──────────────────────────────────────────────────
353
+ // Cada modifier tem 2 seletores alternativos: `&[x]` (forma legado — o
354
+ // host JÁ É `.matcha-table`, self) e `matcha-table[x] &` (forma elemento
355
+ // — o atributo mora no host `<matcha-table>`, mas o alvo real é o filho
356
+ // `.matcha-table` dentro do wrapper; CSS alcança via descendente, não
357
+ // precisa o atributo estar duplicado no filho).
349
358
  // Striped usa :where() pra dropar specificity do :nth-child — hover vence.
350
- &.matcha-table-striped tbody tr:where(:nth-child(even)) td {
359
+ &[striped] tbody tr:where(:nth-child(even)) td,
360
+ matcha-table[striped] & tbody tr:where(:nth-child(even)) td {
351
361
  --matcha-table-cell-bg: var(--matcha-table-row-bg-striped);
352
362
  }
353
363
 
354
- &.matcha-table-hover tbody tr:hover td {
364
+ &[hover] tbody tr:hover td,
365
+ matcha-table[hover] & tbody tr:hover td {
355
366
  --matcha-table-cell-bg: var(--matcha-table-row-bg-hover);
356
367
  }
357
368
 
358
369
  // 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 {
370
+ &[striped] tbody tr:where(:nth-child(even)).is-clickable:hover td,
371
+ matcha-table[striped] & tbody tr:where(:nth-child(even)).is-clickable:hover td,
372
+ &[striped][hover] tbody tr:where(:nth-child(even)):hover td,
373
+ matcha-table[striped][hover] & tbody tr:where(:nth-child(even)):hover td {
361
374
  --matcha-table-cell-bg: var(--matcha-table-row-bg-hover-striped);
362
375
  }
363
376
 
364
- // Variante de hover accent (input `rowHover="accent"` → classe host
365
- // `matcha-table-hover-accent`). Rebinda a var de hover no PRÓPRIO `<table>`,
377
+ // Variante de hover accent (input `rowHover="accent"` → atributo host
378
+ // `data-row-hover="accent"`). Rebinda a var de hover no PRÓPRIO `<table>`,
366
379
  // com especificidade acima do default — dispensa o consumer de furar o
367
380
  // encapsulamento com `::ng-deep`. Substitui o override manual repetido em
368
381
  // members/visitors/history/datas-comemorativas.
369
- &.matcha-table-hover-accent {
382
+ &[data-row-hover="accent"],
383
+ matcha-table[data-row-hover="accent"] & {
370
384
  --matcha-table-row-bg-hover: var(--matcha-color-accent-surface-hover);
371
385
  --matcha-table-row-bg-hover-striped: var(--matcha-color-accent-surface-hover);
372
386
  }
@@ -395,14 +409,30 @@
395
409
 
396
410
  // Bordered — box-shadow inset em vez de border real (não clipa shadows
397
411
  // externos das sticky cols, que projetam pra fora da <table>).
398
- &.matcha-table-bordered {
412
+ // Conhecido: em alguns casos (sticky-header/colunas fixas, forma
413
+ // elemento) o background opaco das cells pode encobrir parte deste
414
+ // traço — não resolvido nesta rodada (fora do escopo desta tarefa); se
415
+ // precisar de borda garantida num caso desses, use a utility class de
416
+ // borda (ex.: `b-1`) direto no consumo do componente.
417
+ &[bordered] {
399
418
  box-shadow: inset 0 0 0 var(--matcha-table-border-row)
400
419
  var(--matcha-table-border-color);
401
420
  border-radius: var(--matcha-table-bordered-radius);
402
421
  }
403
422
 
404
- // Sticky header (vertical scroll)
405
- &.matcha-table-sticky-header thead th {
423
+ // Sticky header (vertical scroll). Forma legado: o host (a própria table) é
424
+ // o container de scroll. Default do componente é overflow-y:hidden (só
425
+ // horizontal é fallback passivo — dois scrolls na tela atrapalham mobile);
426
+ // stickyHeader é opt-in EXPLÍCITO, reabilita overflow-y:auto de propósito
427
+ // + altura máxima (sem isso não há o que rolar, o header não tem contra o
428
+ // que grudar). Altura configurável via var (default 70vh).
429
+ &[sticky-header],
430
+ matcha-table[sticky-header] & {
431
+ max-height: var(--matcha-table-sticky-header-max-height, 70vh);
432
+ overflow-y: auto;
433
+ }
434
+ &[sticky-header] thead th,
435
+ matcha-table[sticky-header] & thead th {
406
436
  position: sticky;
407
437
  top: 0;
408
438
  z-index: 1;
@@ -415,49 +445,59 @@
415
445
  &[data-size="spacious"] tbody td { height: var(--matcha-table-cell-height-spacious); }
416
446
 
417
447
  // ── 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.
448
+ // Performance: nada de box-shadow com blur nem background-image (gradient)
449
+ // aqui são caros de repaint/compositar MULTIPLICADOS por linha (uma
450
+ // tabela de 40+ linhas com 2 colunas sticky = 80 elementos), e causavam
451
+ // queda de FPS real no scroll (medido em produção). Custo mínimo:
452
+ // background-color sólido (fixo, não acompanha hover/tint — troca-se
453
+ // fidelidade visual por performance) + border 1px sólida no lugar da
454
+ // sombra de scroll-edge (borda é essencialmente grátis pro compositor,
455
+ // sombra com blur não é).
456
+ //
457
+ // :not([sticky-header])/:not(matcha-table[sticky-header] &) — combinar
458
+ // sticky column COM sticky header exige que a cell de CANTO (cabeçalho da
459
+ // coluna fixa) fique sticky nos dois eixos (top E left/right) ao mesmo
460
+ // tempo — inconsistente entre browsers em cells de <table> (documentado
461
+ // no JSDoc do componente). Em vez de deixar o canto quebrado, desliga a
462
+ // coluna fixa inteira quando stickyHeader está ativo — só o header fixo
463
+ // (mais universalmente útil) permanece. `sticky-header` agora é atributo
464
+ // no host — o 2º `:not()` cobre o caso em que o host é o wrapper (forma
465
+ // elemento, `sticky-header` não está no `.matcha-table` em si, está no
466
+ // `<matcha-table>` ancestral). `data-sticky-start`/`-end` continuam só no
467
+ // nó real (mirrorAttributesToRealTable), não precisam de alternativa.
420
468
  @for $i from 1 through 4 {
421
- &[data-sticky-start="#{$i}"] {
469
+ &[data-sticky-start="#{$i}"]:not([sticky-header]):not(matcha-table[sticky-header] &) {
422
470
  thead th:nth-child(-n+#{$i}),
423
471
  tbody tr td:nth-child(-n+#{$i}) {
424
472
  position: sticky;
425
473
  z-index: 2;
426
- background: var(--matcha-table-cell-bg);
474
+ background-color: var(--matcha-color-surface-card);
427
475
  }
428
- // Última cell do grupo sticky-start projeta shadow scroll-edge.
476
+ // Última cell do grupo sticky-start marca o scroll-edge com borda fina.
429
477
  thead th:nth-child(#{$i}),
430
478
  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);
479
+ border-right: var(--matcha-border-hairline, 1px) solid var(--matcha-color-surface-border);
436
480
  }
437
481
  }
438
482
 
439
- &[data-sticky-end="#{$i}"] {
483
+ &[data-sticky-end="#{$i}"]:not([sticky-header]):not(matcha-table[sticky-header] &) {
440
484
  thead th:nth-last-child(-n+#{$i}),
441
485
  tbody tr td:nth-last-child(-n+#{$i}) {
442
486
  position: sticky;
443
487
  z-index: 2;
444
- background: var(--matcha-table-cell-bg);
488
+ background-color: var(--matcha-color-surface-card);
445
489
  }
446
490
  thead th:nth-last-child(#{$i}),
447
491
  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);
492
+ border-left: var(--matcha-border-hairline, 1px) solid var(--matcha-color-surface-border);
453
493
  }
454
494
  }
455
495
  }
456
496
 
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; }
497
+ &[data-sticky-start]:not([sticky-header]):not(matcha-table[sticky-header] &) thead th:first-child,
498
+ &[data-sticky-start]:not([sticky-header]):not(matcha-table[sticky-header] &) tbody tr td:first-child { left: 0; }
499
+ &[data-sticky-end]:not([sticky-header]):not(matcha-table[sticky-header] &) thead th:last-child,
500
+ &[data-sticky-end]:not([sticky-header]):not(matcha-table[sticky-header] &) tbody tr td:last-child { right: 0; }
461
501
 
462
502
  // ── Variant accent (semantic row coloring) ────────────────────────────
463
503
  // Defaults canon Figma DSV3: equal=info, plus=success, minus=danger.
@@ -496,7 +536,8 @@
496
536
  }
497
537
 
498
538
  // ── Loading state global — pulse + aria-busy ─────────────────────────
499
- &.matcha-table-loading tbody tr {
539
+ &[loading] tbody tr,
540
+ matcha-table[loading] & tbody tr {
500
541
  animation: matcha-table-loading-pulse
501
542
  var(--matcha-table-loading-pulse-duration)
502
543
  ease-in-out infinite;
@@ -563,6 +604,41 @@
563
604
  }
564
605
  }
565
606
 
607
+ // Sticky header — forma ELEMENTO (`<matcha-table>`, ver table.component.ts).
608
+ // Aqui quem rola de verdade é `.matcha-table__scroll` (o wrapper), não a
609
+ // `<table class="matcha-table">` interna — a altura máxima precisa ir no
610
+ // wrapper. `sticky-header` mora no HOST `<matcha-table>` (@HostBinding,
611
+ // não mais na `<table>` filha) — como o host é ANCESTRAL do wrapper, um
612
+ // descendente simples já alcança, sem precisar de `:has()`.
613
+ matcha-table[sticky-header] > .matcha-table__scroll {
614
+ max-height: var(--matcha-table-sticky-header-max-height, 70vh);
615
+ overflow-y: auto;
616
+ }
617
+
618
+ // roundedTop — regra TOP-LEVEL (fora do bloco .matcha-table acima): alcança
619
+ // o host na forma legado (self, `.matcha-table[rounded-top]`, o próprio
620
+ // `<table>` é a superfície visual) e o wrapper de scroll na forma elemento
621
+ // (descendente a partir do host `<matcha-table rounded-top>` — só o
622
+ // wrapper precisa do radius, ele já clipa a `<table>` interna via
623
+ // overflow non-visible, a `<table>` em si não precisa do próprio radius).
624
+ //
625
+ // Fallback inline no 2º var() é OBRIGATÓRIO: --matcha-table-rounded-top-radius
626
+ // é declarada dentro do bloco `.matcha-table { }` acima — na forma elemento
627
+ // `.matcha-table__scroll` é PAI de `.matcha-table` (o wrapper envolve a
628
+ // table real), não descendente. CSS custom property só desce a árvore, não
629
+ // sobe — sem o fallback aqui a var nunca resolve nesse elemento (bug
630
+ // silencioso: sem erro, só o border-radius nunca aparece). O fallback ainda
631
+ // respeita um override do consumer, se ele setar a var em algum ancestral
632
+ // real do wrapper (ex.: no próprio host `<matcha-table>` ou em `:root`).
633
+ .matcha-table[rounded-top] {
634
+ border-top-left-radius: var(--matcha-table-rounded-top-radius);
635
+ border-top-right-radius: var(--matcha-table-rounded-top-radius);
636
+ }
637
+ matcha-table[rounded-top] .matcha-table__scroll {
638
+ border-top-left-radius: var(--matcha-table-rounded-top-radius, var(--matcha-radius-xl, 16px));
639
+ border-top-right-radius: var(--matcha-table-rounded-top-radius, var(--matcha-radius-xl, 16px));
640
+ }
641
+
566
642
  @keyframes matcha-table-loading-pulse {
567
643
  0%, 100% { opacity: 1; }
568
644
  50% { opacity: var(--matcha-table-loading-pulse-opacity-min); }
@@ -570,8 +646,9 @@
570
646
 
571
647
  // ── Reduced motion ────────────────────────────────────────────────────
572
648
  @media (prefers-reduced-motion: reduce) {
573
- table.matcha-table tbody td,
574
- table.matcha-table.matcha-table-loading tbody tr {
649
+ .matcha-table tbody td,
650
+ .matcha-table[loading] tbody tr,
651
+ matcha-table[loading] .matcha-table tbody tr {
575
652
  transition: none;
576
653
  animation: none;
577
654
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inchurch/matcha-theme",
3
- "version": "22.2.0",
3
+ "version": "22.4.0",
4
4
  "description": "Themes for matcha-design-system",
5
5
  "main": "main.scss",
6
6
  "scripts": {