---
title: "Move Node Button"
description: "Move selected nodes and blocks up or down in the Tiptap editor with keyboard shortcuts, intelligent selection handling, and accessibility support."
canonical_url: "https://tiptap.dev/docs/ui-components/components/move-node-button"
---

# Move Node Button

Move selected nodes and blocks up or down in the Tiptap editor with keyboard shortcuts, intelligent selection handling, and accessibility support.

A fully accessible move node button for Tiptap editors. Reorder selected nodes or blocks in the editor with keyboard shortcut support and smart selection handling.

> **Interactive demo:** [move node button](https://template.tiptap.dev/preview/tiptap-ui/move-node-button)

## Installation

Add the component via the Tiptap CLI:

```bash
npx @tiptap/cli@latest add move-node-button
```

## Components

### `<MoveNodeButton />`

A prebuilt React component that moves nodes up or down in the editor.

#### Usage

```tsx
import { MoveNodeButton } from '@/components/tiptap-ui/move-node-button'
import { useEditor } from '@tiptap/react'

export default function MyEditor() {
  const editor = useEditor({
    // your editor configuration
  })

  return (
    <>
      <MoveNodeButton
        editor={editor}
        direction="up"
        text="Move Up"
        hideWhenUnavailable={true}
        showShortcut={true}
        onMoved={(direction) => console.log(`Node moved ${direction}!`)}
      />
      <MoveNodeButton
        editor={editor}
        direction="down"
        text="Move Down"
        hideWhenUnavailable={true}
        showShortcut={true}
        onMoved={(direction) => console.log(`Node moved ${direction}!`)}
      />
    </>
  )
}
```

#### Props

| Name                  | Type                                  | Default      | Description                                    |
| --------------------- | ------------------------------------- | ------------ | ---------------------------------------------- |
| `editor`              | `Editor \| null`                      | `undefined`  | The Tiptap editor instance                     |
| `direction`           | `"up" \| "down"`                      | **Required** | Direction to move the node                     |
| `text`                | `string`                              | `undefined`  | Optional text label for the button             |
| `hideWhenUnavailable` | `boolean`                             | `false`      | Hides the button when moving is not available  |
| `onMoved`             | `(direction: "up" \| "down") => void` | `undefined`  | Callback fired after a successful move         |
| `showShortcut`        | `boolean`                             | `false`      | Shows a keyboard shortcut badge (if available) |

## Hooks

### `useMoveNode()`

A custom hook to build your own move node button with full control over rendering and behavior.

#### Usage

```tsx
import { useMoveNode } from '@/components/tiptap-ui/move-node-button'
import { parseShortcutKeys } from '@/lib/tiptap-utils'
import { Badge } from '@/components/ui/badge'
import { useEditor } from '@tiptap/react'

function MyMoveNodeButton({ direction }: { direction: 'up' | 'down' }) {
  const editor = useEditor({
    // your editor configuration
  })

  const { isVisible, handleMoveNode, canMoveNode, label, shortcutKeys, Icon } = useMoveNode({
    editor,
    direction,
    hideWhenUnavailable: true,
    onMoved: (direction) => console.log(`Node moved ${direction}!`),
  })

  if (!isVisible) return null

  return (
    <button onClick={handleMoveNode} disabled={!canMoveNode} aria-label={label}>
      <Icon />
      {label}
      {shortcutKeys && <Badge>{parseShortcutKeys({ shortcutKeys })}</Badge>}
    </button>
  )
}
```

#### Props

| Name                  | Type                                  | Default      | Description                                    |
| --------------------- | ------------------------------------- | ------------ | ---------------------------------------------- |
| `editor`              | `Editor \| null`                      | `undefined`  | The Tiptap editor instance                     |
| `direction`           | `"up" \| "down"`                      | **Required** | Direction to move the node                     |
| `hideWhenUnavailable` | `boolean`                             | `false`      | Hides the button if moving cannot be performed |
| `onMoved`             | `(direction: "up" \| "down") => void` | `undefined`  | Callback fired after successful move           |

#### Return Values

| Name             | Type            | Description                                                       |
| ---------------- | --------------- | ----------------------------------------------------------------- |
| `isVisible`      | `boolean`       | Whether the button should be rendered                             |
| `canMoveNode`    | `boolean`       | If a node can be moved in the specified direction                 |
| `handleMoveNode` | `() => boolean` | Function to move the selected node                                |
| `label`          | `string`        | Accessible label text for the button                              |
| `shortcutKeys`   | `string`        | Keyboard shortcut for the direction                               |
| `Icon`           | `React.FC`      | Icon component for the move button (AlignTopIcon/AlignBottomIcon) |

## Utilities

### `canMoveNode(editor, direction)`

Checks if a node can be moved in the specified direction in the current editor state.

#### Parameters

- `editor` (`Editor | null`) - The Tiptap editor instance
- `direction` (`"up" | "down"`) - The direction to check

#### Returns

`boolean` - True if the node can be moved in the specified direction, false otherwise

#### Usage

```tsx
import { canMoveNode } from '@/components/tiptap-ui/move-node-button'
import type { Editor } from '@tiptap/react'

const canMoveUp = canMoveNode(editor, 'up')
const canMoveDown = canMoveNode(editor, 'down')
```

### `moveNode(editor, direction)`

Programmatically moves the selected node or block in the specified direction.

#### Parameters

- `editor` (`Editor | null`) - The Tiptap editor instance
- `direction` (`"up" | "down"`) - The direction to move the node

#### Returns

`boolean` - True if the move was successful, false otherwise

#### Usage

```tsx
import { moveNode } from '@/components/tiptap-ui/move-node-button'
import type { Editor } from '@tiptap/react'

const success = moveNode(editor, 'up')
if (success) {
  console.log('Node moved successfully!')
}
```

### `shouldShowButton(props)`

Determines if the move button should be visible based on editor state and configuration.

#### Parameters

- `props` - Configuration object
  - `editor` (`Editor | null`) - The Tiptap editor instance
  - `direction` (`"up" | "down"`) - The direction to check
  - `hideWhenUnavailable` (`boolean`) - Whether to hide when moving is unavailable

#### Returns

`boolean` - True if the button should be shown, false otherwise

#### Usage

```tsx
import { shouldShowButton } from '@/components/tiptap-ui/move-node-button'
import type { Editor } from '@tiptap/react'

const shouldShow = shouldShowButton({
  editor,
  direction: 'up',
  hideWhenUnavailable: true,
})
```

## Keyboard Shortcuts

The move node button supports the following keyboard shortcuts:

- **Cmd/Ctrl + Shift + Arrow Up**: Move the selected node up
- **Cmd/Ctrl + Shift + Arrow Down**: Move the selected node down

The shortcuts are automatically registered when using either the `<MoveNodeButton />` component or the `useMoveNode()` hook. These shortcuts work with any block-level node including paragraphs, headings, blockquotes, and code blocks.

## Requirements

### Dependencies

- `@tiptap/react` - Core Tiptap React integration
- `@tiptap/pm/state` - ProseMirror state management
- `react-hotkeys-hook` - Keyboard shortcut management

### Referenced Components

- `use-tiptap-editor` (hook)
- `use-mobile` (hook)
- `button` (primitive)
- `badge` (primitive)
- `tiptap-utils` (lib)
- `tiptap-advanced-utils` (lib)
- `align-top-icon` (icon)
- `align-bottom-icon` (icon)
