ComparisonSection

Before and after, side by side, with tags and a call to action.

For client teams

Your roadmap keeps moving. Hiring shouldn't slow it.

Traditional hiring

  • Weeks lost sourcing candidates for one task
  • A contractor found in a rush, never vetted
  • No follow-up once the work is delivered

With Acme

  • A verified freelancer ready when the project starts
  • A complete, professional toolkit from day one
  • Zero overhead on contracts or invoicing
DesignDevelopmentCopywriting
<ComparisonSection.Root tone="highlight" background="muted">
	<ComparisonSection.Content>
		<ComparisonSection.Panels>
			<ComparisonSection.Panel variant="without">
				<ComparisonSection.PanelTitle>Traditional hiring</ComparisonSection.PanelTitle>
				<ComparisonSection.PanelList>
					<ComparisonSection.PanelItem>Slow shortlists</ComparisonSection.PanelItem>
				</ComparisonSection.PanelList>
			</ComparisonSection.Panel>
			<ComparisonSection.Panel variant="with">…</ComparisonSection.Panel>
		</ComparisonSection.Panels>
	</ComparisonSection.Content>
	<ComparisonSection.Media><Illustration /></ComparisonSection.Media>
</ComparisonSection.Root>

variant on the panel picks the cross or the tick and the panel's colour, so the two lists are written identically.

From copy alone

BeforeAfter builds the whole Panels pair from four copy fields, staggering the second panel and each item so they fade in one after the other. Compose the parts directly for anything richer than a list of strings.

Traditional hiring

  • Weeks lost sourcing candidates for one task
  • A contractor found in a rush, never vetted
  • No follow-up once the work is delivered

With Acme

  • A verified freelancer ready when the project starts
  • A complete, professional toolkit from day one
  • Zero overhead on contracts or invoicing
<ComparisonSection.BeforeAfter
	withoutTitle="Traditional hiring"
	withoutItems={["Slow shortlists", "Unclear rates"]}
	withTitle="With Acme"
	withItems={["Vetted in 48 hours", "One fixed fee"]}
/>

API

ComparisonSection.Root

PropTypeDefault
background"brand" | "default" | "gradient" | "gradient-brand" | "gradient-primary" | "muted"—Surface behind the section. The three gradients read as brand moments — one per page is usually enough. brand also flips the foreground to brand-foreground.
spacing"lg" | "md" | "none" | "sm" | "xl""lg"Vertical padding, which grows at md and up. Phones get about 40% less than desktop: two stacked bands at the desktop rhythm leave 150-250 px of blank between sections. none when the section supplies its own rhythm.
tone"brand" | "destructive" | "highlight" | "muted" | "primary""primary"Which brand role colours this section: the tint, the solid fill and any connector line move together. Tokens, so a rebrand reaches them.
exitExit—Inside a <Presence>: plays this child's way out before it unmounts.
renderComponentRenderFn<HTMLProps, {}> | ReactElement<unknown, string | JSXElementConstructor<any>>—Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.

Plus the DOM props of the element it renders. Source: landing/components/comparison-section/root.tsx.

ComparisonSection.BeforeAfter

PropTypeDefault
withItemsreadonly string[]required
withoutItemsreadonly string[]required
withoutTitleReactNoderequired
withTitleReactNoderequired
exitExit—Inside a <Presence>: plays this child's way out before it unmounts.

Plus the DOM props of the element it renders. Source: landing/components/comparison-section/before-after.tsx.

ComparisonSection.Content

PropTypeDefault
exitExit—Inside a <Presence>: plays this child's way out before it unmounts.

Plus every <div> prop. Source: landing/components/comparison-section/content.tsx.

ComparisonSection.Media

PropTypeDefault
exitExit—Inside a <Presence>: plays this child's way out before it unmounts.

Plus every <div> prop. Source: landing/components/comparison-section/media.tsx.

ComparisonSection.Panel

PropTypeDefault
variantComparisonPanelVariantrequiredWhich side of the comparison this panel is — the before or the after.
exitExit—Inside a <Presence>: plays this child's way out before it unmounts.

Plus every <div> prop. Source: landing/components/comparison-section/panel.tsx.

ComparisonSection.PanelItem

PropTypeDefault
iconReactNode—Replaces the default XCircle/CheckCircle mark.
exitExit—Inside a <Presence>: plays this child's way out before it unmounts.

Plus every <li> prop. Source: landing/components/comparison-section/panel-item.tsx.

ComparisonSection.PanelList

PropTypeDefault
exitExit—Inside a <Presence>: plays this child's way out before it unmounts.

Plus every <ul> prop. Source: landing/components/comparison-section/panel-list.tsx.

ComparisonSection.PanelTitle

PropTypeDefault
exitExit—Inside a <Presence>: plays this child's way out before it unmounts.

Plus every <p> prop. Source: landing/components/comparison-section/panel-title.tsx.

ComparisonSection.Panels

PropTypeDefault
exitExit—Inside a <Presence>: plays this child's way out before it unmounts.

Plus every <div> prop. Source: landing/components/comparison-section/panels.tsx.

ComparisonSection.Tag

PropTypeDefault
exitExit—Inside a <Presence>: plays this child's way out before it unmounts.

Plus every <span> prop. Source: landing/components/comparison-section/tag.tsx.

ComparisonSection.TagList

PropTypeDefault
exitExit—Inside a <Presence>: plays this child's way out before it unmounts.

Plus every <div> prop. Source: landing/components/comparison-section/tag-list.tsx.