Keyboard Input

PreviousNext

Style keyboard shortcuts and key names.

Keyboard Input applies the kbd leaf mark to selected text. Use it for shortcuts, key names, and command hints that should render as <kbd>.

Loading…

Features

  • KEYS.kbd leaf mark.
  • Hard selection affinity.
  • HTML deserialization from kbd.
  • <kbd> rendering by default.
  • Registry KbdLeaf for styled keyboard input.
  • Static rendering support through KbdLeafStatic.

Kit Usage

Add Basic Marks

BasicMarksKit includes KbdPlugin.withComponent(KbdLeaf). It does not add a shortcut or input rule for keyboard input.

'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 the Leaf

KbdLeaf provides the registry styling for the <kbd> element.

'use client';
 
import * as React from 'react';
 
import type { PlateLeafProps } from 'platejs/react';
 
import { PlateLeaf } from 'platejs/react';
 
export function KbdLeaf(props: PlateLeafProps) {
  return (
    <PlateLeaf
      {...props}
      as="kbd"
      className="rounded border border-border bg-muted px-1.5 py-0.5 font-mono text-sm shadow-[rgba(255,_255,_255,_0.1)_0px_0.5px_0px_0px_inset,_rgb(248,_249,_250)_0px_1px_5px_0px_inset,_rgb(193,_200,_205)_0px_0px_0px_0.5px,_rgb(193,_200,_205)_0px_2px_1px_-1px,_rgb(193,_200,_205)_0px_1px_0px_0px] dark:shadow-[rgba(255,_255,_255,_0.1)_0px_0.5px_0px_0px_inset,_rgb(26,_29,_30)_0px_1px_5px_0px_inset,_rgb(76,_81,_85)_0px_0px_0px_0.5px,_rgb(76,_81,_85)_0px_2px_1px_-1px,_rgb(76,_81,_85)_0px_1px_0px_0px]"
    >
      {props.children}
    </PlateLeaf>
  );
}
'use client';
 
import * as React from 'react';
 
import type { PlateLeafProps } from 'platejs/react';
 
import { PlateLeaf } from 'platejs/react';
 
export function KbdLeaf(props: PlateLeafProps) {
  return (
    <PlateLeaf
      {...props}
      as="kbd"
      className="rounded border border-border bg-muted px-1.5 py-0.5 font-mono text-sm shadow-[rgba(255,_255,_255,_0.1)_0px_0.5px_0px_0px_inset,_rgb(248,_249,_250)_0px_1px_5px_0px_inset,_rgb(193,_200,_205)_0px_0px_0px_0.5px,_rgb(193,_200,_205)_0px_2px_1px_-1px,_rgb(193,_200,_205)_0px_1px_0px_0px] dark:shadow-[rgba(255,_255,_255,_0.1)_0px_0.5px_0px_0px_inset,_rgb(26,_29,_30)_0px_1px_5px_0px_inset,_rgb(76,_81,_85)_0px_0px_0px_0.5px,_rgb(76,_81,_85)_0px_2px_1px_-1px,_rgb(76,_81,_85)_0px_1px_0px_0px]"
    >
      {props.children}
    </PlateLeaf>
  );
}

Add a Toolbar Control

The registry MoreToolbarButton toggles keyboard input from the More menu.

import { MoreToolbarButton } from '@/components/ui/more-toolbar-button';
 
export function FormattingMoreMenu() {
  return <MoreToolbarButton />;
}
import { MoreToolbarButton } from '@/components/ui/more-toolbar-button';
 
export function FormattingMoreMenu() {
  return <MoreToolbarButton />;
}

Manual Usage

Install the mark package.

pnpm add @platejs/basic-nodes
pnpm add @platejs/basic-nodes

Add KbdPlugin directly when you want the default <kbd> render.

import { KbdPlugin } from '@platejs/basic-nodes/react';
import { createPlateEditor } from 'platejs/react';
 
export const editor = createPlateEditor({
  plugins: [KbdPlugin],
});
import { KbdPlugin } from '@platejs/basic-nodes/react';
import { createPlateEditor } from 'platejs/react';
 
export const editor = createPlateEditor({
  plugins: [KbdPlugin],
});

Attach the registry leaf when you want the same visual treatment as the kit.

import { KbdPlugin } from '@platejs/basic-nodes/react';
 
import { KbdLeaf } from '@/components/ui/kbd-node';
 
export const kbdPlugin = KbdPlugin.withComponent(KbdLeaf);
import { KbdPlugin } from '@platejs/basic-nodes/react';
 
import { KbdLeaf } from '@/components/ui/kbd-node';
 
export const kbdPlugin = KbdPlugin.withComponent(KbdLeaf);

Ownership

SurfaceOwnerWhat It Does
BaseKbdPlugin@platejs/basic-nodesHeadless keyboard-input mark, HTML parser, render tag, selection rule, and toggle transform.
KbdPlugin@platejs/basic-nodes/reactReact wrapper for the headless keyboard-input mark.
KbdLeafRegistry UIStyled client <kbd> leaf using PlateLeaf.
KbdLeafStaticRegistry UIStatic rendering version using SlateLeaf.
BasicMarksKitRegistryAdds KbdPlugin.withComponent(KbdLeaf).
MoreToolbarButtonRegistry UICalls editor.tf.toggleMark(KEYS.kbd) from the More menu.

The package owns the mark. The registry owns keycap styling and toolbar placement.

Behavior

BehaviorSource
Mark keyKEYS.kbd
Leaf behaviornode.isLeaf: true
Toggle transformeditor.tf.kbd.toggle() calls editor.tf.toggleMark(type).
Selection affinityhard
HTML tagskbd
Render outputkbd
Kit componentKbdLeaf
Registry toolbarMoreToolbarButton toggles KEYS.kbd.

API Reference

APIPackageUse
BaseKbdPlugin@platejs/basic-nodesHeadless keyboard-input plugin.
KbdPlugin@platejs/basic-nodes/reactReact keyboard-input plugin.
tf.kbd.toggle()@platejs/basic-nodesToggles the keyboard-input mark at the selection.
KbdLeafRegistry UIStyled client keyboard-input leaf.
KbdLeafStaticRegistry UIStyled static keyboard-input leaf.