Responsive Modifiers API Reference
Complete API reference for TachUI's responsive modifier system, including all methods, types, and configuration options.
Core Types
ResponsiveValue<T>
Generic type for responsive values that can be either a static value or an object with breakpoint-specific values.
type ResponsiveValue<T> = T | Partial<Record<BreakpointKey, T>>
// Examples
type ResponsiveFontSize = ResponsiveValue<number>
// Can be: 16 or { base: 16, md: 20, lg: 24 }
type ResponsiveColor = ResponsiveValue<string>
// Can be: '#000' or { base: '#000', md: '#333' }BreakpointKey
Union type of all available breakpoint names.
type BreakpointKey = 'base' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'ResponsiveStyleConfig
Configuration object for responsive styles.
interface ResponsiveStyleConfig {
[key: string]: ResponsiveValue<any>
}
// Example
const styleConfig: ResponsiveStyleConfig = {
fontSize: { base: 16, md: 20, lg: 24 },
padding: { base: 8, md: 12, lg: 16 },
color: '#333333' // Static value
}BreakpointContext
Current breakpoint information and viewport dimensions.
interface BreakpointContext {
current: BreakpointKey // Currently active breakpoint
width: number // Viewport width in pixels
height: number // Viewport height in pixels
}Responsive Modifier Methods
.responsive()
Apply responsive styles using breakpoint-specific configuration.
.responsive(config: ResponsiveStyleConfig): ResponsiveModifierChain
// Usage
Text("Responsive text")
.modifier
.responsive({
fontSize: { base: 16, md: 20, lg: 24 },
padding: { base: 8, md: 12, lg: 16 },
color: { base: '#333', md: '#000' },
textAlign: 'center' // Applied to all breakpoints
})
.build()Parameters:
config: ResponsiveStyleConfig- Object with CSS properties and responsive values
Returns: ResponsiveModifierChain - Chainable modifier for further customization
Example with all CSS properties:
Text("Full responsive example")
.modifier
.responsive({
// Typography
fontSize: { base: 14, md: 16, lg: 18, xl: 20 },
fontWeight: { base: 'normal', lg: 'bold' },
lineHeight: { base: 1.4, md: 1.5, lg: 1.6 },
textAlign: { base: 'center', md: 'left' },
// Layout
width: { base: '100%', md: '50%', lg: '33.333%' },
padding: { base: 12, md: 16, lg: 20 },
margin: { base: 8, md: 12, lg: 16 },
// Visual
backgroundColor: { base: '#f5f5f5', md: '#ffffff' },
borderRadius: { base: 4, md: 8 },
boxShadow: { base: 'none', md: '0 2px 4px rgba(0,0,0,0.1)' },
// Flexbox
display: { base: 'block', md: 'flex' },
flexDirection: { base: 'column', md: 'row' },
alignItems: { base: 'stretch', md: 'center' },
gap: { base: 8, md: 16 }
})
.build().mediaQuery()
Apply styles for custom media queries.
.mediaQuery(query: string, styles: CSSProperties): ResponsiveModifierChain
// Usage
Text("Media query example")
.modifier
.fontSize(16)
.mediaQuery('(orientation: landscape)', { fontSize: 18 })
.mediaQuery('(prefers-color-scheme: dark)', { color: '#ffffff' })
.mediaQuery('(min-width: 900px)', { fontSize: 20 })
.build()Parameters:
query: string- CSS media query stringstyles: CSSProperties- CSS styles to apply when query matches
Returns: ResponsiveModifierChain - Chainable modifier
Common media query examples:
// Orientation
.mediaQuery('(orientation: portrait)', { /* styles */ })
.mediaQuery('(orientation: landscape)', { /* styles */ })
// Color scheme
.mediaQuery('(prefers-color-scheme: dark)', { /* styles */ })
.mediaQuery('(prefers-color-scheme: light)', { /* styles */ })
// Accessibility
.mediaQuery('(prefers-reduced-motion: reduce)', { /* styles */ })
.mediaQuery('(prefers-contrast: high)', { /* styles */ })
// Device capabilities
.mediaQuery('(hover: hover)', { /* styles */ })
.mediaQuery('(hover: none)', { /* styles */ })
// Resolution
.mediaQuery('(min-resolution: 2dppx)', { /* styles */ })
// Aspect ratio
.mediaQuery('(aspect-ratio: 16/9)', { /* styles */ })
// Custom breakpoints
.mediaQuery('(min-width: 900px) and (max-width: 1199px)', { /* styles */ })Breakpoint Shorthand Modifiers
Apply styles at specific breakpoints and above using shorthand syntax.
.sm // Styles apply at 'sm' breakpoint and above
.md // Styles apply at 'md' breakpoint and above
.lg // Styles apply at 'lg' breakpoint and above
.xl // Styles apply at 'xl' breakpoint and above
['2xl'] // Styles apply at '2xl' breakpoint and above (bracket notation)
// Usage
Text("Shorthand responsive")
.modifier
.fontSize(14) // Base (all breakpoints)
.color('#666') // Base (all breakpoints)
.sm.fontSize(16) // sm and above
.md.fontSize(18) // md and above
.md.color('#333') // md and above
.lg.fontSize(22) // lg and above
.lg.fontWeight('bold') // lg and above
.xl.fontSize(26) // xl and above
['2xl'].fontSize(30) // 2xl and above
.build()Chaining with other modifiers:
Text("Mixed responsive and static")
.modifier
.textAlign('center') // Static - applies to all breakpoints
.fontSize(14) // Base fontSize
.padding(8) // Base padding
.md.fontSize(18) // Override fontSize at md+
.md.padding(12) // Override padding at md+
.lg.fontSize(22) // Override fontSize at lg+
.lg.fontWeight('bold') // Add fontWeight at lg+
.backgroundColor('#f5f5f5') // Static - applies to all breakpoints
.build()Responsive Property Modifiers
All standard TachUI modifiers support responsive values:
Typography Responsive Modifiers
// Font size
.fontSize(value: ResponsiveValue<number | string>)
.fontSize({ base: 16, md: 20, lg: 24 })
// Font weight
.fontWeight(value: ResponsiveValue<FontWeight>)
.fontWeight({ base: 'normal', lg: 'bold' })
// Line height
.lineHeight(value: ResponsiveValue<number | string>)
.lineHeight({ base: 1.4, md: 1.5, lg: 1.6 })
// Text alignment
.textAlign(value: ResponsiveValue<'left' | 'center' | 'right' | 'justify'>)
.textAlign({ base: 'center', md: 'left' })
// Color
.color(value: ResponsiveValue<string>)
.color({ base: '#666', md: '#333', lg: '#000' })Layout Responsive Modifiers
// Dimensions
.width(value: ResponsiveValue<number | string>)
.width({ base: '100%', md: '50%', lg: '33.333%' })
.height(value: ResponsiveValue<number | string>)
.height({ base: 200, md: 300, lg: 400 })
// Spacing
.padding(value: ResponsiveValue<number | string>)
.padding({ base: 8, md: 12, lg: 16, xl: 20 })
.margin(value: ResponsiveValue<number | string>)
.margin({ base: 4, md: 8, lg: 12 })
// Individual spacing
.paddingTop(value: ResponsiveValue<number | string>)
.paddingRight(value: ResponsiveValue<number | string>)
.paddingBottom(value: ResponsiveValue<number | string>)
.paddingLeft(value: ResponsiveValue<number | string>)
.marginTop(value: ResponsiveValue<number | string>)
.marginRight(value: ResponsiveValue<number | string>)
.marginBottom(value: ResponsiveValue<number | string>)
.marginLeft(value: ResponsiveValue<number | string>)Flexbox Responsive Modifiers
// Display
.display(value: ResponsiveValue<'block' | 'flex' | 'grid' | 'none'>)
.display({ base: 'block', md: 'flex' })
// Flex direction
.flexDirection(value: ResponsiveValue<'row' | 'column' | 'row-reverse' | 'column-reverse'>)
.flexDirection({ base: 'column', md: 'row' })
// Justify content
.justifyContent(value: ResponsiveValue<'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly'>)
.justifyContent({ base: 'center', md: 'space-between' })
// Align items
.alignItems(value: ResponsiveValue<'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline'>)
.alignItems({ base: 'stretch', md: 'center' })
// Gap
.gap(value: ResponsiveValue<number | string>)
.gap({ base: 8, md: 16, lg: 24 })Visual Responsive Modifiers
// Background
.backgroundColor(value: ResponsiveValue<string>)
.backgroundColor({ base: '#f5f5f5', md: '#ffffff' })
// Border
.borderWidth(value: ResponsiveValue<number>)
.borderWidth({ base: 1, md: 2 })
.borderRadius(value: ResponsiveValue<number | string>)
.borderRadius({ base: 4, md: 8, lg: 12 })
.borderColor(value: ResponsiveValue<string>)
.borderColor({ base: '#ddd', md: '#ccc' })
// Shadow
.boxShadow(value: ResponsiveValue<string>)
.boxShadow({
base: 'none',
md: '0 2px 4px rgba(0,0,0,0.1)',
lg: '0 4px 8px rgba(0,0,0,0.15)'
})
// Opacity
.opacity(value: ResponsiveValue<number>)
.opacity({ base: 0.8, md: 1.0 })Responsive Utility Functions
useBreakpoint()
Hook for programmatic breakpoint access.
const useBreakpoint: () => {
current: Signal<BreakpointKey>
isAbove: (breakpoint: BreakpointKey) => Signal<boolean>
isBelow: (breakpoint: BreakpointKey) => Signal<boolean>
isBetween: (min: BreakpointKey, max: BreakpointKey) => Signal<boolean>
}
// Usage
const MyComponent = () => {
const bp = useBreakpoint()
const currentBreakpoint = bp.current() // 'md'
const isMobile = bp.isBelow('md')() // false
const isDesktop = bp.isAbove('lg')() // true
const isTabletRange = bp.isBetween('md', 'lg')() // false
return Text(`Current: ${currentBreakpoint}`)
.modifier
.fontSize(isMobile ? 16 : 20)
.build()
}useMediaQuery()
Hook for custom media query matching.
const useMediaQuery: (query: string) => Signal<boolean>
// Usage
const MyComponent = () => {
const isDarkMode = useMediaQuery('(prefers-color-scheme: dark)')
const isLandscape = useMediaQuery('(orientation: landscape)')
const isHighDPI = useMediaQuery('(min-resolution: 2dppx)')
return Text("Media query example")
.modifier
.color(isDarkMode() ? '#ffffff' : '#000000')
.fontSize(isLandscape() ? 18 : 16)
.build()
}useResponsiveValue()
Hook for reactive responsive value resolution.
const useResponsiveValue: <T>(value: ResponsiveValue<T>) => Signal<T>
// Usage
const MyComponent = () => {
const fontSize = useResponsiveValue({
base: 16,
md: 20,
lg: 24
})
const padding = useResponsiveValue({
base: 8,
md: 12,
lg: 16
})
return Text("Dynamic responsive values")
.modifier
.fontSize(fontSize())
.padding(padding())
.build()
}withResponsive()
Higher-order component for responsive behavior.
const withResponsive: <T>(
component: T,
responsiveProps: ResponsiveStyleConfig
) => T
// Usage
const ResponsiveText = withResponsive(Text("Hello"), {
fontSize: { base: 16, md: 20, lg: 24 },
color: { base: '#666', md: '#333' }
})Configuration Functions
configureBreakpoints()
Configure custom breakpoints globally.
const configureBreakpoints: (breakpoints: Record<string, string>) => void
// Usage
configureBreakpoints({
mobile: '480px',
tablet: '768px',
laptop: '1024px',
desktop: '1440px'
})getCurrentBreakpoint()
Get the current active breakpoint.
const getCurrentBreakpoint: () => Signal<BreakpointKey>
// Usage
const currentBp = getCurrentBreakpoint()
console.log(currentBp()) // 'md'createBreakpointContext()
Create a breakpoint context with current viewport information.
const createBreakpointContext: () => BreakpointContext
// Usage
const context = createBreakpointContext()
console.log(context) // { current: 'md', width: 1024, height: 768 }generateMediaQuery()
Generate media query string for a breakpoint.
const generateMediaQuery: (breakpoint: BreakpointKey) => string
// Usage
const mdQuery = generateMediaQuery('md')
console.log(mdQuery) // '(min-width: 768px)'Advanced Utilities
ResponsiveDevTools
Development tools for debugging responsive layouts.
class ResponsiveDevTools {
static enable(options?: {
showOverlay?: boolean
showBreakpoints?: boolean
showPerformance?: boolean
logLevel?: 'error' | 'warn' | 'info' | 'debug'
highlightResponsiveElements?: boolean
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
}): void
static disable(): void
static get enabled(): boolean
static logResponsiveState(): void
static inspectResponsiveValue<T>(
value: ResponsiveValue<T>,
label?: string
): void
static exportConfiguration(): {
breakpoints: Record<BreakpointKey, string>
currentContext: BreakpointContext
performance: any
mediaQueries: Record<string, boolean>
}
}
// Usage
ResponsiveDevTools.enable({
showOverlay: true,
showBreakpoints: true,
highlightResponsiveElements: true
})useResponsiveInspector()
Hook for inspecting responsive values in development.
const useResponsiveInspector: <T>(
value: ResponsiveValue<T>,
label?: string
) => Signal<{
resolvedValue: T | undefined
activeBreakpoint: BreakpointKey
allValues: Partial<Record<BreakpointKey, T>>
isResponsive: boolean
}>
// Usage
const MyComponent = () => {
const responsiveValue = { base: 16, md: 20, lg: 24 }
const inspector = useResponsiveInspector(responsiveValue, 'Font Size')
const info = inspector()
console.log(info.resolvedValue) // 20 (if at 'md' breakpoint)
console.log(info.activeBreakpoint) // 'md'
console.log(info.isResponsive) // true
return Text("Inspected value").build()
}Error Handling
Common Issues and Solutions
TypeScript Error: Breakpoint not found
// ❌ Error: Type '"unknown"' is not assignable to type 'BreakpointKey'
.responsive({
unknown: { fontSize: 20 } // 'unknown' is not a valid breakpoint
})
// ✅ Solution: Use valid breakpoint keys
.responsive({
md: { fontSize: 20 } // 'md' is valid
})Runtime Error: No responsive value found
// ❌ Error: Empty responsive object
const emptyResponsive = {}
useResponsiveValue(emptyResponsive) // Throws error
// ✅ Solution: Always provide at least one breakpoint value
const validResponsive = { base: 16 }
useResponsiveValue(validResponsive) // Works correctlyPerformance Warning: Too many responsive computations
// ❌ Avoid: Creating responsive computations in render loops
items.map(item => useResponsiveValue({ base: item.size }))
// ✅ Better: Pre-compute responsive values
const responsiveSize = useResponsiveValue({ base: 16, md: 20 })
items.map(item => Text(item.text).modifier.fontSize(responsiveSize()).build())Reactive Responsive Values
TachUI's responsive system fully supports reactive values, automatically updating styles when underlying reactive values change.
Theme-Reactive Responsive Colors
import { Text, ColorAsset, createSignal, createComputed } from '@tachui/core'
// Theme-aware responsive component
const ReactiveThemeComponent = () => {
const primaryColor = ColorAsset.init({
light: '#007AFF',
dark: '#0A84FF',
name: 'primaryColor'
})
const backgroundColor = ColorAsset.init({
light: '#ffffff',
dark: '#1c1c1e',
name: 'backgroundColor'
})
return Text("Theme-Reactive Text")
.modifier
.responsive({
base: {
fontSize: 16,
color: primaryColor, // Automatically reacts to theme changes
backgroundColor: backgroundColor,
padding: 16
},
md: {
fontSize: 20,
padding: 24
},
lg: {
fontSize: 24,
padding: 32
}
})
.build()
}Signal-Based Reactive Responsive Values
const DynamicResponsiveComponent = () => {
const [isActive, setIsActive] = createSignal(false)
const [size, setSize] = createSignal<'small' | 'medium' | 'large'>('medium')
// Computed reactive values
const activePadding = createComputed(() =>
isActive() ? 24 : 16
)
const sizeBasedFontSize = createComputed(() => {
const baseSizes = { small: 14, medium: 16, large: 18 }
return {
base: baseSizes[size()],
md: baseSizes[size()] + 2,
lg: baseSizes[size()] + 4
}
})
const statusColor = createComputed(() =>
isActive() ? '#00ff00' : '#666666'
)
return Text("Dynamic Responsive Text")
.modifier
.responsive({
fontSize: sizeBasedFontSize, // Reactive responsive object
color: statusColor, // Reactive color
padding: activePadding, // Reactive padding
transform: createComputed(() =>
`scale(${isActive() ? 1.05 : 1.0})`
)
})
.onClick(() => setIsActive(!isActive()))
.build()
}Mixed Reactive and Static Configurations
const MixedReactiveComponent = () => {
const [userPreference, setUserPreference] = createSignal<'dense' | 'comfortable'>('comfortable')
const adaptiveSpacing = createComputed(() =>
userPreference() === 'dense' ? 8 : 16
)
const themeColor = ColorAsset.init({
light: '#333333',
dark: '#ffffff',
name: 'textColor'
})
return Text("Mixed Reactive Design")
.modifier
.responsive({
base: {
fontSize: 16, // Static
padding: adaptiveSpacing, // Reactive - user preference
color: themeColor, // Reactive - theme
fontWeight: 'normal' // Static
},
md: {
fontSize: 18, // Static override
padding: createComputed(() => adaptiveSpacing() * 1.5), // Reactive derived
// color and fontWeight inherited (reactive + static)
},
lg: {
fontSize: 20, // Static override
fontWeight: 'bold' // Static override
// padding and color inherited from md breakpoint
}
})
.build()
}Reactive Media Queries
const ReactiveMediaQueryComponent = () => {
const [intensity, setIntensity] = createSignal(0.5)
const dynamicOpacity = createComputed(() =>
0.5 + (intensity() * 0.5) // Opacity between 0.5 and 1.0
)
const dynamicFilter = createComputed(() =>
`brightness(${0.8 + (intensity() * 0.4)})` // Brightness between 0.8 and 1.2
)
return Text("Reactive Media Query Text")
.modifier
.responsive({
base: {
fontSize: 16,
opacity: dynamicOpacity // Reactive opacity
},
md: {
fontSize: 20
}
})
.mediaQuery('(min-width: 1200px)', {
filter: dynamicFilter, // Reactive filter
transition: 'filter 0.3s ease'
})
.mediaQuery('(prefers-color-scheme: dark)', {
backgroundColor: '#1a1a1a' // Static dark mode background
})
.build()
}Performance Optimizations for Reactive Values
// ✅ Optimized patterns for reactive responsive values
const OptimizedReactiveComponent = () => {
// Create stable reactive values outside render
const stableColor = useMemo(() =>
ColorAsset.init({ light: '#007AFF', dark: '#0A84FF' }), []
)
const [state, setState] = createSignal({ size: 'medium', active: false })
// Use computed values for complex derivations
const responsiveConfig = createComputed(() => ({
fontSize: {
base: state().size === 'large' ? 18 : 16,
md: state().size === 'large' ? 22 : 20,
lg: state().size === 'large' ? 26 : 24
},
padding: {
base: state().active ? 20 : 16,
md: state().active ? 28 : 24
},
color: stableColor, // Stable reactive asset
transform: state().active ? 'scale(1.02)' : 'scale(1.0)'
}))
return Text("Optimized Reactive Text")
.modifier
.responsive(responsiveConfig) // Single reactive responsive config
.build()
}
// ❌ Avoid: Creating reactive values in render
const UnoptimizedComponent = () => {
const [active, setActive] = createSignal(false)
return Text("Unoptimized")
.modifier
.responsive({
// Bad: Creates new computed on every render
fontSize: createComputed(() => active() ? 20 : 16),
// Bad: Creates new asset on every render
color: ColorAsset.init({ light: '#000', dark: '#fff' })
})
.build()
}Examples
Complex Responsive Component
const ResponsiveCard = ({ title, content, image }: CardProps) => {
const bp = useBreakpoint()
const isMobile = bp.isBelow('md')()
return VStack([
// Image with responsive sizing
Image(image)
.modifier
.responsive({
base: { width: '100%', height: 200 },
md: { width: 300, height: 200 },
lg: { width: 400, height: 250 }
})
.borderRadius({ base: 8, md: 12 })
.build(),
// Title with responsive typography
Text(title)
.modifier
.responsive({
base: {
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
marginBottom: 8
},
md: {
fontSize: 22,
textAlign: 'left',
marginBottom: 12
},
lg: {
fontSize: 26,
marginBottom: 16
}
})
.build(),
// Content with responsive spacing
Text(content)
.modifier
.responsive({
base: {
fontSize: 14,
lineHeight: 1.4,
textAlign: 'center'
},
md: {
fontSize: 16,
lineHeight: 1.5,
textAlign: 'left'
},
lg: {
fontSize: 18,
lineHeight: 1.6
}
})
.build()
])
.modifier
.responsive({
base: {
padding: 16,
gap: 8,
backgroundColor: '#ffffff',
borderRadius: 8,
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
},
md: {
padding: 24,
gap: 12,
borderRadius: 12,
boxShadow: '0 4px 8px rgba(0,0,0,0.15)'
},
lg: {
padding: 32,
gap: 16,
boxShadow: '0 6px 12px rgba(0,0,0,0.2)'
}
})
.mediaQuery('(prefers-color-scheme: dark)', {
backgroundColor: '#1a1a1a',
color: '#ffffff'
})
.build()
}This comprehensive API reference covers all aspects of TachUI's responsive modifier system. For more examples and patterns, see the Responsive Layout Patterns guide.