Skip to main content

Colors

Comprehensive color system that provides Material Design 3 integration, healthcare-specific semantic colors, and extended color palettes for building consistent and accessible healthcare applications.

Quick Example

import React from "react";
import { useAppTheme, DEFAULT_COLORS } from "@ovok/mobile";
import { View, Text } from "react-native";

export const ColorShowcase = () => {
const theme = useAppTheme();

return (
<View style={{ padding: theme.spacing(4) }}>
{/* Primary brand colors */}
<View style={{ backgroundColor: theme.colors.primary, padding: 16 }}>
<Text style={{ color: theme.colors.onPrimary }}>Primary Color</Text>
</View>

{/* Healthcare semantic colors */}
<View style={{ backgroundColor: theme.colors.success, padding: 16 }}>
<Text style={{ color: "white" }}>Healthy Status</Text>
</View>

<View style={{ backgroundColor: theme.colors.error, padding: 16 }}>
<Text style={{ color: "white" }}>Critical Alert</Text>
</View>

{/* Extended palette colors */}
<View style={{ backgroundColor: theme.colors.blue[600], padding: 16 }}>
<Text style={{ color: "white" }}>Medical Blue</Text>
</View>
</View>
);
};

Color System Overview

The color system consists of three main categories:

1. Material Design 3 Colors

Standard MD3 color tokens for consistent design:

  • primary, secondary, tertiary - Brand colors
  • surface, background - Surface colors
  • onPrimary, onSurface, onBackground - Text colors
  • outline, outlineVariant - Border colors

2. Healthcare Semantic Colors

Specialized colors for healthcare applications:

  • success - Healthy states, positive results
  • error - Critical conditions, alerts
  • warning - Attention needed, caution

3. Extended Color Palettes

Complete color families with 11 shades each:

  • gray, blue, green, red, orange, yellow, purple, pink, cyan

Default Color Configuration

export const DEFAULT_COLORS = {
// Brand colors
primary: "#0044D7", // Primary blue
secondary: "#B5CCFF", // Light blue
tertiary: "#504DE6", // Purple

// Healthcare semantic colors
success: "#15B05D", // Green for healthy/positive
error: "#ED3D31", // Red for critical/dangerous
warning: "#FBEE37", // Yellow for caution/attention

// Extended color palettes (see details below)
gray: {
/* 11 shades */
},
blue: {
/* 11 shades */
},
green: {
/* 11 shades */
},
red: {
/* 11 shades */
},
orange: {
/* 11 shades */
},
yellow: {
/* 11 shades */
},
purple: {
/* 11 shades */
},
pink: {
/* 11 shades */
},
cyan: {
/* 11 shades */
},
};

Extended Color Palettes

Each color family includes 11 carefully calibrated shades:

Shade Scale

  • 25 - Lightest tint (backgrounds, subtle highlights)
  • 50 - Very light (light backgrounds)
  • 100 - Light (subtle accents)
  • 200 - Light medium (borders, dividers)
  • 300 - Medium light (disabled states)
  • 400 - Medium (secondary elements)
  • 500 - Base color (standard usage)
  • 600 - Medium dark (primary actions)
  • 700 - Dark (emphasis, headers)
  • 800 - Very dark (strong emphasis)
  • 900 - Darkest (high contrast)
  • 1000 - Ultra dark (maximum contrast)
  • 1100 - Extreme dark (special cases)

Blue Palette

Medical and technology-focused blue shades:

blue: {
25: "#F1F6FF", // Lightest medical backgrounds
50: "#E7EFFF", // Light medical surfaces
100: "#DAE6FF", // Subtle medical accents
200: "#B5CCFF", // Secondary brand color
300: "#8FB3FF", // Light interactive elements
400: "#6A99FF", // Medium interactive elements
500: "#4580FF", // Standard medical blue
600: "#256AFF", // Primary actions
700: "#0044D7", // Primary brand color
800: "#002981", // Dark medical emphasis
900: "#001B56", // Very dark medical
1000: "#0E1A33", // Ultra dark medical
}

Green Palette

Health, success, and positive indicator colors:

green: {
25: "#FAFFFD", // Lightest healthy backgrounds
50: "#F1FEF7", // Light healthy surfaces
100: "#D1F8E3", // Subtle success accents
200: "#A3F1C7", // Light success indicators
300: "#76EAAC", // Medium success elements
400: "#48E390", // Active success states
500: "#1BDC75", // Standard success color
600: "#14C466", // Success actions
700: "#15B05D", // Success semantic color
800: "#108446", // Dark success emphasis
900: "#0A582E", // Very dark success
1000: "#052B17", // Ultra dark success
}

Red Palette

Error, critical, and danger indicator colors:

red: {
25: "#FFF6F5", // Lightest error backgrounds
50: "#FFECEB", // Light error surfaces
100: "#FEC7C3", // Subtle error accents
200: "#FDA19B", // Light error indicators
300: "#F86C62", // Medium error elements
400: "#ED3D31", // Active error states
500: "#ED3D31", // Standard error color
600: "#D32E22", // Error actions
700: "#AF261D", // Error semantic color
800: "#86241D", // Dark error emphasis
900: "#641B16", // Very dark error
1000: "#460F0B", // Ultra dark error
}

Orange Palette

Warning, caution, and attention colors:

orange: {
25: "#FFFDFA", // Lightest warning backgrounds
50: "#FFFBF5", // Light warning surfaces
100: "#FFF5EB", // Subtle warning accents
200: "#FEE2C3", // Light warning indicators
300: "#FDC687", // Medium warning elements
400: "#FBA94B", // Active warning states
500: "#FA9C0F", // Standard warning color
600: "#E18B09", // Warning actions
700: "#C06C0C", // Warning semantic color
800: "#904D14", // Dark warning emphasis
900: "#63300D", // Very dark warning
1000: "#4E2103", // Ultra dark warning
}

Gray Palette

Neutral colors for text, backgrounds, and UI elements:

gray: {
25: "#FCFCFD", // Lightest neutral backgrounds
50: "#F9FAFB", // Light neutral surfaces
100: "#F2F4F7", // Subtle neutral accents
200: "#E4E7EC", // Light neutral borders
300: "#D0D5DD", // Medium neutral dividers
400: "#98A2B3", // Disabled text/elements
500: "#667085", // Secondary text
600: "#475467", // Primary text
700: "#344054", // Dark headings
800: "#1D2939", // Very dark text
900: "#101828", // Darkest text
1000: "#080F1C", // Ultra dark text
1100: "#03070F", // Extreme dark text
}

Usage Patterns

Healthcare Status Indicators

import React from "react";
import { useAppTheme } from "@ovok/mobile";

export const VitalSignCard = ({ value, status, label }) => {
const theme = useAppTheme();

const getStatusColor = (status: string) => {
switch (status) {
case "excellent":
return theme.colors.green[600]; // Strong positive
case "normal":
return theme.colors.success; // Standard success
case "borderline":
return theme.colors.orange[600]; // Warning
case "concerning":
return theme.colors.red[600]; // Error actions
case "critical":
return theme.colors.error; // Critical error
default:
return theme.colors.gray[600]; // Neutral
}
};

const getBackgroundColor = (status: string) => {
switch (status) {
case "excellent":
return theme.colors.green[50]; // Light success background
case "normal":
return theme.colors.green[25]; // Lightest success background
case "borderline":
return theme.colors.orange[50]; // Light warning background
case "concerning":
return theme.colors.red[50]; // Light error background
case "critical":
return theme.colors.red[100]; // Subtle error background
default:
return theme.colors.gray[50]; // Neutral background
}
};

return (
<View
style={{
backgroundColor: getBackgroundColor(status),
borderColor: getStatusColor(status),
borderWidth: 1,
borderRadius: theme.borderRadius(2),
padding: theme.spacing(3),
}}
>
<Text
style={{
color: getStatusColor(status),
fontSize: 24,
fontWeight: "bold",
}}
>
{value}
</Text>
<Text
style={{
color: theme.colors.gray[600],
fontSize: 14,
}}
>
{label}
</Text>
</View>
);
};

Progressive Color Scales

import React from "react";
import { useAppTheme } from "@ovok/mobile";

export const ProgressIndicator = ({ percentage }) => {
const theme = useAppTheme();

// Progressive color based on percentage
const getProgressColor = (percentage: number) => {
if (percentage >= 90) return theme.colors.green[600]; // Excellent
if (percentage >= 75) return theme.colors.green[500]; // Good
if (percentage >= 50) return theme.colors.orange[500]; // Warning
if (percentage >= 25) return theme.colors.red[500]; // Poor
return theme.colors.red[600]; // Critical
};

const getBackgroundColor = (percentage: number) => {
if (percentage >= 75) return theme.colors.green[50]; // Success background
if (percentage >= 50) return theme.colors.orange[50]; // Warning background
return theme.colors.red[50]; // Error background
};

return (
<View
style={{
backgroundColor: getBackgroundColor(percentage),
borderRadius: theme.borderRadius(1),
padding: theme.spacing(1),
}}
>
<View
style={{
backgroundColor: getProgressColor(percentage),
width: `${percentage}%`,
height: 8,
borderRadius: theme.borderRadius(1),
}}
/>
</View>
);
};

Color Palette Display

import React from "react";
import { useAppTheme } from "@ovok/mobile";

export const ColorPaletteGrid = ({ colorFamily }) => {
const theme = useAppTheme();
const shades = [25, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000];

return (
<View style={{ padding: theme.spacing(3) }}>
<Text
style={{
color: theme.colors.gray[800],
fontSize: 18,
fontWeight: "bold",
marginBottom: theme.spacing(2),
}}
>
{colorFamily.charAt(0).toUpperCase() + colorFamily.slice(1)} Palette
</Text>

<View style={{ flexDirection: "row", flexWrap: "wrap" }}>
{shades.map((shade) => (
<View
key={shade}
style={{
width: 60,
height: 60,
backgroundColor: theme.colors[colorFamily][shade],
margin: theme.spacing(1),
borderRadius: theme.borderRadius(1),
justifyContent: "center",
alignItems: "center",
}}
>
<Text
style={{
color: shade > 500 ? "white" : "black",
fontSize: 10,
fontWeight: "bold",
}}
>
{shade}
</Text>
</View>
))}
</View>
</View>
);
};

Customization

Override Specific Colors

import { DEFAULT_COLORS } from "@ovok/mobile";

const customColors = {
...DEFAULT_COLORS,

// Override brand colors
primary: "#1E40AF", // Custom blue
secondary: "#7C3AED", // Custom purple

// Override semantic colors
success: "#059669", // Darker green
error: "#DC2626", // Darker red
warning: "#D97706", // Darker orange

// Override specific palette shades
blue: {
...DEFAULT_COLORS.blue,
600: "#1E40AF", // Match primary
700: "#1E3A8A", // Darker primary
},
};

Healthcare-Specific Color Extensions

const healthcareColors = {
...DEFAULT_COLORS,

// Medical specialization colors
cardiology: "#E11D48", // Heart/cardiovascular
neurology: "#7C3AED", // Brain/nervous system
oncology: "#DC2626", // Cancer/oncology
pediatrics: "#059669", // Children/pediatrics
geriatrics: "#D97706", // Elderly/geriatrics

// Vital sign status colors
normal: "#10B981", // Normal range
borderline: "#F59E0B", // Borderline values
abnormal: "#EF4444", // Abnormal values
critical: "#DC2626", // Critical values

// Medication colors
active: "#3B82F6", // Active medications
discontinued: "#6B7280", // Discontinued
pending: "#F59E0B", // Pending approval
};

Accessibility

Contrast Requirements

All colors meet WCAG accessibility guidelines:

  • Text on backgrounds: Minimum 4.5:1 contrast ratio
  • Large text: Minimum 3:1 contrast ratio
  • UI elements: Minimum 3:1 contrast ratio

Color Blind Considerations

The color system includes considerations for color blindness:

  • Semantic meaning: Never rely solely on color to convey information
  • Pattern/texture: Use icons, patterns, or text alongside colors
  • High contrast: Darker shades provide better distinction

Safe Color Combinations

// ✅ Good contrast combinations
backgroundColor: theme.colors.blue[50], // Light background
textColor: theme.colors.blue[800], // Dark text

backgroundColor: theme.colors.success, // Success background
textColor: "white", // White text

backgroundColor: theme.colors.gray[100], // Light gray background
textColor: theme.colors.gray[800], // Dark gray text

// ❌ Poor contrast combinations
backgroundColor: theme.colors.blue[400], // Medium background
textColor: theme.colors.blue[500], // Similar medium text

Performance

Color Object Reuse

// ✅ Good - Reuse color configurations
const MEDICAL_COLORS = {
cardiology: "#E11D48",
neurology: "#7C3AED",
oncology: "#DC2626",
};

// ❌ Avoid - Creating new objects repeatedly
const getSpecialtyColor = (specialty) =>
({
cardiology: "#E11D48", // New object each time
neurology: "#7C3AED",
oncology: "#DC2626",
})[specialty];

Memoization for Dynamic Colors

const useDynamicColors = (status: string) => {
return React.useMemo(() => {
const theme = useAppTheme();

return {
background: getBackgroundColor(status, theme),
text: getTextColor(status, theme),
border: getBorderColor(status, theme),
};
}, [status]);
};