Recipes & Composites
Recipes are plain functions that combine utilities into reusable design patterns. No new API to learn — just functions.
Basic recipe
Section titled “Basic recipe”import { tw } from 'typewritingclass'
const card = tw .p(6) .bg.white .rounded.lg .shadow.md .textColor.gray900
// Usage:<div className={card}>Content</div>Recipes with variants
Section titled “Recipes with variants”import { tw } from 'typewritingclass'
type ButtonVariant = 'primary' | 'secondary' | 'danger'type ButtonSize = 'sm' | 'md' | 'lg'
const base = tw .rounded.lg .font.semibold .cursor.pointer
const sizes = { sm: tw.px(3).py(1).text.sm, md: tw.px(4).py(2).text.base, lg: tw.px(6).py(3).text.lg,} as const
const variants = { primary: tw .bg.blue500 .textColor.white .hover(tw.bg.blue600), secondary: tw .bg.white .textColor.gray700 .border().borderColor.gray300 .hover(tw.bg.gray50), danger: tw .bg.red500 .textColor.white .hover(tw.bg.red600),} as const
export function button(variant: ButtonVariant = 'primary', size: ButtonSize = 'md') { return `${base} ${sizes[size]} ${variants[variant]}`}<button className={button('primary', 'lg')}>Submit</button><button className={button('secondary', 'sm')}>Cancel</button>Multi-element recipes
Section titled “Multi-element recipes”Return an object of class strings for components with multiple styled elements:
const dialog = { overlay: tw .fixed.inset(0) .flex.items.center.justify.center .bg('black/50'), panel: tw .bg.white .rounded.xl .maxW('32rem').w('full') .shadow.xl, header: tw .px(6).py(4) .borderB().borderColor.gray200 .textColor.gray900 .font.semibold, body: tw .p(6) .textColor.gray700, footer: tw .px(6).py(4) .borderT().borderColor.gray200 .flex.justify.end.gap(2),}<div className={dialog.overlay}> <div className={dialog.panel}> <div className={dialog.header}>Title</div> <div className={dialog.body}>Content</div> <div className={dialog.footer}>Actions</div> </div></div>Recipes with extra styles
Section titled “Recipes with extra styles”Accept additional styles from the consumer:
import { cx, p, bg, rounded, shadow, textColor } from 'typewritingclass'
export function card(...extra: (StyleRule | string)[]) { return cx(p(6), bg.white, rounded.lg, shadow.sm, textColor.gray900, ...extra)}
// Consumer overrides:<div className={card(when(hover)(shadow.lg))}>Enhanced</div>Dynamic recipes
Section titled “Dynamic recipes”Use dcx() and dynamic() for runtime values:
import { dcx, bg, textColor, p, rounded, dynamic } from 'typewritingclass'
export function colorSwatch(color: string) { return dcx(bg(dynamic(color)), textColor.white, p(4), rounded.lg)}function Swatch({ color }: { color: string }) { const { className, style } = colorSwatch(color) return <div className={className} style={style}>{color}</div>}Patterns summary
Section titled “Patterns summary”| Pattern | When to use |
|---|---|
Simple recipe (returns string) | Single styled element |
Multi-element (returns object) | Multiple styled children |
| With variants (enum params) | Visual variants (primary, secondary) |
With ...extra (accepts rules) | Consumers need to extend |
Dynamic (uses dcx) | Runtime-determined values |