A hiring section that answers three questions instead of listing a job board: the answers land on one open role with its team, its location, and its published pay band, and the photograph beside it changes to the part of the studio that role sits in.
A hiring section that asks three questions instead of listing a job board. The answers land on one open role with its team, its location, and its published pay band, and the photograph beside it changes to the part of the studio that role sits in.
Free block
This block is free. No license or account is required: install it with the CLI and use it in unlimited projects.
Radix flavor
npx shadcn add "https://ui.beste.co/r/careers56"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/careers56"That installs the block file, the badge6 eyebrow and button1 seal CTA it is built from, and the questionnaire primitive.
import { Careers56, careers56Demo } from "@/components/beste/block/careers56";
export default function Page() {
return <Careers56 {...careers56Demo} />;
}import { Careers56 } from "@/components/beste/block/careers56";
export default function Page() {
return (
<Careers56
badge={{ label: "Careers" }}
meta="Six open roles"
heading="Skip the job board and answer three questions"
description="Every open role here wants a different kind of week."
shortcuts="numbers"
image={{
src: "https://images.unsplash.com/photo-1594100165806-939c3fbb5b6a",
alt: "Studio wall covered in pinned work in progress",
}}
caption="Twenty-two people, one floor, and a wall that is never empty."
stats={[
{ title: "Median reply", value: "3 days" },
{ title: "Interview rounds", value: "Two" },
]}
questions={[
{
name: "craft",
title: "What do you want to spend the day doing?",
choices: [
{ value: "build", label: "Building the thing" },
{ value: "design", label: "Deciding how it looks" },
],
},
{
name: "experience",
title: "How long have you been at it?",
choices: [
{ value: "mid", label: "Three to six years" },
{ value: "senior", label: "Seven or more" },
],
},
]}
roles={[
{
// both answers have to fit, so this sits above the looser role
match: { craft: "build", experience: "senior" },
title: "Engineering lead",
summary: "You set how the work is built and you still write a good share of it.",
facts: [
{ title: "Team", value: "Engineering, 4 people" },
{ title: "Band", value: "£82,000 to £95,000" },
],
image: {
src: "https://images.unsplash.com/photo-1754390754756-16ee0e29cf36",
alt: "Desk with a laptop, notes, and printed schedules",
},
caption: "The engineering corner.",
button: { label: "Read the full role", href: "https://beste.co" },
},
{
// no match: the catch-all, and it has to be last
title: "Open application",
summary: "Nothing on the list matched, which happens.",
button: { label: "Write to us", href: "https://beste.co" },
},
]}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
badge | Badge | – | Eyebrow above the rule, rendered with Badge6. |
meta | string | – | Short line beside the eyebrow, across the hairline divider. |
heading | string | – | Section heading. |
description | string | – | Section description under the heading. |
questions | FitQuestion[] | [] | The questions, in the order they are asked. |
shortcuts | "letters" | "numbers" | – | Prints a shortcut on every choice of the active question. |
roles | Role[] | [] | Checked in order; the first one whose match fits wins. |
image | RoleImage | – | Standing photograph, shown until a role is matched. |
caption | string | – | Line under the standing photograph. |
stats | Fact[] | [] | Two bordered cells under the photograph. |
labels | Careers56Labels | {} | Overrides for the navigation buttons and the match heading. |
className | string | – | Merged onto the section element. |
type Badge = { label: string };
type ActionButton = { label: string; href: string };
type RoleImage = { src: string; alt: string };
type Fact = { title: string; value: string };
type FitQuestion = {
name: string;
title: string;
description?: string;
choices?: FitChoice[];
};
type FitChoice = { value: string; label: string; description?: string };
type Role = {
match?: Record<string, string>;
title: string;
summary: string;
facts?: Fact[];
image?: RoleImage;
caption?: string;
button?: ActionButton;
};
type Careers56Labels = {
previous?: string;
next?: string;
submit?: string;
restart?: string;
matchTitle?: string;
};match maps a question's name to the value it needs, and every pair has to fit. That is what lets a senior variant of the same craft sit above the general one, as long as it comes first in the array.image keeps the standing photograph, which is the right behaviour for the catch-all and for any role that has no separate picture worth showing.facts alongside the team and the location, so the block reads as a published band rather than a range you have to ask for.careers52
A job description laid out as a reading column with checked responsibility lists and a candid caveat panel, against a sticky rail carrying the published salary band, level, and location alongside the apply action.
careers3
Department-grouped job listings with minimal row layout. Jobs organized by team with location and type indicators.
careers51
A light editorial careers section with a monospace eyebrow over a hairline rule, a two-column heading, and a sticky culture photo with a gradient caption beside team filter pills and hairline job rows showing location, contract type, and a hover arrow.