Flux Design System Patterns
Version 1.0
Overview
A design system is the foundation of consistent, scalable UI development. Flux provides first-class support for design systems through Design Tokens, Component Libraries, and Theme Management. This guide covers best practices for building and maintaining design systems in Flux.
Design Tokens
Design tokens are the atomic values of your design system—colors, typography, spacing, shadows, and more. In Flux, tokens are defined once and referenced throughout your components.
Defining Design Tokens
Create a design-tokens.flux file:
designTokens {
colors: {
// Brand Colors
primary: "#6366F1"
primaryHover: "#4F46E5"
primaryActive: "#4338CA"
accent: "#EC4899"
accentHover: "#DB2777"
// Semantic Colors
success: "#10B981"
warning: "#F59E0B"
error: "#EF4444"
info: "#3B82F6"
// Neutrals
background: "#FFFFFF"
surface: "#F9FAFB"
border: "#E5E7EB"
textPrimary: "#111827"
textSecondary: "#6B7280"
textMuted: "#9CA3AF"
}
typography: {
// Font Families
fontSans: "'Inter', -apple-system, sans-serif"
fontMono: "'Fira Code', monospace"
// Font Sizes
textXs: 12
textSm: 14
textBase: 16
textLg: 18
textXl: 20
text2Xl: 24
text3Xl: 30
text4Xl: 36
// Font Weights
fontLight: 300
fontNormal: 400
fontMedium: 500
fontSemibold: 600
fontBold: 700
// Line Heights
lineHeightTight: 1.25
lineHeightNormal: 1.5
lineHeightRelaxed: 1.75
}
spacing: {
xs: 4
sm: 8
md: 16
lg: 24
xl: 32
xxl: 48
xxxl: 64
}
borderRadius: {
none: 0
sm: 4
md: 8
lg: 12
full: 9999
}
shadows: {
sm: "0 1px 2px 0 rgba(0, 0, 0, 0.05)"
md: "0 4px 6px -1px rgba(0, 0, 0, 0.1)"
lg: "0 10px 15px -3px rgba(0, 0, 0, 0.1)"
xl: "0 20px 25px -5px rgba(0, 0, 0, 0.1)"
}
transitions: {
fast: "150ms"
normal: "300ms"
slow: "500ms"
}
}
Using Design Tokens
Reference tokens in your components with the $token syntax:
component Button {
props: {
label: String
variant: "primary" | "secondary" = "primary"
}
styles: {
// Reference color tokens
backgroundColor: variant == "primary" ? $colors.primary : $colors.surface
color: variant == "primary" ? "white" : $colors.textPrimary
// Reference typography tokens
fontSize: $typography.textBase
fontWeight: $typography.fontSemibold
fontFamily: $typography.fontSans
// Reference spacing tokens
padding: [$spacing.sm, $spacing.md] // [vertical, horizontal]
// Reference border radius tokens
borderRadius: $borderRadius.md
// Reference shadow tokens
boxShadow: $shadows.sm
// Reference transition tokens
transition: $transitions.normal
}
layout: HStack {
children: [
Text { text: props.label }
]
}
}
Component Variants
Design systems thrive on consistency with flexibility. Flux supports component variants to handle different visual treatments.
Size Variants
component Button {
props: {
label: String
size: "sm" | "md" | "lg" = "md"
}
styles: {
fontSize: {
sm: $typography.textSm,
md: $typography.textBase,
lg: $typography.textLg
}[props.size]
padding: {
sm: [$spacing.xs, $spacing.sm],
md: [$spacing.sm, $spacing.md],
lg: [$spacing.md, $spacing.lg]
}[props.size]
borderRadius: {
sm: $borderRadius.sm,
md: $borderRadius.md,
lg: $borderRadius.lg
}[props.size]
}
}
Visual Variants
component Alert {
props: {
message: String
variant: "success" | "warning" | "error" | "info"
}
styles: {
backgroundColor: {
success: lighten($colors.success, 0.9),
warning: lighten($colors.warning, 0.9),
error: lighten($colors.error, 0.9),
info: lighten($colors.info, 0.9)
}[props.variant]
borderLeft: {
width: 4,
color: {
success: $colors.success,
warning: $colors.warning,
error: $colors.error,
info: $colors.info
}[props.variant]
}
color: {
success: darken($colors.success, 0.3),
warning: darken($colors.warning, 0.3),
error: darken($colors.error, 0.3),
info: darken($colors.info, 0.3)
}[props.variant]
padding: $spacing.md
borderRadius: $borderRadius.md
}
layout: HStack {
spacing: $spacing.sm
children: [
Icon {
name: {
success: "check-circle",
warning: "exclamation-triangle",
error: "x-circle",
info: "information-circle"
}[props.variant]
},
Text { text: props.message }
]
}
}
Theming
Flux supports light/dark themes and custom themes through token overrides.
Theme Definition
// themes/light.flux
theme Light {
colors: {
background: "#FFFFFF"
surface: "#F9FAFB"
border: "#E5E7EB"
textPrimary: "#111827"
textSecondary: "#6B7280"
textMuted: "#9CA3AF"
}
}
// themes/dark.flux
theme Dark {
colors: {
background: "#0F172A"
surface: "#1E293B"
border: "#334155"
textPrimary: "#F1F5F9"
textSecondary: "#CBD5E1"
textMuted: "#94A3B8"
}
}
Theme-Aware Components
Components automatically adapt to the active theme:
component Card {
styles: {
// These token references automatically switch with the theme
backgroundColor: $colors.surface
borderColor: $colors.border
borderWidth: 1
borderRadius: $borderRadius.lg
padding: $spacing.lg
boxShadow: $shadows.md
}
layout: VStack {
spacing: $spacing.md
children: props.children
}
}
Custom Themes
// themes/brand.flux
theme BrandTheme extends Light {
colors: {
primary: "#FF6B6B"
accent: "#4ECDC4"
background: "#FFF8F0"
}
typography: {
fontSans: "'Montserrat', sans-serif"
}
borderRadius: {
md: 16 // More rounded than default
lg: 24
}
}
Component Libraries
Organize your design system into reusable component libraries.
Library Structure
design-system/
├── tokens/
│ ├── colors.flux
│ ├── typography.flux
│ ├── spacing.flux
│ └── shadows.flux
├── themes/
│ ├── light.flux
│ ├── dark.flux
│ └── brand.flux
├── primitives/
│ ├── Button.flux
│ ├── Input.flux
│ ├── Text.flux
│ └── Icon.flux
├── components/
│ ├── Card.flux
│ ├── Modal.flux
│ ├── Alert.flux
│ └── Dropdown.flux
└── patterns/
├── Form.flux
├── Table.flux
└── Navigation.flux
Exporting a Library
// index.flux
library MyDesignSystem {
version: "1.0.0"
// Export tokens
export tokens from "./tokens"
export themes from "./themes"
// Export components
export { Button, Input, Text, Icon } from "./primitives"
export { Card, Modal, Alert, Dropdown } from "./components"
export { Form, Table, Navigation } from "./patterns"
}
Consuming a Library
// In your app
import { Button, Card, Alert } from "@mycompany/design-system"
component Dashboard {
layout: VStack {
children: [
Card {
children: [
Alert {
variant: "info"
message: "Welcome to the dashboard!"
}
]
},
Button {
label: "Get Started"
size: "lg"
}
]
}
}
Composition Patterns
The Container Pattern
component Container {
props: {
maxWidth: "sm" | "md" | "lg" | "xl" | "full" = "lg"
}
styles: {
maxWidth: {
sm: 640,
md: 768,
lg: 1024,
xl: 1280,
full: "100%"
}[props.maxWidth]
marginHorizontal: "auto"
paddingHorizontal: $spacing.md
}
layout: VStack {
children: props.children
}
}
The Stack Pattern
component Stack {
props: {
direction: "vertical" | "horizontal" = "vertical"
spacing: Integer = $spacing.md
alignment: "start" | "center" | "end" = "start"
}
layout: props.direction == "vertical" ? VStack : HStack {
spacing: props.spacing
alignment: props.alignment
children: props.children
}
}
The Grid Pattern
component Grid {
props: {
columns: Integer = 12
gap: Integer = $spacing.md
}
layout: Grid {
columns: props.columns
gap: props.gap
children: props.children
}
}
component GridItem {
props: {
span: Integer = 1
start?: Integer
}
styles: {
gridColumn: props.start
? `${props.start} / span ${props.span}`
: `span ${props.span}`
}
layout: VStack {
children: props.children
}
}
Responsive Design
Breakpoints
Define responsive breakpoints in your design tokens:
designTokens {
breakpoints: {
sm: 640
md: 768
lg: 1024
xl: 1280
xxl: 1536
}
}
Responsive Styles
component Hero {
styles: {
padding: {
base: $spacing.md,
md: $spacing.lg,
lg: $spacing.xl,
xl: $spacing.xxl
}
fontSize: {
base: $typography.text2Xl,
md: $typography.text3Xl,
lg: $typography.text4Xl
}
}
layout: VStack {
children: [
Text {
text: "Welcome"
style: "responsive"
}
]
}
}
Responsive Layouts
component ResponsiveGrid {
layout: Grid {
columns: {
base: 1, // 1 column on mobile
sm: 2, // 2 columns on small screens
md: 3, // 3 columns on medium screens
lg: 4 // 4 columns on large screens
}
gap: $spacing.md
children: props.items
}
}
Accessibility
Focus States
component Button {
styles: {
// Default styles
backgroundColor: $colors.primary
color: "white"
// Hover state
'&:hover': {
backgroundColor: $colors.primaryHover
}
// Focus state
'&:focus': {
outline: `2px solid ${$colors.primary}`
outlineOffset: 2
}
// Active state
'&:active': {
backgroundColor: $colors.primaryActive
}
// Disabled state
'&:disabled': {
backgroundColor: $colors.border
color: $colors.textMuted
cursor: "not-allowed"
}
}
// ARIA attributes
accessibility: {
role: "button"
ariaLabel: props.label
ariaDisabled: props.disabled
}
}
Color Contrast
Ensure WCAG compliance:
designTokens {
colors: {
// All text/background combinations meet WCAG AA
primary: "#6366F1" // Contrast ratio: 4.5:1 with white
textPrimary: "#111827" // Contrast ratio: 16:1 with white
textSecondary: "#6B7280" // Contrast ratio: 4.6:1 with white
}
}
// Validate at compile time
@validateContrast(minRatio: 4.5)
component Alert {
styles: {
backgroundColor: $colors.surface
color: $colors.textPrimary
}
}
Semantic HTML
component Heading {
props: {
text: String
level: 1 | 2 | 3 | 4 | 5 | 6 = 1
}
// Generates <h1>, <h2>, etc. based on level
element: `h${props.level}`
styles: {
fontSize: {
1: $typography.text4Xl,
2: $typography.text3Xl,
3: $typography.text2Xl,
4: $typography.textXl,
5: $typography.textLg,
6: $typography.textBase
}[props.level]
fontWeight: $typography.fontBold
}
}
Documentation
Component Documentation
Use JSDoc-style comments to document your components:
/**
* Primary button component for user actions.
*
* @example
* Button {
* label: "Click me"
* variant: "primary"
* size: "md"
* onClick: handleClick
* }
*/
component Button {
props: {
/** The text displayed on the button */
label: String
/** Visual style variant */
variant: "primary" | "secondary" = "primary"
/** Size of the button */
size: "sm" | "md" | "lg" = "md"
/** Click handler function */
onClick: Handler
}
}
Generating Documentation
# Generate documentation site
flux docs generate --output ./docs
# Generate Storybook stories
flux storybook generate --output ./stories
# Generate Figma design tokens
flux figma export --output ./figma-tokens.json
Versioning and Evolution
Semantic Versioning
library MyDesignSystem {
version: "2.1.0" // Major.Minor.Patch
// Breaking changes increment major version
// New features increment minor version
// Bug fixes increment patch version
}
Deprecation Warnings
/**
* @deprecated Use `Button` with `variant="text"` instead
*/
component TextButton {
// ... implementation
}
Migration Path
// v1.x
component OldButton {
props: {
type: "primary" | "secondary"
}
}
// v2.x - backward compatible alias
component OldButton = Button {
variant: props.type // Map old prop to new prop
}
// v3.x - remove deprecated component
// OldButton removed, users must migrate to Button
Best Practices
- Start with Tokens - Define your design tokens before building components
- Compose Components - Build complex components from simple primitives
- Think in Systems - Design for reusability and consistency
- Document Everything - Good documentation is essential for adoption
- Version Carefully - Use semantic versioning and provide migration guides
- Test Across Platforms - Ensure components work on all target frameworks
- Measure Adoption - Track which components are used and improve based on data
- Iterate Often - Design systems evolve—embrace continuous improvement