# @multiplatform.one/theme

The multiplatform.one theming engine: Tamagui color themes plus the **knobs
system** — structural styling (radius, spacing, elevation, typography, animation)
resolved independently of color, so one knob flip restyles a whole screen.

## Install

```bash
pnpm add @multiplatform.one/theme
```

Requires `react` and `tamagui` as peers.

## What it owns

- **Knobs** — `useResolvedKnobs()`, `resolveKnobs()` (the only canonical mapping
  from abstract knobs to Tamagui props), knob types and defaults
- **Presets** — `<Preset preset="…" theme="…">` bundles knobs + intents + theme;
  nested presets cascade, `overrides` merge by key
- **Intents** — contextual overrides (`error`, `accent`, `warning`, `success`),
  including intent + component overrides
- **Recipes** — control/text/elevation state recipes (hover, press, focus-visible)
- **Optics** — the `cornerSmoothing` knob (`round` | `smooth` squircle corners:
  web progressive enhancement via CSS `corner-shape: squircle`, computed
  `superellipse(2)` on Chromium 152; native stays round),
  `hairline` separator treatments (0.5 device-pixel rules with a 1px low-DPI
  fallback), and tracking-by-size in the default font faces
- **Chart palette** — `useChartPalette()`: identity-led series colors
  (single-series = theme identity, categorical cycle, semantic ramps) that
  re-anchor under tints; explicit data colors always pass through
- Theme creation (`createThemes`, `createDefaultThemeConfig`), `Tint`, layout
  tokens, focus state, cookie persistence for SSR-safe knobs

## What it must not do

- No app screens and no component catalog — components live in
  `@multiplatform.one/components`, fields in `@multiplatform.one/forms`

## Usage

```tsx
import { useResolvedKnobs } from "@multiplatform.one/theme";
import { View } from "@multiplatform.one/components";

export function Surface({ intent, compact, ...props }) {
  const { knobProps, control } = useResolvedKnobs({ intent, component: "Button", compact });
  return (
    <View
      {...knobProps.surface}
      {...knobProps.borderRadius}
      {...knobProps.panelPadding}
      {...knobProps.gap}
      hoverStyle={{ ...control.hoverKnobProps }}
      pressStyle={{ ...control.pressKnobProps }}
      {...props}
    />
  );
}
```

Rules that keep knobs sound:

- Always spread complete `knobProps.*` fragments — never cherry-pick resolved tokens.
- Consumer `{...props}` spread last (the only styling eject).
- Resolution order: Preset → intent → intent+component → size → density →
  reduced-motion → `resolveKnobs()` override callback.

Full standard: `agent-os/standards/frontend/knobs-system.md` in the
[multiplatform.one repo](https://gitlab.com/bitspur/frappe/multiplatform.one).

## License

Apache-2.0
