import { StyleRootProvider } from '@uhg-abyss/web/ui/ThemeProvider';The StyleRootProvider is an advanced component that gives you fine-grained control over how styles are injected into your application. It provides options for standard CSS injection or shadow DOM encapsulation, making it ideal for applications that need style isolation or custom styling strategies.
Common use cases
Abyss Parcels with shadow DOM
The most common use case for StyleRootProvider is with Abyss Parcels that use the built-in shadow DOM feature for complete style isolation. See Using with Abyss Parcels for more details.
import { StyleRootProvider } from '@uhg-abyss/web/ui/ThemeProvider';import { ThemeProvider } from '@uhg-abyss/web/ui/ThemeProvider';import { createTheme } from '@uhg-abyss/web/tools/theme';
const theme = createTheme('uhc');
export const MyParcel = () => ( <StyleRootProvider useShadowDom theme={theme} cacheOptions={{ key: 'my-parcel' }} > <ThemeProvider theme={theme}> <ParcelContent /> </ThemeProvider> </StyleRootProvider>);Custom cache configuration
StyleRootProvider allows applications to customize the Emotion cache, which is particularly useful for setting a unique key or controlling style insertion. See Cache options for more details.
import { StyleRootProvider } from '@uhg-abyss/web/ui/ThemeProvider';
const App = () => ( <StyleRootProvider cacheOptions={{ key: 'my-app' }}> {/* App content */} </StyleRootProvider>);Other use cases
- Micro-frontends that need to avoid style conflicts with host applications
- Applications with custom styling requirements
- Web components requiring style encapsulation
Cache options
The cacheOptions prop accepts the following properties from @emotion/cache:
interface CacheOptions { // Unique identifier for the cache / defaults to 'abyss' key?: string;
// Container to insert styles into (useful for shadow DOM) container?: HTMLElement;
// DOM node to insert styles before insertionPoint?: HTMLElement;
// Array of stylis plugins for custom CSS processing stylisPlugins?: any[];
// Nonce security attribute for CSP nonce?: string;
// Vendor-specific CSS property prefixing prefix?: boolean;
// Speedy mode for faster insertions (default: true in production) speedy?: boolean;}Key cache options
-
key: A unique identifier for the cache. This is important when using multiple instances of StyleRootProvider to prevent style collisions. Defaults to
'abyss'if not specified. -
speedy: Controls Emotion's performance optimization mode:
- When
true: Faster style insertion using CSSOM APIs but less readable CSS (default in production) - When
false: More readable CSS with better debugging but slower performance (default in development)
- When
-
container: Specifies where styles should be inserted. Particularly useful for shadow DOM scenarios where styles need to be contained within the shadow root.
-
insertionPoint: Allows you to control where in the DOM styles are inserted, which can be important for style precedence. This is the recommended way to control style insertion order.
-
stylisPlugins: Enables custom CSS processing with Stylis plugins.
For more details on these options, refer to the Emotion Cache Documentation.
Using with Abyss Parcels
One of the primary use cases for StyleRootProvider is with Abyss parcels that need complete style isolation. When used with parcels configured with shadowDOM: true, StyleRootProvider automatically detects and uses the parcel's shadow DOM to create a style boundary.
The useShadowDom prop enables shadow DOM features, preventing styles from leaking between your parcel and the host application.
Note: The theme prop is required for proper font loading in shadow DOM mode.
Integration with the Parcel system
StyleRootProvider automatically integrates with the Abyss Parcel system:
-
Automatic Detection: When used within an Abyss Parcel, it detects the Parcel environment through the global
__ABYSS_PARCEL_BUILD__variable. -
Shadow Root Integration: For Parcels with shadow DOM enabled (
shadowDOM: truein Parcel config), it automatically uses the existing shadow root created by the Parcel system. -
Style Scoping: All styles are properly scoped to the Parcel's shadow DOM, creating a complete style boundary.
-
Font Loading: The theme's fonts are automatically injected into the shadow DOM when the
themeprop is provided.
Example: Parcel with shadow DOM
import { StyleRootProvider } from '@uhg-abyss/web/ui/ThemeProvider';import { ThemeProvider } from '@uhg-abyss/web/ui/ThemeProvider';import { createTheme } from '@uhg-abyss/web/tools/theme';
const theme = createTheme('uhc');
export const MyParcel = () => ( <StyleRootProvider useShadowDom // Enable shadow DOM features theme={theme} // Required for font loading in shadow DOM cacheOptions={{ key: 'my-parcel', // Unique key for this parcel speedy: process.env.NODE_ENV === 'production', // Better debugging in dev }} > <ThemeProvider theme={theme}> {/* Your parcel content here */} </ThemeProvider> </StyleRootProvider>);Best practices for Parcels
- Always use a unique
keyincacheOptionsto prevent potential style collisions - Always provide the
themeprop when using shadow DOM for proper font loading - Consider disabling
speedymode during development for better debugging - Use the same theme instance for both StyleRootProvider and ThemeProvider
Advanced shadow DOM options
The StyleRootProvider offers several advanced options for fine-tuning shadow DOM behavior.
Using an existing shadow root
If you already have a shadow root (for example, from a Web Component), you can pass it directly to the StyleRootProvider:
const MyComponent = () => { const hostRef = useRef(null); const [shadowRoot, setShadowRoot] = useState(null);
useEffect(() => { if (hostRef.current) { const root = hostRef.current.attachShadow({ mode: 'open' }); setShadowRoot(root); } }, []);
return ( <div ref={hostRef}> {shadowRoot && ( <StyleRootProvider shadowRoot={shadowRoot} theme={theme} cacheOptions={{ key: 'custom-shadow' }} > <ThemeProvider theme={theme}> <Content /> </ThemeProvider> </StyleRootProvider> )} </div> );};Shadow root mode
You can control the mode of the shadow root with the shadowRootMode prop:
<StyleRootProvider useShadowDom shadowRootMode="closed" // 'open' (default) or 'closed' theme={theme}> {/* content */}</StyleRootProvider>Constructable stylesheets
For better performance in browsers that support it, you can enable Constructable Stylesheets:
<StyleRootProvider useShadowDom useConstructableStylesheets theme={theme}> {/* content */}</StyleRootProvider>Related components
- ThemeProvider - Basic theme provider for most applications
- NextStyleProvider - Optimized provider for Next.js applications
StyleRootProvider Props
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
cacheOptions | CreateThemeCacheOptions | undefined | - | - | Cache options for Emotion |
children | React.ReactNode | - | Content to be wrapped with the style provider | |
onShadowRootCreated | (shadowRoot: ShadowRoot) => void | - | - | Optional callback when shadow root is created |
shadowRoot | ShadowRoot | null | - | - | Existing shadow root to use |
shadowRootMode | "open" | "closed" | 'open' | - | Shadow root mode |
theme | CreateThemeReturn | - | - | Required to load fonts in shadow DOM mode |
useConstructableStylesheets | boolean | false | - | Whether to use constructable stylesheets |
useShadowDom | boolean | false | - | Whether to use shadow DOM for style isolation Whether to use shadow DOM encapsulation |