Accent Swatch Plugin
Customize your editor's accent color with a visual color picker that remembers your recent choices.
Overview
The accentSwatchPlugin provides a user-friendly color palette for changing the editor's accent color. It features:
- 🎨 Visual color swatch picker
- 💾 Persistent recent colors in localStorage
- 🎯 Eyedropper support (modern browsers)
- ⚡ Native color picker integration
- ✨ Live preview and instant application
Installation
import { Marzipan } from '@pinkpixel/marzipan';
import { accentSwatchPlugin } from '@pinkpixel/marzipan/plugins/accentSwatchPlugin';
new Marzipan('#editor', {
toolbar: true,
plugins: [accentSwatchPlugin()]
});
Options
interface AccentSwatchOptions {
max?: number; // Max swatches to keep (default: 12)
defaults?: string[]; // Seed colors if none saved
title?: string; // Toolbar tooltip (default: 'Accent color')
label?: string; // Toolbar button label (default: ⭘)
}
Usage Examples
Basic Usage
import { accentSwatchPlugin } from '@pinkpixel/marzipan/plugins/accentSwatchPlugin';
new Marzipan('#editor', {
plugins: [accentSwatchPlugin()]
});
With Default Colors
import { accentSwatchPlugin } from '@pinkpixel/marzipan/plugins/accentSwatchPlugin';
new Marzipan('#editor', {
plugins: [
accentSwatchPlugin({
max: 8,
defaults: [
'#8b5cf6', // Purple (default Marzipan accent)
'#ef4444', // Red
'#f59e0b', // Amber
'#10b981', // Green
'#3b82f6', // Blue
'#ec4899', // Pink
'#6366f1', // Indigo
'#14b8a6' // Teal
],
title: 'Change theme color',
label: '🎨'
})
]
});
Coordinated with Theme
import { Marzipan } from '@pinkpixel/marzipan';
import { accentSwatchPlugin } from '@pinkpixel/marzipan/plugins/accentSwatchPlugin';
const themeColors = {
solar: ['#dc8d10', '#cb4b16', '#d33682', '#6c71c4', '#268bd2'],
cave: ['#8b5cf6', '#a78bfa', '#c084fc', '#e879f9', '#f0abfc'],
forest: ['#10b981', '#059669', '#047857', '#065f46', '#064e3b']
};
const theme = 'cave'; // or dynamically determined
new Marzipan('#editor', {
theme,
plugins: [
accentSwatchPlugin({
defaults: themeColors[theme]
})
]
});
Features
Color Selection Methods
The plugin offers three ways to pick colors:
1. Color Picker (Default)
Click the + button to open native color picker:
- Visual gradient selector
- Works in all browsers
- Instant preview
2. Manual Input (Shift+Click)
Hold Shift and click + to type hex value:
- Enter format:
#RRGGBBorRRGGBB - Supports 3-digit shorthand (
#abc→#aabbcc) - Validates input
3. Eyedropper (Alt+Click)
Hold Alt and click + to pick from screen:
- Pick any color visible on screen
- Modern browser support (Chrome, Edge)
- Falls back to manual input if unavailable
Recent Colors
- Automatically saves selected colors
- Up to 12 swatches by default (configurable)
- Most recent colors appear first
- Persists across browser sessions
- Syncs between editor instances
Color Management
Select: Click any swatch to apply color
Remove: Right-click swatch to delete
Add Current: Save current accent to swatches
Reset: Restore default colors
Styling
The plugin exports accentSwatchStyles for custom styling:
import {
accentSwatchPlugin,
accentSwatchStyles
} from '@pinkpixel/marzipan/plugins/accentSwatchPlugin';
// Inject styles
const styleElement = document.createElement('style');
styleElement.textContent = accentSwatchStyles;
document.head.appendChild(styleElement);
new Marzipan('#editor', {
plugins: [accentSwatchPlugin()]
});
Custom CSS Variables
/* Accent Swatch Panel */
--mz-pop-bd: #333; /* Swatch border */
--mz-accent: #8b5cf6; /* Current accent color */
/* Buttons */
--mz-bd: #2b2f36; /* Button border */
--mz-btn-bg: #1a1e24; /* Button background */
--mz-btn-fg: #e7e7e7; /* Button text */
Complete Example
import { Marzipan } from '@pinkpixel/marzipan';
import {
accentSwatchPlugin,
accentSwatchStyles
} from '@pinkpixel/marzipan/plugins';
// Inject styles
const style = document.createElement('style');
style.textContent = accentSwatchStyles;
document.head.appendChild(style);
// Create editor with accent swatch
const [editor] = new Marzipan('#editor', {
toolbar: true,
theme: 'cave',
plugins: [
accentSwatchPlugin({
max: 10,
defaults: [
'#8b5cf6', // Purple
'#a78bfa', // Light purple
'#c084fc', // Lighter purple
'#e879f9', // Pink-purple
'#f0abfc', // Pink
'#ec4899', // Hot pink
'#ef4444', // Red
'#f59e0b', // Orange
'#10b981', // Green
'#3b82f6' // Blue
],
title: 'Customize accent color'
})
],
value: `# Welcome to Marzipan
Try changing the accent color! 🎨
`
});
// Listen for accent changes
editor.container.addEventListener('marzipan:accent', (e) => {
console.log('Accent changed to:', e.detail.color);
// Optionally sync with your app theme
document.body.style.setProperty('--app-accent', e.detail.color);
});
Programmatic Control
Set Accent Color
const [editor] = new Marzipan('#editor', {
plugins: [accentSwatchPlugin()]
});
// Set accent programmatically
document.documentElement.style.setProperty('--mz-accent', '#ef4444');
// Or use the editor's method if available
if (editor.setAccent) {
editor.setAccent('#ef4444');
}
Get Current Accent
// From CSS variable
const accent = getComputedStyle(document.documentElement)
.getPropertyValue('--mz-accent')
.trim();
console.log('Current accent:', accent);
Listen for Changes
editor.container.addEventListener('marzipan:accent', (event) => {
const color = event.detail.color;
// Update your app UI
updateAppTheme(color);
// Save to user preferences
saveUserPreference('accentColor', color);
// Analytics
trackColorChange(color);
});
Accent Color Usage
The accent color is used throughout Marzipan for:
- Active button states
- Focus indicators
- Link colors in preview
- Selection highlights
- Progress indicators
- Custom highlights
CSS Example
/* Use accent in your styles */
.my-button:hover {
background-color: var(--mz-accent);
}
.my-link {
color: var(--mz-accent);
}
.my-border {
border-color: var(--mz-accent);
}
Storage Details
localStorage Key
Colors are stored in localStorage under:
marzipan.accent.colors
Data Format
[
"#8b5cf6",
"#a78bfa",
"#c084fc"
]
Clear Stored Colors
// Clear accent colors from localStorage
localStorage.removeItem('marzipan.accent.colors');
// Or use the Reset button in the UI
Browser Compatibility
Core Features:
- Chrome/Edge 60+
- Firefox 55+
- Safari 11+
Eyedropper API:
- Chrome/Edge 95+
- Not yet supported in Firefox/Safari
- Gracefully falls back to manual input
Native Color Picker:
- All modern browsers
- Best support in Chrome/Edge
Best Practices
Design Considerations
- Provide defaults that match your app's design system
- Limit swatches to prevent clutter (8-12 is ideal)
- Choose accessible colors with good contrast
- Test combinations with your editor theme
- Document colors if using specific palette
Accessibility
Ensure accent colors provide sufficient contrast:
- Text on accent: 4.5:1 minimum
- UI elements: 3:1 minimum
- Test with tools like WCAG Contrast Checker
Theming Integration
Dynamic Accent per Theme
const themeDefaults = {
solar: ['#dc8d10', '#cb4b16', '#d33682'],
cave: ['#8b5cf6', '#a78bfa', '#c084fc'],
forest: ['#10b981', '#059669', '#047857']
};
function createEditor(theme: 'solar' | 'cave' | 'forest') {
return new Marzipan('#editor', {
theme,
plugins: [
accentSwatchPlugin({
defaults: themeDefaults[theme]
})
]
});
}
Sync with System Preferences
// Detect dark mode
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
new Marzipan('#editor', {
theme: prefersDark ? 'cave' : 'solar',
plugins: [
accentSwatchPlugin({
defaults: prefersDark
? ['#8b5cf6', '#a78bfa', '#c084fc'] // Dark mode colors
: ['#dc8d10', '#cb4b16', '#d33682'] // Light mode colors
})
]
});
Troubleshooting
Accent Not Applying
Check if CSS variable is set:
const accent = getComputedStyle(document.documentElement)
.getPropertyValue('--mz-accent');
console.log('Accent:', accent || 'Not set');
Eyedropper Not Working
// Check support
if ('EyeDropper' in window) {
console.log('Eyedropper supported!');
} else {
console.log('Eyedropper not available, use Shift+Click for manual input');
}
Colors Not Persisting
Verify localStorage access:
try {
localStorage.setItem('test', 'test');
localStorage.removeItem('test');
console.log('localStorage available');
} catch (e) {
console.error('localStorage blocked or full');
}
Advanced Usage
Custom Color Validation
// Wrap plugin to add validation
function validatedAccentPlugin(options) {
const basePlugin = accentSwatchPlugin(options);
return (editor) => {
basePlugin(editor);
// Add validation listener
editor.container.addEventListener('marzipan:accent', (e) => {
const color = e.detail.color;
// Check if color is too light/dark
const rgb = parseInt(color.slice(1), 16);
const brightness = (rgb >> 16) + ((rgb >> 8) & 0xff) + (rgb & 0xff);
if (brightness < 100 || brightness > 600) {
console.warn('Accent color may have poor contrast');
}
});
};
}
new Marzipan('#editor', {
plugins: [validatedAccentPlugin({ defaults: ['#8b5cf6'] })]
});
Share Colors Across Editors
// Create multiple editors with shared palette
const sharedPlugin = accentSwatchPlugin({
defaults: ['#8b5cf6', '#ef4444', '#10b981']
});
const editor1 = new Marzipan('#editor1', { plugins: [sharedPlugin] });
const editor2 = new Marzipan('#editor2', { plugins: [sharedPlugin] });
// Changes in one editor affect the other (via localStorage)
See Also
- Plugin Overview - All available plugins
- Themes - Editor theming system
- Configuration - Plugin configuration
- Color Properties - Theme tokens reference
- Bakeshop Demo - Live examples
Marzipan