This repository has been archived on 2026-08-11. You can view files and clone it, but cannot push or open issues or pull requests.
Gishen-Mob/lib/theme.ts
kirukib 7310a349c5 Add Gishen mobile app with complete demo shopping and care flows.
Ship Expo Router screens, seeded stores, and polished UX so auth, shop, checkout, prescriptions, loyalty, family, and account processes work end-to-end offline.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-07 01:21:32 +03:00

169 lines
4.2 KiB
TypeScript

import { Platform } from "react-native";
/**
* Gishen design tokens.
*
* Brand lime is used as a *fill* with ink text (high contrast, distinctive).
* `brandText` is the accessible green reserved for green-on-white text.
*/
const palette = {
lime50: "#F6FAEC",
lime100: "#ECF4D8",
lime200: "#D9E9B2",
lime300: "#C3DB86",
lime400: "#A8C73A",
lime500: "#93B22E",
lime600: "#748E22",
lime700: "#55681B",
ink900: "#101410",
ink700: "#2C332B",
ink500: "#5B6157",
ink300: "#8A9188",
ink100: "#C3C8BE",
paper: "#F7F8F5",
white: "#FFFFFF",
hairline: "#E9ECE2",
wash: "#F1F3EC",
red500: "#D64545",
red50: "#FDF0F0",
amber500: "#E0870F",
amber50: "#FDF5E7",
blue500: "#2F6FED",
blue50: "#EEF3FE",
} as const;
export const colors = {
brand: palette.lime400,
brandDeep: palette.lime500,
brandText: palette.lime600,
brandSoft: palette.lime100,
brandWash: palette.lime50,
brandBorder: palette.lime200,
ink: palette.ink900,
inkDeep: palette.ink900,
inkSecondary: palette.ink500,
muted: palette.ink500,
subtle: palette.ink300,
disabled: palette.ink100,
page: palette.paper,
surface: palette.white,
surfaceAlt: palette.wash,
line: palette.hairline,
danger: palette.red500,
dangerSoft: palette.red50,
warn: palette.amber500,
warnSoft: palette.amber50,
accent: palette.amber500,
info: palette.blue500,
infoSoft: palette.blue50,
inStock: palette.lime600,
outOfStock: palette.red500,
star: "#F5A524",
} as const;
export const space = {
xs: 4,
sm: 8,
md: 12,
lg: 16,
xl: 20,
"2xl": 24,
"3xl": 32,
"4xl": 40,
} as const;
export const radii = {
xs: 8,
sm: 12,
md: 16,
lg: 20,
xl: 24,
card: 20,
pill: 999,
} as const;
/** Screen gutter used by every page so content lines up across the app. */
export const gutter = 20;
export const fonts = {
regular: "Jakarta_400Regular",
medium: "Jakarta_500Medium",
semibold: "Jakarta_600SemiBold",
bold: "Jakarta_700Bold",
extrabold: "Jakarta_800ExtraBold",
} as const;
export type TypeVariant =
| "display"
| "h1"
| "h2"
| "h3"
| "body"
| "bodyMedium"
| "bodySm"
| "label"
| "caption"
| "micro"
| "price"
| "priceLg";
export const typography: Record<
TypeVariant,
{ fontFamily: string; fontSize: number; lineHeight: number; letterSpacing?: number }
> = {
display: { fontFamily: fonts.extrabold, fontSize: 30, lineHeight: 36, letterSpacing: -0.6 },
h1: { fontFamily: fonts.extrabold, fontSize: 24, lineHeight: 30, letterSpacing: -0.4 },
h2: { fontFamily: fonts.bold, fontSize: 18, lineHeight: 24, letterSpacing: -0.2 },
h3: { fontFamily: fonts.semibold, fontSize: 15, lineHeight: 20, letterSpacing: -0.1 },
body: { fontFamily: fonts.regular, fontSize: 14, lineHeight: 21 },
bodyMedium: { fontFamily: fonts.medium, fontSize: 14, lineHeight: 20 },
bodySm: { fontFamily: fonts.regular, fontSize: 13, lineHeight: 19 },
label: { fontFamily: fonts.semibold, fontSize: 13, lineHeight: 17 },
caption: { fontFamily: fonts.medium, fontSize: 12, lineHeight: 16 },
micro: { fontFamily: fonts.semibold, fontSize: 11, lineHeight: 14, letterSpacing: 0.2 },
price: { fontFamily: fonts.bold, fontSize: 16, lineHeight: 21, letterSpacing: -0.2 },
priceLg: { fontFamily: fonts.extrabold, fontSize: 24, lineHeight: 29, letterSpacing: -0.5 },
};
type Shadow = {
shadowColor: string;
shadowOpacity: number;
shadowRadius: number;
shadowOffset: { width: number; height: number };
elevation: number;
};
const shadow = (opacity: number, radius: number, y: number, elevation: number): Shadow => ({
shadowColor: "#16240A",
shadowOpacity: Platform.OS === "android" ? opacity * 1.4 : opacity,
shadowRadius: radius,
shadowOffset: { width: 0, height: y },
elevation,
});
export const shadows = {
/** Resting cards. Nearly invisible, just lifts off the page. */
xs: shadow(0.04, 6, 2, 1),
sm: shadow(0.05, 10, 4, 2),
/** Sheets, floating tab bar, sticky bars. */
md: shadow(0.08, 18, 8, 8),
lg: shadow(0.12, 28, 14, 16),
} as const;
/** Card recipe reused across screens so every surface matches. */
export const card = {
backgroundColor: colors.surface,
borderRadius: radii.card,
borderWidth: 1,
borderColor: colors.line,
} as const;
export const hitSlop = { top: 10, bottom: 10, left: 10, right: 10 } as const;