Skip to content

Commit cff821e

Browse files
committed
Close out the remaining review comments
The two sibling comparison tables carried the same width coupling that ComparisonMatrix just shed: EdgeComparisonMatrix wrote 40% and three 20%s once in the columns array and again in the col-class rules, and Pricing/ComparisonTable did the same with 30% and 17.5%. The doubling is deliberate — inline width is immune to specificity drift, the class rule is the fallback a fixed table needs when the col width is unreachable — so both sides now read one local constant, the stylesheet through a custom property on the section. Eight literals become four, and the emitted values are unchanged. scroll-region-tabindex is renamed to scroll-regions, since it manages role alongside the tab stop and the old name sent anyone looking for what strips role=region to the wrong file. Its docblock now states that the role of a data-scroll-region element belongs to the function: it sets region and removes it again, so a consumer ships role="region" in the markup and never any other role. CLAUDE.md's DataTable entry said caption then colgroup, though colgroup is a prop and ComparisonMatrix passes false, and it left out scrollable — the one prop with a runtime partner, since it emits the role="region" wrapper initScrollRegions then toggles.
1 parent 219209d commit cff821e

7 files changed

Lines changed: 49 additions & 22 deletions

File tree

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ Use the `edit-doc` skill for full props, usage examples, and authoring rules for
9191
- **InstallationCardGrid** — installation option card grid
9292
- **RuleNodeCardGrid** — rule node category card grid
9393
- **DocLink** — product-aware internal links (always use instead of bare markdown links)
94-
- **DataTable** — semantic shell for comparison tables (caption → colgroup → `th scope="col"` header → tbody slot); callers pass `<tr>` rows whose first cell is `<th scope="row">`. Styling contract: the caller's `<style>` must be `is:global`, nested under the caller's own class — scoped rules cannot match the shell DataTable renders
94+
- **DataTable** — semantic shell for comparison tables (caption → optional colgroup → `th scope="col"` header → tbody slot); callers pass `<tr>` rows whose first cell is `<th scope="row">`. `scrollable` wraps the table in a `role="region"` named from the caption, which `initScrollRegions` drops again on viewports where the table does not overflow. Styling contract: the caller's `<style>` must be `is:global`, nested under the caller's own class — scoped rules cannot match the shell DataTable renders
9595
- **DataTableValue** — one comparison cell's value, always as text; icons are decorative, an empty value fails the build
9696
- **Code blocks**`maxLines`, `collapsible`, `wrap`, `download='file.ext'` meta options; `<Code>` component for dynamic code
9797

src/components/DataTable.astro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ const labelLines = (label: string) => label.split('\n');
110110
</Wrapper>
111111

112112
<script>
113-
import { initScrollRegionTabindex } from '@util/scroll-region-tabindex';
114-
initScrollRegionTabindex();
113+
import { initScrollRegions } from '@util/scroll-regions';
114+
initScrollRegions();
115115
</script>
116116

117117
<style lang="scss" is:global>

src/components/IotHub/SectionTable.astro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ const id = captionId?.trim() || slugId(heading, 'ih-table');
4343
</section>
4444

4545
<script>
46-
import { initScrollRegionTabindex } from '@util/scroll-region-tabindex';
47-
initScrollRegionTabindex();
46+
import { initScrollRegions } from '@util/scroll-regions';
47+
initScrollRegions();
4848
</script>
4949

5050
<style lang="scss">

src/components/Landing/EdgeComparisonMatrix.astro

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,27 @@ const { rows = EDGE_VS_GATEWAY_ROWS } = Astro.props;
1212
1313
// Widths are emitted inline as well as via the col classes: inline is immune to any
1414
// later specificity drift, and a fixed table with unreachable col widths silently
15-
// falls back to equal quarters.
15+
// falls back to equal quarters. Both sides read these constants — the stylesheet
16+
// through the custom properties set on the section — so the pair cannot drift.
17+
const FEATURE_COL_PCT = 40; // row-header column
18+
const VALUE_COL_PCT = 20; // each of the three product columns
19+
1620
const columns: DataTableColumn[] = [
17-
{ colClass: 'col-feature', width: '40%', thClass: 'feature' },
18-
{ label: 'IoT\nGateway', colClass: 'col-gateway', width: '20%', thClass: 'gateway' },
19-
{ label: 'ThingsBoard\nEdge', colClass: 'col-edge', width: '20%', thClass: 'edge' },
20-
{ label: 'ThingsBoard\nServer', colClass: 'col-server', width: '20%', thClass: 'server' },
21+
{ colClass: 'col-feature', width: `${FEATURE_COL_PCT}%`, thClass: 'feature' },
22+
{ label: 'IoT\nGateway', colClass: 'col-gateway', width: `${VALUE_COL_PCT}%`, thClass: 'gateway' },
23+
{ label: 'ThingsBoard\nEdge', colClass: 'col-edge', width: `${VALUE_COL_PCT}%`, thClass: 'edge' },
24+
{ label: 'ThingsBoard\nServer', colClass: 'col-server', width: `${VALUE_COL_PCT}%`, thClass: 'server' },
2125
];
2226
---
2327

24-
<section id="matrix" class="edge-matrix">
28+
<section
29+
id="matrix"
30+
class="edge-matrix"
31+
style={{
32+
'--edge-feature-col-w': `${FEATURE_COL_PCT}%`,
33+
'--edge-value-col-w': `${VALUE_COL_PCT}%`,
34+
}}
35+
>
2536
<div class="main-content">
2637
<h2>Which ThingsBoard Product Is Right for You?</h2>
2738

@@ -92,13 +103,13 @@ const columns: DataTableColumn[] = [
92103
border: none;
93104

94105
.col-feature {
95-
width: 40%;
106+
width: var(--edge-feature-col-w);
96107
}
97108

98109
.col-gateway,
99110
.col-edge,
100111
.col-server {
101-
width: 20%;
112+
width: var(--edge-value-col-w);
102113
}
103114
}
104115

src/components/Pricing/ComparisonTable.astro

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,25 @@ const {
2323
} = Astro.props;
2424
2525
// Widths are emitted inline on <col>, which `table-layout: fixed` honours in every
26-
// browser; the per-class width rules below are a redundant fallback.
26+
// browser; the per-class width rules below are a redundant fallback. Both sides read
27+
// these constants — the stylesheet through the custom properties set on the section —
28+
// so the pair cannot drift.
29+
const FEATURE_COL_PCT = 30; // row-header column
30+
const PLAN_COL_PCT = 17.5; // each plan column
31+
2732
const columns: DataTableColumn[] = [
28-
{ width: '30%', thClass: 'pc-comparison-feature-col' },
29-
...headers.map((h) => ({ label: h, width: '17.5%', thClass: 'pc-comparison-plan-col' })),
33+
{ width: `${FEATURE_COL_PCT}%`, thClass: 'pc-comparison-feature-col' },
34+
...headers.map((h) => ({ label: h, width: `${PLAN_COL_PCT}%`, thClass: 'pc-comparison-plan-col' })),
3035
];
3136
---
3237

33-
<div class="pc-comparison-section">
38+
<div
39+
class="pc-comparison-section"
40+
style={{
41+
'--pc-feature-col-w': `${FEATURE_COL_PCT}%`,
42+
'--pc-plan-col-w': `${PLAN_COL_PCT}%`,
43+
}}
44+
>
3445
<h3 class="pc-comparison-title">{title}</h3>
3546
{subtitle && <p class="pc-comparison-subtitle">{subtitle}</p>}
3647

@@ -143,11 +154,11 @@ const columns: DataTableColumn[] = [
143154

144155
.pc-comparison-feature-col {
145156
text-align: left !important;
146-
width: 30%;
157+
width: var(--pc-feature-col-w);
147158
}
148159

149160
.pc-comparison-plan-col {
150-
width: 17.5%;
161+
width: var(--pc-plan-col-w);
151162
}
152163

153164
.pc-comparison-table tbody tr {

src/pages/ce-vs-pe-diff/index.astro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,8 @@ import LegalLayout from '../../layouts/LegalLayout.astro';
282282
{/* Inside the layout: content placed after </LegalLayout> is emitted after
283283
</html>, as the anchor-js tags below already are. */}
284284
<script>
285-
import { initScrollRegionTabindex } from '@util/scroll-region-tabindex';
286-
initScrollRegionTabindex();
285+
import { initScrollRegions } from '@util/scroll-regions';
286+
initScrollRegions();
287287
</script>
288288
</LegalLayout>
289289

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@
55
* cannot scroll is a needless tab stop, and with an accessible name it also
66
* clutters the landmark list. Watches both the region and its content, since a
77
* font swap can change scrollWidth without moving the region's own box.
8+
*
9+
* The `role` of a `[data-scroll-region]` element belongs to this function: it sets
10+
* `region` and removes it again, so a consumer ships `role="region"` in the markup
11+
* and never any other role — one placed here would be stripped on the first layout
12+
* where the region fits.
813
*/
9-
export function initScrollRegionTabindex(): void {
14+
export function initScrollRegions(): void {
1015
const regions = document.querySelectorAll<HTMLElement>('[data-scroll-region]');
1116
if (regions.length === 0) return;
1217

0 commit comments

Comments
 (0)