From d3af0e7d51c2bac5de801bfbbed96a105c442e64 Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Wed, 22 Jul 2026 15:02:57 -0500 Subject: fix(a11y): stop section-header trailing controls letter-wrapping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported on device: the Domain section header's Note button rendered vertically — "N o t e", one character per line in a screen-tall capsule — at a larger (not even accessibility-tier) text size. Same pathology the row badges had: text inside a squeezed HStack compresses to a one-character column instead of the layout adapting. Three-part fix, mirroring the proven row treatment: - CollapsibleSectionView's header is now a ViewThatFits: title, trailing controls, and chevron on one line while they genuinely fit; otherwise the trailing controls drop below the title row. Applies to every section header, not just Domain. - The Note and Track bordered buttons get .fixedSize() so their text can never letter-wrap — their natural width is what pushes the header onto its stacked layout. - The "Tracked" pill becomes an icon-only indicator (eye in a tinted circle) — with Pin and Note beside it the full pill was the first thing to compress, and the word survives for VoiceOver via its label. Enforced audit suite stays green (7 tests, 0 failures, floor runtime). The post-lookup header state itself is not reachable by the harness — it requires a live lookup — so on-device confirmation closes this out. --- DomainDig/ContentView.swift | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'DomainDig/ContentView.swift') diff --git a/DomainDig/ContentView.swift b/DomainDig/ContentView.swift index ea6ead8..103e3b5 100644 --- a/DomainDig/ContentView.swift +++ b/DomainDig/ContentView.swift @@ -1352,7 +1352,16 @@ struct DomainSectionView: View { CollapsibleSectionView(title: "Domain", isCollapsed: $isCollapsed) { if let trackedDomain { HStack(spacing: 8) { - AppStatusBadgeView(model: .init(title: "Tracked", systemImage: "eye.fill", foregroundColor: Color(.statusPositive), backgroundColor: Color(.statusPositiveSurface))) + // Icon-only: the header also carries Pin and Note, and the + // full "Tracked" pill compresses at larger text sizes. + // VoiceOver still hears the word via the label. + Image(systemName: "eye.fill") + .font(appDensity.font(.caption)) + .foregroundStyle(Color(.statusPositive)) + .padding(6) + .background(Color(.statusPositiveSurface), in: Circle()) + .fixedSize() + .accessibilityLabel("Tracked") Button { onTogglePinned() } label: { @@ -1369,6 +1378,8 @@ struct DomainSectionView: View { } .buttonStyle(.bordered) .font(appDensity.font(.caption)) + // Never compress into a vertical letter column. + .fixedSize() } } } else { @@ -1378,6 +1389,7 @@ struct DomainSectionView: View { } .buttonStyle(.bordered) .font(appDensity.font(.caption)) + .fixedSize() } } content: { CardView(allowsHorizontalScroll: false) { -- cgit v1.2.3