Projection UI

Theming

Projection UI 0.1.5 archive

You are reading version 0.1.5. This archive retains its original API and installation requirements. Open the current alpha documentation.

Read this page as Markdown

Quick start

In your entry file (main.tsx or index.tsx):

import '@hannasage/projection-ui/tokens'

This loads a set of CSS custom property defaults. If you wrap your app with ThemeProvider, these are overridden by your theme — but they act as a safe fallback.

2. Define your theme

import type { UITheme } from '@hannasage/projection-ui'

const myTheme: UITheme = {
  bg:        '#07090C',   // page background
  surface:   '#0D1117',   // card / panel
  border:    '#1B2535',   // borders
  text:      '#DDE3EE',   // primary text
  muted:     '#8396AB',   // secondary text / labels
  primary:   '#C9F53A',   // accent — buttons, focus rings
  primaryFg: '#07090C',   // text on top of primary (e.g. button label)
  danger:    '#FF5252',   // destructive actions
  font:      "'IBM Plex Mono', monospace",
  radius:    'soft',      // 'sharp' | 'soft' | 'rounded'
}

Radius presets:

presetbuttons/inputscardspills/toggles
sharp2px4px4px (no pill)
soft6px10px9999px
rounded16px24px9999px

3. Wrap your app

import { ThemeProvider, ToastContainer } from '@hannasage/projection-ui'

export default function App() {
  return (
    <ThemeProvider theme={myTheme}>
      <YourApp />
      <ToastContainer />
    </ThemeProvider>
  )
}

Switching themes is instant — pass a new theme object and all --ui-* CSS variables update automatically.

Dynamic theming

ThemeProvider is just a div that writes CSS vars — swapping themes is a single state update:

const [theme, setTheme] = useState<UITheme>(darkTheme)

<ThemeProvider theme={theme}>
  <button onClick={() => setTheme(lightTheme)}>Toggle theme</button>
</ThemeProvider>

Font licenses

On this page