Underline applies the underline leaf mark to selected text. UnderlinePlugin owns the mark key, shortcut, HTML parsing, render tag, and toggle transform.
Loading…
Kit Usage
Add Basic Marks
BasicMarksKit includes UnderlinePlugin, the underscore input rule, and the standard toolbar buttons that use KEYS.underline.
'use client';
import {
BoldRules,
CodeRules,
HighlightRules,
ItalicRules,
MarkComboRules,
StrikethroughRules,
SubscriptRules,
SuperscriptRules,
UnderlineRules,
} from '@platejs/basic-nodes';
import {
BoldPlugin,
CodePlugin,
HighlightPlugin,
ItalicPlugin,
KbdPlugin,
StrikethroughPlugin,
SubscriptPlugin,
SuperscriptPlugin,
UnderlinePlugin,
} from '@platejs/basic-nodes/react';
import { CodeLeaf } from '@/components/ui/code-node';
import { HighlightLeaf } from '@/components/ui/highlight-node';
import { KbdLeaf } from '@/components/ui/kbd-node';
export const BasicMarksKit = [
BoldPlugin.configure({
inputRules: [
BoldRules.markdown({ variant: '*' }),
BoldRules.markdown({ variant: '_' }),
MarkComboRules.markdown({ variant: 'boldItalic' }),
MarkComboRules.markdown({ variant: 'boldUnderline' }),
MarkComboRules.markdown({ variant: 'boldItalicUnderline' }),
MarkComboRules.markdown({ variant: 'italicUnderline' }),
],
}),
ItalicPlugin.configure({
inputRules: [
ItalicRules.markdown({ variant: '*' }),
ItalicRules.markdown({ variant: '_' }),
],
}),
UnderlinePlugin.configure({
inputRules: [UnderlineRules.markdown()],
}),
CodePlugin.configure({
inputRules: [CodeRules.markdown()],
node: { component: CodeLeaf },
shortcuts: { toggle: { keys: 'mod+e' } },
}),
StrikethroughPlugin.configure({
inputRules: [StrikethroughRules.markdown()],
shortcuts: { toggle: { keys: 'mod+shift+x' } },
}),
SubscriptPlugin.configure({
inputRules: [SubscriptRules.markdown()],
shortcuts: { toggle: { keys: 'mod+comma' } },
}),
SuperscriptPlugin.configure({
inputRules: [SuperscriptRules.markdown()],
shortcuts: { toggle: { keys: 'mod+period' } },
}),
HighlightPlugin.configure({
inputRules: [
HighlightRules.markdown({ variant: '==' }),
HighlightRules.markdown({ variant: '≡' }),
],
node: { component: HighlightLeaf },
shortcuts: { toggle: { keys: 'mod+shift+h' } },
}),
KbdPlugin.withComponent(KbdLeaf),
];'use client';
import {
BoldRules,
CodeRules,
HighlightRules,
ItalicRules,
MarkComboRules,
StrikethroughRules,
SubscriptRules,
SuperscriptRules,
UnderlineRules,
} from '@platejs/basic-nodes';
import {
BoldPlugin,
CodePlugin,
HighlightPlugin,
ItalicPlugin,
KbdPlugin,
StrikethroughPlugin,
SubscriptPlugin,
SuperscriptPlugin,
UnderlinePlugin,
} from '@platejs/basic-nodes/react';
import { CodeLeaf } from '@/components/ui/code-node';
import { HighlightLeaf } from '@/components/ui/highlight-node';
import { KbdLeaf } from '@/components/ui/kbd-node';
export const BasicMarksKit = [
BoldPlugin.configure({
inputRules: [
BoldRules.markdown({ variant: '*' }),
BoldRules.markdown({ variant: '_' }),
MarkComboRules.markdown({ variant: 'boldItalic' }),
MarkComboRules.markdown({ variant: 'boldUnderline' }),
MarkComboRules.markdown({ variant: 'boldItalicUnderline' }),
MarkComboRules.markdown({ variant: 'italicUnderline' }),
],
}),
ItalicPlugin.configure({
inputRules: [
ItalicRules.markdown({ variant: '*' }),
ItalicRules.markdown({ variant: '_' }),
],
}),
UnderlinePlugin.configure({
inputRules: [UnderlineRules.markdown()],
}),
CodePlugin.configure({
inputRules: [CodeRules.markdown()],
node: { component: CodeLeaf },
shortcuts: { toggle: { keys: 'mod+e' } },
}),
StrikethroughPlugin.configure({
inputRules: [StrikethroughRules.markdown()],
shortcuts: { toggle: { keys: 'mod+shift+x' } },
}),
SubscriptPlugin.configure({
inputRules: [SubscriptRules.markdown()],
shortcuts: { toggle: { keys: 'mod+comma' } },
}),
SuperscriptPlugin.configure({
inputRules: [SuperscriptRules.markdown()],
shortcuts: { toggle: { keys: 'mod+period' } },
}),
HighlightPlugin.configure({
inputRules: [
HighlightRules.markdown({ variant: '==' }),
HighlightRules.markdown({ variant: '≡' }),
],
node: { component: HighlightLeaf },
shortcuts: { toggle: { keys: 'mod+shift+h' } },
}),
KbdPlugin.withComponent(KbdLeaf),
];import { createPlateEditor } from 'platejs/react';
import { BasicMarksKit } from '@/components/editor/plugins/basic-marks-kit';
export const editor = createPlateEditor({
plugins: [...BasicMarksKit],
});import { createPlateEditor } from 'platejs/react';
import { BasicMarksKit } from '@/components/editor/plugins/basic-marks-kit';
export const editor = createPlateEditor({
plugins: [...BasicMarksKit],
});Add A Toolbar Button
Use MarkToolbarButton with KEYS.underline.
import { UnderlineIcon } from 'lucide-react';
import { KEYS } from 'platejs';
import { MarkToolbarButton } from '@/components/ui/mark-toolbar-button';
export function UnderlineToolbarButton() {
return (
<MarkToolbarButton nodeType={KEYS.underline} tooltip="Underline (⌘+U)">
<UnderlineIcon />
</MarkToolbarButton>
);
}import { UnderlineIcon } from 'lucide-react';
import { KEYS } from 'platejs';
import { MarkToolbarButton } from '@/components/ui/mark-toolbar-button';
export function UnderlineToolbarButton() {
return (
<MarkToolbarButton nodeType={KEYS.underline} tooltip="Underline (⌘+U)">
<UnderlineIcon />
</MarkToolbarButton>
);
}Manual Usage
Install the mark package.
pnpm add @platejs/basic-nodespnpm add @platejs/basic-nodesAdd UnderlinePlugin directly when you do not want the whole kit.
import { UnderlinePlugin } from '@platejs/basic-nodes/react';
import { createPlateEditor } from 'platejs/react';
export const editor = createPlateEditor({
plugins: [UnderlinePlugin],
});import { UnderlinePlugin } from '@platejs/basic-nodes/react';
import { createPlateEditor } from 'platejs/react';
export const editor = createPlateEditor({
plugins: [UnderlinePlugin],
});Register the Markdown-style input rule when users should type underline delimiters.
import { UnderlineRules } from '@platejs/basic-nodes';
import { UnderlinePlugin } from '@platejs/basic-nodes/react';
export const underlinePlugin = UnderlinePlugin.configure({
inputRules: [UnderlineRules.markdown()],
});import { UnderlineRules } from '@platejs/basic-nodes';
import { UnderlinePlugin } from '@platejs/basic-nodes/react';
export const underlinePlugin = UnderlinePlugin.configure({
inputRules: [UnderlineRules.markdown()],
});Ownership
| Surface | Owner | What It Does |
|---|---|---|
BaseUnderlinePlugin | @platejs/basic-nodes | Headless underline mark, HTML parser, render tag, and toggle transform. |
UnderlinePlugin | @platejs/basic-nodes/react | React wrapper with default mod+u shortcut. |
UnderlineRules.markdown | @platejs/basic-nodes | Optional mark input rule factory. |
BasicMarksKit | Registry | Adds UnderlinePlugin with the underscore input rule. |
MarkToolbarButton | Registry UI | Reads active mark state and calls the mark toggle hook. |
The package owns the mark. The registry owns toolbar placement and icon choice.
Behavior
| Behavior | Source |
|---|---|
| Mark key | KEYS.underline |
| Leaf behavior | node.isLeaf: true |
| Toggle transform | editor.tf.underline.toggle() calls editor.tf.toggleMark(type). |
| Shortcut | UnderlinePlugin registers mod+u. |
| HTML tags | u |
| HTML styles | text-decoration: underline |
| HTML guard | Ignores descendants where textDecoration is none. |
| Render output | u |
API Reference
| API | Package | Use |
|---|---|---|
BaseUnderlinePlugin | @platejs/basic-nodes | Headless underline plugin. |
UnderlinePlugin | @platejs/basic-nodes/react | React underline plugin with shortcut defaults. |
UnderlineRules.markdown() | @platejs/basic-nodes | Creates the underline mark input rule. |
tf.underline.toggle() | @platejs/basic-nodes | Toggles the underline mark at the selection. |