Skip to content

feat(ui): isolate Bible pickers in Shadow DOM - #426

Merged
abharms merged 19 commits into
journey-to-the-shadow-domfrom
ype-5949-isolate-bible-pickers
Sep 28, 2026
Merged

abharms merged 19 commits into
journey-to-the-shadow-domfrom
ype-5949-isolate-bible-pickers

Conversation

@abharms

@abharms abharms commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • automatically isolate BibleChapterPicker.Root and BibleVersionPicker.Root in one Shadow DOM boundary each
  • keep compound members, context, controlled state, callbacks, storage, search, and custom triggers working inside the owning root
  • keep trigger and floating content in the same tree through the existing native top-layer portal seam
  • update picker, Bible Reader, and Bible Card stories to query the new public runtime boundary
  • document the custom-trigger styling contract and keep the change behind the coordinated major-release gate

This is a stacked PR based on #424 (ype-5947-shadow-dom-foundation). It must not be merged or released independently of the coordinated Shadow DOM rollout.

Requirement evidence

Jira acceptance area Evidence
Automatic picker boundaries Both public Roots delegate through the private ShadowIsolationBoundary; direct SSR/hydration tests assert one reused host and no nested member hosts.
Behavior preservation Existing focused unit suites retain state/callback/storage coverage through ReuseShadowBoundary; real-root stories exercise chapter/version/language search, selection, recent versions, and Reader/Card composition.
Trigger and floating content stay together Chapter and Version browser stories assert that trigger, dialog, and aria-controls targets remain inside the same shadow root.
Native top-layer behavior Focused journeys cover clipping escape, collision bounds, outside/Escape dismissal, focus restoration, scrolling, rapid reopen, multiple roots, shared roots, and iframe ownership.
Custom-trigger contract Both pickers prove that the supplied button remains interactive, retains attributes and inline styling, receives embedded SDK utility styles, and rejects hostile document CSS.
SSR and hydration Both Roots server-render the exact empty host, reuse it during hydration, render their content inside it, invoke their native press callback through the hydrated boundary, and report no recoverable hydration error.
Cross-browser journeys Focused picker journeys pass Chromium, Firefox, and Playwright WebKit. Shared portal geometry is proved once rather than duplicated for each picker.
Coordinated rollout only The PR carries an empty changeset and updates the existing rollout/compatibility documents without adding a stable partial-release path.

Review scope

Required outcomes:

  • one automatic boundary per Chapter/Version Root, with no independent member hosts
  • preserved picker state, callback, storage, search, custom-trigger, focus, dismissal, and accessibility behavior
  • private reuse of the existing Shadow DOM/top-layer infrastructure; no public isolation configuration
  • direct SSR/hydration evidence for both Roots and focused Chromium/Firefox/WebKit journeys
  • no independent stable rollout

Permitted support work:

  • shadow-aware updates to existing picker, Reader, and Card stories/tests
  • narrowly required onInput handling for search inside the real shadow boundary
  • inert on the inactive Version/Language panel so hidden controls cannot receive focus
  • updates to the two existing Shadow DOM policy/compatibility documents
  • an empty changeset

Non-goals:

  • automatically isolating Bible Reader or Bible Card themselves
  • a public portal/isolation configuration API
  • picker redesign or a new styling/customization system
  • CSS Parts, arbitrary stylesheet injection, or new styling tokens
  • package-wide release documentation, actual-Safari automation, or assistive-technology claims

Please treat a finding as blocking only when it identifies an unmet in-scope requirement, a documented repository-standard violation in added or modified code, or a concrete regression or defect caused or worsened by this diff. Label other valid improvements as non-blocking follow-ups.

Verification

  • pnpm lint — passed
  • pnpm typecheck — passed
  • pnpm test — passed: all six workspace tasks; UI 574/574
  • full Storybook Chromium project — 82/82 passed
  • focused Chapter and Version picker journeys — 23/23 passed in Chromium, Firefox, and Playwright WebKit before the final evidence-only refinement
  • strengthened Chapter custom-trigger journey — passed in Chromium, Firefox, and Playwright WebKit on final HEAD
  • git diff --check — passed
  • clean-context simplification audit — one duplicate shared proof removed; runtime design judged appropriately minimal
  • independent Standards, Spec, and Compatibility review of implementation snapshot 71a96b4 / fingerprint f9e9bd97…da5f — no hard standard violation, no implementation defect, and no confirmed unintended regression
  • current documentation head fe798d9 / fingerprint 69dc9614…a96dd — subsequent commits stabilize test evidence and align the durable rollout records; they do not expand runtime scope

First-paint and compatibility notes

  • Both pickers intentionally server-render an empty host and appear after hydration. The representative review accepted that existing client-only contract; no picker-specific reservation or CLS framework is introduced.
  • Both pickers retain document-root rem scaling as the accepted sizing input. This PR does not add a picker-specific root-font reset.
  • Document queries, global/CSS-module selectors, external form ownership, and cross-tree label/ARIA ID relationships no longer cross into picker internals.
  • Consumer-supplied trigger elements, ordinary attributes, inline styles, and embedded SDK utility classes remain supported; document-level styling does not cross the boundary.
  • VoiceOver/NVDA and actual-Safari picker validation are not claimed here. Reader-level mixed-overlay validation remains assigned to the Reader rollout ticket.

Jira

YPE-5949 — Isolate Bible chapter and version pickers

RetriggerConfidence Score: 5/5

The PR appears safe to merge into the integration branch, subject to the documented coordinated-release gate.

Summary

The PR gives each Bible picker Root an automatic Shadow DOM boundary, adapts picker and composed Reader/Card coverage to that boundary, and updates rollout documentation.

  • Compound members and overlays remain in their owning root.
  • The rollout remains gated on the coordinated major release.
  • Greptile automatically discovered a related ticket that helped explain the purpose of this PR: isolate the two picker Roots while preserving their compound behavior and avoiding a partial release.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  C[Consumer] --> CR[BibleChapterPicker.Root]
  C --> VR[BibleVersionPicker.Root]
  CR --> CH[Chapter shadow root]
  VR --> VH[Version shadow root]
  CH --> CM[Trigger, content, local overlay]
  VH --> VM[Trigger, content, language members, local overlay]
Loading

Reviews (12) · Last reviewed commit: "docs(ui): refresh Shadow DOM evidence gu..."

@changeset-bot

changeset-bot Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ad5620b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-27T02:09:22.890297Z ad5620b New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Base automatically changed from ype-5947-shadow-dom-foundation to journey-to-the-shadow-dom September 26, 2026 14:54

@cameronapak cameronapak left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

YPE-5949

Summary

Standards: 0 must-fix. Spec: 0 must-fix. Primary concern: none.

Review evidence
  • Scope: revision ad5620b, PR requirements, rollout policies, picker implementations, Shadow DOM infrastructure, callers, and tests/stories.
  • Method: independently traced Standards, Spec, Correctness, compatibility, and reuse across the base-to-HEAD diff.
Behavior or check Method / command Result Evidence source
Root isolation and boundary reuse Source trace through both picker roots, ShadowIsolationBoundary, and hydration coverage One automatic boundary per root; compound members and owned overlays stay in the intended tree Reviewer
State, search, callbacks, storage, custom triggers, focus, and dismissal Traced focused and composed Storybook journeys against the new public roots Required behavior remains covered; no concrete regression found Reviewer and CI
Browser and repository checks GitHub checks at the pinned HEAD Build, test, integration, lint, typecheck, bundle, Firefox Shadow DOM, and WebKit Shadow DOM checks passed CI
Diff integrity git diff --check 4fbd7dbe...ad5620b Passed Reviewer
  • Limits: Jira details were unavailable through the configured integration, so the detailed PR requirements and repository policy documents supplied the spec. Actual Safari and assistive-technology behavior remain explicitly unclaimed.
  • CI and bot review: all required reported checks passed; the earlier fixture concern is resolved on the current HEAD.
  • Event: APPROVE.

Written by Code Reviewer bot on behalf of Cam.

await waitFor(async () => {
await expect(trigger).toHaveTextContent(/genesis 11/i);
await expect(topLayer.querySelector('[data-slot="popover-content"]')).toBeNull();
await expect(root.activeElement).toBe(trigger);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

praise: This focused journey covers the risky boundary end to end instead of only asserting that a shadow root exists.

For Agents: public picker behavior

The story preserves a consumer trigger, proves hostile document CSS cannot cross the boundary, keeps the trigger and overlay in one tree, exercises search and controlled selection, and verifies dismissal plus focus restoration. That gives strong regression evidence for the public behavior this PR changes.

Written by Code Reviewer bot on behalf of Cam.

@abharms
abharms merged commit a75cf71 into journey-to-the-shadow-dom Sep 28, 2026
22 checks passed
@abharms
abharms deleted the ype-5949-isolate-bible-pickers branch September 28, 2026 14:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants