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:
46
src/theme/colors.ts
Normal file
46
src/theme/colors.ts
Normal 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
55
src/theme/glass.ts
Normal 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
5
src/theme/index.ts
Normal 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
17
src/theme/spacing.ts
Normal 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
76
src/theme/typography.ts
Normal 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;
|
||||
Reference in New Issue
Block a user