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