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
headingstringSection heading above the two columns
entriesUseCaseEntry[][]Jobs in the index, first one selected on mount
buttonActionButtonOutline Button12 under the index
labelsUsecase47Labels{}Fixed strings that are not content: the index title
classNamestringExtra 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

usecase52

Placement Mosaic Grid

Six application tiles alternating between landscape and portrait crops, each captioned on a rule with where the work lands, what it is applied to and the constraint it has to survive.

PRO

usecase49

Audience Tabs With Photo

Pill tabs for each audience swap a split panel holding a tall photograph beside a title, summary and ruled list of what that audience actually gets.

PRO

usecase12

Workflow Stage Tabs

Tab navigation showing workflow stages with split image cards featuring stats overlays and descriptions. Perfect for demonstrating product workflow or development process stages.

PRO

usecase51

Two Route Photo Columns

Two picture-led routes side by side, each with an eyebrow, title, dotted-rule expectations list and its own pill CTA, separated on desktop by a small pill divider sitting between the columns.

PRO

usecase59

Linked Situation Rows

Five situations as ruled rows, each one a whole link: a square photograph pinned left, a serif sentence over its paragraph, and an arrow link at the right end that lifts as the row tints on hover.

PRO

usecase50

A Day In The Tool

Showcase built as a ruled timetable: selecting an hour swaps a soft panel that floats the matching interface piece over a dotted field, then explains the moment and states one outcome on its own rule.