feat: design system v2 with liquid glass aesthetic
Overhaul design constants for OLED-first dark mode: - Colors: brand palette, phase colors, glass/shadow tokens, gradients - Typography: Inter font scale matching iOS type system - Spacing: 4px base unit with layout constants - Border radius: liquid glass card radii - Animations: spring/timing presets for UI transitions Add v2 product docs (PRD, PDD, BDSD) and update CLAUDE.md. Install expo-video, expo-sharing, @expo-google-fonts/inter. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
19
src/shared/constants/CLAUDE.md
Normal file
19
src/shared/constants/CLAUDE.md
Normal file
@@ -0,0 +1,19 @@
|
||||
<claude-mem-context>
|
||||
# Recent Activity
|
||||
|
||||
<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->
|
||||
|
||||
### Feb 18, 2026
|
||||
|
||||
| ID | Time | T | Title | Read |
|
||||
|----|------|---|-------|------|
|
||||
| #4831 | 2:57 PM | 🔄 | Spacing Constants Enhanced with Semantic Aliases and Documentation | ~358 |
|
||||
| #4830 | 2:56 PM | 🔵 | Design System Constants Index Review | ~293 |
|
||||
| #4829 | " | 🔵 | Existing Animation Constants Reviewed | ~331 |
|
||||
| #4828 | " | 🔵 | Color System Constants Review for BDSD Planning | ~412 |
|
||||
| #4827 | " | 🔵 | Spacing Constants Implementation Review | ~254 |
|
||||
| #4826 | " | 🔵 | Shadow System Constants Reviewed | ~296 |
|
||||
| #4825 | " | 🔵 | Typography Constants Implementation Verification | ~264 |
|
||||
| #4779 | 1:21 PM | 🔵 | Typography System Constants Analysis | ~354 |
|
||||
| #4778 | 1:20 PM | 🔵 | Design System Color Constants Analysis | ~392 |
|
||||
</claude-mem-context>
|
||||
@@ -1,51 +1,132 @@
|
||||
/**
|
||||
* TabataFit Animation System
|
||||
* Liquid Glass — fluid, organic motion
|
||||
*/
|
||||
|
||||
import { Easing } from 'react-native'
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// DURATIONS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const DURATION = {
|
||||
SNAP: 60,
|
||||
QUICK: 120,
|
||||
FAST: 300,
|
||||
NORMAL: 400,
|
||||
SLOW: 600,
|
||||
XSLOW: 1000,
|
||||
BREATH: 1800,
|
||||
INSTANT: 100,
|
||||
FAST: 200,
|
||||
NORMAL: 300,
|
||||
SLOW: 500,
|
||||
XSLOW: 800,
|
||||
|
||||
// Special
|
||||
BREATH: 2500, // Breathing animation cycle
|
||||
BREATH_HALF: 1250, // Half breath cycle
|
||||
LIQUID: 600, // Liquid morph duration
|
||||
RIPPLE: 400, // Tap ripple
|
||||
PHASE_CHANGE: 300, // Phase transition
|
||||
} as const
|
||||
|
||||
export const EASING = {
|
||||
STANDARD: Easing.inOut(Easing.ease),
|
||||
DECELERATE: Easing.out(Easing.ease),
|
||||
LINEAR: Easing.linear,
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// EASING CURVES
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const EASE = {
|
||||
// Standard iOS easing
|
||||
DEFAULT: Easing.bezier(0.25, 0.1, 0.25, 1),
|
||||
EASE_OUT: Easing.bezier(0, 0, 0.2, 1),
|
||||
EASE_IN: Easing.bezier(0.4, 0, 1, 1),
|
||||
EASE_IN_OUT: Easing.bezier(0.4, 0, 0.2, 1),
|
||||
|
||||
// Liquid / Fluid
|
||||
LIQUID: Easing.bezier(0.4, 0, 0.2, 1),
|
||||
BOUNCE: Easing.bezier(0.68, -0.55, 0.265, 1.55),
|
||||
|
||||
// Sharp / Snappy
|
||||
SNAPPY: Easing.bezier(0.2, 0, 0, 1),
|
||||
} as const
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// SPRING CONFIGS (for react-native Animated.spring)
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const SPRING = {
|
||||
BOUNCY: { tension: 50, friction: 7 },
|
||||
// Bouncy (playful)
|
||||
BOUNCY: {
|
||||
damping: 15,
|
||||
stiffness: 180,
|
||||
mass: 1,
|
||||
},
|
||||
|
||||
// Gentle (smooth)
|
||||
GENTLE: {
|
||||
damping: 20,
|
||||
stiffness: 100,
|
||||
mass: 1,
|
||||
},
|
||||
|
||||
// Snappy (quick)
|
||||
SNAPPY: {
|
||||
damping: 18,
|
||||
stiffness: 300,
|
||||
mass: 1,
|
||||
},
|
||||
|
||||
// Slow (dramatic)
|
||||
SLOW: {
|
||||
damping: 25,
|
||||
stiffness: 80,
|
||||
mass: 1.5,
|
||||
},
|
||||
|
||||
// Liquid (fluid)
|
||||
LIQUID: {
|
||||
damping: 20,
|
||||
stiffness: 200,
|
||||
mass: 1,
|
||||
},
|
||||
} as const
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// PRESET ANIMATION CONFIGS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const ANIMATION = {
|
||||
PULSE_UP: {
|
||||
toValue: 1.08,
|
||||
duration: DURATION.SNAP,
|
||||
useNativeDriver: true,
|
||||
},
|
||||
PULSE_DOWN: {
|
||||
toValue: 1,
|
||||
duration: DURATION.QUICK,
|
||||
easing: EASING.DECELERATE,
|
||||
useNativeDriver: true,
|
||||
},
|
||||
GRADIENT_CROSSFADE: {
|
||||
toValue: 1,
|
||||
duration: DURATION.SLOW,
|
||||
easing: EASING.STANDARD,
|
||||
useNativeDriver: true,
|
||||
},
|
||||
// Fade in
|
||||
FADE_IN: {
|
||||
toValue: 1,
|
||||
duration: DURATION.NORMAL,
|
||||
useNativeDriver: true,
|
||||
easing: EASE.EASE_OUT,
|
||||
},
|
||||
BREATH_HALF: {
|
||||
|
||||
// Scale up (pop in)
|
||||
POP_IN: {
|
||||
spring: SPRING.BOUNCY,
|
||||
},
|
||||
|
||||
// Slide up
|
||||
SLIDE_UP: {
|
||||
duration: DURATION.NORMAL,
|
||||
easing: EASE.EASE_OUT,
|
||||
},
|
||||
|
||||
// Liquid morph
|
||||
LIQUID_MORPH: {
|
||||
duration: DURATION.LIQUID,
|
||||
easing: EASE.LIQUID,
|
||||
},
|
||||
|
||||
// Breathing glow
|
||||
BREATHE: {
|
||||
duration: DURATION.BREATH,
|
||||
easing: EASING.STANDARD,
|
||||
useNativeDriver: false,
|
||||
easing: EASE.EASE_IN_OUT,
|
||||
},
|
||||
|
||||
// Timer tick pulse
|
||||
TIMER_TICK: {
|
||||
duration: 150,
|
||||
easing: EASE.EASE_OUT,
|
||||
},
|
||||
|
||||
// Phase transition
|
||||
PHASE_TRANSITION: {
|
||||
duration: DURATION.PHASE_CHANGE,
|
||||
easing: EASE.EASE_IN_OUT,
|
||||
},
|
||||
} as const
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
/**
|
||||
* TabataFit Border Radius System
|
||||
* Liquid Glass uses generous rounding
|
||||
*/
|
||||
|
||||
export const RADIUS = {
|
||||
NONE: 0,
|
||||
XS: 4,
|
||||
SM: 6,
|
||||
SM: 8,
|
||||
MD: 12,
|
||||
LG: 16,
|
||||
XL: 20,
|
||||
'2XL': 28,
|
||||
'3XL': 32,
|
||||
'4XL': 36,
|
||||
XXL: 24,
|
||||
XXXL: 32,
|
||||
|
||||
// Special
|
||||
FULL: 9999,
|
||||
|
||||
// Liquid glass specific
|
||||
GLASS_CARD: 20,
|
||||
GLASS_MODAL: 28,
|
||||
GLASS_BUTTON: 14,
|
||||
} as const
|
||||
|
||||
@@ -1,76 +1,248 @@
|
||||
export const PHASE_COLORS = {
|
||||
IDLE: '#1E1E2E',
|
||||
GET_READY: '#EAB308',
|
||||
WORK: '#F97316',
|
||||
REST: '#3B82F6',
|
||||
COMPLETE: '#22C55E',
|
||||
} as const
|
||||
/**
|
||||
* TabataFit Color System
|
||||
* Liquid Glass Design (iOS 18.4 inspired)
|
||||
*/
|
||||
|
||||
export const PHASE_GRADIENTS = {
|
||||
IDLE: ['#0A0A14', '#12101F', '#1E1E2E'] as const,
|
||||
GET_READY: ['#451A03', '#92400E', '#D97706'] as const,
|
||||
WORK: ['#450A0A', '#991B1B', '#EA580C'] as const,
|
||||
REST: ['#0C1929', '#1E3A5F', '#2563EB'] as const,
|
||||
COMPLETE: ['#052E16', '#166534', '#16A34A'] as const,
|
||||
} as const
|
||||
|
||||
export const ACCENT = {
|
||||
ORANGE: '#F97316',
|
||||
ORANGE_GLOW: '#FB923C',
|
||||
RED_HOT: '#EF4444',
|
||||
GOLD: '#FBBF24',
|
||||
WHITE: '#FFFFFF',
|
||||
WHITE_DIM: 'rgba(255, 255, 255, 0.6)',
|
||||
WHITE_FAINT: 'rgba(255, 255, 255, 0.15)',
|
||||
} as const
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// BRAND COLORS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const BRAND = {
|
||||
PRIMARY: '#F97316',
|
||||
PRIMARY_LIGHT: '#FB923C',
|
||||
SECONDARY: '#FBBF24',
|
||||
DANGER: '#EF4444',
|
||||
SUCCESS: '#22C55E',
|
||||
INFO: '#3B82F6',
|
||||
PRIMARY: '#FF6B35',
|
||||
PRIMARY_LIGHT: '#FF8C5A',
|
||||
PRIMARY_DARK: '#E55A25',
|
||||
SECONDARY: '#FFD60A',
|
||||
DANGER: '#FF453A',
|
||||
SUCCESS: '#30D158',
|
||||
INFO: '#5AC8FA',
|
||||
} as const
|
||||
|
||||
export const SURFACE = {
|
||||
BASE: '#0A0A14',
|
||||
RAISED: '#12101F',
|
||||
ELEVATED: '#1E1E2E',
|
||||
OVERLAY_LIGHT: 'rgba(255, 255, 255, 0.08)',
|
||||
OVERLAY_MEDIUM: 'rgba(255, 255, 255, 0.15)',
|
||||
OVERLAY_STRONG: 'rgba(255, 255, 255, 0.25)',
|
||||
SCRIM: 'rgba(0, 0, 0, 0.3)',
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// BACKGROUND COLORS (Pure black for OLED)
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const DARK = {
|
||||
BASE: '#000000',
|
||||
SURFACE: '#1C1C1E',
|
||||
ELEVATED: '#2C2C2E',
|
||||
OVERLAY_1: 'rgba(255, 255, 255, 0.05)',
|
||||
OVERLAY_2: 'rgba(255, 255, 255, 0.08)',
|
||||
OVERLAY_3: 'rgba(255, 255, 255, 0.12)',
|
||||
SCRIM: 'rgba(0, 0, 0, 0.6)',
|
||||
} as const
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// TEXT COLORS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const TEXT = {
|
||||
PRIMARY: '#FFFFFF',
|
||||
SECONDARY: 'rgba(255, 255, 255, 0.85)',
|
||||
TERTIARY: 'rgba(255, 255, 255, 0.75)',
|
||||
MUTED: 'rgba(255, 255, 255, 0.6)',
|
||||
HINT: 'rgba(255, 255, 255, 0.45)',
|
||||
DISABLED: 'rgba(255, 255, 255, 0.15)',
|
||||
SECONDARY: '#EBEBF5',
|
||||
TERTIARY: 'rgba(235, 235, 245, 0.6)',
|
||||
MUTED: 'rgba(235, 235, 245, 0.5)',
|
||||
HINT: 'rgba(235, 235, 245, 0.3)',
|
||||
DISABLED: '#3A3A3C',
|
||||
} as const
|
||||
|
||||
export const BORDER = {
|
||||
SUBTLE: 'rgba(255, 255, 255, 0.05)',
|
||||
LIGHT: 'rgba(255, 255, 255, 0.06)',
|
||||
MEDIUM: 'rgba(255, 255, 255, 0.15)',
|
||||
STRONG: 'rgba(255, 255, 255, 0.3)',
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// PHASE COLORS (Timer phases)
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const PHASE = {
|
||||
PREP: '#FF9500',
|
||||
PREP_LIGHT: 'rgba(255, 149, 0, 0.2)',
|
||||
|
||||
WORK: '#FF6B35',
|
||||
WORK_LIGHT: 'rgba(255, 107, 53, 0.2)',
|
||||
WORK_GLOW: 'rgba(255, 107, 53, 0.5)',
|
||||
|
||||
REST: '#5AC8FA',
|
||||
REST_LIGHT: 'rgba(90, 200, 250, 0.2)',
|
||||
REST_GLOW: 'rgba(90, 200, 250, 0.5)',
|
||||
|
||||
COMPLETE: '#30D158',
|
||||
COMPLETE_LIGHT: 'rgba(48, 209, 88, 0.2)',
|
||||
} as const
|
||||
|
||||
export const APP_GRADIENTS = {
|
||||
HOME: ['#0A0A14', '#1A0E2E', '#2D1810'] as const,
|
||||
} as const
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// LIQUID GLASS SYSTEM
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const GLASS = {
|
||||
FILL: 'rgba(255, 255, 255, 0.03)',
|
||||
FILL_MEDIUM: 'rgba(255, 255, 255, 0.06)',
|
||||
FILL_STRONG: 'rgba(255, 255, 255, 0.10)',
|
||||
BORDER: 'rgba(255, 255, 255, 0.08)',
|
||||
BORDER_TOP: 'rgba(255, 255, 255, 0.15)',
|
||||
BLUR_LIGHT: 15,
|
||||
BLUR_MEDIUM: 25,
|
||||
BLUR_HEAVY: 40,
|
||||
BLUR_ATMOSPHERE: 60,
|
||||
// Base glass surface
|
||||
BASE: {
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.05)',
|
||||
borderColor: 'rgba(255, 255, 255, 0.1)',
|
||||
borderWidth: 1,
|
||||
},
|
||||
|
||||
// Elevated glass (cards, modals)
|
||||
ELEVATED: {
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.08)',
|
||||
borderColor: 'rgba(255, 255, 255, 0.15)',
|
||||
borderWidth: 1,
|
||||
},
|
||||
|
||||
// Inset glass (inputs, controls)
|
||||
INSET: {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.25)',
|
||||
borderColor: 'rgba(255, 255, 255, 0.05)',
|
||||
borderWidth: 1,
|
||||
},
|
||||
|
||||
// Brand tinted glass
|
||||
TINTED: {
|
||||
backgroundColor: 'rgba(255, 107, 53, 0.12)',
|
||||
borderColor: 'rgba(255, 107, 53, 0.25)',
|
||||
borderWidth: 1,
|
||||
},
|
||||
|
||||
// Success tinted
|
||||
SUCCESS_TINTED: {
|
||||
backgroundColor: 'rgba(48, 209, 88, 0.12)',
|
||||
borderColor: 'rgba(48, 209, 88, 0.25)',
|
||||
borderWidth: 1,
|
||||
},
|
||||
|
||||
// Blur intensities (for expo-blur)
|
||||
BLUR_LIGHT: 20,
|
||||
BLUR_MEDIUM: 40,
|
||||
BLUR_HEAVY: 60,
|
||||
BLUR_ULTRA: 80,
|
||||
} as const
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// SHADOWS & GLOWS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const SHADOW = {
|
||||
// Glass shadows
|
||||
sm: {
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 4 },
|
||||
shadowOpacity: 0.15,
|
||||
shadowRadius: 12,
|
||||
elevation: 4,
|
||||
},
|
||||
md: {
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 8 },
|
||||
shadowOpacity: 0.25,
|
||||
shadowRadius: 24,
|
||||
elevation: 8,
|
||||
},
|
||||
lg: {
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 12 },
|
||||
shadowOpacity: 0.35,
|
||||
shadowRadius: 40,
|
||||
elevation: 12,
|
||||
},
|
||||
xl: {
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 16 },
|
||||
shadowOpacity: 0.4,
|
||||
shadowRadius: 48,
|
||||
elevation: 16,
|
||||
},
|
||||
|
||||
// Brand glow
|
||||
BRAND_GLOW: {
|
||||
shadowColor: BRAND.PRIMARY,
|
||||
shadowOffset: { width: 0, height: 0 },
|
||||
shadowOpacity: 0.5,
|
||||
shadowRadius: 20,
|
||||
elevation: 10,
|
||||
},
|
||||
BRAND_GLOW_SUBTLE: {
|
||||
shadowColor: BRAND.PRIMARY,
|
||||
shadowOffset: { width: 0, height: 0 },
|
||||
shadowOpacity: 0.3,
|
||||
shadowRadius: 12,
|
||||
elevation: 6,
|
||||
},
|
||||
|
||||
// Liquid glow (breathing effect base)
|
||||
LIQUID_GLOW: {
|
||||
shadowColor: BRAND.PRIMARY,
|
||||
shadowOffset: { width: 0, height: 0 },
|
||||
shadowOpacity: 0.4,
|
||||
shadowRadius: 30,
|
||||
elevation: 15,
|
||||
},
|
||||
} as const
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// BORDER COLORS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const BORDER = {
|
||||
GLASS: 'rgba(255, 255, 255, 0.1)',
|
||||
GLASS_LIGHT: 'rgba(255, 255, 255, 0.05)',
|
||||
GLASS_STRONG: 'rgba(255, 255, 255, 0.2)',
|
||||
BRAND: 'rgba(255, 107, 53, 0.3)',
|
||||
SUCCESS: 'rgba(48, 209, 88, 0.3)',
|
||||
} as const
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// GRADIENTS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const GRADIENTS = {
|
||||
// Video overlays
|
||||
VIDEO_OVERLAY: ['transparent', 'rgba(0, 0, 0, 0.8)'],
|
||||
VIDEO_TOP: ['rgba(0, 0, 0, 0.5)', 'transparent'],
|
||||
|
||||
// Phase gradients
|
||||
WORK: [BRAND.PRIMARY, BRAND.PRIMARY_LIGHT],
|
||||
REST: [PHASE.REST, '#7DD3FC'],
|
||||
PREP: [PHASE.PREP, '#FFB340'],
|
||||
|
||||
// CTA
|
||||
CTA: [BRAND.PRIMARY, BRAND.PRIMARY_LIGHT],
|
||||
|
||||
// Glass shimmers
|
||||
GLASS_SHIMMER: ['rgba(255,255,255,0.1)', 'rgba(255,255,255,0.05)', 'rgba(255,255,255,0.1)'],
|
||||
} as const
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// PHASE COLORS (For timer UI)
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const PHASE_COLORS: Record<string, { fill: string; glow: string }> = {
|
||||
PREP: {
|
||||
fill: PHASE.PREP,
|
||||
glow: 'rgba(255, 149, 0, 0.5)',
|
||||
},
|
||||
WORK: {
|
||||
fill: BRAND.PRIMARY,
|
||||
glow: PHASE.WORK_GLOW,
|
||||
},
|
||||
REST: {
|
||||
fill: PHASE.REST,
|
||||
glow: PHASE.REST_GLOW,
|
||||
},
|
||||
COMPLETE: {
|
||||
fill: PHASE.COMPLETE,
|
||||
glow: 'rgba(48, 209, 88, 0.5)',
|
||||
},
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// BARREL EXPORT
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const COLORS = {
|
||||
...BRAND,
|
||||
...DARK,
|
||||
...TEXT,
|
||||
...PHASE,
|
||||
...SHADOW,
|
||||
BRAND,
|
||||
DARK,
|
||||
TEXT,
|
||||
PHASE,
|
||||
GLASS,
|
||||
BORDER,
|
||||
GRADIENTS,
|
||||
} as const
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
export {
|
||||
PHASE_COLORS,
|
||||
PHASE_GRADIENTS,
|
||||
ACCENT,
|
||||
BRAND,
|
||||
SURFACE,
|
||||
TEXT,
|
||||
BORDER,
|
||||
APP_GRADIENTS,
|
||||
GLASS,
|
||||
} from './colors'
|
||||
export { TYPOGRAPHY } from './typography'
|
||||
export { SPACING, LAYOUT } from './spacing'
|
||||
export { SHADOW, TEXT_SHADOW } from './shadows'
|
||||
export { RADIUS } from './borderRadius'
|
||||
export { DURATION, EASING, SPRING, ANIMATION } from './animations'
|
||||
/**
|
||||
* TabataFit Design System Constants
|
||||
* Liquid Glass Design
|
||||
*/
|
||||
|
||||
export * from './colors'
|
||||
export * from './typography'
|
||||
export * from './spacing'
|
||||
export * from './borderRadius'
|
||||
export * from './animations'
|
||||
|
||||
@@ -1,25 +1,42 @@
|
||||
/**
|
||||
* TabataFit Spacing System
|
||||
* Base: 4px
|
||||
*/
|
||||
|
||||
export const SPACING = {
|
||||
0: 0,
|
||||
0.5: 2,
|
||||
1: 4,
|
||||
1.5: 6,
|
||||
2: 8,
|
||||
2.5: 10,
|
||||
3: 12,
|
||||
3.5: 14,
|
||||
4: 16,
|
||||
5: 20,
|
||||
6: 24,
|
||||
7: 28,
|
||||
8: 32,
|
||||
10: 40,
|
||||
12: 48,
|
||||
14: 56,
|
||||
15: 60,
|
||||
16: 64,
|
||||
20: 80,
|
||||
24: 96,
|
||||
} as const
|
||||
|
||||
export const SPACE = {
|
||||
NONE: 0,
|
||||
XS: 4,
|
||||
SM: 8,
|
||||
MD: 16,
|
||||
LG: 24,
|
||||
XL: 32,
|
||||
XXL: 48,
|
||||
} as const
|
||||
|
||||
export const LAYOUT = {
|
||||
PAGE_HORIZONTAL: 24,
|
||||
SECTION_GAP: 40,
|
||||
INLINE_GAP: 16,
|
||||
CONTROLS_GAP: 32,
|
||||
SCREEN_PADDING: 24,
|
||||
CARD_PADDING: 16,
|
||||
BUTTON_HEIGHT: 56,
|
||||
BUTTON_HEIGHT_SM: 44,
|
||||
TAB_BAR_HEIGHT: 83,
|
||||
HEADER_HEIGHT: 44,
|
||||
TOUCH_TARGET: 44,
|
||||
} as const
|
||||
|
||||
@@ -1,73 +1,262 @@
|
||||
import type { TextStyle } from 'react-native'
|
||||
/**
|
||||
* TabataFit Typography System
|
||||
* Inter font family, Apple-inspired scale
|
||||
*/
|
||||
|
||||
import { TextStyle } from 'react-native'
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// FONT WEIGHTS (using Inter from @expo-google-fonts/inter)
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
const FONT = {
|
||||
REGULAR: 'Inter_400Regular',
|
||||
MEDIUM: 'Inter_500Medium',
|
||||
SEMIBOLD: 'Inter_600SemiBold',
|
||||
BOLD: 'Inter_700Bold',
|
||||
BLACK: 'Inter_900Black',
|
||||
} as const
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// TYPE SCALE
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
export const TYPOGRAPHY = {
|
||||
countdown: {
|
||||
fontSize: 140,
|
||||
fontWeight: '900',
|
||||
fontVariant: ['tabular-nums'],
|
||||
// Display / Hero
|
||||
HERO: {
|
||||
fontFamily: FONT.BLACK,
|
||||
fontSize: 48,
|
||||
lineHeight: 56,
|
||||
letterSpacing: -1,
|
||||
} as TextStyle,
|
||||
|
||||
timeDisplay: {
|
||||
fontSize: 72,
|
||||
fontWeight: '900',
|
||||
fontVariant: ['tabular-nums'],
|
||||
// Large Title (like iOS)
|
||||
LARGE_TITLE: {
|
||||
fontFamily: FONT.BOLD,
|
||||
fontSize: 34,
|
||||
lineHeight: 41,
|
||||
letterSpacing: 0.37,
|
||||
} as TextStyle,
|
||||
|
||||
brandTitle: {
|
||||
fontSize: 56,
|
||||
fontWeight: '900',
|
||||
letterSpacing: 12,
|
||||
// Title 1
|
||||
TITLE_1: {
|
||||
fontFamily: FONT.BOLD,
|
||||
fontSize: 28,
|
||||
lineHeight: 34,
|
||||
letterSpacing: 0.36,
|
||||
} as TextStyle,
|
||||
|
||||
displayLarge: {
|
||||
fontSize: 42,
|
||||
fontWeight: '900',
|
||||
letterSpacing: 4,
|
||||
// Title 2
|
||||
TITLE_2: {
|
||||
fontFamily: FONT.BOLD,
|
||||
fontSize: 22,
|
||||
lineHeight: 28,
|
||||
letterSpacing: 0.35,
|
||||
} as TextStyle,
|
||||
|
||||
displaySmall: {
|
||||
fontSize: 32,
|
||||
fontWeight: '900',
|
||||
letterSpacing: 20,
|
||||
} as TextStyle,
|
||||
|
||||
buttonHero: {
|
||||
fontSize: 30,
|
||||
fontWeight: '900',
|
||||
letterSpacing: 5,
|
||||
} as TextStyle,
|
||||
|
||||
heading: {
|
||||
fontSize: 24,
|
||||
fontWeight: '800',
|
||||
} as TextStyle,
|
||||
|
||||
buttonMedium: {
|
||||
// Title 3
|
||||
TITLE_3: {
|
||||
fontFamily: FONT.SEMIBOLD,
|
||||
fontSize: 20,
|
||||
fontWeight: '700',
|
||||
letterSpacing: 2,
|
||||
lineHeight: 25,
|
||||
letterSpacing: 0.38,
|
||||
} as TextStyle,
|
||||
|
||||
body: {
|
||||
fontSize: 18,
|
||||
fontWeight: '700',
|
||||
// Headline
|
||||
HEADLINE: {
|
||||
fontFamily: FONT.SEMIBOLD,
|
||||
fontSize: 17,
|
||||
lineHeight: 22,
|
||||
letterSpacing: -0.41,
|
||||
} as TextStyle,
|
||||
|
||||
caption: {
|
||||
// Body
|
||||
BODY: {
|
||||
fontFamily: FONT.REGULAR,
|
||||
fontSize: 17,
|
||||
lineHeight: 22,
|
||||
letterSpacing: -0.41,
|
||||
} as TextStyle,
|
||||
|
||||
// Body Bold
|
||||
BODY_BOLD: {
|
||||
fontFamily: FONT.SEMIBOLD,
|
||||
fontSize: 17,
|
||||
lineHeight: 22,
|
||||
letterSpacing: -0.41,
|
||||
} as TextStyle,
|
||||
|
||||
// Callout
|
||||
CALLOUT: {
|
||||
fontFamily: FONT.REGULAR,
|
||||
fontSize: 16,
|
||||
fontWeight: '500',
|
||||
lineHeight: 21,
|
||||
letterSpacing: -0.32,
|
||||
} as TextStyle,
|
||||
|
||||
label: {
|
||||
// Subheadline
|
||||
SUBHEADLINE: {
|
||||
fontFamily: FONT.REGULAR,
|
||||
fontSize: 15,
|
||||
fontWeight: '800',
|
||||
letterSpacing: 1,
|
||||
lineHeight: 20,
|
||||
letterSpacing: -0.24,
|
||||
} as TextStyle,
|
||||
|
||||
overline: {
|
||||
fontSize: 11,
|
||||
fontWeight: '600',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: 1,
|
||||
// Footnote
|
||||
FOOTNOTE: {
|
||||
fontFamily: FONT.REGULAR,
|
||||
fontSize: 13,
|
||||
lineHeight: 18,
|
||||
letterSpacing: -0.08,
|
||||
} as TextStyle,
|
||||
|
||||
// Caption 1
|
||||
CAPTION_1: {
|
||||
fontFamily: FONT.REGULAR,
|
||||
fontSize: 12,
|
||||
lineHeight: 16,
|
||||
letterSpacing: 0,
|
||||
} as TextStyle,
|
||||
|
||||
// Caption 2
|
||||
CAPTION_2: {
|
||||
fontFamily: FONT.REGULAR,
|
||||
fontSize: 11,
|
||||
lineHeight: 13,
|
||||
letterSpacing: 0.07,
|
||||
} as TextStyle,
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// SPECIAL: TIMER TYPOGRAPHY
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// Main countdown number
|
||||
TIMER_NUMBER: {
|
||||
fontFamily: FONT.BLACK,
|
||||
fontSize: 96,
|
||||
lineHeight: 96,
|
||||
letterSpacing: -2,
|
||||
fontVariant: ['tabular-nums'],
|
||||
} as TextStyle,
|
||||
|
||||
// Timer number (compact version)
|
||||
TIMER_NUMBER_COMPACT: {
|
||||
fontFamily: FONT.BLACK,
|
||||
fontSize: 72,
|
||||
lineHeight: 72,
|
||||
letterSpacing: -1.5,
|
||||
fontVariant: ['tabular-nums'],
|
||||
} as TextStyle,
|
||||
|
||||
// Phase label (WORK, REST)
|
||||
TIMER_PHASE: {
|
||||
fontFamily: FONT.BOLD,
|
||||
fontSize: 24,
|
||||
lineHeight: 28,
|
||||
letterSpacing: 2,
|
||||
textTransform: 'uppercase',
|
||||
} as TextStyle,
|
||||
|
||||
// Round indicator
|
||||
TIMER_ROUND: {
|
||||
fontFamily: FONT.MEDIUM,
|
||||
fontSize: 17,
|
||||
lineHeight: 22,
|
||||
letterSpacing: 0,
|
||||
fontVariant: ['tabular-nums'],
|
||||
} as TextStyle,
|
||||
|
||||
// Exercise name during workout
|
||||
EXERCISE_NAME: {
|
||||
fontFamily: FONT.BOLD,
|
||||
fontSize: 28,
|
||||
lineHeight: 34,
|
||||
letterSpacing: 0.36,
|
||||
textAlign: 'center',
|
||||
} as TextStyle,
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// SPECIAL: BUTTON TYPOGRAPHY
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
BUTTON_LARGE: {
|
||||
fontFamily: FONT.SEMIBOLD,
|
||||
fontSize: 18,
|
||||
lineHeight: 22,
|
||||
letterSpacing: 0.5,
|
||||
} as TextStyle,
|
||||
|
||||
BUTTON_MEDIUM: {
|
||||
fontFamily: FONT.SEMIBOLD,
|
||||
fontSize: 16,
|
||||
lineHeight: 20,
|
||||
letterSpacing: 0.3,
|
||||
} as TextStyle,
|
||||
|
||||
BUTTON_SMALL: {
|
||||
fontFamily: FONT.SEMIBOLD,
|
||||
fontSize: 14,
|
||||
lineHeight: 18,
|
||||
letterSpacing: 0.2,
|
||||
} as TextStyle,
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// SPECIAL: CARD TYPOGRAPHY
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
CARD_TITLE: {
|
||||
fontFamily: FONT.SEMIBOLD,
|
||||
fontSize: 17,
|
||||
lineHeight: 22,
|
||||
letterSpacing: -0.41,
|
||||
} as TextStyle,
|
||||
|
||||
CARD_SUBTITLE: {
|
||||
fontFamily: FONT.REGULAR,
|
||||
fontSize: 14,
|
||||
lineHeight: 18,
|
||||
letterSpacing: -0.15,
|
||||
} as TextStyle,
|
||||
|
||||
CARD_METADATA: {
|
||||
fontFamily: FONT.MEDIUM,
|
||||
fontSize: 13,
|
||||
lineHeight: 16,
|
||||
letterSpacing: 0,
|
||||
} as TextStyle,
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// SPECIAL: STATS TYPOGRAPHY
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
STAT_VALUE: {
|
||||
fontFamily: FONT.BLACK,
|
||||
fontSize: 32,
|
||||
lineHeight: 38,
|
||||
letterSpacing: -0.5,
|
||||
fontVariant: ['tabular-nums'],
|
||||
} as TextStyle,
|
||||
|
||||
STAT_LABEL: {
|
||||
fontFamily: FONT.MEDIUM,
|
||||
fontSize: 12,
|
||||
lineHeight: 16,
|
||||
letterSpacing: 0.5,
|
||||
textTransform: 'uppercase',
|
||||
} as TextStyle,
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// SPECIAL: OVERLINE / SECTION HEADER
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
OVERLINE: {
|
||||
fontFamily: FONT.SEMIBOLD,
|
||||
fontSize: 13,
|
||||
lineHeight: 16,
|
||||
letterSpacing: 1.5,
|
||||
textTransform: 'uppercase',
|
||||
} as TextStyle,
|
||||
|
||||
} as const
|
||||
|
||||
export { FONT }
|
||||
|
||||
Reference in New Issue
Block a user