From 4b4f660b9aae2a33aa3c7e68b98ff586bb7b4dbf Mon Sep 17 00:00:00 2001 From: RainbowBird Date: Thu, 13 Mar 2025 10:05:34 +0800 Subject: [PATCH] feat(stage-web): tooltip over colors (#76) --- .../src/pages/settings/themes/index.vue | 115 +++++++++++++++--- 1 file changed, 101 insertions(+), 14 deletions(-) diff --git a/apps/stage-web/src/pages/settings/themes/index.vue b/apps/stage-web/src/pages/settings/themes/index.vue index cc13df7e9..bf54ab967 100644 --- a/apps/stage-web/src/pages/settings/themes/index.vue +++ b/apps/stage-web/src/pages/settings/themes/index.vue @@ -2,6 +2,7 @@ import { Collapsable } from '@proj-airi/stage-ui/components' import { DEFAULT_THEME_COLORS_HUE, useSettings } from '@proj-airi/stage-ui/stores' import { converter } from 'culori' +import { TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipRoot, TooltipTrigger } from 'radix-vue' import { useRouter } from 'vue-router' const router = useRouter() @@ -10,29 +11,82 @@ const settings = useSettings() interface ColorPreset { name: string description: string - colors: string[] + colors: Array<{ + hex: string + name: string + }> } const colorPresets: ColorPreset[] = [ { name: 'Morandi Colors', description: 'Soft, muted tones inspired by Giorgio Morandi\'s paintings', - colors: ['#A5978B', '#D8CAAF', '#B8B4A7', '#C4BCB1', '#E5DED8', '#9A8F7D', '#BEB5A7', '#C9C0B6'], + colors: [ + { hex: '#A5978B', name: 'Taupe' }, + { hex: '#D8CAAF', name: 'Beige' }, + { hex: '#B8B4A7', name: 'Ash Grey' }, + { hex: '#C4BCB1', name: 'Light Taupe' }, + { hex: '#E5DED8', name: 'Ivory' }, + { hex: '#9A8F7D', name: 'Olive Grey' }, + { hex: '#BEB5A7', name: 'Sand' }, + { hex: '#C9C0B6', name: 'Warm Grey' }, + ], }, { name: 'Monet Colors', description: 'Impressionist palette inspired by Claude Monet\'s works', - colors: ['#7A9EAF', '#B8C7CC', '#D4B79C', '#8B9D77', '#C7D5CB', '#E6D0B1', '#94A7B1', '#B4C8C3'], + colors: [ + { hex: '#7A9EAF', name: 'Sky Blue' }, + { hex: '#B8C7CC', name: 'Mist' }, + { hex: '#D4B79C', name: 'Sand' }, + { hex: '#8B9D77', name: 'Moss Green' }, + { hex: '#C7D5CB', name: 'Water Lily' }, + { hex: '#E6D0B1', name: 'Wheat' }, + { hex: '#94A7B1', name: 'Slate Blue' }, + { hex: '#B4C8C3', name: 'Sage' }, + ], }, { name: 'Japanese Colors', description: 'Traditional Japanese color palette', - colors: ['#D9B48F', '#B5917A', '#8C7A6B', '#A17F5F', '#B98C46', '#C7A252', '#DAB300', '#D19826'], + colors: [ + { hex: '#D9B48F', name: 'Tan' }, + { hex: '#B5917A', name: 'Warm Taupe' }, + { hex: '#8C7A6B', name: 'Umber' }, + { hex: '#A17F5F', name: 'Coffee' }, + { hex: '#B98C46', name: 'Bronze' }, + { hex: '#C7A252', name: 'Gold' }, + { hex: '#DAB300', name: 'Mustard' }, + { hex: '#D19826', name: 'Amber' }, + ], }, { name: 'Nordic Colors', description: 'Scandinavian minimalist color scheme', - colors: ['#9BA7B0', '#C1CBD4', '#A5ADB6', '#8B959E', '#D4DCE4', '#7F8A94', '#B3BCC6', '#98A4AE'], + colors: [ + { hex: '#9BA7B0', name: 'Nordic Blue' }, + { hex: '#C1CBD4', name: 'Ice' }, + { hex: '#A5ADB6', name: 'Fjord' }, + { hex: '#8B959E', name: 'Steel' }, + { hex: '#D4DCE4', name: 'Glacier' }, + { hex: '#7F8A94', name: 'Slate' }, + { hex: '#B3BCC6', name: 'Cloud' }, + { hex: '#98A4AE', name: 'Stone' }, + ], + }, + { + name: 'Chinese Traditional Colors', + description: 'Traditional Chinese colors, derived from ancient textiles, porcelain and paintings', + colors: [ + { hex: '#E4C6D0', name: '霞光红 (Rosy Dawn)' }, + { hex: '#A61B29', name: '枣红 (Chinese Red)' }, + { hex: '#5D513C', name: '黄栌 (Smoky Brown)' }, + { hex: '#789262', name: '竹青 (Bamboo Green)' }, + { hex: '#1C0D1A', name: '乌梅紫 (Dark Purple)' }, + { hex: '#F7C242', name: '缃色 (Golden Yellow)' }, + { hex: '#62A9DD', name: '青冥 (Azure Blue)' }, + { hex: '#8C4B3C', name: '赭石 (Ochre)' }, + ], }, ] @@ -58,6 +112,26 @@ function applyPrimaryColorFromHex(color: string) { settings.themeColorsHue = h settings.themeColorsHueDynamic = false } + +/** + * Check if a color is currently selected based on its hue value + * @param hexColor Hex color code to check + * @returns True if the color's hue matches the current theme hue + */ +function isColorSelected(hexColor: string): boolean { + // If dynamic coloring is enabled, no preset color is manually selected + if (settings.themeColorsHueDynamic) + return false + + // Convert hex color to OKLCH + const oklch = converter('oklch')(hexColor) + if (!oklch || !oklch.h) + return false + + // Compare hue values with a small tolerance for floating point comparison + const hueDifference = Math.abs(oklch.h - settings.themeColorsHue) + return hueDifference < 0.01 || hueDifference > 359.99 +}