Button
The marketing call to action, from the brand package.
Not the product Button
There are two Buttons and they are not interchangeable:
| Product | Brand | |
|---|---|---|
| Import | @rogo-technologies/ui/button | @rogo-technologies/brand/button |
| Shape | square-cornered, product radii | pill |
| Palette | product tokens | --marketing-* |
| States | loading, disabled, icon-only, destructive | link-out only |
| Use on | the web app, Excel add-in, internal tools | the marketing site, campaign pages |
A marketing page only ever asks someone to go somewhere, so this one has no loading or
icon-only state and no destructive variant. If you need those, you are on a product surface and
want the other Button. See the design-brand skill for the full split.
import { Button } from "@rogo-technologies/brand/button";
<Button asChild>
<Link href="/demo">Request demo</Link>
</Button>
<Button asChild variant="arrow" inverted size="lg">
<Link href="/demo">Request access</Link>
</Button>Variants
| Variant | Use for |
|---|---|
primary | The page's single most important action. Brand green. |
secondary | A second action beside a primary one, or a CTA on a busy surface. |
ghost | A quiet text action with a trailing 16px arrow. No fill, no disc. |
arrow | The quiet ask under a hero: label plus a trailing arrow disc. |
Pass inverted on a dark band (--marketing-forest, --marketing-dark). It is a flag, not a
fifth variant — primary, secondary, ghost, and arrow each have an inverted treatment.
Ghost and arrow ship their mark. Pass the label only; do not add your own icon.
Sizes
md is the default in chrome and body content, 32px (h-8 / py-1.5 / px-4) on
type-marketing-body-medium-sm; lg is a standalone CTA, 36px (h-9 / py-2 / px-4) on
type-marketing-body-medium-md. Arrow uses the same container heights; the disc stays 24px
(md) / 28px (lg), with a 16px arrow at both sizes. Resting gap is 8px; hover opens it to
12px without moving the icon inside the disc.
Every size presses to 0.98 on a Framer-matched spring (duration: 450ms, bounce: 0.25);
color still transitions in 200ms.
Props
| Prop | Type | Default |
|---|---|---|
variant | "primary" | "secondary" | "ghost" | "arrow" | "primary" |
inverted | boolean | false |
size | "md" | "lg" | "md" |
asChild | boolean | false |
asChild is how you get a link. The component renders a <button> by default; pass asChild
and it renders your child instead, keeping the styling. That is the right way to wrap Next's
Link, because nesting an <a> inside a <button> is invalid HTML and breaks keyboard
activation.