# Applying an ASUI theme

`ASThemeProvider` supplies a theme to ASUI components in its React subtree, including portaled content. Use `createASTheme` to define project-wide styling and `themeOverrides` for local exceptions. Without a provider, components use ASUI's default theme.

## Create a project theme

```tsx
import { ASButton, ASThemeProvider, createASTheme } from '@eleventheye/asui';

const projectTheme = createASTheme({
  preset: 'neutral',
  tokens: {
    color: {
      accent: '#175cd3',
      onAccent: '#ffffff',
      accentHover: '#1849a9',
      accentPressed: '#194185',
      focus: '#175cd3',
    },
    typography: { fontFamily: 'system-ui, sans-serif' },
    radius: { control: '6px' },
  },
  components: {
    button: { rest: { shadow: 'none' } },
  },
});

const App = () => (
  <ASThemeProvider theme={projectTheme}>
    <ASButton text="Save" />
  </ASThemeProvider>
);
```

`createASTheme()` defaults to the `classic` preset. The `neutral` preset provides flat surfaces and simpler decoration. Tokens define shared styling; component overrides define exceptions and take precedence over derived token values. Set foreground, hover, pressed, and focus colors deliberately: changing `accent` does not calculate those colors for you.

Keep reusable themes outside render, or memoize them when their inputs change. Factory themes are immutable. Use `extendASTheme(projectTheme, overrides)` to derive another theme rather than editing a resolved theme. Persist the factory input and reconstruct it with `createASTheme`; resolved themes are not intended for JSON serialization.

See the [theme property reference](./theme-reference.md) for supported tokens, component slots, and preset defaults.

## Inherit, replace, or override

- Omit both props to inherit the nearest provider, falling back to `ASThemeDefault`.
- Pass `theme` to replace the inherited theme completely.
- Pass `themeOverrides` to compose partial token and component overrides with the inherited theme.

Pass only one of `theme` or `themeOverrides` on a provider or component. Supplying both is rejected.

```tsx
<ASThemeProvider theme={projectTheme}>
  <ASButton text="Project styling" />
  <ASThemeProvider themeOverrides={{ tokens: { radius: { control: '2px' } } }}>
    <ASButton text="Scoped corners" />
    <ASButton
      text="Local exception"
      themeOverrides={{
        components: { button: { rest: { background: 'transparent' } } },
      }}
    />
  </ASThemeProvider>
</ASThemeProvider>
```

Nested overrides retain earlier explicit component exceptions. For example, a button background set through `components.button.rest.background` remains an exception when a nested provider changes `tokens.color.accent`. Remove that exception from the theme definition when you want the background to derive from tokens again.

Component theme scopes also reach their ASUI descendants, such as an `ASButton` loader. `useASTheme()` reads the inherited theme in your own components; `useASTheme(theme, themeOverrides)` applies the same replacement or composition rules.

`ASLoader` has a specific compatibility exception: its `theme` prop accepts an `ASLoaderTheme` section rather than a complete theme. Omit it to inherit loader styling, or use `themeOverrides` to customize the inherited full theme.

## Styling scope

The provider adds no DOM element, injects no global styles, and does not load fonts. ASUI uses its own React context, independent of a host styled-components `ThemeProvider`; consumers do not need to augment styled-components' `DefaultTheme`.

Semantic component styles cover buttons, icon buttons, [dropdowns](./dropdown.md), text fields (including multiline), [loaders](./loader.md), switches, snackbars, modals, ChoiceBar and its items, horizontal/vertical bar charts, donut charts, and standalone SVG icons. See the [theme property reference](./theme-reference.md) for each `components` slot and its token mappings. Explicit visual component props retain their documented precedence.

Semantic theming does not mean every property derives from a shared token. SVG icons use `components.icon`; neutral strokes default to `currentColor`, and fills remain transparent unless configured. Glyph icons keep their font-specific API. ASTappable owns pointer interaction, not a visual theme recipe. Loader geometry and animation durations have their own rules, documented in its guide.

Existing complete `ASTheme` objects remain supported. Their existing component values are preserved as explicit styling exceptions, so token overrides cannot infer or recolor an existing gradient. Use component overrides for those values, or create a token-driven project theme with `createASTheme`.

## Adopting semantic themes in an existing project

1. Put the existing complete theme on a root `ASThemeProvider` to retain its appearance. Remove repeated component `theme` props only where inheritance should replace them; retain deliberate local replacements.
2. For a token-driven project theme, define a `createASTheme` input outside render. Choose `classic` to retain ASUI decoration or `neutral` for a simpler starting point, then set project tokens and component exceptions.
3. Move local exceptions into `themeOverrides.components`. Preserve explicit data colors, such as NFL team chart colors. Do not expect token changes to recolor preserved complete-theme gradients or explicit component values.
4. Check supported sizes and interaction states, portal content, fonts, and native controls in the consuming application. Make CSS variables available at portal destinations.

For example, scope a modal background exception to a subtree:

```tsx
<ASThemeProvider themeOverrides={{ components: { modal: { background: '#ffffff' } } }}>
  {children}
</ASThemeProvider>
```

Use each component's guide for its visibility and interaction props. Existing complete themes remain supported; switching to factory inputs is an adoption choice, not a requirement to discard the yellow preset. Loader's section-theme exception and SVG/glyph distinctions are described above. Use `extendASTheme` for reusable variants instead of spreading and editing a resolved theme.

## CSS custom properties and portals

Theme values that accept CSS colors can reference custom properties:

```tsx
const projectTheme = createASTheme({
  preset: 'neutral',
  tokens: { color: { accent: 'var(--project-accent)' } },
});
```

```css
:root {
  --project-accent: #175cd3;
}
```

React context follows the component tree through a portal, but CSS custom properties follow DOM ancestry. Define variables used by portaled components on `:root` or another ancestor of their portal container. Variables defined only on a local application wrapper are not automatically available to an overlay rendered under `body`.

Changing a CSS variable updates styles that reference it. It does not rebuild theme recipes or update other independently configured tokens. Likewise, the provider does not apply its font to arbitrary HTML; apply your application's base typography separately and load any required font assets.
