Skip to content

fix(react-ui): re-export full ThemeProvider barrel from main entry#488

Merged
ankit-thesys merged 2 commits intothesysdev:mainfrom
ankit-thesys:fix/react-ui-theme-provider-export-context
May 4, 2026
Merged

fix(react-ui): re-export full ThemeProvider barrel from main entry#488
ankit-thesys merged 2 commits intothesysdev:mainfrom
ankit-thesys:fix/react-ui-theme-provider-export-context

Conversation

@ankit-thesys
Copy link
Copy Markdown
Contributor

Summary

packages/react-ui/src/index.ts was hand-listing only a subset of ./components/ThemeProvider's exports — useTheme and ThemeContext were left off. Combined with the "./*" exports map (which compiles each component to a standalone subpath chunk while the main entry inlines its own copy), this produced two separate createContext() calls at runtime:

  • <ThemeProvider> imported from @openuidev/react-ui writes to the main bundle's ThemeContext.
  • useTheme imported from @openuidev/react-ui/ThemeProvider reads from the subpath chunk's ThemeContext.

Two contexts, never the same instance. useTheme() always returned the default value when <ThemeProvider> was mounted from the main entry — the only place useTheme was reachable from.

Downstream impact

Caused a real regression in @thesys/artifact: PresentationThemeProvider reads ambient mode via useTheme() so it can scope a second <ThemeProvider cssSelector=".thesys-slide"> for slide-scale typography. Because of the dual-context bug, slides rendered in light mode regardless of the outer <ThemeProvider mode="dark">. Workaround was passing an explicit mode prop into every PresentationThemeProvider instance.

Fix

Replace the hand-listed re-export block with export * from "./components/ThemeProvider" — the pattern used by every other component in this barrel. Picks up useTheme + ThemeContext (which were missing) alongside ThemeProps and ThemeMode (which were previously re-exported via separate lines that are now redundant and removed).

Once consumers migrate from @openuidev/react-ui/ThemeProvider to @openuidev/react-ui for these symbols, both paths share the same compiled chunk = same ThemeContext instance.

-export {
-  ThemeProvider,
-  createTheme,
-  defaultDarkTheme,
-  defaultLightTheme,
-  swatchTokens,
-  type Theme,
-} from "./components/ThemeProvider";
-export type { ThemeProps } from "./components/ThemeProvider/ThemeProvider";
-export type { ThemeMode } from "./components/ThemeProvider/types";
+export * from "./components/ThemeProvider";

Test plan

  • pnpm --filter @openuidev/react-ui typecheck (passes locally — no ambiguous-export errors)
  • pnpm --filter @openuidev/react-ui build (passes locally; built tarball verified to expose useTheme and ThemeContext on the main dist/index.d.mts)
  • Verified end-to-end against @thesys/artifact consumer: with the rebuilt react-ui overridden into the consumer and all useTheme imports flipped to the main entry, slides correctly inherit the outer <ThemeProvider mode> setting.

Notes

  • No public API removals. useTheme, ThemeContext, ThemeProps, ThemeMode, Theme, ThemeProvider, createTheme, default themes, and swatchTokens remain exported from the main entry. The wildcard also surfaces previously-only-via-subpath helpers (black, white, withAlpha, swatch, swatchToken, granular theme interfaces) — these were already public via the subpath; this just promotes them to the main entry.
  • Subpath import (@openuidev/react-ui/ThemeProvider) still works for any existing consumer that depends on it. Consumers mixing subpath useTheme with main-entry <ThemeProvider> will need to migrate to the main entry to get the dedup benefit.

The hand-listed re-export of `./components/ThemeProvider` only surfaced
`ThemeProvider`, `createTheme`, the default themes, `swatchTokens`, and a
couple of types — `useTheme` and `ThemeContext` were left off. Combined
with the `./*` exports map (which compiles each component into a
standalone subpath chunk while the main entry inlines its own copy),
consumers ended up with two separate `createContext()` calls at runtime:

  - `<ThemeProvider>` from `@openuidev/react-ui` writes to the main
    bundle's ThemeContext.
  - `useTheme` from `@openuidev/react-ui/ThemeProvider` reads the
    subpath chunk's ThemeContext.

Two contexts, never the same instance — `useTheme()` always returned
the default value when `<ThemeProvider>` was mounted from the main
entry. Caused a real downstream regression in `@thesys/artifact` where
`PresentationThemeProvider` reads the ambient mode via `useTheme()`;
slides always rendered in light mode regardless of the outer
`<ThemeProvider mode="dark">`.

Switching to `export * from "./components/ThemeProvider"` matches the
pattern used by every other component on this file, picks up
`useTheme` + `ThemeContext` (alongside `ThemeProps` and `ThemeMode`
which were previously listed separately below), and is forward-
compatible with future ThemeProvider additions.
@ankit-thesys ankit-thesys requested a review from i-subham23 May 4, 2026 08:55
Copy link
Copy Markdown
Contributor

@i-subham23 i-subham23 left a comment

Choose a reason for hiding this comment

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

L.G.

@ankit-thesys ankit-thesys merged commit 6abd535 into thesysdev:main May 4, 2026
1 check passed
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