Chainable API with tw
tw is a proxy-based chainable style builder. One import gives you access to every utility, modifier, and value-less shorthand.
import { tw } from 'typewritingclass'
const card = tw .p(6) .bg.white .rounded.xl .shadow.mdProperty-access tokens
Section titled “Property-access tokens”Design tokens (colors, radius, shadows, typography, layout enums) 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 via callable syntax:
tw.bg.blue500(50) // background-color: rgb(59 130 246 / 0.5)tw.bg.blue500(25) // 25% opacityUtilities with arguments
Section titled “Utilities with arguments”Spacing, sizing, and arbitrary CSS values use function calls:
tw.p(4).gap(8).w('100%').h(12)tw.opacity(0.5).z(10).border(1)Value-less utilities
Section titled “Value-less utilities”Accessed as properties instead of function calls:
tw.flex.flexCol.gap(4)tw.relative.overflow.hiddentw.italic.truncate.antialiasedtw.group .bg.white .rounded.lg .p(4)Arbitrary values
Section titled “Arbitrary values”Pass any CSS value as a string argument — useful for one-off values:
tw.bg('#ff6347').rounded('0.625rem')tw.shadow('0 4px 12px rgba(0,0,0,0.15)')Single-utility modifiers (property syntax)
Section titled “Single-utility modifiers (property syntax)”The modifier applies to the next utility in the chain:
tw.bg.white.hover(tw.bg('blue-50')).focus(tw.ring(2))tw.p(4).md.p(8).lg.p(12)tw.bg.white.dark(tw.bg.slate900)tw.opacity(0.5).groupHover(tw.opacity(1))Multi-utility modifiers (function syntax)
Section titled “Multi-utility modifiers (function syntax)”When a modifier should apply to multiple styles, call it as a function:
tw.hover( tw.bg.blue500 .textColor.white .shadow.lg)
const card = tw .p(6) .bg.white .rounded.xl .hover(tw.bg.slate100.shadow.lg.scale(105)) .focus(tw.ring(2).ringColor.blue500)Resolving to class strings
Section titled “Resolving to class strings”The compiler replaces tw chains with class name strings at build time, so they work directly in any context:
// React<div className={tw.p(4).bg.blue500} />
// Vanilla JSelement.className = tw.p(4).bg.blue500
// Template literalsconst classes = `${tw.p(4)} extra-class`Immutable chains
Section titled “Immutable chains”Every access returns a new chain:
const base = tw.flex.flexColconst a = base.gap(4) // flex + flexCol + gap(4)const b = base.gap(8) // flex + flexCol + gap(8)// base is unchangedtw vs cx + when
Section titled “tw vs cx + when”Both APIs produce identical CSS. Choose based on preference:
cx + when | tw | |
|---|---|---|
| Imports | Many individual imports | Single tw import |
| Modifiers | when(hover)(bg.blue600) | tw.hover(tw.bg.blue600) |
| Value-less | cx(flex(), flexCol()) | tw.flex.flexCol |
| Tokens | cx(bg.blue500, rounded.lg) | tw.bg.blue500.rounded.lg |
| Dynamic values | dcx(bg(dynamic(color))) | Use cx/dcx for dynamic values |