Plan Chest Sheet Stack

(Plan chest)

Four drawers, opened one sheet at a time.

Works on paper live flat and unframed. Open a drawer and lift the sheets the way the archivist does.

About this block

Plan Chest Sheet StackPRO

Works on paper listed as ruled plan-chest drawers with their contents and a peek of the sheets, opening a stack where the top sheet lifts clear of the pile before dropping to the back and the next one rises into its place.

Gallery24: Plan Chest Sheet Stack

A plan chest read as a run of ruled drawers. Open one and the sheets sit offset behind each other; lifting the top sheet clears it off the pile before it drops to the back and the next one rises.

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/gallery24?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

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

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

Quick start

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

tsx
import { Gallery24, gallery24Demo } from "@/components/beste/block/gallery24";

export default function Page() {
  return <Gallery24 {...gallery24Demo} />;
}

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

tsx
import { Gallery24 } from "@/components/beste/block/gallery24";

export default function Page() {
  return (
    <Gallery24
      badge={{ label: "Plan chest" }}
      heading="Four drawers, opened one sheet at a time."
      description="Works on paper live flat and unframed."
      drawers={[
        {
          label: "Drawer one",
          contents: "Letterpress and type specimens, 2024 to 2026",
          sheets: [
            {
              src: "/chest/one-01.jpg",
              alt: "Letterpress sheet",
              title: "Alphabet for a Quiet Room",
              artist: "Hélène Marchal",
              medium: "Letterpress on rag paper",
            },
            {
              src: "/chest/one-02.jpg",
              alt: "Specimen sheets",
              title: "Sheets, Before Binding",
              artist: "Hélène Marchal",
              medium: "Ink on uncoated stock",
            },
          ],
        },
      ]}
      labels={{
        openLabel: "Open this drawer",
        closeLabel: "Close the drawer",
        nextLabel: "Lift the top sheet off",
        counterSeparator: "of",
        hint: "Lift the top sheet and the next one rises into its place.",
      }}
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string }–Eyebrow label rendered as a Badge7
headingstring–Section heading in the left header column
descriptionstring–Supporting paragraph in the right header column
drawersDrawer[][]Drawers in the chest, each with its own sheets
labelsGallery24Labels{}Fixed strings that are not content: viewer controls, the counter separator and the hint
lightboxbooleantrueRender the built-in viewer; set false to leave the drawers static
classNamestring–Extra classes for the outer <section>
ts
type Drawer = {
  label: string;
  contents: string;
  sheets: Sheet[];
};

type Sheet = {
  src: string;
  alt: string;
  title: string;
  artist: string;
  medium: string;
};

type Gallery24Labels = {
  openLabel?: string;
  closeLabel?: string;
  nextLabel?: string;
  counterSeparator?: string;
  hint?: string;
};

Behavior notes

  • The pile is an array of indexes rather than a single position, so lifting is a rotation: the first entry moves to the back and everything else steps up one place.
  • The lift happens in two stages. The top sheet first clears the frame upwards, and only when it has left does a timer move it to the back of the order, so nothing is seen sliding under the sheets beneath it.
  • The timer duration and the CSS transition share one constant (LIFT_MS), so the visual and the state change stay in step if the timing is edited.
  • Lifting is ignored while a lift is already running and when a drawer holds fewer than two sheets, so a fast series of clicks cannot desynchronise the pile.
  • The timer is cleared on unmount, so closing the viewer mid-lift leaves nothing pending.
  • Only the top three sheets are rendered, and they are reversed in the markup so the deepest one paints first; the offsets and slight rotations come from a small style table.
  • The right arrow and the down arrow both lift, and Escape closes the drawer, so the pile is workable from the keyboard.
  • Setting lightbox={false} disables every drawer row and switches the cursor back to default, leaving the chest as a static index.

More Gallery blocks

View all Gallery
PRO

gallery23

Wall Scale Viewer

PRO

gallery11

Full Bleed Strip With Sheet Viewer

PRO

gallery18

Edition Inspector

Get Pro access