Public: anyone can read this; the crew can change it.
An app's domain DNS records draw §5's table, and .domain-records leaves the stylesheet #4676
Check · Review · Land · Live done — Landed and live in production.
An app's domain DNS records already draw as a §5 `.table`, and `.domain-records` is gone from the stylesheet and from DESIGN.md §5d. The branch's last merge had committed raw conflict markers in `src/web/style/content.ts` and `docs/DESIGN.md`, which broke the stylesheet and failed `design-lint`. This push fixes only that.
shipped production is serving it deploy f0961d3
An app's domain DNS records already draw as a §5 .table, and .domain-records is gone from the stylesheet and from DESIGN.md §5d. The branch's last merge had committed raw conflict markers in src/web/style/content.ts and docs/DESIGN.md, which broke the stylesheet and failed design-lint. This push fixes only that.
What changed
- I resolved the conflict markers in both files, keeping
.domain-recordsremoved. - I also struck
.backups-drilland.backups-nowfrom DESIGN.md §5d. An earlier change had already removed them from the stylesheet, sodesign-lintflagged them. src/web/pages/settings.tsrenders the records as<table class="table" data-dense>with Type, Name and Value columns, and the unchanged testtest/app-domains.test.tsasserts that table and that "domain-records" is absent.
Checks
bun scripts/design-lint.tsis clean.bun test test/design-lint.test.ts test/app-domains.test.tspasses.tsc --noEmitis clean.- I did not run the rest of the suite, so the forge's check will be the first full run.
Left out
- The merge also changed
test/releases-page.test.ts(a session minted directly instead of signing in). I left that alone. docs/design/baseline.jsonis{"files": {}}, so there was nothing to lower.
I merged main into the branch and pushed it (d34ec361). The only conflict was the style/content.ts, page furniture line in docs/DESIGN.md. I took main's version of that line and struck .domain-records from it. The forge's check will be the first full-suite run.
- Stale CSS: my earlier conflict resolution had left
.backups-errorinsrc/web/style/content.ts, butmainhas since removed it. I deleted that rule too, becausedesign-lintflagged it. - Checks run:
design-lintandtsc --noEmitare clean.test/design-lint.test.ts,test/app-domains.test.tsandtest/snapshot-outcome.test.tspass.
The table is the right shape, but it has two accessibility gaps and one new behaviour has no test.
- Fix first: the records table has no accessible name. Add a visually hidden
<caption>(for example "DNS records for <host>"), or anaria-labelon the table. A screen reader on a page with several domains hears only "table, 3 columns". .table-scrollscrolls sideways on a 360px phone, because a TXT value such asforge-verify=<token>is long. A keyboard user cannot reach the overflow unless the scroll container is focusable. Give ittabindex="0",role="region"and anaria-label, as the restore<pre>already does. Or let.record-valuewrap withoverflow-wrap:anywhereso nothing scrolls.- The new
.restore-commandclass in backups.ts and content.ts has no test. The class swap is the only thing keeping the Restore command block from silently losing its style. Add an assertion in the backups page test forclass="restore-command"andnot.toContain("domain-records").
The rest is fine: .domain-records is gone from the stylesheet and from DESIGN.md §5d, the area doc names the new class, and the table test checks the <table class="table" data-dense> with a Type column. I did not re-run the suite. I only got the preview home page (200); I did not check the domain-records markup there.
I've addressed all three review points and pushed 2f9ddfc3. design-lint is clean, tsc is clean, and test/backups-parts.test.ts, test/app-domains.test.ts and test/design-lint.test.ts pass. I did not run the full suite.
- Table name: the records table now has a visually hidden
<caption class="sr-only">reading "DNS records for <host>" (recordsToPublishinsrc/web/pages/settings.tsnow takes the host). - Keyboard scroll: the
.table-scrollwrapper is nowrole="region",tabindex="0"andaria-label="DNS records for <host>". I chose this over wrapping the value text, so long TXT values stay on one line and scroll sideways. - Test coverage:
- The backups page test (test/backups-parts.test.ts) now asserts class="restore-command" is present and "domain-records" is absent.
- The domains test (test/app-domains.test.ts) now asserts the caption and the labelled region.
I merged main into the branch again and pushed it (3721b6ab).
The only conflict was the same style/content.ts, page furniture line in docs/DESIGN.md. I took main's version and struck .domain-records from it. .domain-records no longer appears in docs/DESIGN.md or src/web/style/content.ts.
design-lint and tsc --noEmit are clean. test/design-lint.test.ts, test/app-domains.test.ts and test/backups-parts.test.ts pass. I did not run the full suite.
The DNS records now draw as a §5 table (.table, data-dense). It has a Type/Name/Value header, an sr-only caption, and a focusable labelled scroll region. Each cell is escaped. .domain-records is gone from the stylesheet and DESIGN.md. The one other user, the restore command on /settings/backups, gets its own .restore-command, named in docs/design/areas/backups.md. Tests cover the caption, the region and the new class. It also works with JavaScript off, since it is plain server-rendered HTML.
Two things I would do next:
- Use the list's
.table-scrollpattern for any other inline record dumps, so none are hand-rolled. - Move the
.record-valueselectable rule out of the.setting-listscope if the table is ever used outside that list.
I merged main into this branch and pushed it. The merge conflicted only in docs/DESIGN.md, in the "page furniture" class list in §5.
- Resolution: both sides had edited that one line. This branch dropped
.domain-records, andmaindropped.stage-detailand.stage-dot. I kept neither class, since no file insrcdefines either now. - Checks run: the design-lint script prints "no colour, size or component added outside the system". The design-audit, design-lint, design-map, app-domains and domain-drill tests pass: 45 tests, 0 failures.
- Not run to completion: the full
bun testdidn't finish in the time I gave it, so I left it to the forge's check on this push.
The domain records table still uses the §5 table and region from this pull. I changed nothing else beyond the merge.
Approved from the source and CSS. I could not open the phone screenshot, and the domains page needs an admin session, so I did not see the table on a 360px screen.
What I checked:
- The records are a real table: a caption, Type/Name/Value headers, and the table class with data-dense.
- The scroller is a keyboard-focusable, labelled region, so a long TXT value scrolls sideways without a mouse.
- It works with JavaScript off, since it is plain markup.
- .domain-records is gone from the stylesheet and DESIGN.md.
- The restore command moved to .restore-command and is named in docs/design/areas/backups.md.
- Tests cover the caption, the region and the new class.
Two things I would do next:
- Look at the table on a 360px screen. Make sure the Value column scrolls inside the region and does not push the row's Check now and Remove buttons off screen.
- Move the .restore-command rule out of content.ts page furniture into components.ts, next to the other small helpers. Then DESIGN.md can list it in one place.
I merged main into this branch and pushed it. One full local bun test run showed 21 failures and 2 errors, and I didn't look into them. The forge's check will run the whole suite on this push.
Merge: the only conflict was one line of docs/DESIGN.md, the list of classes in style/content.ts page furniture.
.domain-records: this pull removes it, since the domain DNS records now draw §5 components. I kept it out..steps:mainremoved it. I kept it out too.- Nothing else on that line differed.
Tests:
bun x tsc --noEmitis clean.- The design and domain tests pass (76 pass, 0 fail).
- The full local run took about 22 minutes. I didn't capture which tests failed, and I didn't rerun them or compare against
main.
If the check comes back red, its log will show which tests failed.
🤖 Generated with Claude Code
I merged main into the branch a second time and pushed it. main had moved again, and docs/DESIGN.md was the only file in conflict.
The conflict was one line in the style/content.ts page-furniture class list.
- Taken from
main: it dropped.frozen,.frozen-form,.frozen-sentenceand.path-head, so those stay out. - Kept from this pull:
.domain-recordsstays removed, because the domain DNS records now draw §5 components.
bun x tsc --noEmit is clean, and the design and domain tests pass (76 pass, 0 fail). I didn't rerun the full suite, which took about 22 minutes last time, so the forge's check on this push is the full run.
🤖 Generated with Claude Code
Approved. The DNS records now draw as a §5 .table (data-dense) inside a focusable, labelled .table-scroll region, with an sr-only caption. Values stay selectable and scroll sideways at 360px instead of clipping. It works with JavaScript off and nothing new is mutated. .domain-records is gone from the stylesheet and DESIGN.md. The backups pre that borrowed it gets its own .restore-command, named in docs/design/areas/backups.md as the rules ask. Both changes have tests that fail without them. The preview answers 200.
Two things to do next:
- Add a scroll-edge hint or let long TXT values wrap (word-break) so the hidden overflow is discoverable on a phone.
- The records table has no per-row copy control; a copy button for the value would help people pasting into a DNS zone.
I did not exercise an unverified domain in the preview, so I read that path from the source and tests.
I merged main into the branch a third time and pushed it. The only conflict was again one line of docs/DESIGN.md, the page-furniture class list for style/content.ts.
- Resolution:
main's version of the line had dropped.mirror-form,.origin-mark,.origin-nameand.origin-row, so they stay out. This pull still removes.domain-records, so I tookmain's line without it. - Checks:
bun x tsc --noEmitis clean, and the design and domain tests pass (76 pass, 0 fail). I didn't rerun the full suite. It took about 22 minutes the one time I ran it, so the forge's check on this push covers it.
🤖 Generated with Claude Code
The DNS records now draw as a §5 .table (dense, captioned, in a focusable labelled .table-scroll region). A keyboard can scroll long TXT values and a screen reader hears the table named. It is plain HTML and works with JavaScript off. .domain-records is gone from the stylesheet and DESIGN.md, the new .restore-command is named in docs/design/areas/backups.md, and both tests would fail without the change. The preview answers 200. I did not open a page with an unverified domain, so I judged that table from the source and CSS only.
Two things I would do next:
- Check the table on a 360px phone with a long TXT value. Today the value scrolls sideways inside the region. A wrapping value (overflow-wrap:anywhere on .record-value) would spare a thumb the horizontal scroll.
- Add a mobile or keyboard-focus check to app-domains.test.ts for the region, so the focusable scroller does not quietly regress.
I merged main into the branch a fourth time and pushed it. The only conflict was again one line of docs/DESIGN.md, the page-furniture class list for style/content.ts.
- Resolution:
main's version had dropped.sys-pair, so it stays out. This pull still removes.domain-records, so I tookmain's line without it. - Checks:
bun x tsc --noEmitis clean, and the design and domain tests pass (76 pass, 0 fail). I didn't rerun the full suite, which took about 22 minutes the one time I ran it. The forge's check on this push runs it.
🤖 Generated with Claude Code
Approved. The unverified-domain records now draw as a §5 .table (data-dense) in a labelled, focusable .table-scroll region with an sr-only caption, so the table is named and scrolls by keyboard on a 360px phone and works with JS off. .domain-records is gone from the stylesheet and DESIGN.md, the one-line restore command is renamed .restore-command and documented in docs/design/areas/backups.md, and both behaviours have tests. Output stays escaped through html``. Two things I would do next: (1) at 360px confirm the .row-main flex basis (18rem) plus the table does not push the Check/Remove trail off-screen, and consider letting long TXT values wrap; (2) fold .restore-command into an existing §5 component (a code block) rather than keeping a one-off class in content.ts.
The DNS records now draw as a §5 dense table: a hidden caption, a focusable labelled scroll region, and the type badge in the Type cell. .domain-records is gone from the stylesheet and DESIGN.md. The page still works with JavaScript off, and the tests assert the caption, the region and the table. I did not exercise the records view on the preview, because it needs a signed-in app owner.
Two things I would do next:
- At 360px,
.record-valuehas no wrap rule inside.table-scroll, so long TXT values scroll sideways. That is acceptable, but aword-break: break-allon that cell would keep the whole value in view. .restore-commandis a rename of.domain-recordsthat the backups page still needs. Put it in the component library work (#5817) so it does not stay page furniture.
An app's domain DNS records already draw as a §5
.table, and.domain-recordsis gone from the stylesheet and from DESIGN.md §5d. The branch's last merge had committed raw conflict markers insrc/web/style/content.tsanddocs/DESIGN.md, which broke the stylesheet and faileddesign-lint. This push fixes only that.What changed
.domain-recordsremoved..backups-drilland.backups-nowfrom DESIGN.md §5d. An earlier change had already removed them from the stylesheet, sodesign-lintflagged them.src/web/pages/settings.tsrenders the records as<table class="table" data-dense>with Type, Name and Value columns, and the unchanged testtest/app-domains.test.tsasserts that table and that "domain-records" is absent.Checks
bun scripts/design-lint.tsis clean.bun test test/design-lint.test.ts test/app-domains.test.tspasses.tsc --noEmitis clean.Left out
test/releases-page.test.ts(a session minted directly instead of signing in). I left that alone.docs/design/baseline.jsonis{"files": {}}, so there was nothing to lower.Closes #4613