Typography
A production-ready typography component built entirely on createComponent primitives — variants for scale and weight, color mode at the base, font families in the weight variant, and a thin wrapper for accessibility. Copy and adapt to your design system.
import React from 'react';import { Text as RNText } from 'react-native';import { createComponent } from 'react-native-small-ui';
// ─── Base ─────────────────────────────────────────────────────────────────────// createComponent handles scale, weight, font families, and color mode.// Typography is kept internal — Text is what consumers use.
const Typography = createComponent(RNText, { variants: { preset: { h1: { fontSize: 34, lineHeight: 41 }, h2: { fontSize: 28, lineHeight: 34 }, h3: { fontSize: 22, lineHeight: 28 }, h4: { fontSize: 20, lineHeight: 28 }, h5: { fontSize: 17, lineHeight: 24 }, h6: { fontSize: 14, lineHeight: 18 }, body: { fontSize: 16, lineHeight: 24 }, caption: { fontSize: 12, lineHeight: 18 }, small: { fontSize: 10, lineHeight: 14 }, }, weight: { thin: { fontWeight: '200', fontFamily: 'Inter-Thin' }, light: { fontWeight: '300', fontFamily: 'Inter-Light' }, normal: { fontWeight: '400', fontFamily: 'Inter' }, semibold: { fontWeight: '600', fontFamily: 'Inter-SemiBold' }, bold: { fontWeight: '700', fontFamily: 'Inter-Bold' }, extrabold: { fontWeight: '900', fontFamily: 'Inter-ExtraBold' }, }, }, defaultVariants: { preset: 'body', weight: 'normal', }, // Global text color — every instance inherits this unless overridden at the call site. _light: { color: '#1a1a1a' }, _dark: { color: '#f0f0f0' },});
// ─── Thin wrapper — handles the one concern createComponent can't ──────────────// accessibilityRole is a behavioral prop, not a style. Three lines, fully transparent:// all library features (style props, _light/_dark, .extend()) reach through via ...props.
const HEADING_PRESETS = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']);
type TypographyProps = React.ComponentProps<typeof Typography>;
export function Text({ preset = 'body', weight = 'normal', ...props }: TypographyProps) { return ( <Typography preset={preset} weight={weight} accessibilityRole={HEADING_PRESETS.has(preset) ? 'header' : undefined} {...props} /> );}// Defaults apply — body size, normal weight, color mode from base<Text>Some paragraph content</Text>
// Heading — accessibilityRole="header" set automatically<Text preset="h1" weight="bold">Welcome Back</Text><Text preset="h3" weight="semibold">Section Title</Text>
// Per-instance color override — _light/_dark work on Text just like any createComponent output<Text preset="caption" weight="semibold" _light={{ color: '#666' }} _dark={{ color: '#aaa' }}> Last updated today</Text>Type scale
Section titled “Type scale”All preset values — h1 through small. The accessibilityRole="header" wrapper applies automatically for h1–h6.
Why this structure
Section titled “Why this structure”| Concern | Where it lives | Why |
|---|---|---|
| Size scale | preset variant |
Typed prop, autocompleted, no manual spread |
| Font weight + family | weight variant |
Weight and face are always paired — one prop selects both |
| Text color | Base _light/_dark |
Every instance inherits it; callers override per-instance |
accessibilityRole |
Thin wrapper | Behavioral prop, not a style — can’t live in a variant |
Typography (the createComponent output) is internal. Text is what the rest of the app imports — it has the same API surface as any SmallUIComponent, plus the accessibility behaviour baked in.