From 627971e505587d7b1c68640e6375245111cb748f Mon Sep 17 00:00:00 2001 From: Coral Zhu Date: Sun, 6 Sep 2026 20:39:15 +0000 Subject: [PATCH] Refactor avatar theme color generation --- packages/ui/src/theme/v2/avatar.test.ts | 32 +++++++++ packages/ui/src/theme/v2/avatar.ts | 94 ++++++++++++++----------- 2 files changed, 85 insertions(+), 41 deletions(-) create mode 100644 packages/ui/src/theme/v2/avatar.test.ts diff --git a/packages/ui/src/theme/v2/avatar.test.ts b/packages/ui/src/theme/v2/avatar.test.ts new file mode 100644 index 00000000..aa544ae1 --- /dev/null +++ b/packages/ui/src/theme/v2/avatar.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, test } from "bun:test" +import { V2_AVATAR_DARK, V2_AVATAR_FG, V2_AVATAR_LIGHT } from "./avatar" + +describe("V2 avatar theme colors", () => { + test("creates matching light and dark theme structures", () => { + expect(Object.keys(V2_AVATAR_LIGHT)).toHaveLength(19) + expect(Object.keys(V2_AVATAR_DARK)).toHaveLength(19) + expect(Object.keys(V2_AVATAR_LIGHT)).toEqual(Object.keys(V2_AVATAR_DARK)) + expect(V2_AVATAR_LIGHT["v2-avatar-fg"]).toBe(V2_AVATAR_FG) + expect(V2_AVATAR_DARK["v2-avatar-fg"]).toBe(V2_AVATAR_FG) + }) + + test.each([ + ["orange", "#ee7330ff", "#d16427ff", "#723d22ff", "#ff8648ff"], + ["yellow", "#e7af36ff", "#cb9f34ff", "#68552bff", "#e7af36ff"], + ["cyan", "#0096b8ff", "#007d9bff", "#005a6eff", "#0096b8ff"], + ["green", "#2eaf5aff", "#198b43ff", "#196130ff", "#49c970ff"], + ["red", "#d92e3cff", "#b82d35ff", "#7a1f23ff", "#d92e3cff"], + ["pink", "#e4429eff", "#c83d8bff", "#8c2d61ff", "#e4429eff"], + ["blue", "#3250dfff", "#2c47c8ff", "#263fa9ff", "#7698fdff"], + ["purple", "#623be2ff", "#5230c2ff", "#361f83ff", "#7152f4ff"], + ["gray", "#5c5c5cff", "#3a3a3aff", "#5c5c5cff", "#aeaeaeff"], + ] as const)( + "preserves the %s avatar colors", + (color, lightBackground, lightBorder, darkBackground, darkBorder) => { + expect(V2_AVATAR_LIGHT[`v2-avatar-bg-${color}`]).toBe(lightBackground) + expect(V2_AVATAR_LIGHT[`v2-avatar-border-${color}`]).toBe(lightBorder) + expect(V2_AVATAR_DARK[`v2-avatar-bg-${color}`]).toBe(darkBackground) + expect(V2_AVATAR_DARK[`v2-avatar-border-${color}`]).toBe(darkBorder) + }, + ) +}) \ No newline at end of file diff --git a/packages/ui/src/theme/v2/avatar.ts b/packages/ui/src/theme/v2/avatar.ts index 52c0cc67..3682ccc1 100644 --- a/packages/ui/src/theme/v2/avatar.ts +++ b/packages/ui/src/theme/v2/avatar.ts @@ -3,46 +3,58 @@ import type { V2ColorValue } from "../types" /** Fixed project avatar colors (OC-2); theme-independent like v1 `avatar-background-*`. */ export const V2_AVATAR_FG = "#ffffffff" -export const V2_AVATAR_LIGHT: Record = { - "v2-avatar-fg": V2_AVATAR_FG, - "v2-avatar-bg-orange": "#ee7330ff", - "v2-avatar-border-orange": "#d16427ff", - "v2-avatar-bg-yellow": "#e7af36ff", - "v2-avatar-border-yellow": "#cb9f34ff", - "v2-avatar-bg-cyan": "#0096b8ff", - "v2-avatar-border-cyan": "#007d9bff", - "v2-avatar-bg-green": "#2eaf5aff", - "v2-avatar-border-green": "#198b43ff", - "v2-avatar-bg-red": "#d92e3cff", - "v2-avatar-border-red": "#b82d35ff", - "v2-avatar-bg-pink": "#e4429eff", - "v2-avatar-border-pink": "#c83d8bff", - "v2-avatar-bg-blue": "#3250dfff", - "v2-avatar-border-blue": "#2c47c8ff", - "v2-avatar-bg-purple": "#623be2ff", - "v2-avatar-border-purple": "#5230c2ff", - "v2-avatar-bg-gray": "#5c5c5cff", - "v2-avatar-border-gray": "#3a3a3aff", -} +const V2_AVATAR_COLORS = { + orange: { + light: ["#ee7330ff", "#d16427ff"], + dark: ["#723d22ff", "#ff8648ff"], + }, + yellow: { + light: ["#e7af36ff", "#cb9f34ff"], + dark: ["#68552bff", "#e7af36ff"], + }, + cyan: { + light: ["#0096b8ff", "#007d9bff"], + dark: ["#005a6eff", "#0096b8ff"], + }, + green: { + light: ["#2eaf5aff", "#198b43ff"], + dark: ["#196130ff", "#49c970ff"], + }, + red: { + light: ["#d92e3cff", "#b82d35ff"], + dark: ["#7a1f23ff", "#d92e3cff"], + }, + pink: { + light: ["#e4429eff", "#c83d8bff"], + dark: ["#8c2d61ff", "#e4429eff"], + }, + blue: { + light: ["#3250dfff", "#2c47c8ff"], + dark: ["#263fa9ff", "#7698fdff"], + }, + purple: { + light: ["#623be2ff", "#5230c2ff"], + dark: ["#361f83ff", "#7152f4ff"], + }, + gray: { + light: ["#5c5c5cff", "#3a3a3aff"], + dark: ["#5c5c5cff", "#aeaeaeff"], + }, +} as const + +function createAvatarTheme(mode: "light" | "dark"): Record { + const theme: Record = { + "v2-avatar-fg": V2_AVATAR_FG, + } -export const V2_AVATAR_DARK: Record = { - "v2-avatar-fg": V2_AVATAR_FG, - "v2-avatar-bg-orange": "#723d22ff", - "v2-avatar-border-orange": "#ff8648ff", - "v2-avatar-bg-yellow": "#68552bff", - "v2-avatar-border-yellow": "#e7af36ff", - "v2-avatar-bg-cyan": "#005a6eff", - "v2-avatar-border-cyan": "#0096b8ff", - "v2-avatar-bg-green": "#196130ff", - "v2-avatar-border-green": "#49c970ff", - "v2-avatar-bg-red": "#7a1f23ff", - "v2-avatar-border-red": "#d92e3cff", - "v2-avatar-bg-pink": "#8c2d61ff", - "v2-avatar-border-pink": "#e4429eff", - "v2-avatar-bg-blue": "#263fa9ff", - "v2-avatar-border-blue": "#7698fdff", - "v2-avatar-bg-purple": "#361f83ff", - "v2-avatar-border-purple": "#7152f4ff", - "v2-avatar-bg-gray": "#5c5c5cff", - "v2-avatar-border-gray": "#aeaeaeff", + for (const [color, variants] of Object.entries(V2_AVATAR_COLORS)) { + const [background, border] = variants[mode] + theme[`v2-avatar-bg-${color}`] = background + theme[`v2-avatar-border-${color}`] = border + } + + return theme } + +export const V2_AVATAR_LIGHT = createAvatarTheme("light") +export const V2_AVATAR_DARK = createAvatarTheme("dark") \ No newline at end of file