asterism branch T-2193/bugfix-capture-view-page-title-accessibility-label commits 1 files 2 touched lines +136 / -1

Pre-push review: T-2193 capture page-title accessibility label

One-line VoiceOver fix in the share extension's CaptureView, plus the bugfix report. Diffed against origin/main (PR #41).

At a glance

  • .accessibilityLabel("Page title").accessibilityLabel("Page title: \(rawTitle)") on the raw-title Text in metadataSection.
  • Sibling rows already use the "Label: value" shape (Article title:, Chapter:, Entry title:), so this is convention alignment, not a new pattern.
  • No automated regression test — the share-extension target has no view-level test harness. The report documents this honestly rather than adding infrastructure for a one-liner.
  • Bugfix report at specs/bugfixes/capture-view-page-title-accessibility-label/report.md is complete and its line references match the code.

Verdict

Ready to push

The code change is a single string edit that brings the raw-title row in line with every other informative row in CaptureView and with reshare.title in ReShareCaptureView. No test, UI test, or other file references the old label or the capture.pageTitle identifier, so nothing else is affected. The report's file/line citations were checked against the tree and are accurate.

Review findings

1 raised · 0 fixed · 1 skipped

Jump to findings →

Commits

Three-level explanation

What changed

When you share a web page to Asterism, the capture sheet shows the page's title. For people using VoiceOver (the iPhone screen reader), the title row used to be announced only as the words "Page title" — the actual title was never spoken. Now VoiceOver says "Page title: the real title".

Why it matters

Without this, a VoiceOver user could not hear which page they were about to save.

Key concept

In SwiftUI, accessibilityLabel replaces what the screen reader says for a view; it does not add to it. A static caption therefore hides the content underneath.

Change

The rawTitle branch of metadataSection(preparation:outcome:) now interpolates the value into its label, matching the "Label: \(value)" convention used by projectedMetadataSection's rows (lines 236, 293) and by ReShareCaptureView's reshare.title row (line 123).

Trade-off

The alternative — dropping the label so VoiceOver reads the Text content — would lose the "Page title" prefix that tells the user what the row is. Keeping an explicit label is consistent with the rest of the view and keeps the capture.pageTitle identifier meaningful.

Testing

No test asserts accessibility label strings for share-extension views; make test-quick builds the extension target and confirms compilation.

Deep dive

Single-hunk change in the share extension. rawTitle is already an unwrapped String via if let rawTitle, so the interpolation is total. The label is not localised — neither are any of the sibling labels in this file, so this does not introduce a new inconsistency.

Edge cases

An empty rawTitle would announce "Page title: " — but the surrounding if let/preparation logic already decides whether to render this branch, and the same edge exists for reshare.title. Not worth guarding here.

Risk

None beyond compilation; nothing else in the tree references the old string or the identifier.

Important changes — detailed

CaptureView: interpolate the raw title into its accessibility label

Asterism/AsterismShareExtension/CaptureView.swift

Why it matters. User-visible accessibility behaviour: VoiceOver previously never announced the page title on the raw-title path.

What to look at. Asterism/AsterismShareExtension/CaptureView.swift:210

Takeaway. accessibilityLabel replaces a view's spoken content. For rows echoing dynamic content, interpolate the value ("Label: value") rather than writing a static caption.
Rationale. Matches the existing convention on every other informative row in this view and on reshare.title in ReShareCaptureView, as the ticket requested.

Key decisions

Keep an explicit label rather than removing it.

Removing accessibilityLabel would let VoiceOver read the Text directly but lose the "Page title" prefix and break the file's "Label: value" convention. Documented in the report's Alternatives section.

No regression test added.

The share extension has no ViewInspector/snapshot/XCUITest harness; the sibling label from T-2190 is equally untested. Building that infrastructure is out of scope for a one-line string fix. Stated in the report.

Review findings

SeverityAreaFindingResolution
infoCaptureView.swift:210Label string is not localised.Consistent with every other label in the file; not a regression. No change.

Per-file diffs

Click to expand.

Asterism/AsterismShareExtension/CaptureView.swift Modified +1 / -1
diff --git a/Asterism/AsterismShareExtension/CaptureView.swift b/Asterism/AsterismShareExtension/CaptureView.swiftindex abc2467..9b10763 100644--- a/Asterism/AsterismShareExtension/CaptureView.swift+++ b/Asterism/AsterismShareExtension/CaptureView.swift@@ -207,7 +207,7 @@ struct CaptureView: View {                 } else if let rawTitle {                     Text(rawTitle)                         .font(AsterismTypography.serifHeading)-                        .accessibilityLabel("Page title")+                        .accessibilityLabel("Page title: \(rawTitle)")                         .accessibilityIdentifier("capture.pageTitle")                 }             }
specs/bugfixes/capture-view-page-title-accessibility-label/report.md Added +135 / -0
diff --git a/specs/bugfixes/capture-view-page-title-accessibility-label/report.md b/specs/bugfixes/capture-view-page-title-accessibility-label/report.mdnew file mode 100644index 0000000..4c51a4e--- /dev/null+++ b/specs/bugfixes/capture-view-page-title-accessibility-label/report.md@@ -0,0 +1,135 @@+# Bugfix Report: CaptureView Page-Title Accessibility Label Hides the Actual Title++**Date:** 2026-08-29+**Status:** Fixed++## Description of the Issue++`CaptureView.swift`'s raw-title row set `.accessibilityLabel("Page title")` on+the `Text(rawTitle)` view. `accessibilityLabel` replaces an element's+accessible content rather than annotating it, so VoiceOver announced the+literal string "Page title" and never read the actual title value the row was+displaying.++**Reproduction steps:**+1. Share a page whose title could not be parsed into a work/chapter (or any+   case where `metadataSection` falls through to the `rawTitle` branch — see+   Q1 in the surrounding doc comment).+2. Open the capture sheet with VoiceOver running.+3. Focus the title row.+4. Observe VoiceOver announces "Page title" — the title itself is never+   spoken.++**Impact:** Low severity, but a real accessibility regression for VoiceOver+users on every capture whose title falls into the raw-title display path —+they cannot hear what page they are about to save without turning to a+sighted assistant.++## Investigation Summary++Pre-existing defect, surfaced during the T-2190 review (which added the+`reshare.title` label on the equivalent row in the re-share flow).++- **Symptoms examined:** The single call site,+  `Asterism/AsterismShareExtension/CaptureView.swift:210`, inside+  `metadataSection(preparation:outcome:)`.+- **Code inspected:** The sibling informative labels in the same file —+  `projectedMetadataSection`'s article/work/chapter rows (each uses+  `"Label: \(value)"`, e.g. `"Chapter: \(chapter)"` at line 293) — and the+  equivalent row in `ReShareCaptureView.swift` (`"Entry title:+  \(state.title)"` on `reshare.title`, line 123).+- **Hypotheses tested:** None needed — the description and the sibling+  pattern make the root cause and fix unambiguous.++## Discovered Root Cause++**Defect type:** Accessibility label replaces content instead of describing+it.++**Why it occurred:** `.accessibilityLabel("Page title")` was written as a+static caption rather than an interpolated description of the row's value,+unlike every other informative row in the same view and its `ReShareCaptureView`+sibling.++**Contributing factors:** No test coverage exists for SwiftUI accessibility+label strings in the share-extension views (see Regression Test section), so+the mismatch between this one row and its siblings went unnoticed.++## Resolution for the Issue++**Changes made:**+- `Asterism/AsterismShareExtension/CaptureView.swift:210` — changed+  `.accessibilityLabel("Page title")` to+  `.accessibilityLabel("Page title: \(rawTitle)")`.++**Approach rationale:** Matches the established convention in this same file+(`"Chapter: \(chapter)"`, `"Article title: \(displayTitle)"`,+`"Work: \(workTitle)..."`) and in `ReShareCaptureView.swift`+(`"Entry title: \(state.title)"`), exactly as the ticket asked.++**Alternatives considered:**+- Removing the `accessibilityLabel` entirely and letting VoiceOver read the+  `Text` content directly — rejected because the existing+  `capture.pageTitle` accessibility identifier and the project's+  established row convention (an explicit `"Label: value"` label on every+  informative row) are both worth keeping consistent with the rest of the+  view.++## Regression Test++No automated regression test was added. `CaptureView.swift` lives in the+`AsterismShareExtension` target, which `make test-core` does not compile+(per `CLAUDE.md`), and this repository has no ViewInspector/SnapshotTesting+dependency or XCUITest harness capable of driving the share extension's UI+(`AccessibilityJourneyUITests.swift` only exercises the main app; there is no+share-extension launch support in `UITestLaunchSupport.swift`). The sibling+label this fix matches (`reshare.title` in `ReShareCaptureView.swift`,+added by T-2190) is likewise untested at the string level. Introducing that+test infrastructure is out of scope for a one-line accessibility-string fix.++Verification instead relied on:+- Reading the sibling label call sites to confirm the fixed string matches+  their established convention.+- `make test-quick`, which builds the full `Asterism Development` scheme+  (including the share extension target) on the simulator and runs the+  unit-test bundle, confirming the change compiles and introduces no+  regressions.+- `make test-core`, confirming the `AsterismCore`/`AsterismIntelligence`+  package tests are unaffected.++**Run command:** `make test-quick` (simulator, safe); `make test-core`++## Affected Files++| File | Change |+|------|--------|+| `Asterism/AsterismShareExtension/CaptureView.swift` | `.accessibilityLabel("Page title")` → `.accessibilityLabel("Page title: \(rawTitle)")` on the raw-title row |++## Verification++**Automated:**+- [ ] Regression test passes — none added, see rationale above+- [x] Full test suite passes (`make test-quick`, `make test-core`)+- [x] Linters/validators pass — no linter/formatter configured in this repo (per `CLAUDE.md`); a clean `make test-core` with no new compiler warnings is the pre-commit bar, and it passed++**Manual verification:**+- Confirmed the fixed string matches the `"Label: value"` convention used by+  every other informative accessibility label in `CaptureView.swift` and by+  `reshare.title` in `ReShareCaptureView.swift`.++## Prevention++**Recommendations to avoid similar bugs:**+- When adding an `.accessibilityLabel` to a row that echoes dynamic content,+  interpolate the value into the label rather than writing a static caption+  — a static caption silently discards the content VoiceOver would otherwise+  read.+- Consider adding ViewInspector (or similar) coverage for the share+  extension's SwiftUI views if these accessibility regressions recur; none+  exists today for either `CaptureView` or `ReShareCaptureView`.++## Related++- T-2193 (this ticket)+- T-2190 (added the `reshare.title` label this fix now matches, and whose+  review surfaced this pre-existing bug)

Things to double-check

Build of the share-extension target.

make test-core does not compile the extension. make test-quick (simulator) was run as part of this review to confirm compilation.