Responsive System
Config-driven breakpoints, responsive object syntax, and $-prefixed breakpoint props — all fully typed from your createUi configuration.
Overview
Stareezy UI's responsive system is driven by your stareezy.config.ts. Declare breakpoints once in createUi({ media }) and TypeScript automatically derives the valid breakpoint keys — so autocomplete and type errors work everywhere without extra setup.
min-width media queries on web, and as window-width comparisons on React Native.Declaring breakpoints with createUi
Pass a media record to createUi(). Keys are breakpoint names, values are min-width thresholds in pixels.
// stareezy.config.ts
import { createUi, themes } from '@stareezy-ui/tokens'
export const ui = createUi({
themes: { aurora: themes.aurora, light: themes.light },
// Declare your responsive breakpoints (mobile-first, min-width px)
media: {
sm: 480,
md: 768,
lg: 1024,
xl: 1280,
'2xl': 1536,
},
// Optional — custom shorthands that also accept responsive values
shorthands: {
p: 'padding',
px: 'paddingHorizontal',
py: 'paddingVertical',
m: 'margin',
br: 'borderRadius',
w: 'width',
h: 'height',
} as const,
})
// Module augmentation — makes breakpoints and shorthands flow into the type system
type AppConfig = typeof ui
declare module '@stareezy-ui/tokens' {
interface SzrCustomConfig extends AppConfig {}
}
export default uicreateUi({ media }) automatically syncs the declared breakpoints into the runtime — no separate configureBreakpoints() call is needed.Config-driven BreakpointKey autocomplete
After the module augmentation above, BreakpointKey is derived directly from your media configuration. TypeScript autocompletes only the keys you declared, and reports a type error for any other key.
// After augmenting SzrCustomConfig with the config above,
// BreakpointKey = "base" | "sm" | "md" | "lg" | "xl" | "2xl"
// ✅ Valid — these keys match the declared breakpoints
<Box p={{ base: 8, md: 16, lg: 24 }} />
// ❌ Type error — "tablet" is not a declared breakpoint
<Box p={{ tablet: 16 }} />
// ↑ Type '"tablet"' is not assignable to type 'BreakpointKey'Without augmentation, the default BreakpointKey is "base" | "sm" | "md" | "lg" | "xl" | "2xl".
Responsive object syntax
Pass a { base?, sm?, md?, lg?, xl?, '2xl'? } object to any layout or shorthand prop. The base value applies unconditionally; each named breakpoint applies at and above its configured threshold (mobile-first).
import { Box, Button, Card } from '@stareezy-ui/components'
// Responsive padding
<Box p={{ base: 8, md: 16, lg: 24 }} />
// Responsive width — full on mobile, auto on desktop
<Button w={{ base: '100%', md: 'auto' }} />
// Responsive flex direction
<Box
flexDirection={{ base: 'column', lg: 'row' }}
gap={{ base: 8, lg: 16 }}
>
<Card p={{ base: 12, md: 20 }} />
<Card p={{ base: 12, md: 20 }} />
</Box>▸ Responsive object syntax — Every layout prop accepts a { base?, sm?, md?, lg?, xl?, '2xl'? } object. The base value applies unconditionally; each named breakpoint activates at and above its min-width threshold.
Responsive values on custom shorthands
Custom shorthands declared through createUi({ shorthands }) accept responsive objects with the same syntax as built-in props.
// With the shorthands declared above:
<Box br={{ base: 4, md: 8, lg: 12 }} /> // borderRadius responsive
<Box px={{ base: 12, lg: 24 }} /> // paddingHorizontal responsive
<Box w={{ base: '100%', md: 320 }} /> // width responsive
// Mix responsive and plain values
<Box p={{ base: 8, md: 16 }} br={8} w="100%" />$-prefixed breakpoint-as-prop syntax
As an alternative to responsive objects, you can group multiple style props under a single $breakpoint key (Tamagui-style). Each $-prefixed prop accepts a partial set of Box style and shorthand props scoped to that breakpoint.
// Equivalent to writing individual responsive objects on each prop
<Box
$md={{ p: 16, br: 8 }}
$lg={{ p: 24, br: 12, flexDirection: 'row' }}
/>
// Same as:
<Box
p={{ base: undefined, md: 16, lg: 24 }}
br={{ base: undefined, md: 8, lg: 12 }}
flexDirection={{ base: undefined, lg: 'row' }}
/>$-prefixed group for the same breakpoint, the $-prefixed value wins.▸ $-prefixed syntax — Use $breakpoint groups to co-locate props for the same breakpoint. They are concise alternatives to responsive objects. When both forms set the same property, the $-group takes precedence.
// $md value wins over the responsive object's md value
<Box
p={{ base: 8, md: 12 }} // md = 12 from responsive object
$md={{ p: 16 }} // md = 16 from $-group — this wins
/>
// Result at md: p = 16All components accept responsive props
Every component in @stareezy-ui/components extends BoxLayoutProps, so responsive layout props work on all of them — not just Box.
import { Button, Input, Card, Badge } from '@stareezy-ui/components'
<Button
p={{ base: 8, md: 12 }}
w={{ base: '100%', md: 'auto' }}
$lg={{ px: 20, py: 10 }}
/>
<Input
w={{ base: '100%', md: 360 }}
mb={{ base: 8, lg: 0 }}
/>
<Card
p={{ base: 12, md: 20, lg: 28 }}
$md={{ flexDirection: 'row' }}
/>
<Badge
px={{ base: 8, md: 12 }}
py={{ base: 4, md: 6 }}
/>Default breakpoints
If you do not augment SzrCustomConfig with a media configuration, the following defaults apply:
| Key | min-width | Typical target |
|---|---|---|
base | 0px | All screens (no media query) |
sm | 480px | Large phones |
md | 768px | Tablets |
lg | 1024px | Laptops |
xl | 1280px | Desktops |
2xl | 1536px | Wide screens |