Color System
Vetra UI's color system uses intuitive, semantic naming that makes it easy to understand and use. Unlike Material Design's technical color roles, Vetra colors are named for their purpose, not their position in a hierarchy.
Philosophy
- Semantic Over Technical: Colors are named for what they do, not abstract roles
- Accessibility First: All color combinations meet WCAG 2.1 AA standards
- Mode-Aware: Automatic adjustment between light and dark modes
- Beautiful by Default: Carefully chosen colors that work well together
Color Roles
The color system is organized into semantic roles that describe how colors are used in real-world scenarios. Each color has a specific purpose and appears in predictable contexts throughout your application.
| Name | Preview | Use Case |
|---|---|---|
| Brand Colors | ||
brand |
Login page primary button, active navigation tab, "Save" action in forms | |
onBrand |
White text on primary buttons, icons on brand-colored backgrounds | |
brandSubtle |
Notification badge background, selected item highlight, info banner | |
onBrandSubtle |
Text and icons on subtle brand backgrounds, badge labels | |
| Accent Colors | ||
accent |
Secondary action buttons, "Learn More" links, special feature highlights | |
onAccent |
White text on secondary buttons, icons on accent-colored surfaces | |
accentSubtle |
Chip backgrounds, tag highlights, subtle feature indicators | |
onAccentSubtle |
Text on chips and tags, labels on accent backgrounds | |
| Canvas Colors | ||
canvas |
Main app background, screen root container, list view background | |
onCanvas |
Primary headings on main background, main body text | |
canvasElevated |
Card backgrounds, dialog surfaces, bottom sheets, floating panels | |
onCanvasElevated |
Text content on cards, dialog titles and body text | |
canvasSubtle |
List item backgrounds, grouped content areas, input field backgrounds | |
onCanvasSubtle |
Text on list items, content in grouped sections | |
| Text Colors | ||
textPrimary |
Page titles, article headings, important labels, primary content | |
textSecondary |
Subtitles, descriptions, metadata, supporting information | |
textTertiary |
Placeholder text, hints, captions, less important labels | |
textDisabled |
Disabled button labels, inactive menu items, unavailable content | |
| Border Colors | ||
border |
Input field borders, card outlines, divider lines, section separators | |
borderSubtle |
Subtle dividers between list items, soft section boundaries | |
borderFocus |
Focus rings on inputs, keyboard navigation indicators, active field outline | |
| Semantic Colors | ||
success |
Success notification backgrounds, checkmark icons, completion indicators | |
onSuccess |
Text on success messages, icons on green backgrounds | |
warning |
Warning alert backgrounds, caution badges, attention indicators | |
onWarning |
Text on warning messages, icons on orange backgrounds | |
danger |
Delete button backgrounds, error alert boxes, critical action indicators | |
onDanger |
"Delete" button text, error message text, icons on red backgrounds | |
info |
Information banners, help tooltips, informational badges | |
onInfo |
Text on info messages, icons on cyan backgrounds | |
Usage Examples
Basic Usage
@Composable
fun MyComponent() {
Column(
modifier = Modifier
.fillMaxSize()
.background(VetraTheme.colors.canvas)
.padding(16.dp)
) {
Text(
text = "Welcome",
style = VetraTheme.typography.displayMd,
color = VetraTheme.colors.textPrimary
)
Text(
text = "Get started with Vetra UI",
style = VetraTheme.typography.bodyLg,
color = VetraTheme.colors.textSecondary
)
}
}
Custom Colors
Override default colors when creating your theme:
val CustomLightColors = VetraLightColorScheme.copy(
brand = Color(0xFF1E40AF), // Custom blue
accent = Color(0xFF9333EA), // Custom purple
success = Color(0xFF059669), // Custom green
)
@Composable
fun App() {
VetraTheme(colors = CustomLightColors) {
// Your app content
}
}
Dynamic Theme Colors
@Composable
fun DynamicThemedApp() {
val brandColor = remember { mutableStateOf(Color(0xFF2563EB)) }
VetraTheme(
colors = VetraLightColorScheme.copy(
brand = brandColor.value
)
) {
// Color picker
ColorPicker(
color = brandColor.value,
onColorChange = { brandColor.value = it }
)
// Your app adapts automatically
VetraButton(onClick = { }) {
Text("Dynamic Color")
}
}
}
Color Naming Comparison
Vetra vs Material
| Vetra | Material Design |
|---|---|
brand |
primary |
onBrand |
onPrimary |
brandSubtle |
primaryContainer |
accent |
secondary |
canvas |
background |
canvasElevated |
surface |
textPrimary |
onSurface |
textSecondary |
onSurfaceVariant |
border |
outline |
danger |
error |
Accessibility
All color combinations in Vetra UI meet WCAG 2.1 AA standards:
- Normal text: Minimum 4.5:1 contrast ratio
- Large text (18sp+ or 14sp+ bold): Minimum 3:1 contrast ratio
- UI components: Minimum 3:1 contrast ratio
Testing Contrast
// Built-in colors are already accessible
Text(
text = "This text is accessible",
color = VetraTheme.colors.textPrimary, // ✓ 4.5:1+ contrast
modifier = Modifier.background(VetraTheme.colors.canvas)
)
// When using custom colors, verify contrast
Text(
text = "Check contrast for custom colors",
color = customColor, // ⚠️ Test this
modifier = Modifier.background(customBackground)
)
Best Practices
✅ Do
- Use semantic color names consistently
- Test your UI in both light and dark modes
- Maintain color hierarchies (primary → secondary → tertiary)
- Use
brandSubtleandaccentSubtlefor backgrounds - Leverage semantic colors for states
❌ Don't
- Use hardcoded hex colors
- Mix Vetra and Material color APIs
- Ignore disabled states
- Use
brandfor large background areas - Skip contrast testing for custom colors
Migration from Material
// Before (Material)
MaterialTheme.colorScheme.primary
MaterialTheme.colorScheme.onSecondaryContainer
MaterialTheme.colorScheme.surfaceVariant
// After (Vetra)
VetraTheme.colors.brand
VetraTheme.colors.onAccentSubtle
VetraTheme.colors.canvasSubtle
Next: Learn about Typography →