diff --git a/.changeset/styled-react-themeprovider.md b/.changeset/styled-react-themeprovider.md
new file mode 100644
index 00000000000..dc5aa5e0a94
--- /dev/null
+++ b/.changeset/styled-react-themeprovider.md
@@ -0,0 +1,7 @@
+---
+"@primer/react": patch
+"@primer/styled-react": minor
+---
+
+@primer/react: Export `useId` and `useSyncedState`
+@primer/styled-react: Add `ThemeProvider` and `BaseStyles`
diff --git a/e2e/components/IconButton.test.ts b/e2e/components/IconButton.test.ts
index 99a4fde5546..955d22588f4 100644
--- a/e2e/components/IconButton.test.ts
+++ b/e2e/components/IconButton.test.ts
@@ -45,9 +45,9 @@ const stories = [
disableAnimations: true,
async setup(page: Page) {
await page.keyboard.press('Tab') // focus on icon button
- await page.getByText('Bold').waitFor({
- state: 'visible',
- })
+ await page.getByText('Bold').waitFor({state: 'visible'})
+ // eslint-disable-next-line playwright/no-wait-for-timeout
+ await page.waitForTimeout(1000) // wait until after "tooltip delay" for a stable screenshot
},
},
{
diff --git a/examples/nextjs/package.json b/examples/nextjs/package.json
index 2247c3c611f..e38c6799d5b 100644
--- a/examples/nextjs/package.json
+++ b/examples/nextjs/package.json
@@ -11,6 +11,7 @@
},
"dependencies": {
"@primer/react": "38.0.0-rc.6",
+ "@primer/styled-react": "1.0.0-rc.7",
"next": "^15.2.3",
"react": "18.3.1",
"react-dom": "18.3.1",
diff --git a/examples/nextjs/src/app/layout.tsx b/examples/nextjs/src/app/layout.tsx
index ec8ff0f19a7..8e845a6afba 100644
--- a/examples/nextjs/src/app/layout.tsx
+++ b/examples/nextjs/src/app/layout.tsx
@@ -1,5 +1,5 @@
import './global.css'
-import {BaseStyles, ThemeProvider} from '@primer/react'
+import {ThemeProvider, BaseStyles} from '@primer/styled-react'
import {StyledComponentsRegistry} from './registry'
export const metadata = {
diff --git a/examples/nextjs/src/app/page.tsx b/examples/nextjs/src/app/page.tsx
index 7b9ad9f2e0d..4910ebc2e78 100644
--- a/examples/nextjs/src/app/page.tsx
+++ b/examples/nextjs/src/app/page.tsx
@@ -1,5 +1,39 @@
-import {Button} from '@primer/react'
+'use client'
+
+import {Button, Stack, Box} from '@primer/react'
+import {useTheme} from '@primer/styled-react'
+import styled from 'styled-components'
+
+const StyledDiv = styled.div(({theme}) => {
+ return {
+ padding: theme.space[5],
+ backgroundColor: theme.colors.btn.primary.bg,
+ }
+})
+
+const ThemeUser = () => {
+ const {theme} = useTheme()
+ return (
+
+ Hello world
+
+ )
+}
export default function IndexPage() {
- return
+ return (
+
+
+ Hello world
+ Hello world
+
+
+ )
}
diff --git a/package-lock.json b/package-lock.json
index 7af8c9703ea..8f0bd5d7c2d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -89,6 +89,7 @@
"version": "0.0.0",
"dependencies": {
"@primer/react": "38.0.0-rc.6",
+ "@primer/styled-react": "1.0.0-rc.7",
"next": "^15.2.3",
"react": "18.3.1",
"react-dom": "18.3.1",
diff --git a/packages/react/src/FeatureFlags/DefaultFeatureFlags.ts b/packages/react/src/FeatureFlags/DefaultFeatureFlags.ts
index f60c9687834..7a1112d7e37 100644
--- a/packages/react/src/FeatureFlags/DefaultFeatureFlags.ts
+++ b/packages/react/src/FeatureFlags/DefaultFeatureFlags.ts
@@ -8,4 +8,5 @@ export const DefaultFeatureFlags = FeatureFlagScope.create({
primer_react_select_panel_fullscreen_on_narrow: false,
primer_react_select_panel_order_selected_at_top: false,
primer_react_select_panel_remove_active_descendant: false,
+ primer_react_use_styled_react_theming: false,
})
diff --git a/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap b/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap
index 6a9e1c692f9..4057c681ce2 100644
--- a/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap
+++ b/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap
@@ -214,6 +214,7 @@ exports[`@primer/react > should not update exports without a semver change 1`] =
"useFocusTrap",
"useFocusZone",
"useFormControlForwardedProps",
+ "useId",
"useIsomorphicLayoutEffect",
"useOnEscapePress",
"useOnOutsideClick",
@@ -224,6 +225,7 @@ exports[`@primer/react > should not update exports without a semver change 1`] =
"useResizeObserver",
"useResponsiveValue",
"useSafeTimeout",
+ "useSyncedState",
"useTheme",
"VisuallyHidden",
"type VisuallyHiddenProps",
diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts
index f37dbea38d8..f4fc3fa7669 100644
--- a/packages/react/src/index.ts
+++ b/packages/react/src/index.ts
@@ -46,6 +46,8 @@ export {useResizeObserver} from './hooks/useResizeObserver'
export {useResponsiveValue, type ResponsiveValue} from './hooks/useResponsiveValue'
export {default as useIsomorphicLayoutEffect} from './utils/useIsomorphicLayoutEffect'
export {useProvidedRefOrCreate} from './hooks/useProvidedRefOrCreate'
+export {useId} from './hooks/useId'
+export {useSyncedState} from './hooks/useSyncedState'
// Utils
export {createComponent} from './utils/create-component'
diff --git a/packages/styled-react/rollup.config.js b/packages/styled-react/rollup.config.js
index 8aae93d5045..60091798713 100644
--- a/packages/styled-react/rollup.config.js
+++ b/packages/styled-react/rollup.config.js
@@ -2,6 +2,7 @@ import babel from '@rollup/plugin-babel'
import {defineConfig} from 'rollup'
import typescript from 'rollup-plugin-typescript2'
import packageJson from './package.json' with {type: 'json'}
+import MagicString from 'magic-string'
const dependencies = [
...Object.keys(packageJson.peerDependencies ?? {}),
@@ -26,9 +27,111 @@ export default defineConfig({
extensions: ['.ts', '.tsx'],
babelHelpers: 'bundled',
}),
+ /**
+ * This custom rollup plugin allows us to preserve directives in source
+ * code, such as "use client", in order to support React Server Components.
+ *
+ * The source for this plugin is inspired by:
+ * https://github.com/Ephem/rollup-plugin-preserve-directives
+ */
+ {
+ name: 'preserve-directives',
+ transform(code) {
+ const ast = this.parse(code)
+ if (ast.type !== 'Program' || !ast.body) {
+ return {
+ code,
+ ast,
+ map: null,
+ }
+ }
+
+ let hasClientDirective = false
+
+ for (const node of ast.body) {
+ if (!node) {
+ continue
+ }
+
+ if (node.type !== 'ExpressionStatement') {
+ continue
+ }
+
+ if (node.directive === 'use client') {
+ hasClientDirective = true
+ break
+ }
+ }
+
+ if (hasClientDirective) {
+ return {
+ code,
+ ast,
+ map: null,
+ meta: {
+ hasClientDirective: true,
+ },
+ }
+ }
+
+ return {
+ code,
+ ast,
+ map: null,
+ }
+ },
+ renderChunk: {
+ order: 'post',
+ handler(code, chunk, options) {
+ // If `preserveModules` is not set to true, we can't be sure if the client
+ // directive corresponds to the whole chunk or just a part of it.
+ if (!options.preserveModules) {
+ return undefined
+ }
+
+ let chunkHasClientDirective = false
+
+ for (const moduleId of Object.keys(chunk.modules)) {
+ const hasClientDirective = this.getModuleInfo(moduleId)?.meta?.hasClientDirective
+ if (hasClientDirective) {
+ chunkHasClientDirective = true
+ break
+ }
+ }
+
+ if (chunkHasClientDirective) {
+ const transformed = new MagicString(code)
+ transformed.prepend(`"use client";\n`)
+ const sourcemap = transformed.generateMap({
+ includeContent: true,
+ })
+ return {
+ code: transformed.toString(),
+ map: sourcemap,
+ }
+ }
+
+ return null
+ },
+ },
+ },
],
+ onwarn(warning, defaultHandler) {
+ // Dependencies or modules may use "use client" as an indicator for React
+ // Server Components that this module should only be loaded on the client.
+ if (warning.code === 'MODULE_LEVEL_DIRECTIVE' && warning.message.includes('use client')) {
+ return
+ }
+
+ if (warning.code === 'CIRCULAR_DEPENDENCY') {
+ throw warning
+ }
+
+ defaultHandler(warning)
+ },
output: {
dir: 'dist',
format: 'esm',
+ preserveModules: true,
},
})
diff --git a/packages/styled-react/src/components/BaseStyles.tsx b/packages/styled-react/src/components/BaseStyles.tsx
new file mode 100644
index 00000000000..e58f33100e8
--- /dev/null
+++ b/packages/styled-react/src/components/BaseStyles.tsx
@@ -0,0 +1,152 @@
+import type React from 'react'
+import {type CSSProperties, type PropsWithChildren} from 'react'
+import {clsx} from 'clsx'
+// eslint-disable-next-line import/no-namespace
+import type * as styledSystem from 'styled-system'
+import {useTheme} from './ThemeProvider'
+
+import 'focus-visible'
+import {createGlobalStyle} from 'styled-components'
+
+export interface SystemCommonProps
+ extends styledSystem.ColorProps,
+ styledSystem.SpaceProps,
+ styledSystem.DisplayProps {}
+
+export interface SystemTypographyProps extends styledSystem.TypographyProps {
+ whiteSpace?: 'normal' | 'nowrap' | 'pre' | 'pre-wrap' | 'pre-line'
+}
+
+const GlobalStyle = createGlobalStyle<{colorScheme?: 'light' | 'dark'}>`
+ * {
+ box-sizing: border-box;
+ }
+
+ body {
+ margin: 0;
+ }
+
+ table {
+ /* stylelint-disable-next-line primer/borders */
+ border-collapse: collapse;
+ }
+
+ [data-color-mode='light'] input {
+ color-scheme: light;
+ }
+
+ [data-color-mode='dark'] input {
+ color-scheme: dark;
+ }
+
+ @media (prefers-color-scheme: light) {
+ [data-color-mode='auto'][data-light-theme*='light'] {
+ color-scheme: light;
+ }
+ }
+
+ @media (prefers-color-scheme: dark) {
+ [data-color-mode='auto'][data-dark-theme*='dark'] {
+ color-scheme: dark;
+ }
+ }
+
+ [role='button']:focus:not(:focus-visible):not(:global(.focus-visible)),
+ [role='tabpanel'][tabindex='0']:focus:not(:focus-visible):not(:global(.focus-visible)),
+ button:focus:not(:focus-visible):not(:global(.focus-visible)),
+ summary:focus:not(:focus-visible):not(:global(.focus-visible)),
+ a:focus:not(:focus-visible):not(:global(.focus-visible)) {
+ outline: none;
+ box-shadow: none;
+ }
+
+ [tabindex='0']:focus:not(:focus-visible):not(:global(.focus-visible)),
+ details-dialog:focus:not(:focus-visible):not(:global(.focus-visible)) {
+ outline: none;
+ }
+
+ /* -------------------------------------------------------------------------- */
+
+ .BaseStyles {
+ font-family: var(--BaseStyles-fontFamily, var(--fontStack-system));
+ /* stylelint-disable-next-line primer/typography */
+ line-height: var(--BaseStyles-lineHeight, 1.5);
+ /* stylelint-disable-next-line primer/colors */
+ color: var(--BaseStyles-fgColor, var(--fgColor-default));
+
+ /* Global styles for light mode */
+ &:has([data-color-mode='light']) {
+ input & {
+ color-scheme: light;
+ }
+ }
+
+ /* Global styles for dark mode */
+ &:has([data-color-mode='dark']) {
+ input & {
+ color-scheme: dark;
+ }
+ }
+
+ /* Low-specificity default link styling */
+ :where(a:not([class*='prc-']):not([class*='PRC-']):not([class*='Primer_Brand__'])) {
+ color: var(--fgColor-accent, var(--color-accent-fg));
+ text-decoration: none;
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+ }
+`
+
+export type BaseStylesProps = PropsWithChildren & {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ as?: React.ComponentType | keyof JSX.IntrinsicElements
+ className?: string
+ style?: CSSProperties
+ color?: string // Fixes `color` ts-error
+} & SystemTypographyProps &
+ SystemCommonProps
+
+export function BaseStyles({
+ children,
+ color,
+ fontFamily,
+ lineHeight,
+ className,
+ as: Component = 'div',
+ style,
+ ...rest
+}: BaseStylesProps) {
+ const {colorMode, colorScheme, dayScheme, nightScheme} = useTheme()
+
+ const baseStyles = {
+ ['--BaseStyles-fgColor']: color,
+ ['--BaseStyles-fontFamily']: fontFamily,
+ ['--BaseStyles-lineHeight']: lineHeight,
+ }
+
+ return (
+
+
+ {children}
+
+ )
+}
diff --git a/packages/styled-react/src/components/FeatureFlaggedTheming.tsx b/packages/styled-react/src/components/FeatureFlaggedTheming.tsx
new file mode 100644
index 00000000000..16751b47d03
--- /dev/null
+++ b/packages/styled-react/src/components/FeatureFlaggedTheming.tsx
@@ -0,0 +1,49 @@
+import {
+ ThemeProvider as PrimerReactThemeProvider,
+ type ThemeProviderProps,
+ BaseStyles as PrimerReactBaseStyles,
+ type BaseStylesProps,
+ useTheme as primerReactUseTheme,
+ useColorSchemeVar as primerReactUseColorSchemeVar,
+} from '@primer/react'
+import {
+ ThemeProvider as StyledReactThemeProvider,
+ useTheme as styledReactUseTheme,
+ useColorSchemeVar as styledReactUseColorSchemeVar,
+} from './ThemeProvider'
+import {BaseStyles as StyledReactBaseStyles} from './BaseStyles'
+import {useFeatureFlag} from '@primer/react/experimental'
+
+export const ThemeProvider: React.FC> = ({children, ...props}) => {
+ const enabled = useFeatureFlag('primer_react_use_styled_react_theming')
+ if (enabled) {
+ return {children}
+ } else {
+ return {children}
+ }
+}
+
+export const BaseStyles: React.FC> = ({children, ...props}) => {
+ const enabled = useFeatureFlag('primer_react_use_styled_react_theming')
+ if (enabled) {
+ return {children}
+ } else {
+ return {children}
+ }
+}
+
+export const useTheme: typeof primerReactUseTheme = () => {
+ const enabled = useFeatureFlag('primer_react_use_styled_react_theming')
+ const styledReactResults = styledReactUseTheme()
+ const primerReactResults = primerReactUseTheme()
+
+ return enabled ? styledReactResults : primerReactResults
+}
+
+export const useColorSchemeVar: typeof primerReactUseColorSchemeVar = (values, fallback) => {
+ const enabled = useFeatureFlag('primer_react_use_styled_react_theming')
+ const styledReactResults = styledReactUseColorSchemeVar(values, fallback)
+ const primerReactResults = primerReactUseColorSchemeVar(values, fallback)
+
+ return enabled ? styledReactResults : primerReactResults
+}
diff --git a/packages/styled-react/src/components/ThemeProvider.tsx b/packages/styled-react/src/components/ThemeProvider.tsx
new file mode 100644
index 00000000000..adea1055ebf
--- /dev/null
+++ b/packages/styled-react/src/components/ThemeProvider.tsx
@@ -0,0 +1,243 @@
+import React from 'react'
+import ReactDOM from 'react-dom'
+import {ThemeProvider as SCThemeProvider} from 'styled-components'
+import {theme as defaultTheme, useId, useSyncedState} from '@primer/react'
+import deepmerge from 'deepmerge'
+
+export const defaultColorMode = 'day'
+const defaultDayScheme = 'light'
+const defaultNightScheme = 'dark'
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export type Theme = {[key: string]: any}
+type ColorMode = 'day' | 'night' | 'light' | 'dark'
+export type ColorModeWithAuto = ColorMode | 'auto'
+
+export type ThemeProviderProps = {
+ theme?: Theme
+ colorMode?: ColorModeWithAuto
+ dayScheme?: string
+ nightScheme?: string
+ preventSSRMismatch?: boolean
+}
+
+const ThemeContext = React.createContext<{
+ theme?: Theme
+ colorScheme?: string
+ colorMode?: ColorModeWithAuto
+ resolvedColorMode?: ColorMode
+ resolvedColorScheme?: string
+ dayScheme?: string
+ nightScheme?: string
+ setColorMode: React.Dispatch>
+ setDayScheme: React.Dispatch>
+ setNightScheme: React.Dispatch>
+}>({
+ setColorMode: () => null,
+ setDayScheme: () => null,
+ setNightScheme: () => null,
+})
+
+// inspired from __NEXT_DATA__, we use application/json to avoid CSRF policy with inline scripts
+const getServerHandoff = (id: string) => {
+ try {
+ const serverData = document.getElementById(`__PRIMER_DATA_${id}__`)?.textContent
+ if (serverData) return JSON.parse(serverData)
+ } catch (_error) {
+ // if document/element does not exist or JSON is invalid, supress error
+ }
+ return {}
+}
+
+export const ThemeProvider: React.FC> = ({children, ...props}) => {
+ // Get fallback values from parent ThemeProvider (if exists)
+ const {
+ theme: fallbackTheme,
+ colorMode: fallbackColorMode,
+ dayScheme: fallbackDayScheme,
+ nightScheme: fallbackNightScheme,
+ } = useTheme()
+
+ // Initialize state
+ const theme = props.theme ?? fallbackTheme ?? defaultTheme
+
+ const uniqueDataId = useId()
+ const {resolvedServerColorMode} = getServerHandoff(uniqueDataId)
+ const resolvedColorModePassthrough = React.useRef(resolvedServerColorMode)
+
+ const [colorMode, setColorMode] = useSyncedState(props.colorMode ?? fallbackColorMode ?? defaultColorMode)
+ const [dayScheme, setDayScheme] = useSyncedState(props.dayScheme ?? fallbackDayScheme ?? defaultDayScheme)
+ const [nightScheme, setNightScheme] = useSyncedState(props.nightScheme ?? fallbackNightScheme ?? defaultNightScheme)
+ const systemColorMode = useSystemColorMode()
+ const resolvedColorMode = resolvedColorModePassthrough.current || resolveColorMode(colorMode, systemColorMode)
+ const colorScheme = chooseColorScheme(resolvedColorMode, dayScheme, nightScheme)
+ const {resolvedTheme, resolvedColorScheme} = React.useMemo(
+ () => applyColorScheme(theme, colorScheme),
+ [theme, colorScheme],
+ )
+
+ // this effect will only run on client
+ React.useEffect(
+ function updateColorModeAfterServerPassthrough() {
+ const resolvedColorModeOnClient = resolveColorMode(colorMode, systemColorMode)
+
+ if (resolvedColorModePassthrough.current) {
+ // if the resolved color mode passed on from the server is not the resolved color mode on client, change it!
+ if (resolvedColorModePassthrough.current !== resolvedColorModeOnClient) {
+ window.setTimeout(() => {
+ // use ReactDOM.flushSync to prevent automatic batching of state updates since React 18
+ // ref: https://github.com/reactwg/react-18/discussions/21
+ ReactDOM.flushSync(() => {
+ // override colorMode to whatever is resolved on the client to get a re-render
+ setColorMode(resolvedColorModeOnClient)
+ })
+
+ // immediately after that, set the colorMode to what the user passed to respond to system color mode changes
+ setColorMode(colorMode)
+ })
+ }
+
+ resolvedColorModePassthrough.current = null
+ }
+ },
+ [colorMode, systemColorMode, setColorMode],
+ )
+
+ return (
+
+
+ {children}
+ {props.preventSSRMismatch ? (
+
+ ) : null}
+
+
+ )
+}
+
+export function useTheme() {
+ return React.useContext(ThemeContext)
+}
+
+export function useColorSchemeVar(values: Partial>, fallback: string) {
+ const {colorScheme = ''} = useTheme()
+ return values[colorScheme] ?? fallback
+}
+
+function useSystemColorMode() {
+ const [systemColorMode, setSystemColorMode] = React.useState(getSystemColorMode)
+
+ React.useEffect(() => {
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ const media = window?.matchMedia?.('(prefers-color-scheme: dark)')
+
+ function matchesMediaToColorMode(matches: boolean) {
+ return matches ? 'night' : 'day'
+ }
+
+ function handleChange(event: MediaQueryListEvent) {
+ const isNight = event.matches
+ setSystemColorMode(matchesMediaToColorMode(isNight))
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ if (media) {
+ // just in case the preference changed before the event listener was attached
+ const isNight = media.matches
+ setSystemColorMode(matchesMediaToColorMode(isNight))
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ if (media.addEventListener !== undefined) {
+ media.addEventListener('change', handleChange)
+ return function cleanup() {
+ media.removeEventListener('change', handleChange)
+ }
+ }
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ else if (media.addListener !== undefined) {
+ media.addListener(handleChange)
+ return function cleanup() {
+ media.removeListener(handleChange)
+ }
+ }
+ }
+ }, [])
+
+ return systemColorMode
+}
+
+function getSystemColorMode(): ColorMode {
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ if (typeof window !== 'undefined' && window.matchMedia?.('(prefers-color-scheme: dark)')?.matches) {
+ return 'night'
+ }
+
+ return 'day'
+}
+
+function resolveColorMode(colorMode: ColorModeWithAuto, systemColorMode: ColorMode) {
+ switch (colorMode) {
+ case 'auto':
+ return systemColorMode
+ default:
+ return colorMode
+ }
+}
+
+function chooseColorScheme(colorMode: ColorMode, dayScheme: string, nightScheme: string) {
+ switch (colorMode) {
+ case 'day':
+ case 'light':
+ return dayScheme
+ case 'dark':
+ case 'night':
+ return nightScheme
+ }
+}
+
+function applyColorScheme(
+ theme: Theme,
+ colorScheme: string,
+): {resolvedTheme: Theme; resolvedColorScheme: string | undefined} {
+ if (!theme.colorSchemes) {
+ return {
+ resolvedTheme: theme,
+ resolvedColorScheme: undefined,
+ }
+ }
+
+ if (!theme.colorSchemes[colorScheme]) {
+ // eslint-disable-next-line no-console
+ console.error(`\`${colorScheme}\` scheme not defined in \`theme.colorSchemes\``)
+
+ // Apply the first defined color scheme
+ const defaultColorScheme = Object.keys(theme.colorSchemes)[0]
+ return {
+ resolvedTheme: deepmerge(theme, theme.colorSchemes[defaultColorScheme]),
+ resolvedColorScheme: defaultColorScheme,
+ }
+ }
+
+ return {
+ resolvedTheme: deepmerge(theme, theme.colorSchemes[colorScheme]),
+ resolvedColorScheme: colorScheme,
+ }
+}
+
+export default ThemeProvider
diff --git a/packages/styled-react/src/index.tsx b/packages/styled-react/src/index.tsx
index 8c1d2e9cad4..14c29eb1ca9 100644
--- a/packages/styled-react/src/index.tsx
+++ b/packages/styled-react/src/index.tsx
@@ -1,3 +1,5 @@
+'use client'
+
export {Box, type BoxProps} from './components/Box'
export {Button} from '@primer/react'
export {Details} from '@primer/react'
@@ -10,13 +12,10 @@ export {TextInput} from '@primer/react'
export {type TextInputProps} from '@primer/react'
// theming depends on styled-components
-export {ThemeProvider} from '@primer/react'
+export {ThemeProvider, useTheme, useColorSchemeVar, BaseStyles} from './components/FeatureFlaggedTheming'
export {merge} from '@primer/react'
export {theme} from '@primer/react'
export {themeGet} from '@primer/react'
-export {useColorSchemeVar} from '@primer/react'
-export {useTheme} from '@primer/react'
-export {BaseStyles} from '@primer/react'
export {
ActionList,