useThemeColorSync
Point the browser's own chrome — Safari's top bar and bottom toolbar, the over-scroll areas, UA-rendered controls and scrollbars — at a given background colour.
ThemeProvider already calls this for you with the active theme's background, so you don't need it for the normal case. Reach for it directly only when some other surface should drive the chrome instead: a full-bleed media viewer, a branded splash or onboarding screen, a route whose background isn't the theme's.
Usage
import { useTheme, useThemeColorSync } from '@multinaire/expo-ui';
function PhotoViewer() {
const { colors } = useTheme();
// Black bars around a full-screen photo, in either theme.
useThemeColorSync('dark', '#000000');
return <Photo source={source} />;
}
Parameters
| Parameter | Type | Description |
|---|---|---|
themeMode | 'light' | 'dark' | Which scheme the browser should render its own controls and scrollbars in — sets CSS color-scheme |
backgroundColor | string | Any CSS colour. Applied to <meta name="theme-color"> and to the html/body background |
Returns nothing.
What it sets
<meta name="theme-color">— Safari tints its top bar and bottom toolbar from this.color-schemeon:root— tells the browser which scheme to render scrollbars, form controls, and other UA chrome in.htmlandbodybackground — paints the over-scroll (rubber-band) areas above and below the document.
Existing theme-color tags are removed first, rather than mutated. Safari ignores a changed content attribute on a tag it has already read, and honours only the first tag whose media matches — so the static prefers-color-scheme pair from +html.tsx is dropped and replaced with a single media-less tag that always wins.
The work runs in a layout effect, so it lands before the browser paints and the chrome never flashes the previous colour.
Platform Notes
- Web only. On native it's a no-op with the same signature, so it's safe to call unconditionally in shared code — the native chrome is driven by
expo-status-bar,expo-navigation-bar, andexpo-system-uiinsideThemeProvider. - Calling it more than once in a tree means the last effect to run wins, and there is no restore on unmount —
ThemeProvider's own call re-asserts the theme colour on the next theme change, not on the next navigation. Set it back yourself when leaving a screen that overrode it.
Covering the first paint
This hook can only run once React has mounted. To keep the frame before that from painting the browser's default white, declare the theme statically in app/+html.tsx as well — see Dark Mode.