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;
} else {
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') {
if (mode === newMode) return;
mode = newMode;
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();
} else {
emitGradient();
}
}
function clear() {
function resetToDefault() {
value = '';
onchange?.('');
}
@@ -68,7 +74,9 @@
<div class="flex items-center justify-between">
<label class="block text-xs font-medium text-gray-600 dark:text-gray-400">{label}</label>
{#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}
<span class="text-[10px] text-gray-400 dark:text-gray-500">Default</span>
{/if}
@@ -103,7 +111,7 @@
type="text"
bind:value={color}
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"
/>
</div>
+17 -9
View File
@@ -358,7 +358,9 @@
<!-- Accent Colors -->
<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>
<div class="grid grid-cols-2 sm:grid-cols-3 gap-4">
<div class="grid grid-cols-2 sm:grid-cols-4 gap-4">
<!-- Primary group -->
<div class="space-y-3">
<ColorPicker
label="Primary"
value={getField('primary') || ''}
@@ -371,6 +373,9 @@
defaultValue={getDefault('primaryHover')}
onchange={(v) => setField('primaryHover', v)}
/>
</div>
<!-- Danger group -->
<div class="space-y-3">
<ColorPicker
label="Danger"
value={getField('danger') || ''}
@@ -383,12 +388,15 @@
defaultValue={getDefault('dangerHover')}
onchange={(v) => setField('dangerHover', v)}
/>
</div>
<!-- Success -->
<ColorPicker
label="Success"
value={getField('success') || ''}
defaultValue={getDefault('success')}
onchange={(v) => setField('success', v)}
/>
<!-- Warning -->
<ColorPicker
label="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>
<div
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 -->
<div
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>
<div class="ml-auto flex gap-1">
@@ -421,13 +429,13 @@
{#each ['To Do', 'In Progress', 'Done'] as colTitle}
<div
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>
{#each [1, 2] as _}
<div
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>
@@ -437,10 +445,10 @@
</div>
<!-- Mini button row -->
<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('danger') || (activeTab === 'light' ? '#eb5a46' : '#ef4444')};">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-gray-800" style="background: {getField('warning') || (activeTab === 'light' ? '#f2d600' : '#eab308')};">Warning</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') || getDefault('danger')};">Danger</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') || getDefault('warning')};">Warning</div>
</div>
</div>
</section>