@scalewing/react 1.35.0 → 1.35.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @scalewing/react
2
2
 
3
+ ## 1.35.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 521903d: `Table` `stickyHeader` (`true` or `'page'`) now pins the whole `TableHeader` as one group (Teisoro F-011 task 2200): the `thead` is sticky, not each `thead th`, so a row under the column headings (such as a running total) stays in view right under them with all its cells, `td` as well as `th`, where before only its `th` pinned (at the same edge as the headings) and its `td` cells scrolled away. Every pinned head cell is on the glass (solid under Reduce Transparency, the system canvas in forced colours) and draws its row rule on its own `::before` instead of a collapsed bottom border, which stayed behind as the row moved and left a gap the rows under it showed through. No public API change, no new class, no new tokens, no new dependency.
8
+
3
9
  ## 1.35.0
4
10
 
5
11
  ### Minor Changes
package/README.md CHANGED
@@ -416,7 +416,7 @@ A header `TableCell` (`as="th"`) with `sort` (`'ascending'`, `'descending'` or `
416
416
 
417
417
  A ledger read across as well as down takes `Table` `columnRules` (a hairline at the inline start of every cell after a row's first, mirrored right to left) and `TableCell` `tone` (`success`, `danger`, `muted` or `accent`: the cell's text in the theme colour, as `Text color` uses it; never the only signal, so keep the sign or the words). `TableRow` `variant="sub"` (default `"default"`) sets a row under the one above, as a batch's items: its row header, a `TableCell as="th" scope="row"`, is indented a `space-6` step with a guide bar at the indent (a sub row without a row header is not indented). `TableRow` `struck` keeps a voided row on the record: the subtle fill and the text muted and struck through, toned cells included; it works with either variant. A line-through is not read aloud, so say why in the row, such as a `Badge` "Voided": a Badge in a line of text is not struck, but one that is itself a flex item (a direct child of `Inline`) is, so put it in the title's line. A row header in the body or footer (`th scope="row"`) reads as body text. An unknown `tone` or `variant` throws a `RangeError`.
418
418
 
419
- `Table` `stickyHeader` pins the header row: `true` (default) to the top of the table's own scroll region, `false` lets it scroll away, and `'page'` pins it to the page's top as the page scrolls. With `'page'`, while the table fits its width its region stops being a scroll box (`sw-table-sticky-page`), so the header stays in view under any sticky `AppHeader` (which covers it); a table wider than its region scrolls sideways in it and pins inside it. Use it for a long table whose last row, such as a non-sticky `TableFooter` total, should scroll with the rows. An unknown value throws a `RangeError`.
419
+ `Table` `stickyHeader` pins the header: the whole `TableHeader` as one group, every row in it (the column headings and any row under them, such as a running total) with all its cells, `th` and `td`, each row under the one above, on the glass with its row and column rules. `true` (default) pins it to the top of the table's own scroll region, `false` lets it scroll away, and `'page'` pins it to the page's top as the page scrolls. With `'page'`, while the table fits its width its region stops being a scroll box (`sw-table-sticky-page`), so the header stays in view under any sticky `AppHeader` (which covers it); a table wider than its region scrolls sideways in it and pins inside it. Use it for a long table whose last row, such as a non-sticky `TableFooter` total, should scroll with the rows. An unknown value throws a `RangeError`.
420
420
 
421
421
  ```tsx
422
422
  <Table aria-label="Site census" stickyHeader="page">
@@ -56,7 +56,7 @@ function reducedTransparencyRules() {
56
56
  .sw-steps-item,
57
57
  .sw-badge-neutral,
58
58
  .sw-segmented,
59
- .sw-table-sticky thead th,
59
+ .sw-table-sticky thead :is(th, td),
60
60
  .sw-table .sw-table-footer-sticky :is(th, td),
61
61
  .sw-denomination-strip .sw-denomination-label,
62
62
  .sw-denomination-strip thead .sw-denomination-corner:first-child,
@@ -9,7 +9,7 @@ import { zIndex } from './stacking.js';
9
9
  * A sticky footer pins its cells to the bottom edge on the header's glass
10
10
  * (solid surface under reduced transparency, the system canvas in forced
11
11
  * colours, as the pinned header cells), on the `stickyFooter` layer: over
12
- * the cells and the pinned header cells, under the ActionBar, which covers
12
+ * the cells and the pinned head group, under the ActionBar, which covers
13
13
  * it, so a page does not pair the two. Where it pins (the page or the
14
14
  * table's own region) is `css-table-page-pin.ts`.
15
15
  */
@@ -41,7 +41,7 @@ export function cssTableFooterClasses() {
41
41
  @media (forced-colors: active) {
42
42
  .sw-table tfoot > tr:first-child > :is(th, td)::before { border-color: CanvasText; }
43
43
  .sw-table .sw-table-footer-sticky :is(th, td),
44
- .sw-table-sticky thead th { background: Canvas; backdrop-filter: none; -webkit-backdrop-filter: none; }
44
+ .sw-table-sticky thead :is(th, td) { background: Canvas; backdrop-filter: none; -webkit-backdrop-filter: none; }
45
45
  }`;
46
46
  }
47
47
  export function tableFooterClassCatalog() {
@@ -54,9 +54,10 @@ export function cssTableLedgerClasses() {
54
54
  border-inline-start: 1px solid var(--sw-color-border);
55
55
  }
56
56
 
57
- /* A sticky header cell is positioned, so the next cell's fill covers a
58
- collapsed border; its rule is a border on its own ::after instead, so
59
- forced colours keep it and the logical inset mirrors it. */
57
+ /* A pinned head cell (in a sticky header group) is positioned, so the
58
+ next cell's fill covers a collapsed border; its rule is a border on its
59
+ own ::after instead, so forced colours keep it and the logical inset
60
+ mirrors it. */
60
61
  .sw-table-sticky.sw-table-column-rules thead :is(th, td) + :is(th, td)::after {
61
62
  border-inline-start: 1px solid var(--sw-color-border);
62
63
  content: '';
@@ -0,0 +1,2 @@
1
+ export declare function cssTableStickyHeaderClasses(): string;
2
+ export declare function tableStickyHeaderClassCatalog(): string[];
@@ -0,0 +1,52 @@
1
+ import { zIndex } from './stacking.js';
2
+ /*
3
+ * A sticky header pins the table's whole head group, not cell by cell: the
4
+ * `thead` itself is sticky at the top edge, so every row in it (the column
5
+ * headings and any row under them, such as a running total) and every cell
6
+ * in those rows, `th` and `td` alike, stays in view together, each row at
7
+ * its own offset under the one above. A cell-by-cell pin would leave a
8
+ * second row's `td` cells to scroll away and stack every row's `th` at the
9
+ * same edge. Where the group pins (the page or the table's own region) is
10
+ * `css-table-page-pin.ts`.
11
+ *
12
+ * Each pinned cell is on the glass (solid surface under Reduce
13
+ * Transparency, the system canvas in forced colours), so the rows that
14
+ * scroll under the group never show through, and positioned, so its rules
15
+ * can draw on it. A collapsed border stays where the cell was as the cell
16
+ * moves and leaves a gap the rows under it show through, so a pinned
17
+ * cell has none at its bottom and draws its row rule as a border on its
18
+ * own ::before (forced colours keep it), as its column rule is on its
19
+ * ::after (`css-table-ledger.ts`). The group is on the `stickyCell`
20
+ * layer, over the body cells and under a pinned footer.
21
+ */
22
+ export function cssTableStickyHeaderClasses() {
23
+ return `.sw-table-sticky thead {
24
+ position: sticky;
25
+ top: 0;
26
+ ${zIndex('stickyCell')}
27
+ }
28
+
29
+ .sw-table-sticky thead :is(th, td) {
30
+ background: var(--sw-glass-fill);
31
+ backdrop-filter: blur(var(--sw-glass-blur)) saturate(var(--sw-glass-saturate));
32
+ -webkit-backdrop-filter: blur(var(--sw-glass-blur)) saturate(var(--sw-glass-saturate));
33
+ border-bottom: 0;
34
+ position: relative;
35
+ }
36
+
37
+ .sw-table-sticky thead :is(th, td)::before {
38
+ border-bottom: 1px solid var(--sw-color-border);
39
+ content: '';
40
+ inset-block-end: 0;
41
+ inset-inline: 0;
42
+ pointer-events: none;
43
+ position: absolute;
44
+ }
45
+
46
+ @media (forced-colors: active) {
47
+ .sw-table-sticky thead :is(th, td)::before { border-color: CanvasText; }
48
+ }`;
49
+ }
50
+ export function tableStickyHeaderClassCatalog() {
51
+ return ['sw-table-sticky'];
52
+ }
@@ -5,8 +5,8 @@ import { cssTableLedgerClasses, tableLedgerClassCatalog, } from './css-table-led
5
5
  import { cssTableFooterClasses, tableFooterClassCatalog, } from './css-table-footer.js';
6
6
  import { cssTablePagePinClasses, tablePagePinClassCatalog, } from './css-table-page-pin.js';
7
7
  import { cssTablePressClasses, tablePressClassCatalog, } from './css-table-press.js';
8
+ import { cssTableStickyHeaderClasses, tableStickyHeaderClassCatalog, } from './css-table-sticky-header.js';
8
9
  import { cssTableSortClasses, tableSortClassCatalog, } from './css-table-sort.js';
9
- import { zIndex } from './stacking.js';
10
10
  const caption = typographyVariants.caption;
11
11
  /*
12
12
  * A selected row is marked by an accent bar at its inline start and nothing
@@ -75,14 +75,7 @@ export function cssTableClasses() {
75
75
  overflow: hidden;
76
76
  }
77
77
 
78
- .sw-table-sticky thead th {
79
- background: var(--sw-glass-fill);
80
- backdrop-filter: blur(var(--sw-glass-blur)) saturate(var(--sw-glass-saturate));
81
- -webkit-backdrop-filter: blur(var(--sw-glass-blur)) saturate(var(--sw-glass-saturate));
82
- position: sticky;
83
- top: 0;
84
- ${zIndex('stickyCell')}
85
- }
78
+ ${cssTableStickyHeaderClasses()}
86
79
 
87
80
  .sw-table-compact th,
88
81
  .sw-table-compact td {
@@ -110,7 +103,7 @@ export function tableClassCatalog() {
110
103
  'sw-table-end',
111
104
  'sw-table-numeric',
112
105
  'sw-table-clip',
113
- 'sw-table-sticky',
106
+ ...tableStickyHeaderClassCatalog(),
114
107
  'sw-table-compact',
115
108
  'sw-table-row-selected',
116
109
  ...tableLayoutClassCatalog(),
@@ -2,8 +2,8 @@
2
2
  * The one stacking order of the generated stylesheet. Every generated
3
3
  * `z-index` reads a layer from here, lowest first:
4
4
  *
5
- * 1. `stickyCell`: a sticky table header cell or row label over the cells
6
- * that scroll under it.
5
+ * 1. `stickyCell`: a sticky table head group (every row in a sticky
6
+ * `thead`) or row label over the cells that scroll under it.
7
7
  * 2. `stickyFooter`: a sticky table footer (a pinned total row) over the
8
8
  * cells and pinned header cells that scroll under it, and under the
9
9
  * ActionBar, which stays the page's last word at the bottom edge.
package/dist/styles.css CHANGED
@@ -1600,15 +1600,33 @@ body {
1600
1600
  overflow: hidden;
1601
1601
  }
1602
1602
 
1603
- .sw-table-sticky thead th {
1604
- background: var(--sw-glass-fill);
1605
- backdrop-filter: blur(var(--sw-glass-blur)) saturate(var(--sw-glass-saturate));
1606
- -webkit-backdrop-filter: blur(var(--sw-glass-blur)) saturate(var(--sw-glass-saturate));
1603
+ .sw-table-sticky thead {
1607
1604
  position: sticky;
1608
1605
  top: 0;
1609
1606
  z-index: 1;
1610
1607
  }
1611
1608
 
1609
+ .sw-table-sticky thead :is(th, td) {
1610
+ background: var(--sw-glass-fill);
1611
+ backdrop-filter: blur(var(--sw-glass-blur)) saturate(var(--sw-glass-saturate));
1612
+ -webkit-backdrop-filter: blur(var(--sw-glass-blur)) saturate(var(--sw-glass-saturate));
1613
+ border-bottom: 0;
1614
+ position: relative;
1615
+ }
1616
+
1617
+ .sw-table-sticky thead :is(th, td)::before {
1618
+ border-bottom: 1px solid var(--sw-color-border);
1619
+ content: '';
1620
+ inset-block-end: 0;
1621
+ inset-inline: 0;
1622
+ pointer-events: none;
1623
+ position: absolute;
1624
+ }
1625
+
1626
+ @media (forced-colors: active) {
1627
+ .sw-table-sticky thead :is(th, td)::before { border-color: CanvasText; }
1628
+ }
1629
+
1612
1630
  .sw-table-compact th,
1613
1631
  .sw-table-compact td {
1614
1632
  padding: var(--sw-space-1) var(--sw-space-2);
@@ -1749,9 +1767,10 @@ body {
1749
1767
  border-inline-start: 1px solid var(--sw-color-border);
1750
1768
  }
1751
1769
 
1752
- /* A sticky header cell is positioned, so the next cell's fill covers a
1753
- collapsed border; its rule is a border on its own ::after instead, so
1754
- forced colours keep it and the logical inset mirrors it. */
1770
+ /* A pinned head cell (in a sticky header group) is positioned, so the
1771
+ next cell's fill covers a collapsed border; its rule is a border on its
1772
+ own ::after instead, so forced colours keep it and the logical inset
1773
+ mirrors it. */
1755
1774
  .sw-table-sticky.sw-table-column-rules thead :is(th, td) + :is(th, td)::after {
1756
1775
  border-inline-start: 1px solid var(--sw-color-border);
1757
1776
  content: '';
@@ -1834,7 +1853,7 @@ body {
1834
1853
  @media (forced-colors: active) {
1835
1854
  .sw-table tfoot > tr:first-child > :is(th, td)::before { border-color: CanvasText; }
1836
1855
  .sw-table .sw-table-footer-sticky :is(th, td),
1837
- .sw-table-sticky thead th { background: Canvas; backdrop-filter: none; -webkit-backdrop-filter: none; }
1856
+ .sw-table-sticky thead :is(th, td) { background: Canvas; backdrop-filter: none; -webkit-backdrop-filter: none; }
1838
1857
  }
1839
1858
 
1840
1859
  .sw-table-wrap.sw-scroll-fits:has(> .sw-table > .sw-table-footer-sticky),
@@ -5671,7 +5690,7 @@ body {
5671
5690
  .sw-steps-item,
5672
5691
  .sw-badge-neutral,
5673
5692
  .sw-segmented,
5674
- .sw-table-sticky thead th,
5693
+ .sw-table-sticky thead :is(th, td),
5675
5694
  .sw-table .sw-table-footer-sticky :is(th, td),
5676
5695
  .sw-denomination-strip .sw-denomination-label,
5677
5696
  .sw-denomination-strip thead .sw-denomination-corner:first-child,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scalewing/react",
3
- "version": "1.35.0",
3
+ "version": "1.35.1",
4
4
  "description": "Scalewing DOM components and package-owned CSS utilities.",
5
5
  "type": "module",
6
6
  "license": "MIT",