docs(appearance): document display preferences

This commit is contained in:
Maofeng
2026-09-29 20:58:46 +08:00
parent aae02d1502
commit 4710a56242
6 changed files with 70 additions and 24 deletions
@@ -15,11 +15,14 @@ toc:
## Controlled atoms {#controlled-atoms}
`ThemeModeField`, `CompactLayoutField`, `ThemeColorPicker`, and `ThemeToggle` are driven by values and callbacks. They do not require preference context, so they can work with forms, preview tools, or another state library.
`ThemeModeField`, `ColorVisionModeField`, `TextScaleField`, `MotionModeField`, `BrightnessField`, `ThemeColorPicker`, and `ThemeToggle` are driven by values and callbacks. They do not require preference context, so they can work with forms, preview tools, or another state library.
```tsx
<ThemeModeField value={mode} onValueChange={setMode} />
<CompactLayoutField checked={compacted} onCheckedChange={setCompacted} />
<ColorVisionModeField value={colorVisionMode} onValueChange={setColorVisionMode} />
<TextScaleField value={textScale} onValueChange={setTextScale} />
<MotionModeField value={motionMode} onValueChange={setMotionMode} />
<BrightnessField value={brightness} onValueChange={setBrightness} />
```
## Compose a theme card {#compose-card}
@@ -28,11 +31,9 @@ toc:
```tsx
<ThemeConfigCard
active={resolvedTheme === "light"}
compacted={compacted}
config={lightTheme}
onConfigChange={setLightTheme}
scheme="light"
config={{ baseColor, accentColor }}
onConfigChange={setThemeColors}
scheme={resolvedTheme}
/>
```
+18 -3
View File
@@ -17,6 +17,13 @@ toc:
Build one complete preference definition map at the application boundary. Spread definitions from appearance, locale, keyboard, and other feature packages into this map, then create or load the initial values.
Import Appearance after UI in the application stylesheet. No UI component changes are required:
```css
@import "@workspace/ui/globals.css";
@import "@workspace/appearance/globals.css";
```
```tsx
import {
createDefaultPreferences,
@@ -54,11 +61,11 @@ export function Root({ children }: { children: React.ReactNode }) {
## Register effects {#effects}
`appearancePreferenceEffect` combines two exported callbacks: `applyAppearancePreferenceEffect` updates document classes and theme variables before paint, while `subscribeSystemThemePreferenceEffect` watches the operating-system theme after paint. Register the composed effect in the stable `effects` array passed to `PreferencesProvider`.
`appearancePreferenceEffect` updates document classes, root attributes, and theme variables before paint, then watches operating-system theme and motion preferences after paint. Register it in the stable `effects` array passed to `PreferencesProvider`.
## Inject theme variables {#theme-style}
Use `buildThemeStyleSheet` to generate the CSS variables for light, dark, and system modes. Keep the stable element ID so the appearance effect can update the same node when color preferences change.
Use `buildThemeStyleSheet` to generate light and dark CSS variables from one base color, one accent color, and a color-vision mode. Keep the stable element ID so the appearance effect can update the same node when preferences change.
```tsx
import {
@@ -69,11 +76,19 @@ import {
;<style
id={THEME_STYLE_ELEMENT_ID}
dangerouslySetInnerHTML={{
__html: buildThemeStyleSheet(themeLight, themeDark),
__html: buildThemeStyleSheet(
{ baseColor, accentColor },
colorVisionMode,
brightness
),
}}
/>
```
Assistance modes adjust chart and destructive semantic colors and set `data-ui-color-vision`. They are not color-vision simulators and do not transform photos, video, or brand assets.
Text scaling changes the root font size through `data-ui-text-scale`; reduced motion shortens global animation through `data-ui-motion` while preserving low-motion loading feedback; brightness adjusts theme surface variables without using `filter: brightness()`.
## Persist updates {#persistence}
The shared `onPreferenceChange` receives a typed `{ key, value }` only when a value actually changes. Forward it to a server function or cookie writer owned by the application.
+9 -2
View File
@@ -13,14 +13,17 @@ toc:
## Package role {#package-role}
`@workspace/appearance` provides the definitions, effects, theme data, and UI components for theme modes, base colors, accent colors, and compact layouts. It does not create its own provider or store. The application aggregates it with other preference packages through `@workspace/preferences`.
`@workspace/appearance` owns theme mode, base color, accent color, color-vision assistance, text scale, motion, and interface brightness. It does not create its own provider or store, and it does not require changes to `@workspace/ui`. The application aggregates it with other preference packages through `@workspace/preferences`.
## Atomic components {#atomic-components}
The controlled components can be composed independently without preference context:
- `ThemeModeField` selects light, dark, or system mode.
- `CompactLayoutField` toggles the main content width.
- `ColorVisionModeField` selects the standard, protan, deutan, or tritan assistance palette.
- `TextScaleField` scales the interface to 100%, 125%, 150%, or 200%.
- `MotionModeField` follows the system, reduces motion, or enables full motion.
- `BrightnessField` selects dim, normal, or bright interface surfaces.
- `ThemeColorPicker` and `ThemeColorSwatchButton` select theme colors.
- `ThemePreview` previews a set of theme variables.
- `ThemeConfigCard` combines the preview, base color, and accent color controls.
@@ -60,3 +63,7 @@ export function App() {
```
Add definitions and effects from locale, keyboard, or other packages to the same objects. The application can persist every `{ key, value }` update through the shared `onPreferenceChange` and parse cookies on the server with the aggregated definitions.
Color-vision assistance does not filter the complete document or its images. It replaces semantic colors such as `destructive` and `chart-*`, and writes `data-ui-color-vision` to `<html>` so application components can add icons, labels, shapes, or patterns. Important information must never rely on color alone.
Text, motion, and brightness are also implemented entirely through root attributes and CSS variables. Once the Appearance stylesheet is imported, existing UI components, portals, and application content inherit these settings.