import type { ReactNode } from "react"; import { useDensity } from "../../core/DensityContext"; import { useCurrentColorMode, useCurrentScopedTheme, } from "../../core/ThemeContext"; import { DensityScope } from "./DensityScope"; import type { PortalAccentScopeProps } from "./PortalAccentScope"; import { ScopedTheme } from "./ScopedTheme"; import { resolveStableTheme } from "./StableAccentScope"; /** * Web themes resolve through CSS custom-property inheritance from the theme * className, and a portal renders outside the themed DOM subtree — so the scope * has to be rebuilt there from the base mode. Two nested scopes, because the * accent blocks are partial: the outer one re-declares the full `light`/`dark` * token set the portal escaped, the inner one layers the accent (or the theme * inherited from the caller, in `mode`, when `accent` is unset) on top of it. Both stay * mounted, so toggling `accent` never remounts the subtree. The density is a * class inherited the same way, so it is rebuilt there too. */ export function PortalAccentScope({ mode, accent, children, }: PortalAccentScopeProps): ReactNode { const currentTheme = useCurrentScopedTheme(); const currentColorMode = useCurrentColorMode(); const density = useDensity(); const modeToUse = mode ?? currentColorMode; const theme = resolveStableTheme({ currentTheme, mode: modeToUse, accent }); return ( {children} ); }