Skip to content

Quick Start

Everything chains off a single import:

import { tw } from 'typewritingclass'

Chain utilities to build styles. The chain resolves to a class string automatically:

<div className={tw.p(6).bg('white').rounded('lg').shadow('md')} />

Utilities that take no arguments are accessed as properties:

tw.flex.flexCol.gap(4)
tw.relative.overflow('hidden')
tw.italic.truncate

Access a modifier as a property and it applies to the next utility:

tw.bg('white').hover.bg('blue-50')
tw.p(4).md.p(8).lg.p(12)
tw.bg('white').dark.bg('slate-900')

For multiple utilities under one modifier, call it as a function:

tw.hover(tw.bg('blue-500').textColor('white').shadow('lg'))
import { tw } from 'typewritingclass'
// Card container
const card = tw
.group.bg('white').rounded('xl').shadow('md').p(6)
.hover(tw.shadow('lg').scale(102))
.dark.bg('slate-800')
// Title responds to group hover
const title = tw.textColor('slate-900').font('700')
.groupHover.textColor('blue-600')
.dark.textColor('white')
// Responsive layout
const container = tw.flex.flexCol.gap(4).md.flex.gap(8)
function Card() {
return (
<div className={card}>
<h2 className={title}>Hello, typewritingclass</h2>
</div>
)
}

Every access returns a new chain. The original is never mutated:

const base = tw.flex.flexCol
const withGap4 = base.gap(4) // flex + flexCol + gap(4)
const withGap8 = base.gap(8) // flex + flexCol + gap(8)
// base is still just flex + flexCol

For runtime values (props, state, user input), use the functional API with dcx() and dynamic():

import { dcx, bg, p, rounded, dynamic } from 'typewritingclass'
function Banner({ color }: { color: string }) {
const { className, style } = dcx(p(6), bg(dynamic(color)), rounded('lg'))
return <div className={className} style={style}>Welcome!</div>
}

The tw chain and the functional cx()/when() API are interchangeable and produce identical CSS:

import { cx, p, bg, rounded, when, hover } from 'typewritingclass'
// Equivalent to tw.p(4).bg('blue-500').rounded('lg').hover.bg('blue-600')
const card = cx(p(4), bg('blue-500'), rounded('lg'), when(hover)(bg('blue-600')))

Both APIs can coexist in the same project. Use whichever reads better for each situation.