Vitus Labs
Rocketstyle

Rocketstyle

Dimension-based component styling system with theming, pseudo-states, and chainable API.

Rocketstyle is a dimension-based styling system for React. It wraps any component and adds named styling dimensions (states, sizes, variants), theme integration with light/dark mode, pseudo-state tracking, provider/consumer patterns, and a chainable configuration API.

Installation

npm install @vitus-labs/rocketstyle

Requires @vitus-labs/core and a CSS engine connector (@vitus-labs/connector-styler).

Try It Live

This demo shows the dimension-based styling concept — select a state and size to see how styles compose:

function DimensionDemo() {
const [state, setState] = React.useState('primary')
const [size, setSize] = React.useState('md')

const states = {
  primary: { backgroundColor: '#0d6efd', color: '#fff' },
  secondary: { backgroundColor: '#6c757d', color: '#fff' },
  danger: { backgroundColor: '#dc3545', color: '#fff' },
  success: { backgroundColor: '#198754', color: '#fff' },
}

const sizes = {
  sm: { fontSize: 12, padding: '6px 12px' },
  md: { fontSize: 14, padding: '10px 20px' },
  lg: { fontSize: 16, padding: '14px 28px' },
}

const merged = { ...states[state], ...sizes[size] }

return (
  <div style={{ fontFamily: 'system-ui' }}>
    <div style={{ display: 'flex', gap: 16, marginBottom: 16, flexWrap: 'wrap' }}>
      <div style={{ display: 'flex', gap: 4, alignItems: 'center', fontSize: 13 }}>
        State:
        {Object.keys(states).map((s) => (
          <button key={s} onClick={() => setState(s)} style={{
            padding: '4px 10px', borderRadius: 4, fontSize: 12, cursor: 'pointer',
            border: state === s ? '2px solid #333' : '1px solid #ccc',
            background: state === s ? '#f0f0f0' : '#fff',
          }}>{s}</button>
        ))}
      </div>
      <div style={{ display: 'flex', gap: 4, alignItems: 'center', fontSize: 13 }}>
        Size:
        {Object.keys(sizes).map((s) => (
          <button key={s} onClick={() => setSize(s)} style={{
            padding: '4px 10px', borderRadius: 4, fontSize: 12, cursor: 'pointer',
            border: size === s ? '2px solid #333' : '1px solid #ccc',
            background: size === s ? '#f0f0f0' : '#fff',
          }}>{s}</button>
        ))}
      </div>
    </div>
    <button style={{
      ...merged,
      border: 'none',
      borderRadius: 6,
      cursor: 'pointer',
      fontWeight: 500,
      transition: 'all 0.2s',
    }}>
      Button ({state} / {size})
    </button>
    <pre style={{
      marginTop: 12, padding: 12, borderRadius: 6,
      background: '#f8f9fa', fontSize: 12, lineHeight: 1.5,
    }}>
      {JSON.stringify(merged, null, 2)}
    </pre>
  </div>
)
}

render(<DimensionDemo />)

Quick Start

import { init } from '@vitus-labs/core'
import * as styler from '@vitus-labs/connector-styler'
import rocketstyle from '@vitus-labs/rocketstyle'

init(styler)

const Button = rocketstyle()({
  name: 'Button',
  component: 'button',
})
  .theme((theme) => ({
    fontFamily: theme.fontFamily?.base,
    borderRadius: '4px',
  }))
  .states((theme) => ({
    primary: {
      backgroundColor: 'blue',
      color: 'white',
    },
    secondary: {
      backgroundColor: 'gray',
      color: 'black',
    },
  }))
  .sizes((theme) => ({
    sm: { fontSize: '12px', padding: '4px 8px' },
    md: { fontSize: '14px', padding: '8px 16px' },
    lg: { fontSize: '16px', padding: '12px 24px' },
  }))
  .styles((css) => css`
    cursor: pointer;
    border: none;
    font-family: ${({ $rocketstyle }) => $rocketstyle.fontFamily};
    font-size: ${({ $rocketstyle }) => $rocketstyle.fontSize};
    padding: ${({ $rocketstyle }) => $rocketstyle.padding};
    background-color: ${({ $rocketstyle }) => $rocketstyle.backgroundColor};
    color: ${({ $rocketstyle }) => $rocketstyle.color};
    border-radius: ${({ $rocketstyle }) => $rocketstyle.borderRadius};

    &:hover {
      opacity: 0.9;
    }
  `)

// Usage — explicit prop syntax
<Button state="primary" size="lg">Click me</Button>

// Boolean shorthand (useBooleans enabled by default)
<Button primary lg>Click me</Button>

Factory Function

The factory uses a curried call pattern:

rocketstyle(options?)(config)

Options (First Call)

OptionTypeDefaultDescription
dimensionsRecord<string, string | DimensionConfig>See belowCustom dimension definitions
useBooleansbooleantrueEnable boolean shorthand props

Config (Second Call)

OptionTypeDescription
namestringRequired. Component display name
componentComponentType | stringRequired. React component or HTML tag to wrap

Default Dimensions

{
  states: 'state',          // Maps to `state` prop
  sizes: 'size',            // Maps to `size` prop
  variants: 'variant',      // Maps to `variant` prop
  multiple: {               // Multi-select dimension
    propName: 'multiple',
    multi: true             // Accepts array values
  }
}

Custom Dimensions

Override the defaults entirely:

const Card = rocketstyle({
  dimensions: {
    colors: 'color',
    shapes: {
      propName: 'shape',
      multi: true,         // Allows array: shape={['rounded', 'elevated']}
    },
  },
})({
  name: 'Card',
  component: 'div',
})
  .colors((theme) => ({
    primary: { backgroundColor: 'blue' },
    secondary: { backgroundColor: 'gray' },
  }))
  .shapes((theme) => ({
    rounded: { borderRadius: '8px' },
    elevated: { boxShadow: '0 2px 8px rgba(0,0,0,0.1)' },
  }))

Each custom dimension key becomes a chainable method automatically.

Validation

In development mode, the factory validates:

  1. component is provided
  2. name is provided
  3. dimensions is not empty
  4. Dimension names don't conflict with reserved keys

Throws a JSON-structured error if validation fails.

Reserved Dimension Names

These names cannot be used as dimension keys:

light, dark, theme, styles, compose, attrs,
provider, consumer, DEBUG, name, component,
inversed, passProps, styled

Render Pipeline

When a rocketstyle component renders, it follows this sequence:

1. Ref handling         — merge forwarded ref + internal $rocketstyleRef
2. Local context        — read parent provider state via useLocalContext()
3. Theme resolution     — get theme + mode from context, apply inversed flag
4. Base theme cache     — WeakMap lookup → getThemeFromChain() if miss
5. Dimension themes     — WeakMap lookup → getDimensionThemes() if miss
6. Mode resolution      — resolve mode callbacks in base + dimension themes
7. Dimension map        — build keysMap + keywords for boolean resolution
8. Props merge          — { ...localCtx, ...props } (explicit props win)
9. Pseudo-state merge   — combine context pseudo + explicit pseudo props
10. Styling attrs       — resolve active dimension values from props
11. $rocketstyle        — merge base theme + active dimension themes
12. Final props         — strip reserved props, add $rocketstyle/$rocketstate
13. Render              — <StyledComponent {...finalProps} />

Steps 4-6 use WeakMap caching — the expensive theme computation runs only once per unique theme reference.

Boolean Shorthand

When useBooleans is enabled (default), dimension values can be used as boolean props:

// These are equivalent:
<Button state="primary" size="lg" />
<Button primary lg />

Resolution Rules

  • Explicit props take priority: state="primary" always wins over boolean secondary
  • Boolean shorthand only activates when the explicit prop is not set
  • For single-select dimensions, last boolean prop wins (props keys are reversed)
  • For multi-select dimensions (multi: true), all matching booleans are collected into an array
  • Standard HTML boolean attributes (disabled, checked, hidden, etc.) are excluded from shorthand matching

Disabling Boolean Shorthand

const Component = rocketstyle({
  useBooleans: false,
})({
  name: 'Component',
  component: 'div',
})

// Only explicit prop syntax works:
<Component state="primary" />
// <Component primary /> would NOT work

Type Utilities

// Extract rocketstyle dimension props
type ButtonDimensions = typeof Button['$$rocketstyle']

// Extract original component props
type OriginProps = typeof Button['$$originTypes']

// Extract extended props from .attrs() chains
type ExtendedProps = typeof Button['$$extendedTypes']

// Get all combined props
type AllProps = typeof Button['$$types']

// Check if component is rocketstyle
import { isRocketComponent } from '@vitus-labs/rocketstyle'
isRocketComponent(Button) // true

Static Properties

Every rocketstyle component has these properties:

PropertyTypeDescription
IS_ROCKETSTYLEtrueMarker for identification
displayNamestringComponent name from config
metaobjectUser-defined statics from .statics()
getStaticDimensions(theme) => DimensionInfoGet dimension map for a theme
getDefaultAttrs(props, theme, mode) => attrsCompute attrs without rendering
$$rocketstyleType-onlyDimension props type
$$originTypesType-onlyOriginal component props type
$$extendedTypesType-onlyExtended props from .attrs()
$$typesType-onlyAll combined props type

getStaticDimensions

Returns the dimension configuration resolved against a theme:

const info = Button.getStaticDimensions(theme)
// {
//   dimensions: { state: { primary: true, secondary: true }, size: { sm: true, md: true, lg: true } },
//   keywords: { state: true, primary: true, secondary: true, size: true, sm: true, md: true, lg: true },
//   useBooleans: true,
//   multiKeys: { multiple: true },
// }

Debug Mode

Enable per-component debug logging:

const Button = rocketstyle()({
  name: 'Button',
  component: 'button',
}).config({ DEBUG: true })

In development, this logs on every render:

  • Component name
  • Resolved $rocketstyle values
  • Resolved $rocketstate values
  • Active dimension selections
  • Theme mode

All components also get a data-rocketstyle attribute in development with the component name.

Exports

import rocketstyle, {
  Provider,
  context,
  isRocketComponent,
} from '@vitus-labs/rocketstyle'

import type {
  RocketStyleComponent,
  RocketComponentType,
  RocketProviderState,
  ConsumerCtxCBValue,
  ConsumerCtxCb,
  ConsumerCb,
  Dimensions,
  DimensionValue,
  DimensionCallbackParam,
  ExtractDimensionProps,
  DimensionProps,
  ExtractDimensions,
  StylesDefault,
  StylesCb,
  RocketStyleInterpolationProps,
  ConfigAttrs,
  AttrsCb,
  ThemeCb,
  ThemeModeCallback,
  ThemeModeKeys,
  GenericHoc,
  ComposeParam,
  DefaultProps,
  IsRocketComponent,
  ThemeMode,
  TProvider,
  IRocketStyleComponent,
  Rocketstyle,
} from '@vitus-labs/rocketstyle'

API Reference

Prop

Type

Prop

Type

On this page