Skip to content

YPE-1434: Add a demo/example app of the React SDK that is more aligned with the Swift & Kotlin demo apps#189

Open
cameronapak wants to merge 19 commits intomainfrom
cp/ype-1434-react-sdk-demo-app-update-demo-app-to-be
Open

YPE-1434: Add a demo/example app of the React SDK that is more aligned with the Swift & Kotlin demo apps#189
cameronapak wants to merge 19 commits intomainfrom
cp/ype-1434-react-sdk-demo-app-update-demo-app-to-be

Conversation

@cameronapak
Copy link
Collaborator

@cameronapak cameronapak commented Mar 5, 2026

https://lifechurch.atlassian.net/browse/YPE-1434

Warning

There's lots of lines of code changed. However, there's actually a lot less because the main code diff monster is the pnpm lock file.

If you want the best way to get an understanding of this PR, please watch this video:

Click Watch Video Overview

Screenshot

cameronapak and others added 5 commits March 5, 2026 11:21
- Delete examples/nextjs (kitchen-sink style app)
- Add examples/vite-react with Vite, Tailwind v4, and shadcn/ui
- 3 pages: Bible Reader (JHN.1), Verse of the Day, Bible Card (JHN.3.16)
- Responsive navbar with mobile hamburger menu (shadcn Sheet)
- Dark mode toggle with system/light/dark support
- Auth integrated into navbar (sign in/sign out + user info)
- All components use Bible version 3034

BREAKING CHANGE: examples/nextjs has been removed

Amp-Thread-ID: https://ampcode.com/threads/T-019cbee2-c92a-74a8-9150-5378fa196155
Co-authored-by: Amp <amp@ampcode.com>
Refactor the global CSS to correctly implement Tailwind v4's CSS layer
strategy. This ensures SDK styles are properly cascaded and do not
override consumer styles. Custom `@layer yv-sdk-*` directives are
introduced, and standard Tailwind layers are imported before SDK layers
to maintain the correct order of precedence. The `:where()` pseudo-class
is used to scope Tailwind's reset CSS to `[data-yv-sdk]`, preventing it
from affecting the host application.
Refactor the theme provider to correctly handle the 'system' theme. This
includes listening for system theme changes and applying the correct
class to the document element. Additionally, the `YouVersionProvider`
now receives the theme directly from the `useTheme` hook.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The `YouVersionProvider` import was moved after the `ThemeProvider` and
`App` imports to ensure correct CSS loading order.
@changeset-bot
Copy link

changeset-bot bot commented Mar 5, 2026

🦋 Changeset detected

Latest commit: 6d86548

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 Minor
@youversion/platform-react-hooks Minor
@youversion/platform-react-ui Minor
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 self-assigned this Mar 5, 2026
@cameronapak cameronapak marked this pull request as ready for review March 5, 2026 21:03
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 5, 2026

Greptile Summary

This PR replaces the old Next.js example app with a new Vite + React demo that more closely mirrors the Swift and Kotlin SDK demo apps. It bundles a CSS cascade isolation fix for packages/ui (wrapping all SDK styles in yv-sdk-* @layer blocks), a minor changeset for all three SDK packages, and a new .superset/config.json for automated environment setup.

Key changes:

  • The examples/nextjs/ directory has been removed and replaced by a clean examples/vite-react/ app built with Tailwind v4, Shadcn UI (new-york style), Radix UI, and the YouVersion Platform React SDK
  • ThemedApp.tsx correctly bridges the consumer ThemeProvider (light/dark/system) with YouVersionProvider, using VITE_YVP_AUTH_REDIRECT_URL ?? window.location.origin as the auth redirect — previous hardcoded localhost issue has been resolved
  • packages/ui/src/styles/global.css now wraps all SDK Tailwind imports and CSS rules inside named @layer directives (yv-sdk-theme, yv-sdk-base, yv-sdk-utilities, yv-sdk-bible-reader), with the standard Tailwind layer names pre-declared to enforce cascade priority so SDK styles cannot bleed into consumer apps
  • The changeset has been updated from patch to minor to correctly reflect the observable cascade behavior change
  • All previously flagged issues (hardcoded auth URL, trailing newline, changeset bump level, yv-sdk-animate dead layer, @utility/@layer non-standard nesting) have been addressed

Confidence Score: 5/5

  • Safe to merge — all previously identified issues have been addressed and no new issues were found.
  • The PR is a well-scoped demo app replacement with a complementary CSS cascade fix. All prior review feedback has been incorporated: the auth redirect URL is now environment-driven, the changeset bump is correctly set to minor, trailing newlines are present, and dead CSS layer names have been removed. The new Vite+React example is clean, idiomatic, and correctly structured with good separation of concerns between consumer theming and SDK theming.
  • No files require special attention. The .superset/config.json references a SUPERSET_ROOT_PATH environment variable that is not documented in the repo, but this is a low-severity concern for a CI/tooling config file.

Important Files Changed

Filename Overview
packages/ui/src/styles/global.css CSS layer isolation refactor: all SDK styles now live inside yv-sdk-* named @layer blocks. The top-level @layer declaration establishes cascade order (consumer Tailwind layers < SDK layers < consumer unlayered CSS). tw-animate-css remains intentionally unlayered. Theme variables and reset rules are properly scoped to [data-yv-sdk].
examples/vite-react/src/ThemedApp.tsx Bridges the consumer ThemeProvider and the SDK YouVersionProvider. Auth redirect URL is now sourced from VITE_YVP_AUTH_REDIRECT_URL env var with a sensible window.location.origin fallback, addressing the previous hardcoded localhost issue.
examples/vite-react/src/components/navbar.tsx Responsive navbar with desktop nav links, mobile Sheet drawer, ModeToggle, and SDK auth integration via useYVAuth/YouVersionAuthButton. Well-structured with good accessibility (sr-only labels).
examples/vite-react/src/components/theme-provider.tsx Custom ThemeProvider that applies light/dark/system themes via classList on the document root, with OS preference change listener cleanup and localStorage persistence. Correctly handles the 'system' mode with matchMedia.
examples/vite-react/src/index.css Consumer-side Tailwind v4 setup with shadcn theme tokens, dark mode custom variant, and base layer styles. Previously identified trailing newline issue has been addressed.
.changeset/fix-css-layer-isolation.md Changeset now correctly marks all three packages as minor, reflecting the observable cascade behavior change for consumers. Previously flagged patch bump has been addressed.
.superset/config.json New superset config with a setup script that builds packages and copies .env.local files from SUPERSET_ROOT_PATH. The SUPERSET_ROOT_PATH environment variable is undocumented in the repo.

Sequence Diagram

sequenceDiagram
    participant Browser
    participant main.tsx
    participant ThemeProvider
    participant ThemedApp
    participant YouVersionProvider
    participant App
    participant Navbar
    participant Pages

    Browser->>main.tsx: Load app
    main.tsx->>ThemeProvider: Wrap (reads localStorage theme)
    ThemeProvider->>ThemedApp: Provide theme context
    ThemedApp->>ThemedApp: useTheme() → 'light' | 'dark' | 'system'
    ThemedApp->>ThemedApp: Read env vars (VITE_YVP_APP_KEY, VITE_YVP_API_HOST, VITE_YVP_AUTH_REDIRECT_URL)
    ThemedApp->>YouVersionProvider: theme, appKey, apiHost, authRedirectUrl, includeAuth
    YouVersionProvider->>YouVersionProvider: Resolve 'system' → 'light'|'dark' via matchMedia
    YouVersionProvider->>YouVersionProvider: Set data-yv-theme on root element
    YouVersionProvider->>App: Render children
    App->>Navbar: currentPage, onNavigate
    Navbar->>Navbar: useYVAuth() → auth, userInfo, signOut
    Navbar-->>Browser: Show auth state (SignIn button or username + Sign out)
    App->>Pages: Render BibleReaderPage / VotdPage / BibleCardPage
Loading

Last reviewed commit: 810ebe6

cameronapak and others added 7 commits March 6, 2026 09:21
…heme guard works

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ensure that the initial theme read from localStorage is a valid theme
before setting it. This prevents unexpected behavior if localStorage
contains an invalid theme value.
Include the `VITE_YVP_AUTH_REDIRECT_URL` environment variable in the
Vite example to allow for proper authentication redirection. This also
updates the default value to use `window.location.origin`.
@cameronapak
Copy link
Collaborator Author

Muh dawg, the great, the deterministic function known as an LLM, or better known as @greptile, please re-review this. I've made all the changes you've specified.

cameronapak and others added 3 commits March 6, 2026 09:42
Integrates the YouVersionProvider into the example application to
demonstrate its usage with theme and environment variables. This change
moves the provider logic to a new `ThemedApp.tsx` component and updates
`main.tsx` to use it.
The `useTheme` hook now returns an object with a `theme` property, which
needs to be destructured for correct usage.
Extract useTheme hook and ThemeProviderContext to separate files,
stop exporting unused buttonVariants from button.tsx.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@cameronapak
Copy link
Collaborator Author

Hey @greptile, the reptile, do you want 15% or more off your car insurance?? JK. Please re-re-review this and then if not 5/5, please tell me why

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 6, 2026

3.5/5

You've addressed the previous review comments well, but there's a critical issue that will cause runtime errors:

🚨 Critical Issue

examples/vite-react/src/components/ui/sheet.tsx:3 - Broken Radix UI import

The import pattern is fundamentally incorrect:

import { Dialog as SheetPrimitive } from 'radix-ui';

Then using it as:

<SheetPrimitive.Root ...>
<SheetPrimitive.Trigger ...>

This won't work. The problems:

  1. Wrong package: "radix-ui": "^1.4.3" in package.json is not an official Radix package. Official Radix packages are scoped as @radix-ui/*

  2. Wrong import syntax: You're destructuring Dialog but then trying to use it as a namespace with .Root, .Trigger, etc. This will throw Cannot read property 'Root' of undefined

Fix:

import * as SheetPrimitive from '@radix-ui/react-dialog';

And update package.json:

"@radix-ui/react-dialog": "^1.1.2"

Remove the "radix-ui": "^1.4.3" dependency.


✅ What's Good

  • CSS layer isolation properly implemented
  • Auth redirect URL now uses env var with smart fallback (window.location.origin)
  • Clean architectural separation with ThemedApp wrapper
  • All previous issues resolved

Why Not 5/5?

This is a demo app meant to showcase the SDK. A broken Sheet component that throws runtime errors undermines that purpose. Fix the Radix import and you're golden! 🦎

@cameronapak
Copy link
Collaborator Author

@greptile, here's a response for your response:

Thanks for the review! However, the Radix UI import concern is actually a false positive
   — the code is correct as-is.

  radix-ui is the official unified package. Radix UI now publishes a single radix-ui
  package that includes all primitives. From the https://github.com/radix-ui/website/blob/
  main/data/primitives/docs/overview/introduction.mdx:

  Install the main radix-ui package, which includes all primitives. This is the
  recommended way to start to prevent version conflicts and manage updates easily. The
  package is tree-shakeable.

  npm install radix-ui

  The import syntax is documented and correct. The
  https://github.com/radix-ui/website/blob/main/data/primitives/docs/components/dialog.mdx
   show this exact pattern:

  import { Dialog } from "radix-ui";

  export default () => (
    <Dialog.Root>
      <Dialog.Trigger />
      <Dialog.Portal>
        <Dialog.Overlay />
        <Dialog.Content>
          <Dialog.Title />
          <Dialog.Description />
          <Dialog.Close />
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  );

  The Radix docs also show the aliased destructure pattern (which is what our sheet.tsx
  uses):

  import { Dialog as DialogPrimitive } from "radix-ui";

  The older @radix-ui/react-dialog scoped packages still work but the unified radix-ui
  package is now the recommended approach. No changes needed here.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 6, 2026

You're absolutely right—thanks for the clarification and the documentation links! I wasn't aware that Radix UI now recommends the unified radix-ui package over the scoped packages. The import pattern you're using is correct per their official docs.

No changes needed here. Appreciate you taking the time to explain!

@cameronapak
Copy link
Collaborator Author

You're absolutely right—thanks for the clarification and the documentation links! I wasn't aware that Radix UI now recommends the unified radix-ui package over the scoped packages. The import pattern you're using is correct per their official docs.

No changes needed here. Appreciate you taking the time to explain!

@greptile, can you update your confidence score then??

@cameronapak cameronapak changed the title YPE-1434: React SDK demo/example app YPE-1434: Add a demo/example app of the React SDK that is more aligned with the Swift & Kotlin demo apps Mar 6, 2026
  The nested @layer yv-sdk-utilities inside @Utility created an
  unintended
  CSS sub-layer (yv-sdk-utilities.yv-sdk-utilities), giving touch-hitbox
  different cascade priority than other utilities. Unnecessary since
  Tailwind's layer() import config already handles layer placement.
@cameronapak
Copy link
Collaborator Author

@greptile, please re-re-re-review this PR

Replaced double quotes with single quotes for CSS imports. Updated CSS
variables to use single quotes for consistency.
@cameronapak
Copy link
Collaborator Author

@greptile, please update your original review. You last said, "Safe to merge; only a minor missing newline issue in index.css.", but I've since fixed that

@youversion youversion deleted a comment from chatgpt-codex-connector bot Mar 6, 2026
@cameronapak
Copy link
Collaborator Author

@greptile, I've made all the changes you've asked. Please update your review

The `.superset` directory and its configuration were not being used and
have been removed from the project.
@dsilva609
Copy link
Collaborator

Small thing I noticed in dark mode. Shouldn't the sign in/out button also respect the theme selected?

image

@cameronapak
Copy link
Collaborator Author

Small thing I noticed in dark mode. Shouldn't the sign in/out button also respect the theme selected?

image

Yes, that's something that is part of a pre-existing component. I can make a Jira ticket for that!

Copy link
Collaborator

@dsilva609 dsilva609 left a comment

Choose a reason for hiding this comment

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

This looks awesome! Nice work 🎉

Copy link
Collaborator

@bmanquen bmanquen left a comment

Choose a reason for hiding this comment

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

Just one comment/question on versioning.

Comment on lines +2 to +4
"@youversion/platform-core": minor
"@youversion/platform-react-hooks": minor
"@youversion/platform-react-ui": minor
Copy link
Collaborator

Choose a reason for hiding this comment

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

This feels more like a patch because to me it feels more like a bug fix than a new feature.

Feel free to push back if I am wrong on this.

{auth.isAuthenticated ? (
<div className="flex items-center gap-2">
<span className="text-sm text-muted-foreground hidden sm:block">
{userInfo?.name || 'User'}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is probably where you are getting "User" in the nav. It must be defaulting to "User" here.

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