CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-quill

A modern, powerful rich text editor built for compatibility and extensibility

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

theme-system.mddocs/

Theme System

Theme system providing Snow and Bubble themes with customizable UI components and toolbar layouts. Themes control the visual presentation and user interface elements of the Quill editor, including toolbar positioning, styling, and interactive behaviors.

Capabilities

Base Theme Class

Abstract base class that all Quill themes extend, providing common UI management functionality.

/**
 * Base theme class for UI management
 */
abstract class Theme {
  /** Default theme configuration options */
  static DEFAULTS: Record<string, unknown>;
  
  /** Theme registry for available themes */
  static themes: Record<string, ThemeConstructor>;
  
  /** Quill instance this theme belongs to */
  quill: Quill;
  
  /** Theme configuration options */
  options: Record<string, unknown>;
  
  /** Registered modules for this theme */
  modules: Record<string, Module>;
  
  /**
   * Create theme instance
   * @param quill - Quill editor instance
   * @param options - Theme configuration options
   */
  constructor(quill: Quill, options: Record<string, unknown>);
  
  /**
   * Initialize theme after construction
   */
  init(): void;
  
  /**
   * Add and initialize module
   * @param name - Module name
   * @returns Initialized module instance
   */
  addModule(name: string): Module;
}

interface ThemeOptions {
  [key: string]: unknown;
}

interface ThemeConstructor {
  new (quill: Quill, options: ThemeOptions): Theme;
  DEFAULTS: ThemeOptions;
}

Usage Examples:

// Define custom theme
class CustomTheme extends Theme {
  static DEFAULTS = {
    modules: {
      toolbar: [
        ['bold', 'italic'],
        ['link']
      ]
    }
  };
  
  constructor(quill, options) {
    super(quill, options);
    this.buildCustomUI();
  }
  
  init() {
    super.init();
    this.setupCustomBehaviors();
  }
  
  buildCustomUI() {
    // Custom UI setup
  }
}

// Register custom theme
Quill.register('themes/custom', CustomTheme);

// Use custom theme
const quill = new Quill('#editor', {
  theme: 'custom'
});

Snow Theme

Professional theme with toolbar positioned above the editor, suitable for document editing interfaces.

class SnowTheme extends BaseTheme {
  static DEFAULTS: {
    modules: {
      toolbar: ToolbarConfig;
    };
  };
  
  /**
   * Extend toolbar with Snow-specific features
   * @param toolbar - Toolbar module instance
   */
  extendToolbar(toolbar: Toolbar): void;
  
  /**
   * Build Snow theme UI
   */
  buildTheme(): void;
}

class SnowTooltip extends BaseTooltip {
  /** Root element for tooltip */
  root: HTMLElement;
  
  /**
   * Listen for tooltip events
   */
  listen(): void;
  
  /**
   * Show tooltip at position
   */
  show(): void;
  
  /**
   * Hide tooltip
   */
  hide(): void;
  
  /**
   * Position tooltip relative to reference
   * @param reference - Reference element or bounds
   */
  position(reference: HTMLElement | Bounds): void;
}

Usage Examples:

// Use Snow theme (default)
const quill = new Quill('#editor', {
  theme: 'snow',
  modules: {
    toolbar: [
      [{ 'header': [1, 2, 3, false] }],
      ['bold', 'italic', 'underline'],
      [{ 'color': [] }, { 'background': [] }],
      [{ 'list': 'ordered'}, { 'list': 'bullet' }],
      [{ 'align': [] }],
      ['link', 'image', 'video'],
      ['clean']
    ]
  }
});

// Snow theme with custom toolbar container
const quill2 = new Quill('#editor2', {
  theme: 'snow',
  modules: {
    toolbar: {
      container: '#toolbar-container'
    }
  }
});

// Access Snow-specific features
const toolbar = quill.getModule('toolbar');
// Snow theme adds link editing functionality

Bubble Theme

Contextual theme with floating toolbar that appears near selected text, suitable for inline editing scenarios.

class BubbleTheme extends BaseTheme {
  static DEFAULTS: {
    modules: {
      toolbar: ToolbarConfig;
    };
  };
  
  /**
   * Extend toolbar with Bubble-specific features
   * @param toolbar - Toolbar module instance
   */
  extendToolbar(toolbar: Toolbar): void;
  
  /**
   * Build Bubble theme UI
   */
  buildTheme(): void;
}

class BubbleTooltip extends BaseTooltip {
  /**
   * Show tooltip at current selection
   */
  show(): void;
  
  /**
   * Hide tooltip
   */
  hide(): void;
  
  /**
   * Position tooltip near selection
   */
  position(): void;
}

Usage Examples:

// Use Bubble theme
const quill = new Quill('#editor', {
  theme: 'bubble',
  modules: {
    toolbar: [
      ['bold', 'italic'],
      ['link'],
      [{ 'header': 1 }, { 'header': 2 }]
    ]
  }
});

// Bubble theme shows toolbar on text selection
// No permanent toolbar is visible

// Custom bubble configuration
const quill2 = new Quill('#editor2', {
  theme: 'bubble',
  bounds: '#editor-container', // Constrain bubble to container
  modules: {
    toolbar: [
      ['bold', 'italic', 'underline'],
      ['link']
    ]
  }
});

Base Theme Components

Common UI components used across themes.

/**
 * Base theme with common UI functionality
 */
class BaseTheme extends Theme {
  /** Array of picker instances */
  pickers: Picker[];
  
  /** Tooltip instance */
  tooltip: BaseTooltip;
  
  /**
   * Build toolbar buttons
   * @param buttons - Button elements
   * @param icons - Icon definitions
   */
  buildButtons(buttons: HTMLElement[], icons: Record<string, string>): void;
  
  /**
   * Build picker controls
   * @param selects - Select elements
   * @param icons - Icon definitions
   */
  buildPickers(selects: HTMLElement[], icons: Record<string, string>): void;
}

/**
 * Base tooltip functionality
 */
class BaseTooltip extends Tooltip {
  /** Text input element */
  textbox: HTMLInputElement;
  
  /** Current link range being edited */
  linkRange: Range | null;
  
  /**
   * Enter edit mode
   * @param mode - Edit mode ('link', 'video', 'formula')
   * @param preview - Preview element
   */
  edit(mode?: string, preview?: HTMLElement): void;
  
  /**
   * Cancel editing
   */
  cancel(): void;
  
  /**
   * Save changes
   */
  save(): void;
  
  /**
   * Set up event listeners
   */
  listen(): void;
  
  /**
   * Restore focus to editor
   */
  restoreFocus(): void;
}

Usage Examples:

// Access theme components
const quill = new Quill('#editor', { theme: 'snow' });

// Get tooltip for custom functionality
const theme = quill.theme;
if (theme.tooltip) {
  // Custom tooltip behavior
  theme.tooltip.edit('link');
}

// Access pickers
if (theme.pickers) {
  theme.pickers.forEach(picker => {
    // Custom picker behavior
    picker.update();
  });
}

UI Components

Reusable UI components used by themes.

/**
 * Dropdown picker component
 */
class Picker {
  /** Original select element */
  select: HTMLSelectElement;
  
  /** Picker container element */
  container: HTMLElement;
  
  /** Picker label element */
  label: HTMLElement;
  
  /** Picker options container */
  options: HTMLElement;
  
  /**
   * Build picker UI from select element
   */
  buildPicker(): void;
  
  /**
   * Close picker dropdown
   */
  close(): void;
  
  /**
   * Escape picker (close without selection)
   */
  escape(): void;
  
  /**
   * Select item
   * @param item - Item to select
   * @param trigger - Whether to trigger change event
   */
  selectItem(item: HTMLElement, trigger?: boolean): void;
  
  /**
   * Toggle picker visibility
   */
  togglePicker(): void;
  
  /**
   * Update picker state
   */
  update(): void;
}

/**
 * Color picker component
 */
class ColorPicker extends Picker {
  /**
   * Build color picker with color swatches
   */
  buildItem(option: HTMLOptionElement): HTMLElement;
}

/**
 * Icon picker component
 */
class IconPicker extends Picker {
  /**
   * Build icon picker with SVG icons
   */
  buildItem(option: HTMLOptionElement): HTMLElement;
}

/**
 * Tooltip component
 */
class Tooltip {
  /** Root tooltip element */
  root: HTMLElement;
  
  /** Quill instance */
  quill: Quill;
  
  /** Bounds for positioning */
  boundsContainer: HTMLElement;
  
  /**
   * Hide tooltip
   */
  hide(): void;
  
  /**
   * Position tooltip relative to reference
   * @param reference - Reference element or bounds
   */
  position(reference: HTMLElement | Bounds): void;
  
  /**
   * Show tooltip
   */
  show(): void;
}

Usage Examples:

// Access UI components
const quill = new Quill('#editor', { 
  theme: 'snow',
  modules: {
    toolbar: [
      [{ 'color': [] }],
      [{ 'background': [] }]
    ]
  }
});

const toolbar = quill.getModule('toolbar');
const theme = quill.theme;

// Find color pickers
const colorPickers = theme.pickers.filter(picker => {
  return picker.select.classList.contains('ql-color');
});

// Custom picker behavior
colorPickers.forEach(picker => {
  picker.container.addEventListener('click', (e) => {
    console.log('Color picker clicked');
  });
});

Theme Customization

Customize existing themes or create new ones.

// Extend Snow theme
class CustomSnowTheme extends SnowTheme {
  constructor(quill, options) {
    super(quill, options);
    this.addCustomStyles();
  }
  
  addCustomStyles() {
    // Add custom CSS classes
    this.quill.container.classList.add('custom-snow');
  }
  
  extendToolbar(toolbar) {
    super.extendToolbar(toolbar);
    
    // Add custom toolbar functionality
    toolbar.addHandler('custom', (value) => {
      // Custom handler
    });
  }
}

// Register custom theme
Quill.register('themes/custom-snow', CustomSnowTheme);

Usage Examples:

// Theme with custom CSS
const quill = new Quill('#editor', {
  theme: 'snow'
});

// Add custom CSS classes
quill.container.classList.add('dark-theme');

// Custom theme configuration
const quill2 = new Quill('#editor2', {
  theme: 'snow',
  modules: {
    toolbar: {
      container: [
        [{ 'header': [1, 2, 3, false] }],
        ['bold', 'italic'],
        ['custom-button'] // Custom button
      ],
      handlers: {
        'custom-button': () => {
          console.log('Custom button clicked');
        }
      }
    }
  }
});

// No theme (base editor only)
const quill3 = new Quill('#editor3'); // No theme specified

// Theme switching
function switchTheme(themeName) {
  // Destroy current editor
  const content = quill.getContents();
  quill.container.innerHTML = '';
  
  // Create new editor with different theme
  const newQuill = new Quill(quill.container, {
    theme: themeName,
    modules: quill.options.modules
  });
  
  // Restore content
  newQuill.setContents(content);
  
  return newQuill;
}

// Switch to bubble theme
const bubbleQuill = switchTheme('bubble');

Theme Events and Integration

Themes can listen to editor events and provide custom behaviors.

class EventfulTheme extends Theme {
  constructor(quill, options) {
    super(quill, options);
    this.setupEventListeners();
  }
  
  setupEventListeners() {
    this.quill.on('selection-change', this.onSelectionChange.bind(this));
    this.quill.on('text-change', this.onTextChange.bind(this));
  }
  
  onSelectionChange(range, oldRange, source) {
    // Theme-specific selection handling
    if (range) {
      this.showContextualUI(range);
    } else {
      this.hideContextualUI();
    }
  }
  
  onTextChange(delta, oldDelta, source) {
    // Theme-specific text change handling
    this.updateUI();
  }
}

Usage Examples:

// Theme with custom event handling
class InteractiveTheme extends SnowTheme {
  constructor(quill, options) {
    super(quill, options);
    
    // Add selection highlighting
    this.quill.on('selection-change', (range) => {
      if (range && range.length > 0) {
        this.highlightSelection(range);
      } else {
        this.clearHighlight();
      }
    });
  }
  
  highlightSelection(range) {
    // Add visual selection indicator
    const bounds = this.quill.getBounds(range);
    if (bounds) {
      this.showSelectionIndicator(bounds);
    }
  }
  
  clearHighlight() {
    this.hideSelectionIndicator();
  }
}

Quill.register('themes/interactive', InteractiveTheme);

const quill = new Quill('#editor', {
  theme: 'interactive'
});

Install with Tessl CLI

npx tessl i tessl/npm-quill

docs

delta-operations.md

editor-core.md

formatting-system.md

index.md

module-system.md

registry-system.md

theme-system.md

tile.json