Skip to main content

Multipliers

Multiplier constants that define the base units for spacing and border radius calculations, enabling consistent scaling and responsive design throughout your healthcare application.

Quick Example

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

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

return (
<View
style={{
padding: theme.spacing(4), // 16px (4 * 4)
marginBottom: theme.spacing(3), // 12px (3 * 4)
gap: theme.spacing(2), // 8px (2 * 4)
borderRadius: theme.borderRadius(3), // 12px (3 * 4)
}}
>
<Text>Consistent spacing using multipliers</Text>
</View>
);
};

Default Multipliers

export const DEFAULT_MULTIPLIERS = {
spacing: 4, // Base spacing unit in pixels
borderRadius: 4, // Base border radius unit in pixels
} as const;

Spacing Multiplier

The spacing multiplier defines the base unit for all spacing calculations:

  • Default: 4 pixels
  • Usage: theme.spacing(value) returns value * spacingMultiplier
  • Purpose: Consistent padding, margins, gaps, and layout spacing

Border Radius Multiplier

The border radius multiplier defines the base unit for border radius calculations:

  • Default: 4 pixels
  • Usage: theme.borderRadius(value) returns value * borderRadiusMultiplier
  • Purpose: Consistent corner rounding across UI elements

Spacing System

Common Spacing Values

With the default 4px multiplier:

theme.spacing(0.5); // 2px  - Minimal spacing
theme.spacing(1); // 4px - Tight spacing
theme.spacing(2); // 8px - Small gaps
theme.spacing(3); // 12px - Medium spacing
theme.spacing(4); // 16px - Standard padding
theme.spacing(5); // 20px - Large spacing
theme.spacing(6); // 24px - Section spacing
theme.spacing(8); // 32px - Component separation
theme.spacing(12); // 48px - Page margins
theme.spacing(16); // 64px - Large sections

Spacing Usage Patterns

Component Internal Spacing

export const HealthCard = ({ children }) => {
const theme = useAppTheme();

return (
<View
style={{
padding: theme.spacing(4), // 16px internal padding
gap: theme.spacing(3), // 12px between elements
}}
>
{children}
</View>
);
};

Layout and Margins

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

return (
<ScrollView
contentContainerStyle={{
padding: theme.spacing(4), // 16px screen padding
paddingBottom: theme.spacing(8), // 32px bottom padding
}}
>
<View style={{ gap: theme.spacing(6) }}>
{" "}
{/* 24px between sections */}
<HealthCard />
<HealthCard />
<HealthCard />
</View>
</ScrollView>
);
};

Form Elements

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

return (
<View
style={{
padding: theme.spacing(4), // 16px form padding
gap: theme.spacing(4), // 16px between form fields
}}
>
<TextInput
style={{
paddingHorizontal: theme.spacing(3), // 12px input padding
paddingVertical: theme.spacing(2), // 8px input padding
}}
/>
<Button
style={{
marginTop: theme.spacing(6), // 24px button spacing
}}
/>
</View>
);
};

Border Radius System

Common Border Radius Values

With the default 4px multiplier:

theme.borderRadius(0); // 0px  - No rounding (sharp corners)
theme.borderRadius(1); // 4px - Subtle rounding
theme.borderRadius(2); // 8px - Standard rounding
theme.borderRadius(3); // 12px - Medium rounding
theme.borderRadius(4); // 16px - Prominent rounding
theme.borderRadius(6); // 24px - Large rounding
theme.borderRadius(8); // 32px - Very large rounding
theme.borderRadius(12); // 48px - Extreme rounding

Border Radius Usage Patterns

UI Element Hierarchy

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

return (
<View>
{/* Subtle elements */}
<View
style={{
borderRadius: theme.borderRadius(1), // 4px - Input fields, small buttons
backgroundColor: theme.colors.surface,
}}
/>

{/* Standard elements */}
<View
style={{
borderRadius: theme.borderRadius(2), // 8px - Cards, standard buttons
backgroundColor: theme.colors.surface,
}}
/>

{/* Prominent elements */}
<View
style={{
borderRadius: theme.borderRadius(3), // 12px - Feature cards, modals
backgroundColor: theme.colors.surface,
}}
/>

{/* Large elements */}
<View
style={{
borderRadius: theme.borderRadius(4), // 16px - Hero sections, large cards
backgroundColor: theme.colors.surface,
}}
/>
</View>
);
};

Healthcare Component Styling

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

return (
<View
style={{
backgroundColor: theme.colors.surface,
borderRadius: theme.borderRadius(3), // 12px - Card rounding
padding: theme.spacing(4), // 16px - Card padding
marginBottom: theme.spacing(3), // 12px - Card spacing
shadowRadius: theme.borderRadius(2), // 8px - Shadow rounding
}}
>
<View
style={{
backgroundColor: theme.colors.primary,
borderRadius: theme.borderRadius(2), // 8px - Badge rounding
padding: theme.spacing(2), // 8px - Badge padding
alignSelf: "flex-start",
}}
>
<Text style={{ color: "white" }}>{status}</Text>
</View>

<Text style={{ fontSize: 24, marginTop: theme.spacing(2) }}>{value}</Text>
</View>
);
};

Responsive Multipliers

Device-Specific Scaling

import { useWindowDimensions } from "react-native";

export const useResponsiveMultipliers = () => {
const { width } = useWindowDimensions();

// Determine device type
const isTablet = width > 768;
const isLargeTablet = width > 1024;

return React.useMemo(() => {
if (isLargeTablet) {
return {
spacing: 6, // 6px base unit for large tablets
borderRadius: 8, // 8px base unit for large tablets
};
} else if (isTablet) {
return {
spacing: 5, // 5px base unit for tablets
borderRadius: 6, // 6px base unit for tablets
};
} else {
return {
spacing: 4, // 4px base unit for mobile
borderRadius: 4, // 4px base unit for mobile
};
}
}, [isLargeTablet, isTablet]);
};

Accessibility Scaling

import { PixelRatio } from "react-native";

export const useAccessibilityMultipliers = () => {
const fontScale = PixelRatio.getFontScale();

return React.useMemo(() => {
// Scale multipliers based on user's font size preferences
const scaleFactor = Math.min(fontScale, 1.3); // Cap at 130%

return {
spacing: Math.round(4 * scaleFactor),
borderRadius: 4, // Keep border radius constant for visual consistency
};
}, [fontScale]);
};

Dynamic Theme Configuration

export const ResponsiveThemeProvider = ({ children }) => {
const { width } = useWindowDimensions();
const isTablet = width > 768;

const themeConfig = React.useMemo(
() => ({
colors: DEFAULT_COLORS,
dark: false,
spacingMultiplier: isTablet ? 6 : 4, // Larger spacing on tablets
borderRadiusMultiplier: isTablet ? 8 : 4, // More pronounced rounding on tablets
}),
[isTablet],
);

return <ThemeProvider theme={themeConfig}>{children}</ThemeProvider>;
};

Custom Multiplier Configurations

Compact Design

const compactMultipliers = {
spacing: 3, // Tighter spacing for dense layouts
borderRadius: 2, // Less rounding for compact design
};

Spacious Design

const spaciousMultipliers = {
spacing: 6, // Generous spacing for comfortable layouts
borderRadius: 8, // More pronounced rounding
};

Medical Device Interface

const medicalDeviceMultipliers = {
spacing: 8, // Large touch targets for medical environments
borderRadius: 12, // High visibility rounding
};

Healthcare-Specific Configurations

const healthcareConfigurations = {
// Emergency room - high visibility
emergency: {
spacing: 8,
borderRadius: 6,
},

// Patient room - comfortable
patient: {
spacing: 6,
borderRadius: 8,
},

// Mobile clinic - compact
mobile: {
spacing: 3,
borderRadius: 2,
},

// Elderly care - accessibility-focused
elderly: {
spacing: 10,
borderRadius: 4,
},
};

Best Practices

Consistent Spacing Hierarchy

// ✅ Good - Use consistent spacing hierarchy
<View
style={{
padding: theme.spacing(4), // Container padding
gap: theme.spacing(3), // Element spacing
marginBottom: theme.spacing(6), // Section spacing
}}
>
<Text style={{ marginBottom: theme.spacing(2) }}> {/* Text spacing */}
Title
</Text>
<Text style={{ marginBottom: theme.spacing(1) }}> {/* Tight spacing */}
Subtitle
</Text>
</View>

// ❌ Avoid - Arbitrary spacing values
<View
style={{
padding: 13, // Arbitrary value
gap: 7, // Arbitrary value
marginBottom: 23, // Arbitrary value
}}
>

Semantic Spacing

// Define semantic spacing constants
const SPACING = {
tight: 1, // theme.spacing(1) = 4px
small: 2, // theme.spacing(2) = 8px
medium: 3, // theme.spacing(3) = 12px
standard: 4, // theme.spacing(4) = 16px
large: 6, // theme.spacing(6) = 24px
section: 8, // theme.spacing(8) = 32px
} as const;

// Usage with semantic meaning
<View
style={{
padding: theme.spacing(SPACING.standard), // Standard padding
gap: theme.spacing(SPACING.medium), // Medium element gaps
marginBottom: theme.spacing(SPACING.section), // Section separation
}}
>

Component-Specific Constants

// Define component-specific spacing
const CARD_SPACING = {
padding: 4, // Internal card padding
gap: 3, // Between card elements
margin: 3, // Between cards
} as const;

const FORM_SPACING = {
padding: 4, // Form padding
fieldGap: 4, // Between form fields
buttonMargin: 6, // Above form buttons
} as const;

Performance Considerations

Memoization

// ✅ Good - Memoize multiplier-dependent calculations
const useComponentStyles = () => {
const theme = useAppTheme();

return React.useMemo(
() => ({
container: {
padding: theme.spacing(4),
borderRadius: theme.borderRadius(2),
},
content: {
gap: theme.spacing(3),
marginBottom: theme.spacing(6),
},
}),
[theme.spacing, theme.borderRadius],
);
};

Static References

// ✅ Good - Use multiplier constants for configuration
const COMPONENT_CONFIG = {
containerPadding: 4, // Will be multiplied by theme.spacing
contentGap: 3, // Will be multiplied by theme.spacing
borderRadius: 2, // Will be multiplied by theme.borderRadius
} as const;

// Usage in component
const styles = {
container: {
padding: theme.spacing(COMPONENT_CONFIG.containerPadding),
borderRadius: theme.borderRadius(COMPONENT_CONFIG.borderRadius),
},
};
  • ThemeProvider - Configures multipliers via theme props
  • useAppTheme - Provides access to spacing and borderRadius functions