Skip to content

feat(ui): Guarantee consuming-app global CSS can't distort Bible components - Shadow DOM - #348

Draft
cameronapak wants to merge 12 commits into
mainfrom
journey-to-the-shadow-dom
Draft

feat(ui): Guarantee consuming-app global CSS can't distort Bible components - Shadow DOM#348
cameronapak wants to merge 12 commits into
mainfrom
journey-to-the-shadow-dom

Conversation

@cameronapak

@cameronapak cameronapak commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

This PR is in progress and will continue to be defined. This PR was created as a feature branch for https://lifechurch.atlassian.net/browse/YPE-4113.

Greptile Summary

The PR prototypes automatic Shadow DOM style isolation for YouVersionAuthButton and documents the resulting compatibility boundaries.

  • Adds a reusable shadow-root host with constructable-stylesheet and fallback style delivery.
  • Wraps the authentication button while preserving its public React props and forwarded ref.
  • Adds hostile-CSS demonstrations, browser stories, lifecycle tests, an ADR, and a coordinated major changeset.

Confidence Score: 5/5

The PR appears safe to merge because no blocking failure remains within the eligible follow-up-review scope.

No blocking failure remains.

Important Files Changed

Filename Overview
packages/ui/src/lib/shadow-root-host.tsx Adds the shadow-root lifecycle, per-document constructed stylesheet cache, fallback style resource, host reset, and React portal.
packages/ui/src/lib/shadow-isolation.tsx Adds a typed higher-order wrapper that preserves component props and forwarded refs while introducing the isolation host.
packages/ui/src/components/YouVersionAuthButton.tsx Moves the existing authentication-button implementation behind automatic Shadow DOM isolation and pins its intended font utility.
packages/ui/src/styles/global.css Adds shadow-host pseudo-element suppression to the generated SDK stylesheet.
packages/ui/src/components/YouVersionAuthButton.shadow-isolation.stories.tsx Adds browser coverage for hostile global selectors, host pseudo-elements, and same-origin iframe stylesheet adoption.
packages/ui/src/lib/shadow-root-host.test.tsx Adds focused unit coverage for Strict Mode attachment, host resets, and fallback stylesheet identity.
docs/adr/0005-prototype-shadow-dom-style-isolation.md Documents the prototype architecture, compatibility impact, verified behavior, and deliberately deferred concerns.
.changeset/prototype-shadow-dom-isolation.md Records the prototype as a coordinated major release across the fixed-version SDK packages.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Consumer[Consumer application] --> Host[Light-DOM shadow host]
  Host --> Root[Open shadow root]
  Styles[Embedded SDK stylesheet] --> Root
  Root --> Portal[React portal]
  Portal --> Button[YouVersionAuthButton implementation]
  HostCSS[Consumer global CSS] -. selector boundary .-> Host
Loading

Reviews (3): Last reviewed commit: "Merge branch 'main' into journey-to-the-..." | Re-trigger Greptile

Context used (3)

* feat(ui)!: prototype automatic Shadow DOM isolation

* docs(examples): add hostile CSS POC demo

* docs(examples): clarify hostile CSS vectors

* docs(ui): align shadow DOM prototype ADR

* test(ui): strengthen shadow isolation proof

* refactor(ui): remove shadow isolation type assertions

* fix(ui): block hostile shadow host pseudo-elements

* docs(ui): clarify shadow isolation trade-offs

* test(ui): align shadow isolation demo conventions

* docs(examples): keep hostile demo labels readable

* fix(ui): use style precedence for shadow fallback stylesheet

Addresses PR review feedback: the non-adoptedStyleSheets fallback
rendered a bare <style> tag inside the shadow-root portal. Use
React 19's <style href precedence> resource form instead so React
hoists and de-duplicates the stylesheet within the shadow root
rather than risking duplicate insertion.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: abharms <aharms@works24.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
@cameronapak cameronapak self-assigned this Aug 19, 2026
@changeset-bot

changeset-bot Bot commented Aug 19, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 0222ae9

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

This PR includes changesets to release 4 packages
Name Type
@youversion/platform-core Major
@youversion/platform-react-hooks Major
@youversion/platform-react-ui Major
vite-react Patch

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

@cameronapak cameronapak reopened this Aug 25, 2026
@cameronapak
cameronapak marked this pull request as draft August 25, 2026 14:20
abharms and others added 10 commits August 25, 2026 12:45
* feat(ui): prototype shadow-local top-layer popovers

* fix(ui): reconcile shadow portal strategy changes

* fix(ui): narrow shadow portal spike scope

* fix(ui): harden shadow portal lifecycle

---------

Co-authored-by: abharms <aharms@works24.com>
* feat(ui): validate shadow DOM dialog top layer

* docs(ui): separate shadow DOM rollout plan

* refactor(ui): simplify shadow dialog coordination

* test(ui): prove shadow dialog escapes clipping

* refactor(ui): tighten shadow dialog portal behavior

---------

Co-authored-by: abharms <aharms@works24.com>
* fix(ui): harden Shadow DOM CSS isolation

* test(ui): cover InputGroup SDK radius token

* test(ui): align input group radius assertion

---------

Co-authored-by: abharms <aharms@works24.com>
* fix(ui): route verse actions through shadow portals

* style(ui): use logical overflow in shadow story

* fix(ui): address verse action popover review feedback

---------

Co-authored-by: abharms <aharms@works24.com>
* test(ui): validate shadow consumer compatibility (YPE-5436)

* test(ui): strengthen shadow compatibility evidence (YPE-5436)

* test(ui): await shadow content rendering (YPE-5436)

* docs(ui): qualify shadow automation guidance (YPE-5436)

* docs(ui): clarify shadow compatibility stories (YPE-5436)

* docs(ui): tighten shadow rollout research handoff (YPE-5436)

* test(ui): remove instructional copy assertions

* test(ui): address YPE-5436 review feedback

---------

Co-authored-by: abharms <aharms@works24.com>
)

* test(ui): prove nested overlays through the production shadow seam

Exercise YPE-5355 nested and concurrent overlay scenarios against the real ShadowRootHost + Radix path, without adding an ownership registry.

* fix(ui): restore shadow dialog focus after a rapid reopen

The production seam handled nested and concurrent overlays without a new ownership registry. Rapid reopen during exit captured the outgoing overlay as the restore target; skip portal-container nodes and fall back to the last wrapper control.

* test(ui): add static Storybook frames for the production overlay seam

Leave the ticket scenarios on screen so the production VerseActionPopover, permission dialog, nested popover, and independent overlays can be inspected without racing the play function.

* test(ui): finalize YPE-5355 overlay evidence

* docs: keep overlay proof evidence-only

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: abharms <aharms@works24.com>
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.

3 participants