React Web Guide
This guide sets up Toned in a React web project with Vite and the ready-made base token vocabulary. With another bundler, generate the CSS in a build script instead; see Without Vite.
1. Install Dependencies
npm install @toned/core @toned/react @toned/systems @toned/themes2. Compose the System
@toned/systems/base exports its token vocabulary. Compose it into a system of your own, in a pure module that both the build and the application import. The base tokens read unprefixed custom properties, which @toned/themes supplies, so this system has no namespace id:
import { defineSystem } from '@toned/core'
import { system as base } from '@toned/systems/base'
const { breakpoints, ...tokens } = base
export const ui = defineSystem(tokens, { breakpoints })
export const { stylesheet } = uiA system of your own design follows Getting Started instead.
3. Define Styles
Sheets import stylesheet from the system module. Keep them separate from components, so the build can collect them:
import type { Variants } from '@toned/core'
import { stylesheet } from '../system.ts'
export const buttonStyles = stylesheet({
Root: {
$kind: 'pressable',
bgColor: 'action',
borderRadius: 'medium',
borderWidth: 'none',
paddingX: 3,
paddingY: 2,
cursor: 'pointer',
},
Label: {
$kind: 'text',
textColor: 'on_action',
typography: 'label-medium',
},
}).variants(($: Variants<{
variant: 'primary' | 'secondary'
}>) => ({
[$.variant('secondary')]: {
Root: {
bgColor: 'action_secondary',
},
Label: {
textColor: 'on_action_secondary',
},
},
}))4. Add the Vite Plugin
The Vite plugin generates the CSS and its manifest at build time. Pass the complete system and every sheet, including those of lazy routes, and list the declaration modules it should watch:
import toned from '@toned/core/vite'
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'
import { buttonStyles } from './src/styles/button.ts'
import { ui } from './src/system.ts'
export default defineConfig({
plugins: [
toned({
system: ui,
sheets: [buttonStyles],
inputs: ['src/system.ts', 'src/styles/button.ts'],
}),
react(),
],
})5. Provide the Renderer
Import the theme values and the generated CSS in your entry point, create a renderer from the system and the generated manifest, and provide it with the web host:
import '@toned/themes/shadcn/config.css'
import 'virtual:toned.css'
import manifest from 'virtual:toned.manifest'
import { createWebRenderer } from '@toned/core/server'
import { TonedProvider } from '@toned/react'
import { webHost } from '@toned/react/hosts/web'
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { App } from './App.tsx'
import { ui } from './system.ts'
const renderer = createWebRenderer(ui, { manifest })
createRoot(document.getElementById('root')!).render(
<StrictMode>
<TonedProvider renderer={renderer} host={webHost}>
<App />
</TonedProvider>
</StrictMode>,
)/// <reference types="vite/client" />
declare module 'virtual:toned.css' {}
declare module 'virtual:toned.manifest' {
import type { BuildManifest } from '@toned/core/build'
const manifest: BuildManifest
export default manifest
}6. Use Styles in Components
Bind your stylesheet once, at module scope, with createElements. Variants go on the family provider; host props go on the parts:
import { createElements } from '@toned/react'
import { buttonStyles } from './styles/button.ts'
const S = createElements(buttonStyles)
export function Button({ label, variant = 'primary' }: {
label: string
variant?: 'primary' | 'secondary'
}) {
return (
<S variant={variant}>
<S.Root as="button" type="button">
<S.Label as="span">{label}</S.Label>
</S.Root>
</S>
)
}What the Renderer Decides
The renderer owns the system, the output backend and the manifest check; the host owns refs, events and elements. Components choose no output mode. A web renderer emits class names for the generated CSS: breakpoints are CSS @media rules, and :hover, :focus and :active are CSS, with no JavaScript event listeners. See Interactive Styles.
List every sheet in the plugin's sheets: Toned never injects missing CSS at runtime, and the renderer diagnoses a condition absent from the manifest. The React reference covers themes, multiple systems and native hosts.