feat(theme): implement dynamic theme logo with reactive color updates

This commit is contained in:
catlog22
2026-02-28 23:08:27 +08:00
parent e42597b1bc
commit e83414abf3
7 changed files with 179 additions and 31 deletions

View File

@@ -3,6 +3,7 @@
// ========================================
// Line-style logo for Claude Code Workflow
import { useEffect, useState } from 'react';
import { cn } from '@/lib/utils';
interface CCWLogoProps {
@@ -14,11 +15,54 @@ interface CCWLogoProps {
showDot?: boolean;
}
/**
* Hook to get reactive theme accent color
*/
function useThemeAccentColor(): string {
const [accentColor, setAccentColor] = useState<string>(() => {
if (typeof document === 'undefined') return 'hsl(220, 60%, 65%)';
const root = document.documentElement;
const accentValue = getComputedStyle(root).getPropertyValue('--accent').trim();
return accentValue ? `hsl(${accentValue})` : 'hsl(220, 60%, 65%)';
});
useEffect(() => {
const updateAccentColor = () => {
const root = document.documentElement;
const accentValue = getComputedStyle(root).getPropertyValue('--accent').trim();
setAccentColor(accentValue ? `hsl(${accentValue})` : 'hsl(220, 60%, 65%)');
};
// Initial update
updateAccentColor();
// Watch for theme changes via MutationObserver
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.attributeName === 'data-theme') {
updateAccentColor();
}
});
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['data-theme'],
});
return () => observer.disconnect();
}, []);
return accentColor;
}
/**
* Line-style CCW logo component
* Features three horizontal lines with a status dot that follows theme color
*/
export function CCWLogo({ size = 24, className, showDot = true }: CCWLogoProps) {
const accentColor = useThemeAccentColor();
return (
<svg
width={size}
@@ -27,7 +71,7 @@ export function CCWLogo({ size = 24, className, showDot = true }: CCWLogoProps)
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={cn('ccw-logo', className)}
style={{ color: 'hsl(var(--accent))' }}
style={{ color: accentColor }}
aria-label="Claude Code Workflow"
>
{/* Three horizontal lines - line style */}

View File

@@ -74,7 +74,7 @@ export function Header({
to="/"
className="flex items-center gap-2 text-lg font-semibold hover:opacity-80 transition-opacity"
>
<CCWLogo size={24} className="text-primary" />
<CCWLogo size={24} />
<span className="hidden sm:inline text-primary">{formatMessage({ id: 'navigation.header.brand' })}</span>
<span className="sm:hidden text-primary">{formatMessage({ id: 'navigation.header.brandShort' })}</span>
</Link>

View File

@@ -870,6 +870,16 @@
/* ===========================
CCW Logo
=========================== */
.ccw-logo {
color: hsl(var(--accent));
.ccw-logo,
svg.ccw-logo,
header .ccw-logo {
color: hsl(var(--accent)) !important;
}
/* Ensure dot inherits color */
.ccw-logo circle,
svg.ccw-logo circle {
fill: currentColor;
}
/* Theme-specific accent colors are applied automatically via --accent variable */