Clinia UI

CTA

The clinia.com call to action: a mono uppercase label beside a square arrow tile.

When to use

  • Send a visitor to the next step on a marketing page: book a demo, read a case study, start building.
  • The main action of a hero, a feature section or a closing band.

When not to use

  • A product (base-luma) surface: use Button.
  • A form submit or an action inside a dialog or a menu on a marketing site: use Button, which the Sera style already shapes for marketing.
  • A link inside a sentence: use a text link.

Install

npx shadcn@latest add @clinia/cta

Usage

tsx
import Link from "next/link";
import { Cta } from "@/components/ui/cta";

<Cta variant="primary" render={<Link href="/demo" />}>
  Book a demo
</Cta>

Clinia rules

  • One primary CTA per section. Pair it with a ghost or default CTA, never with a second primary.
  • On a dark band, add the dark class to the band. The tokens switch inside it, so primary becomes a Serene fill with an Infinite tile.
  • Labels are short and name the result: Book a demo, Read the case study. Write them in sentence case: the component sets the capitals.
  • Keep the forward arrow for a CTA that moves the visitor on. Use iconPosition="start" with a back arrow or a person icon for Back and Log in.
  • No Vital tile. The clinia.com styleguide has one (--cta-icon-vital), but Vital never colours a control.
  • The tile is always the inverse of the CTA's fill, so the arrow reads in both themes. Don't recolor it.

Do and don't

Do give a section one primary CTA, paired with a quieter one.
Don't put two primary CTAs side by side.

States

default
default · disabled
primary
primary · disabled
ghost
ghost · disabled
sm
focus
icon start · log in
ghost · back
no icon

Focus cells apply the component's focus-visible classes statically. Toggle the site theme to review both themes.

Sizes

SizeHeightGapRadiusType
defaulth-9 · 36px, xl:h-[38px] · 38pxgap-2.5 · 10px, xl:gap-4 · 16px--radius-lgtext-xs · 12px, xl:text-sm · 14px
smh-9 · 36pxgap-2.5 · 10px--radius-lgtext-xs · 12px

Accessibility

Built in

  • Focus-visible shows a solid Trust ring with an offset, so it reads on the frosted default fill and on a photo.
  • The label is real text, so it names the CTA. The rolling copy and the arrow tile are hidden from assistive tech.
  • Reduced motion keeps the colour change and drops the label roll and the arrow slide.

Your responsibility

  • Give a CTA that navigates an href, or render={<Link href="…" />} for a router link. It then renders a plain link: Enter follows it and Space scrolls the page, as on any link.
  • Give an icon-only use a visible label instead. A CTA always has text.
  • On a photo, check the ground behind default and ghost: the frosted tint can't promise contrast over every image. Use primary there.

How to test

  1. Press Tab until the CTA has focus: the Trust ring appears and, without reduced motion, the label rolls.
  2. With a screen reader, it's announced once, as its label, then as a link when it has an href and as a button when it doesn't.
  3. Turn on reduced motion and hover: only the fill changes.

API

PropValuesDefaultDescription
variant
defaultprimaryghost
default

primary for the one main action in a section, default (a frosted tint) beside it or over a photo, ghost for a quiet action. On a dark band, make the band a dark island so primary turns light.

size
defaultsm
default

Height 36px. default grows to 38px and a 14px label from the xl breakpoint; sm stays at 12px.

href
string
–

Renders a native link to this URL. For a router link, pass render={<Link href="…" />} instead: any render element with an href also renders as a link.

icon
React.ReactNode
<ArrowForwardIcon />

The icon beside the label. Defaults to the forward arrow; pass null for a label-only CTA.

iconPosition
startend
end

start puts the icon before the label, as in Back or Log in.

iconTile
boolean
true

Set the icon in its square tile. Turn off for a bare 16px icon, as in a ghost Back link.

All other props come from Base UI Button.