Tiptap extension for applying text colors in rich text editors
npx @tessl/cli install tessl/npm-tiptap--extension-color@3.4.0@tiptap/extension-color is a text color extension for Tiptap, a headless rich text editor built on ProseMirror. This extension enables users to apply custom text colors to any text selection within Tiptap editor instances, with support for hex colors, RGB/RGBA values, and named CSS colors.
npm install @tiptap/extension-color@tiptap/extension-text-style (workspace dependency), @tiptap/core (peer dependency)import { Color } from "@tiptap/extension-color";For default import:
import Color from "@tiptap/extension-color";With options type (note: ColorOptions is re-exported from @tiptap/extension-text-style):
import { Color, ColorOptions } from "@tiptap/extension-color";For CommonJS:
const { Color } = require("@tiptap/extension-color");
// or
const Color = require("@tiptap/extension-color").default;import { Editor } from "@tiptap/core";
import Document from "@tiptap/extension-document";
import Paragraph from "@tiptap/extension-paragraph";
import Text from "@tiptap/extension-text";
import { TextStyle } from "@tiptap/extension-text-style";
import { Color } from "@tiptap/extension-color";
// Create editor with Color extension
const editor = new Editor({
extensions: [
Document,
Paragraph,
Text,
TextStyle, // Required dependency
Color, // Color extension
],
content: '<p>Hello <span style="color: #958DF1">colored</span> world!</p>',
});
// Set text color
editor.commands.setColor("#FF0000"); // Hex color
editor.commands.setColor("rgba(255, 0, 0, 0.5)"); // RGBA color
editor.commands.setColor("red"); // Named color
// Remove text color
editor.commands.unsetColor();
// Check if text has specific color
const isPurple = editor.isActive("textStyle", { color: "#958DF1" });
// Get current color
const currentColor = editor.getAttributes("textStyle").color;The Color extension is built on Tiptap's extension system and relies on the TextStyle extension for mark-based styling. Note: @tiptap/extension-color is a thin wrapper package that re-exports the Color extension from @tiptap/extension-text-style. Key components include:
color attribute to specified node types with HTML parsing/renderingsetColor and unsetColor commands for the editorConfigure which node types can have color applied.
interface ColorOptions {
/**
* The types where the color can be applied
* @default ['textStyle']
* @example ['heading', 'paragraph']
*/
types: string[];
}
const Color: Extension<ColorOptions>;Usage Examples:
// Default configuration (textStyle only)
Color
// Custom configuration for specific node types
Color.configure({
types: ['heading', 'paragraph', 'textStyle']
})Apply and remove text colors using editor commands.
interface Commands<ReturnType> {
color: {
/**
* Set the text color
* @param color The color to set (hex, rgb, rgba, or named CSS color)
* @example editor.commands.setColor('red')
* @example editor.commands.setColor('#FF0000')
* @example editor.commands.setColor('rgba(255, 0, 0, 0.5)')
*/
setColor: (color: string) => ReturnType;
/**
* Unset the text color
* @example editor.commands.unsetColor()
*/
unsetColor: () => ReturnType;
};
}Usage Examples:
// Chainable command usage
editor.chain().focus().setColor("#958DF1").run();
editor.chain().focus().unsetColor().run();
// Direct command usage
editor.commands.setColor("red");
editor.commands.unsetColor();
// Multiple color formats supported
editor.commands.setColor("#FF0000"); // Hex
editor.commands.setColor("rgb(255, 0, 0)"); // RGB
editor.commands.setColor("rgba(255, 0, 0, 0.5)"); // RGBA with transparency
editor.commands.setColor("hsl(0, 100%, 50%)"); // HSL
editor.commands.setColor("red"); // Named CSS colorsCheck active color states and retrieve current color values.
/**
* Check if text has specific color applied
* @param mark The mark name (always 'textStyle' for color)
* @param attributes Object with color property to check
* @returns boolean indicating if the color is active
*/
editor.isActive(mark: 'textStyle', attributes: { color: string }): boolean;
/**
* Get current text style attributes including color
* @param mark The mark name (always 'textStyle' for color)
* @returns Object containing current attributes including color
*/
editor.getAttributes(mark: 'textStyle'): { color?: string | null };Usage Examples:
// Check if specific color is active
const isPurple = editor.isActive('textStyle', { color: '#958DF1' });
const isRed = editor.isActive('textStyle', { color: 'red' });
// Get current color
const attributes = editor.getAttributes('textStyle');
const currentColor = attributes.color; // string | null | undefined
// Conditional styling based on active color
if (editor.isActive('textStyle', { color: '#958DF1' })) {
// Style UI button as active for purple color
}The extension automatically handles HTML parsing and rendering of colored text.
HTML Output:
<!-- Extension generates inline styles -->
<span style="color: #958DF1">Purple text</span>
<span style="color: rgba(255, 0, 0, 0.5)">Transparent red text</span>HTML Parsing:
style attribute over computed styles to preserve original format/**
* Configuration options for the Color extension
* Note: This type is re-exported from @tiptap/extension-text-style
*/
interface ColorOptions {
/**
* Array of node type names where color can be applied
* @default ['textStyle']
*/
types: string[];
}
/**
* Extended TextStyle attributes to include color
* Note: This interface is augmented in @tiptap/extension-text-style
*/
interface TextStyleAttributes {
/**
* CSS color value or null if no color is set
*/
color?: string | null;
}
/**
* The Color extension instance
* Note: This is re-exported from @tiptap/extension-text-style
*/
const Color: Extension<ColorOptions>;
/**
* Default export - the Color extension instance
*/
export default Color;The Color extension handles common edge cases gracefully:
import { useEditor, EditorContent } from "@tiptap/react";
import { Color } from "@tiptap/extension-color";
import { TextStyle } from "@tiptap/extension-text-style";
function ColorEditor() {
const editor = useEditor({
extensions: [Document, Paragraph, Text, TextStyle, Color],
content: "<p>Hello world!</p>",
});
return (
<div>
<input
type="color"
onChange={(e) => editor?.commands.setColor(e.target.value)}
value={editor?.getAttributes("textStyle").color || "#000000"}
/>
<button onClick={() => editor?.commands.unsetColor()}>
Remove Color
</button>
<EditorContent editor={editor} />
</div>
);
}<template>
<div>
<input
type="color"
@input="editor.commands.setColor($event.target.value)"
:value="editor.getAttributes('textStyle').color || '#000000'"
/>
<button @click="editor.commands.unsetColor()">Remove Color</button>
<editor-content :editor="editor" />
</div>
</template>
<script>
import { Editor, EditorContent } from "@tiptap/vue-3";
import { Color } from "@tiptap/extension-color";
import { TextStyle } from "@tiptap/extension-text-style";
export default {
components: { EditorContent },
data() {
return {
editor: new Editor({
extensions: [Document, Paragraph, Text, TextStyle, Color],
content: "<p>Hello world!</p>",
}),
};
},
};
</script>