Guide

Token API

Tokens, the t accessor, createUi, and theme-reactive component props.

Token<T>

Every design value is a frozen Token<T> object with three fields:

type Token<T> = {
  readonly __token: true  // discriminant — lets the compiler detect token props
  readonly id: string     // stable unique identifier, e.g. "celurenBlue-500"
  readonly value: T       // resolved design value, e.g. "#024CCE"
}

Create your own tokens with the token() factory:

import { token } from '@stareezy-ui/tokens'

const brandPrimary = token('#FF6B35', 'brand-primary')
brandPrimary.value // "#FF6B35"
brandPrimary.id    // "brand-primary"
The __token: true discriminant is what lets the Babel/Vite compiler detect token props at build time and replace them with atomic CSS class names — zero runtime cost.

Static token props

Pass token objects directly as props on Box and other primitives. TypeScript autocompletes and validates every value:

import { colors, spacing, radius } from '@stareezy-ui/tokens'
import { Box, Text } from '@stareezy-ui/components'

function Card() {
  return (
    <Box
      bg={colors.celurenBlue[500]}   // Token<string> — always #024CCE
      p={spacing[4]}                 // Token<number> — always 16px
      rounded={radius.md}            // Token<number> — always 10px
    >
      <Text type="M-heading-bold" text="Hello" />
    </Box>
  )
}

Static tokens always resolve to their fixed .value — they don't change when the theme switches. Use them for values that should be the same across all themes.

Theme-reactive props with t

The t accessor returns ThemeToken references — lightweight objects that resolve to the current theme's value at render time. When the theme switches, every component using a ThemeToken re-renders with the correct color automatically.

import { t } from '@stareezy-ui/tokens'
import { Box, Text } from '@stareezy-ui/components'

function Card() {
  return (
    // These resolve to the CURRENT theme's value at render time:
    // aurora  → backgrounds.primary = #00ff88
    // dark    → backgrounds.primary = #024cce
    // steins-gate → backgrounds.primary = #4a9eff
    <Box
      bg={t.backgrounds.primary}
      borderColor={t.border.primaryBrand}
      p={16}
      rounded={8}
    >
      <Text
        style={{ color: t.text.primary }}  // also works in style objects
        type="M-heading-bold"
        text="Auto-switches with theme"
      />
    </Box>
  )
}
t is a typed proxy tree — TypeScript knows every valid path. t.text.primary, t.backgrounds.secondary, t.border.danger — all autocomplete and type-check.

Available t slots

t.text
.primary.secondary.tertiary.placeholder.disable.inverse.importantBrand.danger.success.dangerPrimary.successPrimary.warningPrimary
t.backgrounds
.primary.secondary.disabled.primaryBlack
t.border
.default.secondary.tertiary.primaryBrand.danger.success.dangerPrimary.successPrimary.primaryBlack

Resolving ThemeTokens manually

When you need the raw string value inside a component (e.g. for a non-Box element), use useResolveThemeToken:

import { t, useResolveThemeToken } from '@stareezy-ui/tokens'

function MyComponent() {
  const brandColor = useResolveThemeToken(t.text.importantBrand)
  // aurora      → "#00ff88"
  // steins-gate → "#4a9eff"
  // dark/light  → "#024cce"

  return <canvas style={{ borderColor: brandColor }} />
}

createUi

Call createUi() once at app startup to register themes, custom tokens, breakpoints, fonts, and shorthands. The returned ui object exposes ui.t (same as the standalone t), ui.tokens, and helper methods.

import { createUi, token, themes } from '@stareezy-ui/tokens'

export const ui = createUi({
  // Register all four themes
  themes: {
    aurora:        themes.aurora,
    dark:          themes.dark,
    light:         themes.light,
    'steins-gate': themes['steins-gate'],
  },

  // Custom token groups — fully typed on ui.tokens
  tokens: {
    brand: {
      primary:   token('#FF6B35', 'brand-primary'),
      secondary: token('#004E89', 'brand-secondary'),
    },
  },

  // Responsive breakpoints
  media: { sm: 480, md: 768, lg: 1024, xl: 1280, '2xl': 1536 },

  // Prop shorthands for Box
  shorthands: { bg: 'backgroundColor', p: 'padding' },
})

// Access custom tokens with full type safety
ui.tokens.brand.primary.value   // "#FF6B35"
ui.tokens.colors.celurenBlue[500].value // "#024CCE"

// ui.t is the same as the standalone t accessor
<Box bg={ui.t.backgrounds.primary} />
Export ui from a single ui.config.ts file and import it wherever you need typed token access. This is the recommended pattern — one config, full type inference everywhere.

Accessing raw values

Every token exposes its raw value via .value. Use this when you need a plain string or number (e.g. inline styles, RN StyleSheet, canvas):

import { colors, spacing, radius } from '@stareezy-ui/tokens'

colors.celurenBlue[500].value  // "#024CCE"
spacing[4].value               // 16
radius.md.value                // 10

// In a non-Box context
const style = {
  backgroundColor: colors.celurenBlue[500].value,
  padding: spacing[4].value,
  borderRadius: radius.md.value,
}

Token categories

colors

Full palette — celurenBlue, raisinBlack, beauBlue, lawnGreen, crimsonRed, neutral…

semanticColors

Role-based — text.primary, backgrounds.primary, border.default…

spacing

Scale from 0 to 480px, named aliases (tiny, small, medium…)

radius

Border radius — sm (6), md (10), lg (16), xl (24), full (9999)

typography

Font families, sizes, weights — Inter + Plus Jakarta Sans

shadow

Box shadow presets — sm, md, lg, xl

motion

Duration, easing, spring — for animations

glow

Glow effects — aurora green, nebula purple, teal