pyreon

@pyreon/rocketstyle enables multi-dimensional style composition for Pyreon components. Define orthogonal style dimensions (themes, sizes, variants, states) and compose them declaratively.

@pyreon/rocketstylestable

Installation

npm install @pyreon/rocketstyle
bun add @pyreon/rocketstyle
pnpm add @pyreon/rocketstyle
yarn add @pyreon/rocketstyle

Overview

Rocketstyle lets you define multiple independent style dimensions on a component -- for example, theme, size, variant, and state. Each dimension has a set of named values, and each value maps to a style callback. At render time, the active value from each dimension is resolved and all styles are merged together.

This approach scales better than flat variant props because dimensions compose multiplicatively without requiring you to enumerate every combination.

Quick Start

The canonical chain is .config(...).attrs(...).theme((t) => ({...})) → dimension methods (.states / .sizes / .variants / .multiple / .modifiers).

import rocketstyle from '@pyreon/rocketstyle'

// Create the rocketstyle factory once (per app / per design system).
// `useBooleans: false` is the default since 2026-04 — dimension props
// accept string values (`state="primary"`), not boolean shorthand.
const rs = rocketstyle({ useBooleans: false })

const Button = rs('button')
  .config({ name: 'Button' })
  .attrs({
    tag: 'button',
    direction: 'inline',
    alignX: 'center',
    alignY: 'center',
    gap: 8,
  })
  .theme((t) => ({
    borderRadius: '4px',
    cursor: 'pointer',
    fontWeight: 500,
    border: 'none',
  }))
  .states({
    primary: { background: 'royalblue', color: 'white' },
    danger: { background: '#dc3545', color: 'white' },
    ghost: { background: 'transparent', color: '#333', borderWidth: '1px', borderColor: '#ccc' },
  })
  .sizes({
    sm: { padding: '4px 8px', fontSize: '12px' },
    md: { padding: '8px 16px', fontSize: '14px' },
    lg: { padding: '12px 24px', fontSize: '16px' },
  })

// Dimensions become props
<Button state="primary" size="lg">Submit</Button>
<Button state="danger" size="sm">Delete</Button>
<Button state="ghost" size="md">Cancel</Button>

Dimensions

Rocketstyle supports five built-in dimension types — every one is optional:

MethodProp nameMulti?Description
.states(...)statenoInteractive state (e.g., primary, secondary, disabled, loading).
.sizes(...)sizenoSize scale (e.g., sm, md, lg, xl).
.variants(...)variantnoStructural variation (e.g., outlined, filled, text).
.multiple(...)multipleyesMulti-select dimension — accepts an array of values that compose.
.modifiers(...)modifieryesMulti-select with prop-name transform — for cross-cutting style flags.

Each dimension is defined by calling its method with a map of named values to style objects or styled-callbacks. Custom dimensions can be declared via rocketstyle({ dimensions: { ... } }) at factory-init time.

Style Callbacks

Dimension values can be static objects or dynamic callbacks that receive the component's props and theme:

const Card = rs('div')
  .states({
    light: { background: '#fff', color: '#333' },
    dark: (props) => ({
      background: props.elevated ? '#2d2d2d' : '#1a1a1a',
      color: '#e0e0e0',
    }),
  })

Chaining with Attrs

Rocketstyle builds on @pyreon/attrs, so you can chain .attrs() calls alongside dimension definitions:

const IconButton = rs('button')
  .config({ name: 'IconButton' })
  .attrs({ 'aria-label': 'icon button', direction: 'inline', alignX: 'center', alignY: 'center' })
  .states({
    primary: { background: 'royalblue', color: 'white' },
  })
  .sizes({
    sm: { width: '32px', height: '32px' },
    md: { width: '40px', height: '40px' },
  })

Provider and Context

Rocketstyle components can be configured at the tree level using the built-in Provider:

import { Provider } from '@pyreon/rocketstyle'

;<Provider value={{ state: 'dark', size: 'sm' }}>
  {/* All rocketstyle components inside inherit these defaults */}
  <Button>Uses dark state, sm size</Button>
  <Card>Also dark and small</Card>
</Provider>

Integration with Styler

Rocketstyle is designed to work with @pyreon/styler. Dimension style objects are resolved into CSS classes via the styler's styled API, giving you scoped styles with deduplication and SSR support.

API Reference

ExportTypeDescription
rocketstyleFunctionWraps a component and returns a multi-dimension style builder
ProviderComponentContext provider for tree-level dimension defaults
contextContextThe raw Pyreon context object used by Provider
isRocketComponentFunctionType guard to check if a value is a rocketstyle component

Types

TypeDescription
RocketstyleThe builder interface with .config(), .attrs(), .theme(), .states(), .sizes(), .variants(), .multiple(), .modifiers()
RocketStyleComponentA component produced by the rocketstyle builder
DimensionsMap of dimension names to their value definitions
DimensionPropsProps auto-generated from dimension definitions
ThemeModeTheme mode configuration type
StylesCbStyle callback signature: (props) => StyleObject

Key Features

  • Multi-dimensional style composition (states, sizes, variants, multiple, modifiers + custom)

  • Auto-generated props from dimension definitions

  • Static style objects or dynamic style callbacks

  • Built on @pyreon/attrs -- chainable .attrs() calls

  • Tree-level defaults via Provider/Context

  • Works with @pyreon/styler for scoped CSS-in-JS

  • Full TypeScript support with inferred dimension props

  • Compile-time wrapper collapse (opt-in) — literal-prop call sites like <Button state="primary" size="medium">Save</Button> collapse the 5-layer mount (rocketstyle → attrs → Element → Wrapper → styled) into one cloneNode at build time (~44× faster for that shape). Enable via pyreon({ collapse: true }) — see Compile-time rocketstyle collapse.

Rocketstyle