Skip to content

Getting Started

Install TypeStyles and ship your first typed component styles in a few minutes

TypeStyles is CSS in TypeScript: style objects (selectors, media queries, pseudos), typed variants, tokens as CSS variables, and ordinary className strings in React, Vue, Svelte, or HTML. No compiler is required for the default runtime path.

You need TypeScript and a bundler or runtime that resolves node_modules (Vite, webpack, Next.js, and others work; no TypeStyles-specific loader for the default path).

Installation

bash
pnpm add typestyles

Optional — Vite: for dev HMR and build-time CSS extraction, add @typestyles/vite. Other bundlers: Zero-runtime extraction.

Your first styles

Use createTypeStyles once so styles and tokens share one scopeId (namespaced CSS variables and predictable class names). Put the module in a file you import from your UI — the live example below includes the full source and a className usage snippet.

Scoped button + tokens

Read-only live output. Toggle variants to see the preview, DOM classes, and emitted CSS update together.

        import { createTypeStyles } from 'typestyles';

export const { styles, tokens } = createTypeStyles({ scopeId: 'app' });

export const color = tokens.create('color', {
  primary: '#0066ff',
  surface: '#ffffff',
});

export const button = styles.component('button', {
  base: {
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    padding: '8px 16px',
    borderRadius: '6px',
    fontWeight: 500,
    border: 'none',
    cursor: 'pointer',
    color: color.surface,
    backgroundColor: color.primary,
  },
  variants: {
    intent: {
      primary: { backgroundColor: color.primary, color: color.surface },
      ghost: {
        backgroundColor: 'transparent',
        color: color.primary,
        border: `1px solid ${color.primary}`,
      },
    },
  },
  defaultVariants: { intent: 'primary' },
});

      
            <button type="button" className={button({ intent: 'primary' })}>
  Example button
</button>
          
          class="app-button-base app-button-intent-primary"
        
          :root {
  --app-color-primary: #0066ff;
  --app-color-surface: #ffffff;
}

.app-button-base {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 8px 16px;
  border-radius: 6px;
  font-weight: 500;
  border: none;
  cursor: pointer;
  color: var(--app-color-surface);
  background-color: var(--app-color-primary);
}

.app-button-intent-primary {
  background-color: var(--app-color-primary);
  color: var(--app-color-surface);
}
        

Toggle Ghost in the demo and check the DOM and Emitted CSS panels (or DevTools on the preview button). Scoped class names are prefixed with your scopeId, and token-backed values resolve to custom properties such as --app-color-primary.

What just happened: definitions register when the module loads; the first time a class is used, TypeStyles injects rules into a managed <style> tag. For SSR, streaming, or static CSS in production, see SSR and Zero-runtime extraction.

For React-specific patterns (refs, merging className, server components), see React integration. Vue and Svelte work the same way — see the runnable examples below.

Runnable examples

Clone the typestyles monorepo and run from the repo root (pnpm install once):

Example Command README
Vite + React (recommended starting point) pnpm vite-app dev examples/vite-app
Next.js App Router + extraction verify pnpm next-app dev examples/next-app
Vue 3 pnpm vue-app dev examples/vue-app
Svelte 5 pnpm svelte-app dev examples/svelte-app
Runtime only (no bundler plugin) pnpm parcel-app dev examples/parcel-app

Full index: examples/README.md · maintainer map: docs/README.md

Next steps

Topic What you will learn
Styles Flat vs dimensioned styles.component, styles.class, composition, mental model
Components Variants, compounds, multipart slots
Tokens Namespaces, themes, tokens.use
Framework comparison How TypeStyles compares to other tools
Migration Mapping from Panda, CVA, StyleX, Emotion
Design system with tokens Primitives → semantics → components
Class naming Semantic vs hashed output