Role Comparison Table

Compare Roles

Find your fit

Not sure which role is right for you? Compare positions side by side to understand the differences in team, skills, and expectations.

Frontend Engineer
Backend Engineer
Full-Stack Engineer
Team
Product Engineering
Platform Team
Growth Team
Focus Area
UI/UX implementation, component libraries, performance
APIs, data pipelines, system design
End-to-end feature development, experimentation
Experience Level
2–5 years
3–6 years
3–5 years
Key Skills
React, TypeScript, CSS, accessibility
Node.js, PostgreSQL, Redis, AWS
React, Node.js, SQL, A/B testing
Location
Remote or SF
Remote or SF
Remote only
Salary Range
$130K – $180K
$140K – $190K
$135K – $185K
Frontend Engineer
TeamProduct Engineering
Focus AreaUI/UX implementation, component libraries, performance
Experience Level2–5 years
Key SkillsReact, TypeScript, CSS, accessibility
LocationRemote or SF
Salary Range$130K – $180K
Backend Engineer
TeamPlatform Team
Focus AreaAPIs, data pipelines, system design
Experience Level3–6 years
Key SkillsNode.js, PostgreSQL, Redis, AWS
LocationRemote or SF
Salary Range$140K – $190K
Full-Stack Engineer
TeamGrowth Team
Focus AreaEnd-to-end feature development, experimentation
Experience Level3–5 years
Key SkillsReact, Node.js, SQL, A/B testing
LocationRemote only
Salary Range$135K – $185K
About this block

Role Comparison TablePRO

Side-by-side role comparison grid showing team, skills, experience, and salary for different positions. Responsive table-to-card layout.

Careers31: Role Comparison Table

Side-by-side role comparison that renders an optional centered header (badge, <strong>-aware heading, description) above a comparison matrix: on desktop a CSS-grid table with one leading attribute column plus one column per role and zebra-striped rows, collapsing on mobile into one stacked card per role that lists each attribute against its value.

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

Base UI flavor

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

This installs the block to components/beste/block/careers31.tsx, plus the badge shadcn/ui primitive it uses for the section eyebrow badge.

Quick start

The installed file exports careers31Demo alongside the block: the exact props behind the preview above. Spread it to get a working role comparison table in one line.

tsx
import { Careers31, careers31Demo } from "@/components/beste/block/careers31";

export default function CareersPage() {
  return <Careers31 {...careers31Demo} />;
}

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

tsx
import { Careers31 } from "@/components/beste/block/careers31";

export default function CareersPage() {
  return (
    <Careers31
      badge={{ label: "Compare Roles", variant: "secondary" }}
      heading="Find your <strong>fit</strong>"
      description="Compare positions side by side."
      attributes={["Team", "Experience Level", "Location"]}
      roles={[
        {
          title: "Frontend Engineer",
          values: ["Product Engineering", "2 to 5 years", "Remote or SF"],
        },
        {
          title: "Backend Engineer",
          values: ["Platform Team", "3 to 6 years", "Remote or SF"],
        },
      ]}
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string; variant?: "default" | "secondary" | "outline" }–Optional eyebrow badge above the heading
headingstring–Section heading, supports inline <strong>
descriptionstring–Supporting paragraph under the heading
attributesstring[][]Row labels forming the leading attribute column
rolesRoleColumn[][]One comparison column per role
classNamestring–Extra classes for the outer <section>
ts
type RoleColumn = {
  title: string;
  values: string[];
};

Behavior notes

  • The entire header block is conditionally rendered and only appears when at least one of badge, heading, or description is set; each of the three is then individually gated too.
  • heading is injected via dangerouslySetInnerHTML, so inline <strong> markup renders and is recolored to text-primary; any other HTML in the string is also rendered unescaped.
  • The desktop table sets its column count inline with gridTemplateColumns: repeat(${roles.length + 1}, minmax(0, 1fr)), so the leading attribute column plus every role column share equal width and the layout expands automatically as you add roles.
  • Rows are aligned purely by index: role.values[rowIndex] is paired with attributes[rowIndex], so each role's values array must be ordered to match attributes, and a missing value falls back to a literal em dash placeholder.
  • Zebra striping is computed from rowIndex % 2 === 0, applying bg-muted/30 to even attribute rows on desktop and even attribute blocks within each mobile card.
  • The desktop grid (hidden md:block) and the mobile stacked cards (flex md:hidden) are two separate DOM trees toggled purely by breakpoint, so both are always present in markup.
  • The block is display-only: there are no callbacks, no internal state, and no interactive elements, so it takes "use client" but performs no client-side behavior.

More Careers blocks

View all Careers
PRO

careers14

Meet the Team Gallery

PRO

careers1

Job Listings List

PRO

careers18

Department Overview Grid

Get Pro access