MdxEditor
Props, ref and sync options
import { MdxEditor } from "@fumadocs-editor/ui";Props
Prop
Type
sync
Prop
Type
Page variant
variant="page" makes the editor the page: no frame, the header row with
the sync status and mode tabs stays at the top, and the document scrolls in
a column centered on the viewport. header puts your own controls in that
row. Studio is built on it.
import { useState, type CSSProperties } from "react";
import { MdxEditor } from "@fumadocs-editor/ui";
export function Page({ path }: { path: string }) {
const [panel, setPanel] = useState(false);
return (
// the open panel takes a column of its own instead of covering the text
<div style={{ "--fde-page-inset": panel ? "18rem" : "0px" } as CSSProperties}>
<MdxEditor
variant="page"
header={{
start: (
<button type="button" onClick={() => setPanel(!panel)}>
Files
</button>
),
}}
sync={{ path }}
/>
{panel && (
<aside style={{ position: "fixed", top: "3.25rem", left: "0.75rem", width: "17rem" }} />
)}
</div>
);
}
Two custom properties on an ancestor tune the column: --fde-page-width
(default 52rem) and --fde-page-inset, the space at the start the column
keeps clear of, for a panel floating there. The column stays centered while
there is room and moves right of the inset when there is not.
Parts
MdxEditor is a preset: sync status, Visual / MDX tabs, one surface at a
time. When that layout does not fit, compose the parts yourself.
import { MdxEditor, useSourceText } from "@fumadocs-editor/ui";
function Source() {
const { value, onChange, error, readOnly } = useSourceText();
return <CodeMirror value={value} onChange={onChange} readOnly={readOnly} />;
}
<MdxEditor.Root sync={{ path }} ref={ref}>
<MdxEditor.Status />
<div className="split">
<MdxEditor.Visual />
<Source />
</div>
</MdxEditor.Root>;| Part | What it is |
|---|---|
MdxEditor.Root | The document: parse, sync, collab, the ref. Takes the props below minus the frame ones |
MdxEditor.Visual | The WYSIWYG surface, static paint first |
MdxEditor.Source | The MDX in a textarea, parse error above it |
MdxEditor.Status | Sync dot and the keep-mine / take-disk chip; nothing without sync |
MdxEditor.Tabs | Visual / MDX switch for hosts that show one surface at a time |
Ref
Prop
Type
The ref satisfies SyncedDocument, so it can be handed to
createFileSession directly.
Keyboard
The toolbar appears over selected text. A resting caret has no chrome, so formatting comes from the keyboard:
| Keys | Does |
|---|---|
⌘B ⌘I ⌘E ⌘⇧S | Toggle bold, italic, code or strikethrough; with no selection, for what you type next |
→ at the line's end | Stop the marks in force, so the next words come out plain |
⌘. | Open the block's menu (attributes, inserts, move, delete) |
⌥↑ ⌥↓ | Move the block |
Esc | Select the component around the caret, then its parent |
⌘A | Select the region, then the component around it, then its parent; plain select-all after |
Tab ⇧Tab | Next or previous region of a component |
⌘Enter | Insert the next sibling (a new Step, Tab, File) from anywhere inside one |
With a mouse, double-click a component's chrome (its icon, rail or padded edge) to select it; its menu and joystick follow. Code blocks and tables have no chrome to double-click, so a joystick appears beside them while the caret is inside: click it to select the block, drag it to move it.
On a touch screen there are no shortcuts, so the toolbar stays up while you type, below the caret or the selection and clear of the system's copy menu. The block's joystick sits in the gutter beside the block.
EditorThemeProvider
Theme context for standalone hosts. Tracks the choice, persists it and sets
.light or .dark on a wrapper so the --fde-* tokens resolve. Read or change
it with useEditorTheme().
Prop
Type
Last updated on