# Read-only viewer > Render a fully-composed editor as a viewer. Users can select, zoom, preview, and download - but nothing about the document is mutable. Source: https://docs.docmosaic.com/docs/recipes/read-only `Editor.Root readOnly` flips the editor into viewer mode. Every mutating interaction is suppressed; export, preview, and selection keep working. ## When you'd use this - Embedding a finished contract / template for review. - Sharing a built document with a stakeholder who shouldn't accidentally drag a section. - Pairing an editable canvas with a frozen reference canvas in a compare view. - A "preview" before commit step inside a multi-step flow. ## Basic - root-level `readOnly` ```tsx import { Editor } from '@docmosaic/react'; import '@docmosaic/react/styles.css'; export function DocumentViewer({ document }: { document: Document }) { return ( ); } ``` ## What changes in `readOnly` | Surface | Behavior in `readOnly` | | ------------------------ | ----------------------------------------------------------------------------- | | Canvas drag / drop | No-op. Section positions are frozen. | | Section resize | Handles never render. Resize hook never arms. | | Section file upload | Drop, drag-over, click-to-upload are no-ops. Crop overlay is suppressed. | | Section floating toolbar | Hidden - duplicate / delete / layer buttons aren't rendered. | | Drawing mode | Pointer captures ignored. The Draw button isn't rendered. | | Page list | Add Image / Add Page buttons hidden. Per-page delete hidden. Reorder ignored. | | Properties bar | Document name input, page size, orientation select are `disabled`. | | PropertiesPanel | Layout / Text / Shape inputs are `disabled`. Layer sub-section hides. | | Page background | `Editor.PageBackground` returns `null`. | | Toolbar | `UndoButton`, `RedoButton`, `Add*Button`, `DrawButton` return `null`. | | | `PreviewButton`, `PrintButton`, `DownloadButton` stay live. | | Keybindings | Every mutating action (undo, redo, delete, nudge) is suppressed. | | | `Escape` (deselect) still works. | Selection (click, shift-click, marquee) keeps working - read-only is about mutation, not navigation. ## Canvas-level - `Editor.StaticCanvas` When the root is editable but a single canvas surface should refuse mutations, use `Editor.StaticCanvas`. The folding rule is `effectiveReadOnly = root.readOnly || canvas.readOnly`. ```tsx
``` This is the right primitive when: - You want a side-by-side "current vs. reference" view. - The root needs the toolbar / undo / page list to stay live for adjacent editable surfaces. - You're rendering a snapshot inside an otherwise-editable flow. ## Detecting read-only in custom primitives ```tsx import { useEditor } from '@docmosaic/react'; function CustomAddButton() { const { actions, readOnly } = useEditor(); if (readOnly) return null; return ; } ``` ## See also - [Designer](/docs/concepts/designer) - composition model and primitive layering - [StaticCanvas](/docs/primitives/static-canvas) - [Keybindings](/docs/concepts/keybindings) - full default keymap