@bettoredge/styles
v0.4.2
Published
Modern theming and styled components for BettorEdge applications
Maintainers
Readme
@bettoredge/styles
Modern theming and styled components for BettorEdge applications with full dark/light mode support.
Installation
npm install @bettoredge/styles
# or
yarn add @bettoredge/stylesQuick Start
1. Wrap your app with ThemeProvider
import { ThemeProvider } from '@bettoredge/styles';
export default function App() {
return (
<ThemeProvider>
<YourApp />
</ThemeProvider>
);
}2. Use themed components
import { View, Text, Button, useTheme } from '@bettoredge/styles';
function MyScreen() {
const { isDark, setMode } = useTheme();
return (
<View variant="card" padding="lg" gap="md">
<Text variant="h1">Hello World</Text>
<Text variant="body" color="secondary">
Welcome to BettorEdge design system
</Text>
<Button
variant="primary"
onPress={() => setMode(isDark ? 'light' : 'dark')}
>
Toggle Theme
</Button>
</View>
);
}Features
- Semantic Color System: Colors adapt automatically to light/dark mode
- Modern Design: Softer colors, better contrast, accessible
- Type Safe: Full TypeScript support
- Cross-Platform: Works with Expo, React Native, and react-native-web
- Zero Config: Works out of the box with sensible defaults
- Flexible: Easy to customize and extend
Components
Text
Typography component with semantic variants and colors.
// Variants
<Text variant="h1">Heading 1</Text>
<Text variant="h2">Heading 2</Text>
<Text variant="h3">Heading 3</Text>
<Text variant="bodyLarge">Large body text</Text>
<Text variant="body">Body text</Text>
<Text variant="caption">Caption text</Text>
<Text variant="label">Label Text</Text>
// Colors
<Text color="primary">Primary text</Text>
<Text color="secondary">Secondary text</Text>
<Text color="tertiary">Tertiary text</Text>
<Text color="link">Link text</Text>
<Text color="success">Success text</Text>
<Text color="error">Error text</Text>
<Text color="warning">Warning text</Text>
// Weights
<Text bold>Bold text</Text>
<Text semibold>Semibold text</Text>
<Text medium>Medium text</Text>
// Alignment
<Text center>Centered text</Text>View
Container component with surface variants and automatic theming.
// Variants
<View variant="base">Base surface</View>
<View variant="elevated">Elevated surface</View>
<View variant="card">Card (with shadow)</View>
<View variant="header">Header surface</View>
<View variant="footer">Footer surface</View>
// Spacing
<View padding="md">Padded view</View>
<View paddingHorizontal="lg" paddingVertical="sm">Custom padding</View>
<View gap="md">View with gap between children</View>
// Border
<View rounded="lg">Rounded corners</View>
<View bordered>With border</View>
// Shadow
<View shadow="sm">Small shadow</View>
<View shadow="md">Medium shadow</View>
<View shadow="lg">Large shadow</View>Button
Interactive button with multiple variants and states.
// Variants
<Button variant="primary" onPress={handlePress}>Primary</Button>
<Button variant="secondary" onPress={handlePress}>Secondary</Button>
<Button variant="outline" onPress={handlePress}>Outline</Button>
<Button variant="ghost" onPress={handlePress}>Ghost</Button>
<Button variant="success" onPress={handlePress}>Success</Button>
<Button variant="error" onPress={handlePress}>Error</Button>
<Button variant="warning" onPress={handlePress}>Warning</Button>
// Sizes
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
// States
<Button disabled>Disabled</Button>
<Button loading>Loading</Button>
// Full width
<Button fullWidth>Full Width Button</Button>TextInput
Themed text input with labels, errors, and helper text.
// Basic
<TextInput
placeholder="Enter text"
value={value}
onChangeText={setValue}
/>
// With label
<TextInput
label="Email"
placeholder="[email protected]"
value={email}
onChangeText={setEmail}
/>
// With error
<TextInput
label="Password"
error="Password is required"
value={password}
onChangeText={setPassword}
/>
// With helper text
<TextInput
label="Username"
helperText="Choose a unique username"
value={username}
onChangeText={setUsername}
/>
// Sizes
<TextInput size="sm" />
<TextInput size="md" />
<TextInput size="lg" />
// Disabled
<TextInput disabled value="Cannot edit" />
// Full width
<TextInput fullWidth />Theme Access
useTheme Hook
import { useTheme } from '@bettoredge/styles';
function MyComponent() {
const { theme, mode, isDark, setMode } = useTheme();
// Access colors
const primaryColor = theme.colors.primary.default;
const backgroundColor = theme.colors.surface.base;
// Access spacing
const padding = theme.spacing.md; // 16
// Access typography
const fontSize = theme.typography.fontSize.lg; // 16
const fontWeight = theme.typography.fontWeight.semibold; // '600'
// Toggle theme
const toggleTheme = () => setMode(isDark ? 'light' : 'dark');
return (
<View style={{ backgroundColor, padding }}>
<Text style={{ color: primaryColor, fontSize, fontWeight }}>
Current mode: {mode}
</Text>
</View>
);
}Color System
Brand Colors (Fixed)
Your brand identity colors that remain consistent across themes:
brand.cobalt-#003566brand.midnight-#002A51brand.electric-#005FB7brand.cyan-#08A4BDbrand.slate-#6E8894brand.mint-#B2F2D6brand.yellow-#FFD60A
Semantic Colors (Theme-Adaptive)
Colors that automatically adapt to light/dark mode:
Primary
primary.default- Main action colorprimary.hover- Hover stateprimary.active- Active/pressed stateprimary.disabled- Disabled state
Surface
surface.base- Main backgroundsurface.elevated- Cards, modalssurface.header- Top navigationsurface.footer- Bottom navigationsurface.input- Input backgrounds
Text
text.primary- Main headingstext.secondary- Body texttext.tertiary- Supporting texttext.link- Linkstext.disabled- Disabled text
Status
status.success- Success statestatus.error- Error statestatus.warning- Warning statestatus.info- Info state
Spacing Scale
Consistent spacing throughout your app:
xs: 4pxsm: 8pxmd: 16pxlg: 24pxxl: 32pxxxl: 48px
Typography Scale
Font sizes:
xs: 10pxsm: 12pxmd: 14pxlg: 16pxxl: 20pxxxl: 24pxxxxl: 32px
Font weights:
regular: 400medium: 500semibold: 600bold: 700
Advanced Usage
Custom Theme Mode
// Force a specific theme
<ThemeProvider initialMode="dark">
<App />
</ThemeProvider>
// Or use 'auto' for system theme (default)
<ThemeProvider initialMode="auto">
<App />
</ThemeProvider>Accessing Raw Colors
import { colors } from '@bettoredge/styles';
// Access brand colors
const electricBlue = colors.brand.electric;
// Access neutral palette
const gray500 = colors.neutral.gray500;
// Access status colors
const successGreen = colors.status.success;Backward Compatibility
The package includes a useColors() hook for backward compatibility with your old color system:
import { useColors } from '@bettoredge/styles';
function OldComponent() {
const colors = useColors();
// Old API still works
const backgroundColor = colors.views.background;
const textColor = colors.text.h1;
}Examples
Login Form
import { View, Text, TextInput, Button } from '@bettoredge/styles';
function LoginForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
return (
<View variant="card" padding="lg" gap="md">
<Text variant="h2">Sign In</Text>
<Text variant="body" color="tertiary">
Enter your credentials to continue
</Text>
<View gap="md" style={{ marginTop: 16 }}>
<TextInput
label="Email"
placeholder="[email protected]"
value={email}
onChangeText={setEmail}
fullWidth
/>
<TextInput
label="Password"
placeholder="••••••••"
value={password}
onChangeText={setPassword}
secureTextEntry
fullWidth
/>
</View>
<Button variant="primary" fullWidth onPress={handleLogin}>
Sign In
</Button>
<Button variant="ghost" fullWidth onPress={handleForgotPassword}>
Forgot Password?
</Button>
</View>
);
}Settings Screen with Theme Toggle
import { View, Text, Button, useTheme } from '@bettoredge/styles';
function SettingsScreen() {
const { theme, isDark, setMode } = useTheme();
return (
<View variant="base" padding="lg" gap="lg">
<Text variant="h1">Settings</Text>
<View variant="card" padding="lg" gap="sm">
<Text variant="h3">Appearance</Text>
<Text variant="body" color="tertiary">
Choose your preferred theme
</Text>
<View gap="sm" style={{ marginTop: 8 }}>
<Button
variant={!isDark ? 'primary' : 'outline'}
onPress={() => setMode('light')}
fullWidth
>
☀️ Light Mode
</Button>
<Button
variant={isDark ? 'primary' : 'outline'}
onPress={() => setMode('dark')}
fullWidth
>
🌙 Dark Mode
</Button>
</View>
</View>
</View>
);
}License
Private - BettorEdge
Support
For issues, questions, or contributions, contact the BettorEdge development team.
