# 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