fix: add custom accent color picker to Preferences page

The Preferences page had its own inline accent color section that wasn't
updated with the custom picker. Now shows:
- 5 preset swatches + separator + custom swatch with pipette icon
- Color picker + hex input appear when custom is selected
- Larger swatches (w-8 h-8) matching the page's spacious layout

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-15 01:45:27 +01:00
parent 2eab705a8a
commit ed7efd923b
+55 -3
View File
@@ -1,4 +1,4 @@
import { Sun, Monitor, Moon } from 'lucide-react'
import { Sun, Monitor, Moon, Pipette } from 'lucide-react'
import { clsx } from 'clsx'
import { useThemeStore, ACCENT_PRESETS, type ThemeMode } from '../store/theme'
@@ -9,7 +9,7 @@ const MODES: { key: ThemeMode; icon: typeof Sun; label: string }[] = [
]
export default function PreferencesPage() {
const { mode, accent, setMode, setAccent } = useThemeStore()
const { mode, accent, customHex, setMode, setAccent, setCustomHex } = useThemeStore()
return (
<div className="p-8 max-w-2xl">
@@ -54,7 +54,8 @@ export default function PreferencesPage() {
<p className="text-sm font-medium text-content">Accent color</p>
<p className="text-xs text-content-muted mt-0.5">Used for buttons, links, and highlights</p>
</div>
<div className="flex gap-3 pt-1">
<div className="flex items-center gap-3 pt-1 flex-wrap">
{/* Preset swatches */}
{ACCENT_PRESETS.map(({ key, label, hex }) => (
<button
key={key}
@@ -71,6 +72,57 @@ export default function PreferencesPage() {
}}
/>
))}
{/* Separator */}
<div className="w-px h-6 bg-border-default" />
{/* Custom color swatch */}
<button
onClick={() => setAccent('custom')}
title="Custom color"
className={clsx(
'w-8 h-8 rounded-full transition-all flex items-center justify-center border',
accent === 'custom' ? 'scale-125' : 'hover:scale-110',
)}
style={{
backgroundColor: customHex,
borderColor: accent === 'custom' ? 'transparent' : 'var(--color-border)',
outline: accent === 'custom' ? `2px solid ${customHex}` : undefined,
outlineOffset: accent === 'custom' ? '3px' : undefined,
}}
>
{accent !== 'custom' && (
<Pipette size={14} className="text-white drop-shadow-sm" />
)}
</button>
{/* Color picker + hex input (when custom is active) */}
{accent === 'custom' && (
<div className="flex items-center gap-2">
<input
type="color"
value={customHex}
onChange={(e) => setCustomHex(e.target.value)}
className="w-8 h-8 rounded-lg border border-border-default cursor-pointer p-0"
title="Pick a custom accent color"
/>
<input
type="text"
value={customHex}
onChange={(e) => {
const v = e.target.value
if (/^#[0-9a-fA-F]{6}$/.test(v)) setCustomHex(v)
}}
onBlur={(e) => {
let v = e.target.value
if (!v.startsWith('#')) v = '#' + v
if (/^#[0-9a-fA-F]{6}$/.test(v)) setCustomHex(v)
}}
className="w-24 px-2 py-1.5 text-sm font-mono border border-border-default rounded-lg bg-surface text-content focus:outline-none focus:border-accent"
placeholder="#6366f1"
/>
</div>
)}
</div>
</div>
</section>