Theming

Complete control over your editor's appearance

Customize every aspect of your LexKit editor with powerful theming capabilities. From CSS classes to Tailwind utilities, make your editor match your design system perfectly.

CSS ClassesTailwind ReadyType SafeExtensible

Theme System Overview

LexKit's theming system builds on Lexical's foundation while adding powerful customization options.

Lexical Foundation

Extends Lexical's built-in theme system with additional properties for toolbar, containers, and custom extensions.

CSS & Tailwind

Use any CSS classes or Tailwind utilities. Full control over styling without framework restrictions.

Type Safe

Full TypeScript support with intelligent autocomplete and compile-time validation.

Quick Start

Get started with theming in just a few lines of code.

1. Define Your Theme

Create a custom theme object

import { LexKitTheme } from '@lexkit/editor'

const myTheme: LexKitTheme = {
  // Content styling
  paragraph: 'mb-4 text-gray-800',
  heading: {
    h1: 'text-2xl font-bold mb-4',
    h2: 'text-xl font-semibold mb-3',
    h3: 'text-lg font-medium mb-2',
  },
  text: {
    bold: 'font-bold',
    italic: 'italic',
    underline: 'underline',
    strikethrough: 'line-through',
    code: 'bg-gray-100 px-1 py-0.5 rounded text-sm font-mono',
  },
  quote: 'border-l-4 border-gray-300 pl-4 italic',
  link: 'text-blue-600 hover:text-blue-800 underline',

  // Toolbar styling
  toolbar: {
    button: 'px-3 py-2 text-sm font-medium rounded hover:bg-gray-100 transition-colors',
    buttonActive: 'bg-blue-100 text-blue-700',
    buttonDisabled: 'opacity-50 cursor-not-allowed',
    group: 'flex gap-1 border border-gray-200 rounded p-1',
  },

  // Container styling
  container: 'border border-gray-200 rounded-lg overflow-hidden',
  wrapper: 'min-h-[200px] p-4',
  richText: {
    contentEditable: 'outline-none',
    placeholder: 'text-gray-400 italic',
  },
}
2. Apply the Theme

Apply your theme to the editor

<Provider
  extensions={extensions}
  config={{ theme: myTheme }}
>
  <MyEditor />
</Provider>

Tailwind CSS Example

See how to style your editor using pure Tailwind CSS classes.

Tailwind Theme Configuration

Complete Tailwind theme example

import { LexKitTheme } from '@lexkit/editor'

const tailwindTheme: LexKitTheme = {
  // Content styling
  paragraph: 'mb-4 text-gray-800 leading-relaxed',
  heading: {
    h1: 'text-3xl font-bold mb-6 text-gray-900',
    h2: 'text-2xl font-bold mb-4 text-gray-900',
    h3: 'text-xl font-semibold mb-3 text-gray-900',
  },
  text: {
    bold: 'font-bold text-gray-900',
    italic: 'italic text-gray-700',
    underline: 'underline decoration-blue-500',
  },
  quote: 'border-l-4 border-blue-500 pl-4 italic text-gray-600 mb-4',

  // Toolbar styling
  toolbar: {
    button: 'px-3 py-2 text-sm font-medium rounded-md transition-colors',
    buttonActive: 'bg-blue-600 text-white shadow-sm',
    buttonDisabled: 'bg-gray-100 text-gray-400 cursor-not-allowed',
    group: 'flex gap-2'
  },

  // Container styling
  container: 'border border-gray-200 rounded-lg overflow-hidden',
  wrapper: 'min-h-[300px] p-4',
  richText: {
    contentEditable: 'outline-none min-h-[200px]',
    placeholder: 'text-gray-400 italic'
  }
}

Live Examples

See theming in action with these interactive examples.

Custom CSS Classes Theme

Using custom CSS classes for complete styling control

Experience complete theme customization! This editor uses entirely custom CSS classes.

Dynamic Dark Mode Theme

Switch between light and dark themes dynamically

Theme: Light

Type here to see theme switching...

Same component, different theme - no manual styling needed!

Custom CSS Classes Theme

Using custom CSS classes for complete styling control

Experience the power of theming! This editor uses custom CSS classes for complete control over appearance.

Tailwind CSS Theme

Pure Tailwind utilities for modern, responsive styling

Start writing with Tailwind-styled editor...

This editor is styled entirely with Tailwind CSS classes — no custom CSS files needed!

Theme Properties

Complete reference of all available theme properties.

Lexical Built-in Properties
CategoryPropertyDescription
Text Formattingtext.boldBold text styling
Text Formattingtext.italicItalic text styling
Text Formattingtext.underlineUnderline text styling
Text Formattingtext.strikethroughStrikethrough styling
Text Formattingtext.codeInline code styling
Content ElementsparagraphParagraph styling
Content Elementsheading.h1-h6Heading levels (h1 through h6)
Content ElementsquoteBlockquote styling
Content ElementslinkLink styling
Content ElementsimageImage styling
LexKit Custom Properties
CategoryPropertyDescription
Toolbartoolbar.buttonBase button styling
Toolbartoolbar.buttonActiveActive button styling
Toolbartoolbar.buttonDisabledDisabled button styling
Toolbartoolbar.groupButton group container
ContainerscontainerMain editor container
ContainerswrapperEditor wrapper element
ContainersrichText.contentEditableContent editable area
ContainersrichText.placeholderPlaceholder text
Extension-Specific Properties
ExtensionPropertyDescription
Draggable Blocksdraggable.handleDrag handle styling
Draggable Blocksdraggable.handleHoverHover state for drag handle
Draggable Blocksdraggable.blockDraggingBlock being dragged styling
Draggable Blocksdraggable.dropIndicatorDrop zone indicator styling
Floating ToolbarfloatingToolbar.containerToolbar container styling
Floating ToolbarfloatingToolbar.buttonToolbar buttons styling
Floating ToolbarfloatingToolbar.buttonActiveActive button state styling

Extension-Specific Theming

Customize the appearance of specific extensions like draggable blocks and floating toolbar.

Extension Theme Properties

Extension-specific theme configuration

const themeWithExtensions: LexKitTheme = {
  // Base properties
  paragraph: 'editor-paragraph',
  text: {
    bold: 'editor-bold',
  },

  // Draggable blocks extension
  draggable: {
    handle: 'absolute -left-8 top-0 w-6 h-6 bg-gray-200 hover:bg-gray-300 rounded cursor-move flex items-center justify-center',
    handleHover: 'bg-gray-300',
    handleDragging: 'bg-blue-500',
    blockDragging: 'opacity-50 border-2 border-blue-500 border-dashed',
    dropIndicator: 'h-1 bg-blue-500 my-2 rounded',
    upButton: 'absolute -left-6 -top-3 w-5 h-5 bg-white border border-gray-300 rounded-full flex items-center justify-center text-xs hover:bg-gray-50',
    downButton: 'absolute -left-6 -bottom-3 w-5 h-5 bg-white border border-gray-300 rounded-full flex items-center justify-center text-xs hover:bg-gray-50',
    blockIsDragging: 'shadow-lg transform rotate-2',
    buttonStack: 'flex flex-col gap-1',
  },

  // Floating toolbar extension
  floatingToolbar: {
    container: 'absolute z-50 bg-white border border-gray-300 rounded-lg shadow-lg p-2 flex gap-1',
    button: 'w-8 h-8 flex items-center justify-center rounded hover:bg-gray-100 text-sm',
    buttonActive: 'bg-blue-100 text-blue-700',
  },
}

Advanced Usage

Take your theming to the next level with advanced techniques.

Theme Merging

Combine themes or override specific properties without rewriting everything.

Theme merging example

import { mergeThemes, defaultLexKitTheme, LexKitTheme } from '@lexkit/editor'

// Start with default theme
const baseTheme = defaultLexKitTheme

// Override specific properties
const customOverrides: Partial<LexKitTheme> = {
  text: {
    bold: 'my-custom-bold-class',
    italic: 'my-custom-italic-class',
  },
  toolbar: {
    button: 'my-toolbar-button',
    buttonActive: 'my-toolbar-button-active',
  },
  container: 'my-editor-container',
}

// Merge themes
const finalTheme = mergeThemes(baseTheme, customOverrides)

// Use the merged theme
<Provider extensions={extensions} config={{ theme: finalTheme }}>
  <MyEditor />
</Provider>
Dynamic Theming

Change themes dynamically based on user preferences or application state.

Dynamic theme switching example

"use client"

import { useState } from 'react'
import { LexKitTheme } from '@lexkit/editor'

const lightTheme: LexKitTheme = {
  container: 'bg-white border-gray-200',
  paragraph: 'text-gray-900',
  toolbar: {
    button: 'bg-gray-100 hover:bg-gray-200 text-gray-900',
  },
}

const darkTheme: LexKitTheme = {
  container: 'bg-gray-900 border-gray-700',
  paragraph: 'text-white',
  toolbar: {
    button: 'bg-gray-700 hover:bg-gray-600 text-white',
  },
}

function ThemeableEditor() {
  const [isDark, setIsDark] = useState(false)
  const currentTheme = isDark ? darkTheme : lightTheme

  return (
    <div>
      <button
        onClick={() => setIsDark(!isDark)}
        className="mb-4 px-4 py-2 bg-blue-500 text-white rounded"
      >
        Toggle {isDark ? 'Light' : 'Dark'} Theme
      </button>

      <Provider extensions={extensions} config={{ theme: currentTheme }}>
        <MyEditor />
      </Provider>
    </div>
  )
}
CSS Variables

Use CSS custom properties for dynamic color schemes and responsive design.

CSS Variables theme example

/* CSS with custom properties */
:root {
  --editor-bg: #ffffff;
  --editor-text: #1f2937;
  --editor-border: #e5e7eb;
  --button-primary: #3b82f6;
  --button-hover: #2563eb;
}

.dark {
  --editor-bg: #1f2937;
  --editor-text: #f9fafb;
  --editor-border: #374151;
  --button-primary: #60a5fa;
  --button-hover: #3b82f6;
}

/* Theme using CSS variables */
const responsiveTheme: LexKitTheme = {
  container: 'border border-[var(--editor-border)] rounded-lg bg-[var(--editor-bg)]',
  paragraph: 'text-[var(--editor-text)] mb-4 leading-relaxed',
  text: {
    bold: 'font-bold text-[var(--editor-text)]',
  },
  toolbar: {
    button: 'px-3 py-2 bg-[var(--button-primary)] hover:bg-[var(--button-hover)] text-white rounded-md transition-colors',
  },
}
Component-Level Theming

Apply different themes to different editor instances in the same application.

Component-level theming example

import { LexKitTheme } from '@lexkit/editor'

// Different themes for different editor instances
const minimalTheme: LexKitTheme = {
  container: 'border border-gray-200 rounded',
  paragraph: 'text-sm text-gray-700',
  toolbar: {
    button: 'w-6 h-6 text-xs',
  },
}

const richTheme: LexKitTheme = {
  container: 'border-2 border-blue-200 rounded-lg shadow-lg',
  paragraph: 'text-base text-gray-900 leading-relaxed',
  heading: {
    h1: 'text-3xl font-bold text-blue-900',
  },
  toolbar: {
    button: 'px-4 py-2 text-sm font-medium bg-blue-50 hover:bg-blue-100',
    buttonActive: 'bg-blue-200',
  },
}

function MultiEditorApp() {
  return (
    <div className="space-y-8">
      {/* Minimal editor for comments */}
      <div>
        <h3 className="text-lg font-semibold mb-2">Comment Editor</h3>
        <Provider extensions={basicExtensions} config={{ theme: minimalTheme }}>
          <CommentEditor />
        </Provider>
      </div>

      {/* Rich editor for content creation */}
      <div>
        <h3 className="text-lg font-semibold mb-2">Content Editor</h3>
        <Provider extensions={richExtensions} config={{ theme: richTheme }}>
          <ContentEditor />
        </Provider>
      </div>
    </div>
  )
}

Best Practices

Tips for creating maintainable and performant themes.

Design System Integration

Use your existing design system tokens and classes. Maintain consistency across your application by leveraging established patterns and variables.

Performance Considerations

Keep themes lightweight and avoid complex selectors. Use CSS custom properties for dynamic values to minimize re-renders.

Accessibility First

Ensure sufficient color contrast and consider focus states. Test with screen readers and keyboard navigation to maintain usability.

Responsive Design

Design themes that work across different screen sizes. Use responsive utilities and consider touch interactions for mobile devices.

Migration Guide

Upgrading from plain Lexical themes to LexKit theming.

From Lexical to LexKit

Before (Lexical only)

Plain Lexical theme configuration

const lexicalTheme = {
  paragraph: 'editor-paragraph',
  text: {
    bold: 'editor-bold',
  },
}

<LexicalComposer initialConfig={{ theme: lexicalTheme }}>
  <Editor />
</LexicalComposer>

After (LexKit)

LexKit theme configuration with extensions

import { LexKitTheme } from '@lexkit/editor'

const lexkitTheme: LexKitTheme = {
  ...lexicalTheme,
  toolbar: {
    button: 'toolbar-button',
  },
  container: 'editor-container',
}

<Provider extensions={extensions} config={{ theme: lexkitTheme }}>
  <MyEditor />
</Provider>