Complete "Reacting to light/dark theme changes" pattern documentation

Reference existing JSDoc examples instead of maintaining a separate one in
`docs/patterns.ts`:
- Vanilla JS: `applyDocumentTheme_fromHostContext` from `styles.examples.ts`
- React: `useDocumentTheme_conditionalRender` for reactive theme reading

Expand `applyDocumentTheme_fromHostContext` example to show both the
`onhostcontextchanged` handler and initial theme application after `connect()`.

Note in the docs that `useHostStyles()` applies theme automatically, so React
apps don't need additional setup unless they want to read the theme reactively
for conditional rendering.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jonathan Hefner 2026-01-19 11:58:47 -06:00
commit 77306d1aaf
3 changed files with 20 additions and 20 deletions

View file

@ -39,9 +39,17 @@ Hosts provide CSS variables (e.g., `--color-background-primary`) that match thei
{@includeCode ../src/react/useHostStyles.examples.tsx#useHostStyles_basicUsage}
## [TODO] Reacting to light/dark theme changes
## Reacting to light/dark theme changes
{@includeCode ./patterns.ts#lightDarkTheme}
The host provides a `theme` value (`"light"` or `"dark"`) in the context. Apply it to `<html data-theme="...">` so you can use CSS selectors like `[data-theme="dark"]` for styling.
**Vanilla JS:**
{@includeCode ../src/styles.examples.ts#applyDocumentTheme_fromHostContext}
**React:** `useHostStyles()` (shown above) applies theme automatically. To read the theme reactively for conditional rendering:
{@includeCode ../src/react/useDocumentTheme.examples.tsx#useDocumentTheme_conditionalRender}
## [TODO] Support fullscreen / exit fullscreen

View file

@ -31,22 +31,6 @@ function errorsToModel(app: App) {
//#endregion errorsToModel
}
/**
* Example: Reacting to light/dark theme changes
*/
function lightDarkTheme(app: App) {
//#region lightDarkTheme
const applyTheme = (theme: string) => {
document.documentElement.dataset.theme = theme;
};
applyTheme(app.getHostContext()?.theme ?? "light");
app.onhostcontextchanged = (params) => {
if (params.theme) applyTheme(params.theme);
};
//#endregion lightDarkTheme
}
/**
* Example: Support fullscreen / exit fullscreen
*/
@ -103,7 +87,6 @@ function migrateFromOpenai() {
// Suppress unused variable warnings
void authenticatedCalls;
void errorsToModel;
void lightDarkTheme;
void fullscreen;
void persistData;
void lowerPerceivedLatency;

View file

@ -21,7 +21,7 @@ import {
function getDocumentTheme_checkCurrent() {
//#region getDocumentTheme_checkCurrent
const theme = getDocumentTheme();
const isDark = theme === "dark";
document.body.classList.toggle("dark", theme === "dark");
//#endregion getDocumentTheme_checkCurrent
}
@ -30,11 +30,20 @@ function getDocumentTheme_checkCurrent() {
*/
function applyDocumentTheme_fromHostContext(app: App) {
//#region applyDocumentTheme_fromHostContext
// Apply when host context changes
app.onhostcontextchanged = (params) => {
if (params.theme) {
applyDocumentTheme(params.theme);
}
};
// Apply initial theme after connecting
app.connect().then(() => {
const ctx = app.getHostContext();
if (ctx?.theme) {
applyDocumentTheme(ctx.theme);
}
});
//#endregion applyDocumentTheme_fromHostContext
}