Files

P4-03 — Builder preview keyboard boundary

Implementation and local checkpoint validation complete on 2026-09-12, from ebd4a3e24541dabd7ff3b732c07fa972ab843f96 on codex/ui-redesign-phase4. Approved scope: P4-03, coordinated with archived audit A02/F14. No concurrent D01 work was present in the clean starting tree. No save/revision refactor, renderer replacement, route/layout redesign, P4-04 or B07. F04 remains open. The commit containing this record is the implementation checkpoint (git log -- docs/redesign/phase-4/p4-03).

Reconciliation before implementation

The actual CvBuilderEditor owns preview fitting, measurement, pagination, mobile panes, settings history and saves. Its overflowing page container has neither a name nor an explicit keyboard tab stop. Visible titled page iframes and the hidden measurement iframe are separate from that container. Keep their document rendering/links and the existing P4-01 focus CSS; do not add focusability to every Box or replace the preview engine.

Phase 3's future independent editor panes, manual zoom and broader content architecture are not added by this ticket. Existing compact presentation changes at 900px, while the MUI grid changes at 1024px; preserve and test both boundaries rather than silently unifying them. Prior records retain the CV overflow warning, not a requirement to repair document pagination/print layout in this keyboard slice. Phase 2's F15 shorthand for preview focus is superseded by Phase 1/3's corrected F14/A02 attribution.

Change-impact mapping before application changes

PRES contracts Retained behaviour → P4-03 change Existing automated protection New automated / visual evidence required
PRES-C06, PRES-E08 Server-rendered pages, fit and mobile Edit/Preview → named keyboard-scrollable preview cv-builder-deep-link; redesign-preservation; semantic-foundations Real one/multipage keyboard entry, scroll, exit; EN/NB, themes, phone/tablet/desktop transitions; visible shared focus
PRES-C07, PRES-C10, PRES-C11 CV-only overrides, local undo/redo, autosave/draft and AI-review lifetime → unchanged through preview focus/resize cv-builder-deep-link; ai-section-assistant; canonical/sibling browser isolation Edit/Preview/resize/undo/redo retains current CV settings; native API persistence and canonical/sibling isolation; inherited AI apply/reject tests
PRES-C08, PRES-C09, PRES-C12 Template settings, document metrics/pagination, shared preview/PDF → rendering retained cvBuilder; CvBuilder backend; long searchable PDF and public PDF browser; B03 admission Native loaded pages and preview retry; full existing render/PDF suite; no template/printed-paper change
PRES-E09 Account-owned preview/settings and private-tree lifetime → unchanged session-boundary; account-isolation; backend ownership/session tests Full inherited security/browser checks; no new preview network path

These scoped rows extend the 57-group preservation matrix and Phase 3 impact matrix. They do not replace any contract or claim exhaustive visual coverage. Tests were added before the corresponding application changes; executed results follow below.

Reproduction and implementation

The initial native Chromium regression against P4-02 loaded a real one-page CV and failed because there was no Live preview region. After adding that boundary, a second regression narrowed a focused desktop preview to 390px and reproduced its disappearance: the stored mobile preference still selected Edit. These match the archived A02 requirement for a named scroll container and focus preservation across viewport transitions. The before logs are retained locally as .artifacts/p4-03-before.log and p4-03-transition-before.log.

Only job-tracker-ui/src/views/CvBuilderEditor.tsx changes application behaviour:

  • The existing scroll Box becomes a named region, using the existing translated cvEditorLivePreview string, with one keyboard tab stop. Native Page Down and Ctrl+Home/End operate on this existing scroll container. No custom key handler, focus trap or preview component is added.
  • Focus in either existing pane records that pane in mobilePane. A focused preview stays visible when the viewport narrows; a focused editor field stays in Edit. This is a deliberate presentation-preference correction. Existing Edit/Preview buttons and component instances remain, without touching settings, undo stacks, save queues or resource identity.
  • P4-01's existing [tabindex]:focus-visible rule supplies the 3px semantic outline. No new colour, spacing, theme override or visual component system is added. Both iframe types, sandboxing, document HTML, page measurement/cropping, fit arithmetic and PDF paths remain unchanged.

Retained implementations: CvBuilderEditor, CvCustomizeTab, native iframes, MUI theme, translations, server renderer and all editor persistence handlers. Refactored/replaced implementations: none. Added capability: explicit keyboard access to the existing preview region and focus-aware reuse of the existing responsive preference; no new CV product feature.

Changed-file inventory: the editor file above; new job-tracker-ui/e2e/builder-preview-keyboard.spec.ts; this p4-03 record, scan evidence and screenshots; successor links in docs/redesign/phase-2/TRACEABILITY.md and docs/redesign/phase-4/README.md; current status/deferred work in docs/roadmap/todo.md. No existing test cases or production files outside the editor are changed.

Behavioural regression coverage

job-tracker-ui/e2e/builder-preview-keyboard.spec.ts adds four real-API workflows: light/English, dark/Bokmål, light/Bokmål and dark/English. Every workflow creates a disposable non-admin account, a canonical profile, a one-page CV and a longer CV. Browser requests cannot leave localhost. Authentication, B02 context, source/variant persistence and rendering use the real local API; one preview POST is deliberately delayed and failed with 503 to test recovery. No model/provider or production request is made.

Each workflow verifies:

  1. Real loaded one-page and multipage documents; named region reached through Tab, visible inherited focus and measured outline contrast of at least 3:1 against the adjacent application surface.
  2. Page Down changes the preview scroll position; Ctrl+End reaches the bottom and Ctrl+Home returns to the top. Shift+Tab leaves the region, Tab returns, and forward traversal through existing page iframes exits. Titled iframes are retained in the tab sequence.
  3. CV-only headline edit/autosave; keyboard Edit/Preview and preview entry at 390, 768 and 899px, then populated scans at 900, 1024 and 1440px. The same editor field/value survives these transitions.
  4. Resizing while the preview owns focus retains visible preview focus; resizing while the editor owns focus retains that visible field. Local Undo/Redo still works after the full sequence.
  5. A held preview update retains the previous document. Failure keeps the focused region and old content; Retry renders the current settings. Subsequent Redo/save succeeds. Native API reads prove the canonical profile and sibling CV are unchanged.

Existing Jest tests already protect variant loading/denial, preview retry, dirty save, Undo/Redo, AI review and related state. No redundant DOM-attribute-only Jest case was added: browser behaviour is the new missing evidence. Frontend count remains 345, while browser actual passes increase by four from 39 to 43. The existing P2-D01 expected failure remains unchanged and is not counted as a successful frozen-package workflow.

The first forward-traversal test pressed a fixed number of Tab keys and could re-enter after successfully exiting. The corrected test observes each step and stops on exit; recorded traversal includes page 1, page 2, then the outer body for the synthetic no-link document. No iframe was removed from keyboard access to make that test pass.

Visual and accessibility evidence

Screenshots cover seven states for all four theme/language combinations, with a 1440×900 desktop and 390/768/899×844 narrow viewports. The browser also exercises 900 and 1024px. This preserves the distinct 900px pane and 1024px grid boundaries. Reduced motion is active. Captures wait for a paint cycle; no screenshot-only application styling is applied.

Combination Representative screenshots
Light / English One page, last page, phone, loading, error
Dark / Bokmål One page, last page, phone, tablet, error
Light / Bokmål One page, phone, near breakpoint, error
Dark / English One page, phone, near breakpoint, error

The scope is keyboard access to the document viewport. It is not certification of rendered margins, page breaks, theme/template fidelity or all print content. Printed paper remains white in both application themes. Existing small scaled text on phone, long editor tabs, fixed-shell occlusion during page scrolling and overflow warnings remain visible in evidence; the region's focus sides remain visible. No overflow clipping workaround or page-height/layout change was introduced.

Manual Narrator/NVDA, mobile screen reader, real touch/software keyboard, 200%/400% browser zoom, 320px reflow and forced-colors testing remain unverified. DOM naming, real Chromium keyboard traversal and axe do not substitute for that evidence. Page iframe links/rendered content retain their previous behaviour; the synthetic focus-exit fixture is not an exhaustive screen-reader/link traversal of every template.

SCAN_RESULTS.json records the general-run totals and the final focused run's nodes, incomplete-rule counts and forward Tab traversals. The general run has 74 scans (38 P4-01, 20 P4-02 and 16 P4-03), with the existing command list finding in four scans, mobile workspace scrollable-region-focusable in two and light Tooltip color-contrast in two. The final focused rerun has 16 scans: 14 without violations and the two explicit light Tooltip findings. No new preview-region violation is reported. This focused rerun repeats the four added cases; it does not add another four cases to the baseline count. All 28 committed screenshots were refreshed during that final run and representative rendered states were inspected in both modes/languages and at desktop/phone/tablet widths.

Existing defects intentionally deferred

  • P4-03-D01 — shared Tooltip contrast: a full loaded scan exposed the existing light Redo tooltip at 3.89:1 (white on composite #81808a). Its MUI/default colour path and theme.ts are unchanged from P4-02. Full findings are retained; the test narrowly recognizes only a color-contrast finding targeting .MuiTooltip-tooltip in the final post-Redo scan. Every preview rule and other contrast target remains blocking. Repair in a separately scoped shared-theme follow-up; this is not an all-accessibility pass.
  • Existing CV rendering accuracy debt: Connor reiterated that margins and theme/template output remain incorrect. The minimal one-page fixture also retains the existing horizontal-overflow warning. The future CV rendering work needs concrete expected margin/page/template output and preview/PDF comparison across preserved settings (PRES-C06/C08/C09/C12). This ticket does not fix or claim correctness for that renderer. The earlier statement that the preview will be overhauled is a direction for a dedicated later scope, not authorization to fold it into P4-03 or P4-04.
  • Existing preview state announcements: updating/unavailable chips and retry remain the current implementation. Their visual recovery and retained focus are tested; a comprehensive preview announcement design/manual AT audit is not added here.
  • P4-02-D01–D04, P2-D01, stale-record concurrency and F04 remain open. The audit's D01 and redesign P2-D01 are different issues; neither is addressed by pane focus.

Validation and handoff

The inherited baseline is 916 backend, 345 frontend, 39 browser actual passes plus P2-D01 expected failure, rate-limit 9, ingress 6, PDF admission 1 and Compose/configuration 3. The final application change precedes all complete suite/build checks below. A subsequent capture-only test adjustment scrolls the existing loading/error label into view for its screenshot; it does not change application behaviour or remove assertions.

Gate P4-02 baseline P4-03 final result
Backend Release xUnit 916 pass 916 pass, 0 failed/skipped
Frontend Jest 345 pass / 73 suites 345 pass / 73 suites; no cases removed
General Chromium 39 actual pass + P2-D01 expected failure 43 actual pass + unchanged P2-D01 expected failure; +4 cases
Focused preview Chromium No dedicated fixture 4 pass; final capture rerun, 3.2 minutes
Standalone TypeScript / affected E2E type check / lint pass pass; no TS2571 recurrence
Frontend production / API Release build pass pass; API warnings-as-errors, 0 warnings/errors
Account/IP rate-limit HTTP checks 9 pass 9 pass
Production-mode ingress HTTP checks 6 pass 6 pass
Shared PDF admission HTTP probe 1 pass 1 pass
Effective Compose / adversarial configuration 3 pass 3 pass

Reproduction commands, from repository root unless changed below:

$env:DOTNET_ROOT='C:/Users/Connor/.dotnet'
& C:/Users/Connor/.dotnet/dotnet.exe test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --configuration Release --no-restore --logger 'trx;LogFileName=p4-03.trx' --results-directory .artifacts/redesign-p4-03 -- xUnit.parallelizeTestCollections=false xUnit.maxParallelThreads=1
& C:/Users/Connor/.dotnet/dotnet.exe build JobTrackerApi/JobTrackerApi.csproj --configuration Release --no-restore -warnaserror
python scripts/test-ingress.py
Set-Location job-tracker-ui
npm test -- --watchAll=false --runInBand
npm run typecheck
node node_modules/typescript/bin/tsc --project ../.artifacts/p4-03-e2e-tsconfig.json
npm run lint
$env:NEXT_PUBLIC_API_BASE_URL='http://localhost:5302/api'
$env:NEXT_TELEMETRY_DISABLED='1'
npm run build
$env:DOTNET_HOST_PATH='C:/Users/Connor/.dotnet/dotnet.exe'
$env:PLAYWRIGHT_STATIC_EXPORT='true'
$env:PLAYWRIGHT_PREBUILT_EXPORT='true'
$env:P4_03_CAPTURE='true'
$env:PLAYWRIGHT_JSON_OUTPUT_FILE='../.artifacts/p4-03-browser-results.json'
node node_modules/@playwright/test/cli.js test --reporter=list,json
$env:PLAYWRIGHT_JSON_OUTPUT_FILE='../.artifacts/p4-03-final-focused.json'
node node_modules/@playwright/test/cli.js test e2e/builder-preview-keyboard.spec.ts --reporter=list,json
node node_modules/@playwright/test/cli.js test --config=playwright.rate-limits.config.ts
node node_modules/@playwright/test/cli.js test --config=playwright.ingress.config.ts
node node_modules/@playwright/test/cli.js test --config=playwright.pdf.config.ts
Set-Location ..
python scripts/supply-chain.py scan-secrets
git diff --check
git diff --cached --check

The ignored E2E type config extends the existing frontend tsconfig, includes only e2e/builder-preview-keyboard.spec.ts, disables incremental caching and resolves frontend Node types. No package, dependency, CI, infrastructure, backend, schema or theme change was needed. Logs, isolated SQLite data and authenticated browser traces remain ignored; committed screenshots contain only synthetic data.

The complete general run took 6.7 minutes. Its console reports “44 passed” because the unchanged expected failure is an expected outcome. JSON distinguishes 43 passed → passed plus one failed → failed, with no unexpected result. Actual passes comprise 23 pre-P4-01 + 12 P4-01 + 4 P4-02 + 4 P4-03. The full backend suite includes B01–B05 guards; the independent HTTP probes additionally exercise B02/B04 principal/session boundaries, B06 forwarded trust and B03 shared resource admission. None of this is evidence of deployed F04 closure.

Final repository review: the staged tracked-secret scan passed; git diff --check and git diff --cached --check passed; 117 current/root Markdown documents were checked with zero missing local link targets (historical archive snapshots excluded). The staged non-document diff contains only the existing editor and its new browser fixture. No test skip, expected-failure rename, package/CI modification or unrelated application change is included.

The scoped acceptance criteria are satisfied locally: the existing preview has a named keyboard boundary, native scrolling and exit work, focused panes survive resize, and the existing edit/save/Undo/Redo and ownership regressions remain healthy. The retained tooltip defect and manual/rendering/production gaps above are not claimed closed. Rollback is limited to the three editor attribute/handler changes; there is no data migration or setting-format change.

Recommended next ticket only: P4-04 — page layout and typography primitives, under its separate approved consumer scope. No P4-04 implementation, broader CV rendering work, B07 or production deployment is included in this checkpoint.