Skip to main content

Overview

The horizontal-rule extension adds support for horizontal rule nodes, which create visual dividers between sections of content. These render as <hr> elements.

Installation

npm install @prosekit/extensions

Usage

import { defineHorizontalRule } from '@prosekit/extensions/horizontal-rule'
import { createEditor } from '@prosekit/core'

const extension = defineHorizontalRule()
const editor = createEditor({ extension })

API Reference

defineHorizontalRule()

Defines a horizontal rule node with commands, input rules, and node specification. Returns: HorizontalRuleExtension This extension includes:
  • Node specification
  • Insert command
  • Input rules for Markdown-style syntax

defineHorizontalRuleSpec()

Defines only the horizontal rule node specification. Returns: HorizontalRuleSpecExtension

defineHorizontalRuleCommands()

Defines horizontal rule-related commands. Returns: HorizontalRuleCommandsExtension

defineHorizontalRuleInputRule()

Defines input rules for Markdown-style horizontal rule syntax. Returns: PlainExtension

insertHorizontalRule()

Returns a command that inserts a horizontal rule at the current selection. Returns: Command
import { insertHorizontalRule } from '@prosekit/extensions/horizontal-rule'

const command = insertHorizontalRule()

Node Specification

The horizontal rule node is defined with the following properties:
  • name: horizontalRule
  • group: block
  • parseDOM: [{ tag: 'hr' }]
  • toDOM: Renders as <div class="prosekit-horizontal-rule"><hr></div>
Note: The <hr> is wrapped in a <div> to make it taller and easier to click in the editor.

Commands

insertHorizontalRule()

Inserts a horizontal rule at the current cursor position.
import { useEditor } from '@prosekit/react'

function HorizontalRuleButton() {
  const editor = useEditor()
  
  return (
    <button onClick={() => editor.commands.insertHorizontalRule()}>
      Insert Divider
    </button>
  )
}
Command signature:
insertHorizontalRule: []

Input Rules

The extension supports Markdown-style horizontal rule syntax:
--- → Horizontal rule
Type three dashes (---) on an empty line to insert a horizontal rule.

Examples

Basic Setup

import { createEditor } from '@prosekit/core'
import { union } from '@prosekit/core'
import { defineDoc } from '@prosekit/extensions/doc'
import { defineParagraph } from '@prosekit/extensions/paragraph'
import { defineHorizontalRule } from '@prosekit/extensions/horizontal-rule'
import { defineText } from '@prosekit/extensions/text'

const extension = union([
  defineDoc(),
  defineParagraph(),
  defineHorizontalRule(),
  defineText(),
])

const editor = createEditor({ extension })

Insert Button

import { useEditor } from '@prosekit/react'
import { Button } from './ui/button'

function DividerButton() {
  const editor = useEditor()
  
  return (
    <Button
      onClick={() => editor.commands.insertHorizontalRule()}
      aria-label="Insert horizontal rule"
    >
      <MinusIcon /> Divider
    </Button>
  )
}

Toolbar Integration

import { useEditor } from '@prosekit/react'

function Toolbar() {
  const editor = useEditor()
  
  return (
    <div className="toolbar">
      <button onClick={() => editor.commands.setParagraph()}>
        Paragraph
      </button>
      <button onClick={() => editor.commands.setHeading({ level: 1 })}>
        H1
      </button>
      <button onClick={() => editor.commands.insertHorizontalRule()}>
        HR
      </button>
    </div>
  )
}

Programmatic Insertion

const editor = useEditor()

// Insert a horizontal rule
editor.commands.insertHorizontalRule()

// Insert after specific content
editor.commands.focus()
// ... navigate to position
editor.commands.insertHorizontalRule()

Using the Direct Command

import { insertHorizontalRule } from '@prosekit/extensions/horizontal-rule'
import { useEditor } from '@prosekit/react'

function MyComponent() {
  const editor = useEditor()
  
  const handleClick = () => {
    const command = insertHorizontalRule()
    editor.execute(command)
  }
  
  return <button onClick={handleClick}>Insert HR</button>
}

Styling

Horizontal rules are wrapped in a div for better editor interaction:
/* Container for easier selection */
.prosekit-horizontal-rule {
  padding: 1rem 0;
  cursor: pointer;
}

.prosekit-horizontal-rule:hover {
  background-color: rgba(0, 0, 0, 0.05);
}

/* The actual horizontal rule */
.prosekit-horizontal-rule hr {
  border: none;
  border-top: 2px solid #e5e7eb;
  margin: 0;
}

/* Selected state */
.prosekit-horizontal-rule.ProseMirror-selectednode {
  outline: 2px solid #3b82f6;
  outline-offset: 2px;
}

Minimal Styling

.prosekit-editor hr {
  border: none;
  border-top: 1px solid #ddd;
  margin: 2rem 0;
}

Custom Styles

/* Dotted line */
.prosekit-editor hr.dotted {
  border-top: 2px dotted #ccc;
}

/* Gradient line */
.prosekit-editor hr.gradient {
  height: 2px;
  border: none;
  background: linear-gradient(to right, transparent, #333, transparent);
}

/* With text */
.prosekit-horizontal-rule::after {
  content: '• • •';
  display: block;
  text-align: center;
  color: #999;
  margin-top: -0.75rem;
  background: white;
  width: fit-content;
  padding: 0 1rem;
  margin-left: auto;
  margin-right: auto;
}

HTML Structure

Input HTML:
<hr>
Output HTML (in editor):
<div class="prosekit-horizontal-rule">
  <hr>
</div>
Output HTML (exported):
<hr>

Use Cases

  • Separating sections in long documents
  • Creating visual breaks between topics
  • Dividing content chapters
  • Adding structure to articles
  • Marking thematic breaks in content

Behavior

Selection

Horizontal rules are selectable nodes. Click on them to select, then:
  • Press Delete or Backspace to remove
  • Use arrow keys to navigate past them

Insertion

Horizontal rules are inserted at the current cursor position and create their own block:
Paragraph 1
[cursor]
Paragraph 2

↓ (insert HR)

Paragraph 1
---
Paragraph 2

Accessibility

Horizontal rules are semantic HTML elements:
  • Represent a thematic break in content
  • Screen readers announce them as separators
  • Should be used for meaningful content separation, not just visual styling
  • Paragraph - Text blocks separated by horizontal rules
  • Heading - Section headers before dividers