Core API
Proxy-based chainable style builder. The recommended way to write styles.
import { tw } from 'typewritingclass'Property-access tokens
Section titled “Property-access tokens”Design tokens are accessed as properties — no strings needed:
tw.bg.blue500 // background-color: #3b82f6tw.textColor.slate900 // color: #0f172atw.rounded.lg // border-radius: 0.5remtw.shadow.md // box-shadowtw.text.lg // font-size + line-heighttw.font.bold // font-weight: 700tw.items.center // align-items: centertw.justify.between // justify-content: space-betweentw.cursor.pointer // cursor: pointerColor tokens support opacity:
tw.bg.blue500(50) // rgb(59 130 246 / 0.5)Utilities with arguments
Section titled “Utilities with arguments”tw.p(4).gap(8).w('100%').h(12)tw.opacity(0.5).border(1).z(10)Arbitrary values
Section titled “Arbitrary values”tw.bg('#ff6347').rounded('0.625rem')Value-less utilities
Section titled “Value-less utilities”tw.flex.flexCol.relative.truncateSingle-utility modifiers (property syntax)
Section titled “Single-utility modifiers (property syntax)”The modifier applies to the next utility in the chain:
tw.hover(tw.bg.blue500)tw.md.p(8)tw.dark(tw.bg.slate900)Multi-utility modifiers (function syntax)
Section titled “Multi-utility modifiers (function syntax)”tw.hover( tw.bg.blue500 .textColor.white .shadow.lg)tw.dark( tw.bg.slate800 .textColor.slate100)Resolution
Section titled “Resolution”The compiler replaces tw chains with class name strings at build time:
<div className={tw.p(4).bg.blue500} /> // React / Next.jselement.className = tw.p(4).bg.blue500 // Vanilla JS (also auto-coerces)Immutability
Section titled “Immutability”Every chain is immutable — property access and method calls return new chains:
const base = tw.flex.flexColconst a = base.gap(4) // flex + flexCol + gap(4)const b = base.gap(8) // flex + flexCol + gap(8)Reserved name remappings
Section titled “Reserved name remappings”| tw name | Maps to |
|---|---|
tw.content | content_() |
tw.float | float_() |
tw.static | static_() |
tw.placeholder | placeholder_ modifier |
tw.selection | selection_ modifier |
tw.has | has_() modifier |
Composes style rules and string class names into a single CSS class string.
function cx(...args: (StyleRule | string)[]): stringLater arguments override earlier ones via CSS layer ordering. Standalone utilities support property-access tokens:
import { cx, p, bg, rounded } from 'typewritingclass'
cx(p(4), bg.blue500, rounded.lg)// => "_a1b2c _d3e4f _g5h6i"
// With opacitycx(bg.blue500(25), rounded.lg, p(4))
// Mix with plain stringscx('my-class', p(4), bg.white)
// With modifierscx(p(4), when(hover)(bg.blue600), when(md)(p(8)))Like cx() but also returns an inline style object for dynamic CSS values.
function dcx(...args: (StyleRule | string)[]): { className: string; style: Record<string, string> }import { dcx, bg, p, dynamic } from 'typewritingclass'
const { className, style } = dcx(p(4), bg(dynamic('#e11d48')))// className => "_a1b2c _d3e4f"// style => { '--twc-d0': '#e11d48' }
<div className={className} style={style} />when()
Section titled “when()”Applies modifiers (pseudo-states, breakpoints, dark mode) to style rules.
function when(...modifiers: Modifier[]): (...rules: StyleRule[]) => StyleRuleModifiers are applied right-to-left (first modifier is innermost):
when(hover)(bg.blue600) // :hoverwhen(md)(p(8)) // @media (min-width: 768px)when(hover, md)(bg.blue700) // hover inside md breakpointwhen(dark)(bg.slate900, textColor.white) // dark modedynamic()
Section titled “dynamic()”Wraps a value for runtime CSS custom property injection.
function dynamic<T extends string | number>(value: T): DynamicValue<T>Use with dcx() — the value becomes a var(--twc-dN) reference in CSS and is applied via inline style:
const { className, style } = dcx(bg(dynamic(color)))<div className={className} style={style} />isDynamic()
Section titled “isDynamic()”Type guard for DynamicValue. Useful when building custom utilities:
function isDynamic(v: unknown): v is DynamicValuelayer()
Section titled “layer()”Assigns explicit layer priority, overriding automatic layer numbering:
function layer(priority: number): (...rules: StyleRule[]) => StyleRuleconst base = layer(0)(p(4), bg.white) // low priority, easily overriddencx(base, bg.blue500) // blue overrides whitecreateRule() / createDynamicRule()
Section titled “createRule() / createDynamicRule()”Low-level functions for building custom utilities. See Writing Utilities.
createRule({ padding: '1rem' })createDynamicRule({ color: 'var(--twc-d0)' }, { '--twc-d0': '#ff0000' })generateCSS()
Section titled “generateCSS()”Returns the full CSS string for all registered rules. Used by the compiler and SSR integrations:
function generateCSS(): stringinterface StyleRule { _tag: 'StyleRule' declarations: Record<string, string> selectors: string[] mediaQueries: string[] supportsQueries: string[] dynamicBindings?: Record<string, string> selectorTemplate?: string}
interface DynamicValue<T = string | number> { _tag: 'DynamicValue' __value: T __id: string}
interface DynamicResult { className: string style: Record<string, string>}
type Utility = (value: any) => StyleRuletype Modifier = (rule: StyleRule) => StyleRuleInput types
Section titled “Input types”| Type | Accepted values | Used by |
|---|---|---|
ColorInput | Theme tokens, CSS color strings, dynamic() | bg(), textColor(), borderColor() |
SpacingInput | Numbers (spacing scale), CSS strings, dynamic() | p(), m(), gap() and variants |
SizeInput | Numbers, CSS strings, size tokens, dynamic() | w(), h(), size(), minW(), etc. |
RadiusInput | Radius tokens, CSS strings, dynamic() | rounded() and variants |
ShadowInput | Shadow tokens, CSS strings, dynamic() | shadow() |