Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Image Preview Dialog Block for React

A site-survey plans tab with its full-screen inspector shown open: three drawn sheets in a viewport you pan by dragging, zoom with Fit, 100%, 200% and 400% or a slider, a minimap that jumps, and a real SVG download.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Look closely at a large drawing without leaving the page, with this plan inspector for React with Base UI. It opens from the Plans tab of Surveybay, a site-survey tool: the header holds an outline Inspect plans Button, and the tab, three plans listed with a thumbnail of each sheet, is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The Dialog fills the screen. Its viewport is a scroll region holding a drawn greyscale site plan: drag to pan, or focus it and use the arrow keys. A Toggle Group zooms to Fit, 100%, 200% or 400%, a Slider zooms in between and a minimap in the corner shows where the view sits on the sheet with a rectangle you can press to jump. The zoom keeps the middle of the view in the middle. Previous and next move between the plot plan, the foundation plan and the drainage plan ("Level 2 of 3"), and a Download Trigger button saves the sheet as a real SVG file. The sheets are drawn and nothing is fetched. For preview the inspector is drawn open in place when the page loads; the header button opens the real full-screen Dialog.

FAQ

Why is the inspector already open, and what do I keep?

So you can see it without a click. On load the inspector is a copy drawn in place over the plans list: a native dialog element that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The Inspect plans button opens the real full-screen Dialog, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same Viewer component and share the block's state, so the sheet and the zoom chosen in the copy are there in the real one. In your app keep the Dialog and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.

How is this different from a photo lightbox?

A lightbox steps through pictures; this inspects one large drawing. The sheet is 1200 by 750 units of vector lines and labels, so it stays sharp at 400%, and the controls are about reading it: Fit scales it to the window, the stops and the slider set an exact zoom, the minimap shows where you are, and the arrow keys and dragging pan. For photographs of a gallery, use the lightbox block.

How do zoom and pan work?

The sheet is an image whose width is 1200 × scale pixels inside a scroll region, so panning is the browser's own scrolling: the arrow keys, the wheel, touch, and a mouse drag that moves the scroll position. Before a zoom the view remembers which point of the sheet is in the middle, and afterwards scrolls back to it. Fit is measured from the viewport's size and follows it when the window is resized. The minimap's rectangle is the scroll position and viewport as shares of the sheet; pressing it centres that point.

What stays local in the demo, and how do I wire it up?

The three sheets are drawn SVG strings in PLANS; nothing is fetched or uploaded. Download saves the sheet's own SVG text as plot-plan.svg and the like, a real file. In your app load the sheets from your API into the same shape (a name, a file name and an image address), keep Viewer as it is, and point Download at the original file instead of regenerated text.

Is it accessible from the keyboard?

Yes. The viewport is a focusable region named for the sheet and its zoom, and the arrow keys pan it. The zoom stops are a toggle group, the slider has a name, previous and next are named buttons that stay in place at the ends, and a polite message says the sheet you moved to. The minimap is a pointer shortcut and hidden from assistive technology, since the arrow keys do the same. The trigger is passed to DialogTrigger through render, and the dialog is controlled with open and onOpenChange. Escape closes it and focus returns to Inspect plans.

How does it look on a phone?

Both the copy on load and the real dialog fill the screen. The minimap and the slider are hidden and the controls become one bar: previous and next, the zoom stops and Download. Dragging pans with a finger as any scrolling region does.

  • Pro

    Lightbox Gallery

    Stage and thumbnails

    Nine pictures of a photography studio's year on shared hairlines, a featured frame and a caption under each, where every frame opens one viewer dialog with the whole picture, its credit, Previous and Next, a counter, arrow keys and a swipe.

  • Pro

    A profile page with its cover-crop dialog shown open: a drawn landscape in an image cropper with shape, zoom, turn and reset controls, and the same crop shown live as an avatar, a card thumbnail and a banner strip.

  • Pro

    A shared drive's document list with a full-screen viewer shown open: three drawn pages that turn with buttons or arrow keys, a Fit, 125% and 150% zoom, a details list, activity, a Copy link button and a Download that saves a text file.

  • Pro

    Media Upload Dialog

    Media and widgets

    A video library with its upload dialog shown open: a drop zone for images, video and audio that names the files it turns away and why, tiles for the ones that pass with a check each, bulk removal, a total and an Add button that puts the clips in the library.

  • Pro

    Image Preview Changelog

    Spotlights and media

    Six releases as figures, each with a drawn greyscale thumbnail of what shipped (a table, a dialog, a chart, a menu, a calendar, a settings form) and a caption; resting on a thumbnail opens a larger copy in a card.

  • Pro

    Add Card Dialog

    Payments and plans

    A transit wallet's payment methods page with its add-card dialog shown open: a card drawn in greys that fills in as you type, a number that groups itself and names its network, checks on the number, expiry and code, and an Add card button that keeps only the last four digits.