Paired Hang Compare

(Hung in pairs)

Works that were made to be argued with each other.

Open any frame, then hold the next one beside it. The room was hung the same way, two at a time.

About this block

Paired Hang ComparePRO

Works hung two to a bay on staggered ruled cards, opening a viewer that can hold a second work beside the first: the frame splits, both pictures keep their own caption and the pair can be walked together.

Gallery20: Paired Hang Compare

Works hung two to a bay, each on its own rule with alternate columns dropped down the wall. The viewer can hold two at once: the next work slides in beside the open one and the pair share a caption row.

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

Base UI flavor

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

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

Quick start

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

tsx
import { Gallery20, gallery20Demo } from "@/components/beste/block/gallery20";

export default function Page() {
  return <Gallery20 {...gallery20Demo} />;
}

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

tsx
import { Gallery20 } from "@/components/beste/block/gallery20";

export default function Page() {
  return (
    <Gallery20
      badge={{ label: "Hung in pairs" }}
      heading="Works that were made to be argued with each other."
      description="Open any frame, then hold the next one beside it."
      works={[
        {
          src: "/pairs/alphabet.jpg",
          alt: "Letterpress work",
          title: "Alphabet for a Quiet Room",
          artist: "Hélène Marchal",
          year: "2025",
          medium: "Letterpress on rag paper",
        },
        {
          src: "/pairs/sheets.jpg",
          alt: "Specimen sheets",
          title: "Sheets, Before Binding",
          artist: "Hélène Marchal",
          year: "2025",
          medium: "Ink on uncoated stock",
        },
      ]}
      labels={{
        openLabel: "Open this work",
        closeLabel: "Close the pair",
        previousLabel: "Previous work",
        nextLabel: "Next work",
        compareLabel: "Hold the next work beside it",
        compareTitle: "Held beside",
        counterSeparator: "of",
      }}
    />
  );
}

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
worksWork[][]Works on the wall, in hanging order
labelsGallery20Labels{}Fixed strings that are not content: viewer controls, the compare labels and the counter separator
lightboxbooleantrueRender the built-in viewer; set false to leave the frames static
classNamestring–Extra classes for the outer <section>
ts
type Work = {
  src: string;
  alt: string;
  title: string;
  artist: string;
  year: string;
  medium: string;
};

type Gallery20Labels = {
  openLabel?: string;
  closeLabel?: string;
  previousLabel?: string;
  nextLabel?: string;
  compareLabel?: string;
  compareTitle?: string;
  counterSeparator?: string;
};

Behavior notes

  • Pairing is a mode rather than a second selection: the held work is always the one after the open one, wrapping at the end, so stepping keeps the comparison moving through the hang.
  • The pairing state survives stepping, which is what lets a visitor walk the whole wall two works at a time.
  • The viewer's grid and its caption row both switch to two columns only when a second work is held, so a single work still fills the panel rather than sitting in half of it.
  • The held work's caption is separated by md:border-l md:pl-8 and titled with its own label, so the pair never reads as one long credit.
  • On the wall every work opens on a border-t rule and alternate columns are dropped by md:mt-12, which is what gives the hang its two-height rhythm.
  • Captions use flex-wrap items-baseline justify-between, so the title and the credit share a baseline and wrap cleanly rather than colliding.
  • 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 paired hang as a static wall.

More Gallery blocks

View all Gallery
PRO

gallery7

Counter Scrolling Image Bands

PRO

gallery12

Exhibition Wall Hang

PRO

gallery13

Catalogue Index Plates

Get Pro access