🎨 Customization Guide

Learn how to customize themes, create custom shapes, and extend the design tool functionality.

🎨 Theming

Custom CSS Variables

Override the default theme by defining custom CSS variables:

:root { --primary-color: #667eea; --secondary-color: #764ba2; --background-color: #ffffff; --text-color: #2d3748; --border-color: #e2e8f0; --success-color: #48bb78; --warning-color: #ed8936; --error-color: #f56565; }

Dark Mode Support

The design tool includes built-in dark mode support:

import { useCanvasManager } from '@rifrocket/fabricjs-design-tool'; const canvasManager = useCanvasManager(canvas, { darkMode: true, backgroundColor: '#1a202c' }); // Toggle dark mode programmatically canvasManager.toggleDarkMode();

Custom Toolbar

Customize the toolbar with your own components:

import { Header } from '@rifrocket/fabricjs-design-tool/ui'; function CustomHeader() { return ( <Header logo={<img src="/my-logo.png" alt="Logo" />} customActions={[ { label: 'Custom Action', onClick: handleCustomAction }, { label: 'Export PDF', onClick: handlePDFExport } ]} /> ); }

✨ Custom Shapes

Creating Custom Shape Classes

Extend Fabric.js to create your own shape types:

import { fabric } from 'fabric'; // Create a custom star shape const StarShape = fabric.util.createClass(fabric.Polygon, { type: 'star', initialize: function(options) { const points = this.createStarPoints(options.points || 5, options.radius || 50); this.callSuper('initialize', points, options); }, createStarPoints: function(numPoints, radius) { const points = []; const angle = Math.PI / numPoints; for (let i = 0; i < numPoints * 2; i++) { const r = i % 2 === 0 ? radius : radius / 2; points.push({ x: Math.cos(i * angle) * r, y: Math.sin(i * angle) * r }); } return points; } }); // Register the shape fabric.StarShape = StarShape;

Using Custom Shapes with ShapeFactory

Integrate custom shapes into the shape factory:

import { shapeFactory } from '@rifrocket/fabricjs-design-tool'; // Extend the shape factory shapeFactory.createStar = function(options = {}) { return new fabric.StarShape({ left: options.left || 100, top: options.top || 100, points: options.points || 5, radius: options.radius || 50, fill: options.fill || '#ffcc00', stroke: options.stroke || '#ff6600', strokeWidth: options.strokeWidth || 2, ...options }); }; // Use in your application const star = shapeFactory.createStar({ left: 200, top: 150, points: 6, fill: 'gold' }); canvas.add(star);

Custom Shape Presets

Define presets for commonly used shapes:

const shapePresets = { logo: { type: 'rectangle', width: 200, height: 60, fill: '#667eea', rx: 8, ry: 8 }, button: { type: 'rectangle', width: 120, height: 40, fill: '#48bb78', rx: 20, ry: 20 }, icon: { type: 'circle', radius: 20, fill: '#ed8936' } }; // Apply presets function addPresetShape(presetName, position) { const preset = shapePresets[presetName]; const shape = shapeFactory[`create${preset.type.charAt(0).toUpperCase() + preset.type.slice(1)}`]({ ...preset, left: position.x, top: position.y }); canvas.add(shape); }

🛠️ Custom Tools

Creating Custom Tool Buttons

Add custom functionality to the toolbar:

import { LeftSidebar } from '@rifrocket/fabricjs-design-tool/ui'; function CustomLeftSidebar({ canvas }) { const handleAddWatermark = () => { const watermark = new fabric.Text('CONFIDENTIAL', { left: canvas.width / 2, top: canvas.height / 2, fontSize: 60, fill: 'rgba(255, 0, 0, 0.3)', angle: -45, selectable: false }); canvas.add(watermark); }; const customTools = [ { icon: '💧', label: 'Add Watermark', onClick: handleAddWatermark }, { icon: '📏', label: 'Add Ruler', onClick: () => addRulerTool(canvas) } ]; return ( <LeftSidebar customTools={customTools} showDefaultTools={true} /> ); }

Custom Export Formats

Add support for additional export formats:

import { canvasUtils } from '@rifrocket/fabricjs-design-tool'; import jsPDF from 'jspdf'; // Extend export functionality canvasUtils.exportToPDF = function(canvas, options = {}) { const pdf = new jsPDF({ orientation: options.orientation || 'landscape', unit: 'px', format: [canvas.width, canvas.height] }); const imgData = canvas.toDataURL('image/png'); pdf.addImage(imgData, 'PNG', 0, 0, canvas.width, canvas.height); if (options.download) { pdf.save(options.filename || 'design.pdf'); } return pdf; }; // Use custom export const exportToPDF = () => { canvasUtils.exportToPDF(canvas, { filename: 'my-design.pdf', download: true }); };

🔌 Plugin System

Creating a Plugin

Build reusable plugins for specific functionality:

// Create a grid plugin const GridPlugin = { name: 'grid', version: '1.0.0', install(canvas, options = {}) { const gridSize = options.gridSize || 20; const gridColor = options.gridColor || '#e0e0e0'; canvas.on('after:render', () => { this.drawGrid(canvas, gridSize, gridColor); }); return { toggleGrid: () => this.toggleGrid(canvas), setGridSize: (size) => this.setGridSize(canvas, size) }; }, drawGrid(canvas, size, color) { const ctx = canvas.getContext(); const width = canvas.width; const height = canvas.height; ctx.strokeStyle = color; ctx.lineWidth = 1; // Draw vertical lines for (let x = 0; x <= width; x += size) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, height); ctx.stroke(); } // Draw horizontal lines for (let y = 0; y <= height; y += size) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(width, y); ctx.stroke(); } } }; // Use the plugin const gridControls = GridPlugin.install(canvas, { gridSize: 25, gridColor: '#f0f0f0' });

Plugin Manager

Manage multiple plugins with a plugin manager:

class PluginManager { constructor(canvas) { this.canvas = canvas; this.plugins = new Map(); } install(plugin, options = {}) { if (this.plugins.has(plugin.name)) { console.warn(`Plugin ${plugin.name} is already installed`); return; } const api = plugin.install(this.canvas, options); this.plugins.set(plugin.name, { plugin, api, options }); return api; } uninstall(pluginName) { const pluginData = this.plugins.get(pluginName); if (pluginData && pluginData.plugin.uninstall) { pluginData.plugin.uninstall(this.canvas); } this.plugins.delete(pluginName); } getPlugin(pluginName) { const pluginData = this.plugins.get(pluginName); return pluginData ? pluginData.api : null; } } // Usage const pluginManager = new PluginManager(canvas); const gridAPI = pluginManager.install(GridPlugin); const rulerAPI = pluginManager.install(RulerPlugin); // Use plugin APIs gridAPI.toggleGrid(); rulerAPI.showRulers();

📡 Custom Events

Custom Event Listeners

Listen to canvas events and add custom behavior:

import { useCanvasManager } from '@rifrocket/fabricjs-design-tool'; function useCustomEvents(canvas) { useEffect(() => { if (!canvas) return; // Custom object selection handler const handleSelection = (e) => { const obj = e.target; console.log('Object selected:', obj.type); // Add custom behavior if (obj.type === 'text') { showTextEditingPanel(obj); } }; // Auto-save on modifications const handleModified = () => { debounce(() => { const canvasData = canvas.toJSON(); localStorage.setItem('canvas-backup', JSON.stringify(canvasData)); }, 1000)(); }; canvas.on('selection:created', handleSelection); canvas.on('object:modified', handleModified); return () => { canvas.off('selection:created', handleSelection); canvas.off('object:modified', handleModified); }; }, [canvas]); }

Custom Event Emitters

Create custom events for plugin communication:

class EventEmitter { constructor() { this.events = {}; } on(eventName, callback) { if (!this.events[eventName]) { this.events[eventName] = []; } this.events[eventName].push(callback); } emit(eventName, data) { const callbacks = this.events[eventName]; if (callbacks) { callbacks.forEach(callback => callback(data)); } } off(eventName, callback) { if (this.events[eventName]) { this.events[eventName] = this.events[eventName].filter(cb => cb !== callback); } } } // Usage const designToolEvents = new EventEmitter(); // Plugin A listens for events designToolEvents.on('shape:created', (shapeData) => { console.log('New shape created:', shapeData); }); // Plugin B emits events designToolEvents.emit('shape:created', { type: 'rectangle', id: 'rect-1', timestamp: Date.now() });