Job Index With Image Panel

(Pick a job)

Same studio, four very different afternoons.

(The jobs)
Unbranded paper packaging in soft daylight

A name, a face and a shelf to stand on

Naming, packaging and the first run of photography, delivered as one parcel so nothing arrives half-finished.

Weeks to shelf
14
Ranges launched
Eleven
About this block

Job Index With Image PanelPRO

Ruled index of jobs on the left that swaps the panel beside it, where each selection brings its own photograph, explanation and two ruled outcome figures.

Usecase47: Job Index With Image Panel

A ruled index of jobs on one side, and on the other the selected job's photograph, statement, story and results. Selecting an entry swaps the whole panel; the CTA lives under the index.

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

Base UI flavor

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

This installs the block to components/beste/block/usecase47.tsx plus the badge7 eyebrow and button12 pill button it uses.

Quick start

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

tsx
import { Usecase47, usecase47Demo } from "@/components/beste/block/usecase47";

export default function Page() {
  return <Usecase47 {...usecase47Demo} />;
}

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

tsx
import { Usecase47 } from "@/components/beste/block/usecase47";

export default function Page() {
  return (
    <Usecase47
      badge={{ label: "Pick a job" }}
      heading="Same studio, four very different afternoons."
      labels={{ indexTitle: "The jobs" }}
      entries={[
        {
          label: "Launching something new",
          title: "A name, a face and a shelf to stand on",
          description: "Naming, packaging and the first run of photography, as one parcel.",
          src: "/jobs/launch.jpg",
          alt: "Unbranded paper packaging",
          results: [
            { title: "Weeks to shelf", value: "14" },
            { title: "Ranges launched", value: "Eleven" },
          ],
        },
        {
          label: "Fixing what exists",
          title: "Keeping the good half, replacing the rest",
          description: "An audit of what already works, then surgery rather than a rebuild.",
          src: "/jobs/fix.jpg",
          alt: "Type specimen sheets on a table",
          results: [{ title: "Assets retained", value: "Two thirds" }],
        },
      ]}
      button={{ label: "Talk through your job", href: "/contact" }}
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string }–Eyebrow label rendered as a Badge7
headingstring–Section heading above the two columns
entriesUseCaseEntry[][]Jobs in the index, first one selected on mount
buttonActionButton–Outline Button12 under the index
labelsUsecase47Labels{}Fixed strings that are not content: the index title
classNamestring–Extra classes for the outer <section>
ts
type UseCaseEntry = {
  label: string;
  title: string;
  description: string;
  src: string;
  alt: string;
  results: CaseResult[];
};

type CaseResult = {
  title: string;
  value: string;
};

type ActionButton = {
  label: string;
  href: string;
};

Behavior notes

  • The first entry is selected on mount, so the panel is never empty and the section reads as a page rather than a prompt.
  • Index rows are real button elements with aria-pressed, each opening on a border-t rule, so the list reads as a ruled index rather than a stack of tabs.
  • Selection is shown by weight of colour on the label (text-foreground against text-muted-foreground) with a transition, which keeps the index quiet while still making the current row obvious.
  • The CTA sits under the index rather than under the panel, so it stays visible whichever job is selected and never pushes the results off the fold.
  • The panel column is wider than the index (md:grid-cols-[1fr_1.5fr]), so the photograph gets the room and the index stays a list.
  • Results render as a real dl in two columns, each on its own rule, so a job with one result and a job with two both look deliberate.
  • Below md the index stacks above the panel in source order, so a phone reads the list of jobs first and then the selected one.

More Use Case blocks

View all Use Case
PRO

usecase49

Audience Tabs With Photo

PRO

usecase52

Placement Mosaic Grid

PRO

usecase12

Workflow Stage Tabs

Get Pro access