Dark Room Fade Viewer

(Low light)

A room kept dark so the work can be seen.

Shown at forty lux on the conservator's instruction. The viewer follows the same rule: it comes up slowly.

About this block

Dark Room Fade ViewerPRO

Inverted low-light room where staggered frames hang on a dark panel, opening a viewer with no chrome at all: the work fades up like a lamp on a dimmer, the caption follows it, and a dot rail walks the hang.

Gallery19: Dark Room Fade Viewer

A room kept dark so the work can be seen: the section itself is an inverted panel, and the viewer brings each work up like a lamp on a dimmer, with a dot rail instead of arrows and the whole plate as the way out.

Upgrade to Pro

Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.

Upgrade Now

Installation

Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.

Radix flavor

bash
npx shadcn add "https://ui.beste.co/r/gallery19?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
npx shadcn add "https://ui.beste.co/r-base/gallery19?email=YOUR_EMAIL&license_key=YOUR_KEY"

This installs the block to components/beste/block/gallery19.tsx plus the badge7 eyebrow it uses.

Quick start

The installed file exports gallery19Demo alongside the block: the exact props behind the preview above. Spread it to get a working gallery in one line.

tsx
import { Gallery19, gallery19Demo } from "@/components/beste/block/gallery19";

export default function Page() {
  return <Gallery19 {...gallery19Demo} />;
}

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsx
import { Gallery19 } from "@/components/beste/block/gallery19";

export default function Page() {
  return (
    <Gallery19
      badge={{ label: "Low light" }}
      heading="A room kept dark so the work can be seen."
      note="Shown at forty lux on the conservator's instruction."
      frames={[
        {
          src: "/dark/stair.jpg",
          alt: "Stairwell with one window",
          title: "Stair, One Window",
          artist: "Idris Kane",
          meta: "Silver gelatin print, 2023",
        },
        {
          src: "/dark/ribs.jpg",
          alt: "Ceiling ribs from below",
          title: "Ribs, From Below",
          artist: "Marta Ekelund",
          meta: "Pigment print, 2024",
        },
      ]}
      labels={{
        openLabel: "Bring this work up",
        closeLabel: "Bring the lights back",
        jumpLabel: "Go to this work",
        counterSeparator: "of",
      }}
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string }Eyebrow label rendered as a Badge7
headingstringCentred section heading inside the dark panel
notestringCentred paragraph under the heading
framesFrame[][]Works in the room, in order
labelsGallery19Labels{}Fixed strings that are not content: viewer controls, the dot rail label and the counter separator
lightboxbooleantrueRender the built-in viewer; set false to leave the frames static
classNamestringExtra classes for the outer <section>
ts
type Frame = {
  src: string;
  alt: string;
  title: string;
  artist: string;
  meta: string;
};

type Gallery19Labels = {
  openLabel?: string;
  closeLabel?: string;
  jumpLabel?: string;
  counterSeparator?: string;
};

Behavior notes

  • The work comes up on a dimmer: the viewer mounts dark, then fades in inside a requestAnimationFrame, and it goes dark again for a moment whenever the work changes, so every change reads as a light being brought up rather than a swap.
  • The caption fades on the same curve with a delay-200, so the picture arrives first and its credit follows.
  • The whole plate is the close control, which is why the viewer has no close button and no arrows on the picture.
  • The dot rail sits inside that plate, so its buttons call stopPropagation to jump between works without closing the viewer underneath.
  • The section is a fixed inverted surface, so its text-background tokens are hardcoded rather than adaptive, and the Badge7 is passed className="text-background/70" for the same reason.
  • Every second frame is dropped by lg:mt-10, so the wall reads as hung at two heights rather than as a straight row.
  • Escape closes and the left and right arrows step through, wrapping in both directions.
  • Setting lightbox={false} disables every frame button and switches the cursor back to default, leaving the dark room as a static wall.

More Gallery blocks

View all Gallery
PRO

gallery5

Filmstrip Stage Viewer

Cinematic stage frame with the caption and frame counter set on a gradient at its foot, round arrow controls on the picture itself, and a scrolling filmstrip below where the inactive thumbnails sit back at low opacity.

PRO

gallery11

Full Bleed Strip With Sheet Viewer

Edge-to-edge strip of tall frames opening a viewer where the picture fills the screen and the caption, note and thumbnails sit in a sheet that slides off the bottom when you want the frame uncovered.

PRO

gallery23

Wall Scale Viewer

Works listed with the sizes they are printed at, opening a viewer that hangs the piece in a photographed room and scales it as you switch size pills, so the dimensions stop being an abstraction.

PRO

gallery10

Overview Toggle Viewer

Square grid whose viewer holds two states: a single frame with caption and controls, or an in-place overview of the whole set that you can jump from without closing the layer.

PRO

gallery16

Artist Room Index

Exhibition split into artist rooms, each with a sticky statement column beside its works, opening a viewer that shows the chosen piece large with the next one waiting as a thumbnail you can step straight into.

PRO

gallery2

Lightbox Frame Grid

Captioned image grid where any tile opens a full-screen lightbox on a dark scrim, with a frame counter, keyboard arrows, escape to close and previous and next controls beside the caption.