Private
Public Access
1
0

Fix ColorPicker solid color issues, add per-field reset, regroup accents

ColorPicker fixes:
- Color picker now initializes to default color instead of black when
  field is cleared/empty
- Switching Solid<>Gradient no longer emits black; restores default color
  when switching back to Solid from a gradient value
- No-op guard prevents re-emitting when clicking the already-active mode
- Reset button now says "Reset to default" when a default is available
- Text input placeholder shows the default value

Branding page:
- Accent Colors regrouped: Primary+hover and Danger+hover are stacked
  together, Success and Warning standalone in a 4-column grid
- Mini preview fallbacks now use getDefault() helper instead of
  hardcoded values, keeping them in sync with the defaults map

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Catherine Renelle
2026-02-27 17:52:52 -05:00
parent 8c9a5abc5a
commit faa2608a47
2 changed files with 53 additions and 37 deletions
+12 -4
View File
@@ -35,7 +35,8 @@
color = v; color = v;
} else { } else {
mode = 'color'; mode = 'color';
color = '#000000'; // Show the default color in the picker when no custom value is set
color = defaultValue && defaultValue.startsWith('#') ? defaultValue : '#000000';
} }
}); });
@@ -50,15 +51,20 @@
} }
function switchMode(newMode: 'color' | 'gradient') { function switchMode(newMode: 'color' | 'gradient') {
if (mode === newMode) return;
mode = newMode; mode = newMode;
if (newMode === 'color') { if (newMode === 'color') {
// Restore from default if available, not leftover gradient state
if (!value || value.startsWith('linear-gradient') || value.startsWith('radial-gradient')) {
color = defaultValue && defaultValue.startsWith('#') ? defaultValue : '#000000';
}
emitColor(); emitColor();
} else { } else {
emitGradient(); emitGradient();
} }
} }
function clear() { function resetToDefault() {
value = ''; value = '';
onchange?.(''); onchange?.('');
} }
@@ -68,7 +74,9 @@
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<label class="block text-xs font-medium text-gray-600 dark:text-gray-400">{label}</label> <label class="block text-xs font-medium text-gray-600 dark:text-gray-400">{label}</label>
{#if value} {#if value}
<button onclick={clear} class="text-[10px] text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">Reset</button> <button onclick={resetToDefault} class="text-[10px] text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">
{defaultValue ? 'Reset to default' : 'Clear'}
</button>
{:else if defaultValue} {:else if defaultValue}
<span class="text-[10px] text-gray-400 dark:text-gray-500">Default</span> <span class="text-[10px] text-gray-400 dark:text-gray-500">Default</span>
{/if} {/if}
@@ -103,7 +111,7 @@
type="text" type="text"
bind:value={color} bind:value={color}
oninput={emitColor} oninput={emitColor}
placeholder="#000000" placeholder={defaultValue || '#000000'}
class="flex-1 rounded border border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100 px-2 py-1 text-xs font-mono focus:border-[var(--color-primary)] focus:outline-none" class="flex-1 rounded border border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100 px-2 py-1 text-xs font-mono focus:border-[var(--color-primary)] focus:outline-none"
/> />
</div> </div>
+41 -33
View File
@@ -358,37 +358,45 @@
<!-- Accent Colors --> <!-- Accent Colors -->
<section class="rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 p-5"> <section class="rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 p-5">
<h2 class="text-sm font-semibold text-gray-800 dark:text-gray-200 mb-4">Accent Colors</h2> <h2 class="text-sm font-semibold text-gray-800 dark:text-gray-200 mb-4">Accent Colors</h2>
<div class="grid grid-cols-2 sm:grid-cols-3 gap-4"> <div class="grid grid-cols-2 sm:grid-cols-4 gap-4">
<ColorPicker <!-- Primary group -->
label="Primary" <div class="space-y-3">
value={getField('primary') || ''} <ColorPicker
defaultValue={getDefault('primary')} label="Primary"
onchange={(v) => setField('primary', v)} value={getField('primary') || ''}
/> defaultValue={getDefault('primary')}
<ColorPicker onchange={(v) => setField('primary', v)}
label="Primary hover" />
value={getField('primaryHover') || ''} <ColorPicker
defaultValue={getDefault('primaryHover')} label="Primary hover"
onchange={(v) => setField('primaryHover', v)} value={getField('primaryHover') || ''}
/> defaultValue={getDefault('primaryHover')}
<ColorPicker onchange={(v) => setField('primaryHover', v)}
label="Danger" />
value={getField('danger') || ''} </div>
defaultValue={getDefault('danger')} <!-- Danger group -->
onchange={(v) => setField('danger', v)} <div class="space-y-3">
/> <ColorPicker
<ColorPicker label="Danger"
label="Danger hover" value={getField('danger') || ''}
value={getField('dangerHover') || ''} defaultValue={getDefault('danger')}
defaultValue={getDefault('dangerHover')} onchange={(v) => setField('danger', v)}
onchange={(v) => setField('dangerHover', v)} />
/> <ColorPicker
label="Danger hover"
value={getField('dangerHover') || ''}
defaultValue={getDefault('dangerHover')}
onchange={(v) => setField('dangerHover', v)}
/>
</div>
<!-- Success -->
<ColorPicker <ColorPicker
label="Success" label="Success"
value={getField('success') || ''} value={getField('success') || ''}
defaultValue={getDefault('success')} defaultValue={getDefault('success')}
onchange={(v) => setField('success', v)} onchange={(v) => setField('success', v)}
/> />
<!-- Warning -->
<ColorPicker <ColorPicker
label="Warning" label="Warning"
value={getField('warning') || ''} value={getField('warning') || ''}
@@ -403,12 +411,12 @@
<h2 class="text-sm font-semibold text-gray-800 dark:text-gray-200 mb-4">Preview</h2> <h2 class="text-sm font-semibold text-gray-800 dark:text-gray-200 mb-4">Preview</h2>
<div <div
class="rounded-lg overflow-hidden border border-gray-200 dark:border-gray-600" class="rounded-lg overflow-hidden border border-gray-200 dark:border-gray-600"
style="background: {getField('pageBg') || (activeTab === 'light' ? '#f9fafb' : '#030712')}; min-height: 200px;" style="background: {getField('pageBg') || getDefault('pageBg')}; min-height: 200px;"
> >
<!-- Mini nav --> <!-- Mini nav -->
<div <div
class="h-8 flex items-center px-3" class="h-8 flex items-center px-3"
style="background: {getField('navBg') || (activeTab === 'light' ? '#0079bf' : '#3b82f6')};" style="background: {getField('navBg') || getDefault('navBg')};"
> >
<span class="text-white text-xs font-bold">Pounce</span> <span class="text-white text-xs font-bold">Pounce</span>
<div class="ml-auto flex gap-1"> <div class="ml-auto flex gap-1">
@@ -421,13 +429,13 @@
{#each ['To Do', 'In Progress', 'Done'] as colTitle} {#each ['To Do', 'In Progress', 'Done'] as colTitle}
<div <div
class="w-28 rounded-lg p-2" class="w-28 rounded-lg p-2"
style="background: {getField('columnBg') || (activeTab === 'light' ? '#ebecf0' : '#1f2937')}; border: 1px solid {getField('columnBorder') || 'transparent'}; color: {getField('columnText') || 'inherit'}; opacity: {getField('columnOpacity') != null && getField('columnOpacity') !== '' ? getField('columnOpacity') : 1};" style="background: {getField('columnBg') || getDefault('columnBg')}; border: 1px solid {getField('columnBorder') || getDefault('columnBorder')}; color: {getField('columnText') || getDefault('columnText')}; opacity: {getField('columnOpacity') != null && getField('columnOpacity') !== '' ? getField('columnOpacity') : 1};"
> >
<div class="text-[10px] font-semibold mb-1.5" style="color: {getField('columnText') || (activeTab === 'light' ? '#374151' : '#d1d5db')};">{colTitle}</div> <div class="text-[10px] font-semibold mb-1.5" style="color: {getField('columnText') || (activeTab === 'light' ? '#374151' : '#d1d5db')};">{colTitle}</div>
{#each [1, 2] as _} {#each [1, 2] as _}
<div <div
class="mb-1 p-1.5 shadow-sm" class="mb-1 p-1.5 shadow-sm"
style="background: {getField('cardBg') || (activeTab === 'light' ? '#ffffff' : '#374151')}; border: 1px solid {getField('cardBorder') || (activeTab === 'light' ? '#e5e7eb' : '#4b5563')}; border-radius: {getField('cardRadius') || '0.5rem'}; opacity: {getField('cardOpacity') != null && getField('cardOpacity') !== '' ? getField('cardOpacity') : 1};" style="background: {getField('cardBg') || getDefault('cardBg')}; border: 1px solid {getField('cardBorder') || getDefault('cardBorder')}; border-radius: {getField('cardRadius') || '0.5rem'}; opacity: {getField('cardOpacity') != null && getField('cardOpacity') !== '' ? getField('cardOpacity') : 1};"
> >
<div class="h-1.5 rounded" style="background: {getField('cardText') || (activeTab === 'light' ? '#374151' : '#d1d5db')}; width: 60%; opacity: 0.5;"></div> <div class="h-1.5 rounded" style="background: {getField('cardText') || (activeTab === 'light' ? '#374151' : '#d1d5db')}; width: 60%; opacity: 0.5;"></div>
</div> </div>
@@ -437,10 +445,10 @@
</div> </div>
<!-- Mini button row --> <!-- Mini button row -->
<div class="flex gap-2 px-3 pb-3"> <div class="flex gap-2 px-3 pb-3">
<div class="rounded px-2 py-1 text-[10px] text-white" style="background: {getField('primary') || (activeTab === 'light' ? '#0079bf' : '#3b82f6')};">Primary</div> <div class="rounded px-2 py-1 text-[10px] text-white" style="background: {getField('primary') || getDefault('primary')};">Primary</div>
<div class="rounded px-2 py-1 text-[10px] text-white" style="background: {getField('danger') || (activeTab === 'light' ? '#eb5a46' : '#ef4444')};">Danger</div> <div class="rounded px-2 py-1 text-[10px] text-white" style="background: {getField('danger') || getDefault('danger')};">Danger</div>
<div class="rounded px-2 py-1 text-[10px] text-white" style="background: {getField('success') || (activeTab === 'light' ? '#61bd4f' : '#22c55e')};">Success</div> <div class="rounded px-2 py-1 text-[10px] text-white" style="background: {getField('success') || getDefault('success')};">Success</div>
<div class="rounded px-2 py-1 text-[10px] text-gray-800" style="background: {getField('warning') || (activeTab === 'light' ? '#f2d600' : '#eab308')};">Warning</div> <div class="rounded px-2 py-1 text-[10px] text-gray-800" style="background: {getField('warning') || getDefault('warning')};">Warning</div>
</div> </div>
</div> </div>
</section> </section>