import React, { useState } from 'react'; import { useSiteDesign, DEFAULT_SITE_DESIGN } from '../../state/SiteDesignContext'; import { FONT_FAMILIES } from '../../constants/presets'; import { AssetPicker } from '../../ui/AssetPicker'; type DesignTab = 'basic' | 'advanced'; /* ---------- Color picker with preset swatches ---------- */ const COLOR_SWATCHES = [ '#3b82f6', '#8b5cf6', '#10b981', '#ef4444', '#f59e0b', '#ec4899', '#06b6d4', '#f97316', ]; const NEUTRAL_SWATCHES = [ '#ffffff', '#f9fafb', '#e5e7eb', '#9ca3af', '#6b7280', '#374151', '#1f2937', '#111827', ]; interface ColorFieldProps { label: string; value: string; onChange: (value: string) => void; swatches?: string[]; } const ColorField: React.FC = ({ label, value, onChange, swatches = COLOR_SWATCHES }) => (
onChange(e.target.value)} style={{ width: 32, height: 32, padding: 0, border: '2px solid var(--color-border)', borderRadius: 'var(--radius-sm)', cursor: 'pointer', background: 'none', }} /> onChange(e.target.value)} style={{ flex: 1, fontSize: 11, fontFamily: 'monospace' }} />
{swatches.map((c) => (
); /* ---------- Font dropdown ---------- */ interface FontFieldProps { label: string; value: string; onChange: (value: string) => void; } const FontField: React.FC = ({ label, value, onChange }) => (
); /* ---------- Border radius presets ---------- */ const BORDER_RADIUS_PRESETS = [ { label: '0', value: '0' }, { label: '4px', value: '4px' }, { label: '8px', value: '8px' }, { label: '12px', value: '12px' }, { label: '16px', value: '16px' }, ]; interface RadiusFieldProps { label: string; value: string; onChange: (value: string) => void; } const RadiusField: React.FC = ({ label, value, onChange }) => (
{BORDER_RADIUS_PRESETS.map((p) => ( ))}
); /* ---------- Nav style toggle ---------- */ interface NavStyleFieldProps { value: 'light' | 'dark'; onChange: (value: 'light' | 'dark') => void; } const NavStyleField: React.FC = ({ value, onChange }) => (
{(['light', 'dark'] as const).map((s) => ( ))}
); /* ---------- Main SiteDesignPanel ---------- */ export const SiteDesignPanel: React.FC = () => { const { design, updateDesign, resetToDefaults } = useSiteDesign(); const [tab, setTab] = useState('basic'); return (
{/* Header */}
Site Design Tokens
{/* Tab switcher */}
{(['basic', 'advanced'] as DesignTab[]).map((t) => ( ))}
{/* Basic tab */} {tab === 'basic' && ( <>
updateDesign({ favicon: url })} mediaType="image" variant="full" placeholder="Or paste favicon URL..." />

Shown in browser tabs and bookmarks. Applies site-wide.

updateDesign({ primaryColor: v })} /> updateDesign({ secondaryColor: v })} /> updateDesign({ accentColor: v })} /> updateDesign({ headingFont: v })} /> updateDesign({ bodyFont: v })} /> updateDesign({ linkColor: v })} /> )} {/* Advanced tab */} {tab === 'advanced' && ( <> updateDesign({ primaryColor: v })} /> updateDesign({ secondaryColor: v })} /> updateDesign({ accentColor: v })} /> updateDesign({ successColor: v })} /> updateDesign({ warningColor: v })} /> updateDesign({ errorColor: v })} /> updateDesign({ backgroundColor: v })} swatches={NEUTRAL_SWATCHES} /> updateDesign({ textColor: v })} swatches={NEUTRAL_SWATCHES} /> updateDesign({ mutedTextColor: v })} swatches={NEUTRAL_SWATCHES} /> updateDesign({ borderColor: v })} swatches={NEUTRAL_SWATCHES} /> updateDesign({ headingFont: v })} /> updateDesign({ bodyFont: v })} /> updateDesign({ buttonFont: v })} /> updateDesign({ linkColor: v })} /> updateDesign({ borderRadius: v })} /> updateDesign({ buttonRadius: v })} /> updateDesign({ navStyle: v })} /> )} {/* Reset button */}

Design tokens are saved with your project and applied to new components.

); };