Skip to content

API reference

Media Queries

Toned supports responsive styling through breakpoints defined in your system configuration. Token values can be overridden at specific breakpoints, and the system handles media query generation automatically.

Using Breakpoints in Stylesheets

Use an @media key that names a breakpoint to create a responsive override block inside any element definition:

TypeScript
const layoutStyles = stylesheet({
  Root: {
    paddingX: 2,
    flexLayout: 'column',

    '@media md': {
      paddingX: 4,
      flexLayout: 'row',
    },

    '@media lg': {
      paddingX: 6,
    },
  },
})

Breakpoint blocks support the same token properties and $style escape hatch as the base element definition. Properties set inside a breakpoint block override the base values when the viewport matches.

'@media md' can also be written as the builder call [q.media('md')], and the compatibility short key '@md' declares the same rule. Container and platform conditions follow the same pattern. See Conditions and selectors for every form.

Root-Level Breakpoints

Breakpoints can be declared at the root level of a stylesheet to apply overrides across multiple elements at once. This is useful when a layout change at a given viewport affects several elements simultaneously:

TypeScript
const cardStyles = stylesheet({
  Root: {
    paddingX: 2,
    flexLayout: 'column',
  },
  Title: {
    $kind: 'text',
    typography: 'heading-3',
  },
  Sidebar: {
    display: 'none',
  },

  // At medium viewports, adjust multiple elements together
  '@media md': {
    Root: { paddingX: 4, flexLayout: 'row' },
    Title: { typography: 'heading-2' },
    Sidebar: { display: 'flex' },
  },

  '@media lg': {
    Root: { paddingX: 6 },
  },
})

Root-level and element-level breakpoints can be mixed freely. They produce the same result — root-level is shorthand for applying overrides to several elements under the same breakpoint.

Breakpoints in Variants

Responsive overrides work inside variant blocks too, letting you combine conditional and responsive styling. Breakpoints can be set on individual elements within a variant:

TypeScript
import type { Variants } from '@toned/core'

const styles = stylesheet({
  Root: { paddingX: 2, flexLayout: 'column', gap: 2 },
}).variants(($: Variants<{ layout: 'grid' | 'list' }>) => ({
  [$.layout('grid')]: {
    Root: {
      '@media md': {
        flexLayout: 'row',
        flexWrap: 'wrap',
      },
      '@media lg': {
        gap: 4,
      },
    },
  },
}))

Using Breakpoints Inline

The t utility accepts the same @media blocks, so a one-off style can be responsive without defining a stylesheet:

TypeScript
import { t } from '@toned/systems/base'

function Panel() {
  return <div {...t({ paddingX: 2, '@media md': { paddingX: 4 } })} />
}

t is the compatibility inline helper: it reads the installed configuration, and its blocks compile to CSS custom properties, so they apply only to web output with CSS media enabled. They are also one level deep, so the root-level and variant forms shown above apply to stylesheets only.

Give the property a base value, as paddingX: 2 does above. A block with no base compiles to a fallback-less chain, so below the breakpoint the property resolves to its initial value rather than to whatever a class or an inherited rule set.

Declaring Breakpoints

The examples above use the base system's breakpoints. In your own system, declare named viewport thresholds in logical pixels:

system.ts
import { defineSystem } from '@toned/core'

export const ui = defineSystem({
  id: 'responsive',
  tokens: {},
  conditions: {
    media: {
      xs: 0,    // mobile-first default
      sm: 480,  // small phones landscape
      md: 768,  // tablets
      lg: 992,  // small desktops
      xl: 1200, // large desktops
    },
  },
})

How Breakpoints Apply

The renderer given to TonedProvider decides how a breakpoint is evaluated; the stylesheet is the same everywhere.

Web

A web renderer uses the CSS generated at build time, where each breakpoint is a real @media rule. Matching happens in the browser, with no JavaScript listener or React render:

App.tsx
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 { ui } from './system.ts'

const renderer = createWebRenderer(ui, { manifest })

export function App({ children }: { children: React.ReactNode }) {
  return (
    <TonedProvider renderer={renderer} host={webHost}>
      {children}
    </TonedProvider>
  )
}

React Native

A native renderer evaluates a stylesheet's breakpoints against the viewport width the native host reports, and patches the mounted hosts when it changes. See the React Native guide for the host capabilities this needs.

Inline t blocks have no native equivalent: they compile to CSS custom properties, which only a browser reads. Without CSS media an inline @ block is dropped, the base token value still applies, and a development-only warning explains why. Where you need responsive styling on React Native, use stylesheet with useStyles instead.