DocumentClassProvider
Collects every useDocumentClass() request in its tree and applies the merged classes and attributes to the real body and html elements.
import { DocumentClassProvider, DocumentClassProviderProps } from '@salla.sa/twilight-theme-engine/providers';In plain words
Several components can want classes on <body> at the same time. DocumentClassProvider keeps the list, merges it, writes the result to the page, and removes what it added when a component goes away.
TwilightProvider already wraps your theme in one. Mount it yourself only in a tree without TwilightProvider, such as a component test.
Signature
function DocumentClassProvider(props: DocumentClassProviderProps): JSX.Element
interface DocumentClassProviderProps {
children: ReactNode;
}Example
import { render } from '@testing-library/react';
import { DocumentClassProvider } from '@salla.sa/twilight-theme-engine/providers';
import { ProductPage } from '../app/components/ProductPage';
it('marks the body while the page is mounted', () => {
const { unmount } = render(
<DocumentClassProvider>
<ProductPage />
</DocumentClassProvider>
);
expect(document.body.classList.contains('page-product')).toBe(true);
unmount();
expect(document.body.classList.contains('page-product')).toBe(false);
});
How it behaves
Its DOM sync is a separate child component that writes in an effect, so server HTML is never touched. It records what it added in a
data-de-managedattribute and removes exactly that on the next change, leaving classes set by other code alone.Without any provider,
useDocumentClass()writes to the DOM itself.
Gotchas
Do not nest a second one inside
TwilightProvider. Both sync to the same<body>and share itsdata-de-managedrecord, so each removes the other's classes, theme classes such ascolor-mode-lightandrtlincluded. Registrations below the inner one are also invisible touseDocumentClassOutput()above it.Without a provider, components calling
useDocumentClass()overwrite each other: each write replaces the shared managed record, and each unmount clears it, taking the other components' attributes along (src/hooks/useDocumentClass.ts).