A pay transparency table whose track pills swap the band column while the levels, their scope, and the headcount at each stay in place, closing on the written rules that govern the numbers beside a soft panel carrying the call to action.
A pay transparency table whose track pills swap the band column while the levels, their scope and the headcount at each stay in place, closing on the written rules that govern the numbers beside a soft panel carrying the call to action.
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.
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
npx shadcn add "https://ui.beste.co/r/careers55?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/careers55?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/careers55.tsx plus the badge23 and button21 components it uses for the eyebrow and the action.
The installed file exports careers55Demo alongside the block: the exact props behind the preview above. Spread it to get a working table in one line.
import { Careers55, careers55Demo } from "@/components/beste/block/careers55";
export default function PayPage() {
return <Careers55 {...careers55Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Careers55 } from "@/components/beste/block/careers55";
export default function PayPage() {
return (
<Careers55
badge={{ label: "What we pay" }}
heading="Every band, every level, published and not negotiable"
description="The number on the advert is the number you get."
tracks={["Engineering", "Operations"]}
columns={["Level", "Scope", "Band", "People here"]}
levels={[
{
level: "L1",
title: "Joining",
scope: "Works on a defined piece with review.",
bands: { Engineering: "£52,000", Operations: "£38,000" },
people: "2",
},
{
level: "L3",
title: "Senior",
scope: "Owns a system and is trusted on a migration call alone.",
bands: { Engineering: "£92,000 to £108,000", Operations: "£58,000 to £66,000" },
people: "7",
},
]}
rulesTitle="The rules around it"
rules={[
"One band per level, with a range only where the level spans two jobs.",
"Location does not change the band.",
]}
ctaTitle="Know the number before you apply"
ctaBody="Every open role carries its band in the advert."
button={{ label: "See open roles", href: "/careers" }}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
badge | { label: string } | – | Eyebrow above the hairline rule, rendered through Badge23 |
heading | string | – | Section heading in the left column of the header |
description | string | – | Supporting paragraph, right-aligned from md up |
tracks | string[] | [] | Track pills, the first one starts selected |
columns | string[] | [] | Column headings, also reused as mobile row labels |
levels | Level[] | [] | Table rows, each carrying a band per track |
rulesTitle | string | – | Heading above the written rules |
rules | string[] | [] | The policy that governs the numbers |
ctaTitle | string | – | Heading in the closing panel |
ctaBody | string | – | Paragraph in the closing panel |
button | { label: string; href: string } | – | Action in the closing panel |
className | string | – | Extra classes for the outer section |
type ActionLink = {
label: string;
href: string;
};
type Level = {
level: string;
title: string;
scope: string;
bands: Record<string, string>;
people: string;
};bands is keyed by track name, so every entry in tracks needs a matching key on every level. A missing key renders an em dash rather than breaking the row.hidden md:grid, so on mobile the labels come from columns[2] and columns[3] rendered inline inside the band and headcount cells instead. Passing fewer than four column labels leaves those mobile labels blank.mt-8 md:mt-0 to compensate, so the spacing above the table is correct at both widths.border-b rather than border-t, matching the header's border-b, so the rules read as one continuous table.tabular-nums in both the band and headcount columns, so they stay optically aligned across different digit counts.button elements with aria-pressed and explicit cursor-pointer, since Tailwind v4 buttons default to cursor: default.flex flex-col justify-center, so its content stays vertically centered against the rules list beside it however long that list runs.careers35
Transparent salary bands with level, role, visual range bars, and equity details. Pay transparency table with responsive card fallback.
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.
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.
careers21
Transparent compensation philosophy with salary, equity, bonus, and perks cards. Shows total rewards approach with highlighted details.