feat: add glassmorphism design system

Dark-first color palette, glass surface styles with blur
backing, typography with text shadows, and spacing constants.
This commit is contained in:
Mathis Pruvot
2026-05-28 11:48:54 +00:00
parent 961d29ebe8
commit 1cccfbcb11
5 changed files with 199 additions and 0 deletions

46
src/theme/colors.ts Normal file
View File

@@ -0,0 +1,46 @@
export const colors = {
// Base palette — dark-first, tinted with deep blue
background: "#06060C",
surface: "#0E0E18",
surfaceElevated: "#16162A",
// Glass materials
glass: {
background: "rgba(255, 255, 255, 0.06)",
backgroundHover: "rgba(255, 255, 255, 0.10)",
backgroundActive: "rgba(255, 255, 255, 0.14)",
border: "rgba(255, 255, 255, 0.10)",
borderLight: "rgba(255, 255, 255, 0.18)",
highlight: "rgba(255, 255, 255, 0.04)",
},
// Text
text: {
primary: "#F2F0ED",
secondary: "rgba(242, 240, 237, 0.60)",
tertiary: "rgba(242, 240, 237, 0.35)",
inverse: "#06060C",
},
// Accents — derived from user images at runtime, these are defaults
accent: {
primary: "rgba(180, 160, 255, 0.80)",
secondary: "rgba(120, 200, 255, 0.60)",
warm: "rgba(255, 180, 140, 0.70)",
},
// Semantic
success: "rgba(120, 220, 160, 0.80)",
error: "rgba(255, 120, 120, 0.80)",
warning: "rgba(255, 200, 100, 0.80)",
// Shadows
shadow: {
soft: "rgba(0, 0, 0, 0.25)",
medium: "rgba(0, 0, 0, 0.40)",
strong: "rgba(0, 0, 0, 0.60)",
},
// Gradient mesh colors for empty states
meshGradient: ["#1a0533", "#0a1628", "#061a1a", "#0f0a1e"],
} as const;

55
src/theme/glass.ts Normal file
View File

@@ -0,0 +1,55 @@
import { Platform, ViewStyle } from "react-native";
import { colors } from "./colors";
export const glassIntensity = {
subtle: 15,
medium: 25,
strong: 40,
heavy: 60,
} as const;
export type GlassVariant = "subtle" | "medium" | "strong" | "heavy";
export const glassSurface = (
variant: GlassVariant = "medium"
): ViewStyle => ({
backgroundColor: colors.glass.background,
borderWidth: 1,
borderColor: colors.glass.border,
overflow: "hidden",
...Platform.select({
ios: {
shadowColor: colors.shadow.soft,
shadowOffset: { width: 0, height: 8 },
shadowOpacity: variant === "strong" ? 0.3 : 0.15,
shadowRadius: 24,
},
android: {
elevation: variant === "strong" ? 12 : 6,
},
}),
});
export const glassRadius = {
xs: 8,
sm: 12,
md: 16,
lg: 24,
xl: 32,
pill: 999,
} as const;
export const glassBorder = {
thin: {
borderWidth: 0.5,
borderColor: colors.glass.border,
},
normal: {
borderWidth: 1,
borderColor: colors.glass.border,
},
accent: {
borderWidth: 1,
borderColor: colors.glass.borderLight,
},
} as const;

5
src/theme/index.ts Normal file
View File

@@ -0,0 +1,5 @@
export { colors } from "./colors";
export { glassSurface, glassIntensity, glassRadius, glassBorder } from "./glass";
export type { GlassVariant } from "./glass";
export { typography } from "./typography";
export { spacing, layout } from "./spacing";

17
src/theme/spacing.ts Normal file
View File

@@ -0,0 +1,17 @@
export const spacing = {
xs: 4,
sm: 8,
md: 16,
lg: 24,
xl: 32,
xxl: 48,
} as const;
export const layout = {
screenPadding: 20,
cardPadding: 16,
bottomSheetPeek: 180,
bottomSheetHalf: 360,
tabBarHeight: 72,
headerHeight: 56,
} as const;

76
src/theme/typography.ts Normal file
View File

@@ -0,0 +1,76 @@
import { TextStyle, Platform } from "react-native";
import { colors } from "./colors";
const fontFamily = Platform.select({
ios: "System",
android: "sans-serif",
default: "System",
});
const baseShadow: TextStyle = {
textShadowColor: "rgba(0, 0, 0, 0.5)",
textShadowOffset: { width: 0, height: 1 },
textShadowRadius: 4,
};
export const typography = {
title: {
fontSize: 28,
fontWeight: "700",
color: colors.text.primary,
fontFamily,
letterSpacing: -0.5,
...baseShadow,
} as TextStyle,
heading: {
fontSize: 20,
fontWeight: "600",
color: colors.text.primary,
fontFamily,
letterSpacing: -0.3,
...baseShadow,
} as TextStyle,
body: {
fontSize: 16,
fontWeight: "400",
color: colors.text.primary,
fontFamily,
lineHeight: 22,
} as TextStyle,
bodySecondary: {
fontSize: 14,
fontWeight: "400",
color: colors.text.secondary,
fontFamily,
lineHeight: 20,
} as TextStyle,
caption: {
fontSize: 12,
fontWeight: "500",
color: colors.text.tertiary,
fontFamily,
letterSpacing: 0.2,
} as TextStyle,
label: {
fontSize: 13,
fontWeight: "600",
color: colors.text.secondary,
fontFamily,
letterSpacing: 0.5,
textTransform: "uppercase",
} as TextStyle,
button: {
fontSize: 16,
fontWeight: "600",
color: colors.text.primary,
fontFamily,
letterSpacing: 0.3,
...baseShadow,
} as TextStyle,
} as const;