shadimage
starck
componentblue-cta-buttonsource: ok · refreshed

Blue CTA Button

The dimensional call-to-action used by SessionWatcher, with configurable color tones and macOS or Windows platform modes.

npx shadcn add "https://ui.starck.studio/r/blue-cta-button.json"
free

Where it goes

cta

Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.

Files1 · source cached 10/8/2026, 11:25:17 AM

registry/default/blue-cta-button.tsx
import * as React from "react"

const blueCtaTones = ["blue", "violet", "emerald", "rose"] as const

type BlueCtaTone = (typeof blueCtaTones)[number]

const blueCtaPlatforms = ["macos", "windows"] as const

type BlueCtaPlatform = (typeof blueCtaPlatforms)[number]

type BlueCtaButtonProps = React.ComponentProps<"button"> & {
  icon?: React.ReactNode
  tone?: BlueCtaTone
  platform?: BlueCtaPlatform
}

type BlueCtaToneStyle = React.CSSProperties & {
  "--starck-blue-cta-start": string
  "--starck-blue-cta-middle": string
  "--starck-blue-cta-end": string
  "--starck-blue-cta-dark": string
  "--starck-blue-cta-glow": string
}

const blueCtaToneStyles = {
  blue: {
    "--starck-blue-cta-start": "#0b75e5",
    "--starck-blue-cta-middle": "#0a73e4",
    "--starck-blue-cta-end": "#0972e4",
    "--starck-blue-cta-dark": "0 40 120",
    "--starck-blue-cta-glow": "10 118 240",
  },
  violet: {
    "--starck-blue-cta-start": "#8257f5",
    "--starck-blue-cta-middle": "#7447eb",
    "--starck-blue-cta-end": "#693cdd",
    "--starck-blue-cta-dark": "58 24 140",
    "--starck-blue-cta-glow": "124 58 237",
  },
  emerald: {
    "--starck-blue-cta-start": "#10a978",
    "--starck-blue-cta-middle": "#07966a",
    "--starck-blue-cta-end": "#05855e",
    "--starck-blue-cta-dark": "0 82 58",
    "--starck-blue-cta-glow": "5 150 105",
  },
  rose: {
    "--starck-blue-cta-start": "#f14f70",
    "--starck-blue-cta-middle": "#e73f61",
    "--starck-blue-cta-end": "#d93254",
    "--starck-blue-cta-dark": "130 20 52",
    "--starck-blue-cta-glow": "244 63 94",
  },
} satisfies Record<BlueCtaTone, BlueCtaToneStyle>

const blueCtaBaseClassName =
  "starck-blue-cta inline-flex cursor-pointer items-center justify-center gap-1.5 px-5 py-2 text-sm font-medium tracking-[-0.022em] whitespace-nowrap text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[rgb(var(--starck-blue-cta-glow)/0.6)] focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"

// The capsule is an Apple shape: macOS has drawn fully-rounded buttons since
// Big Sur, so it reads as native there. Windows 11 has no such shape - Fluent
// buttons are rounded rectangles - and a pill next to a Windows logo looks like
// a Mac button in costume. 10px reads as Fluent at CTA scale without going
// sharp next to soft cards.
const blueCtaPlatformClassNames = {
  macos: "rounded-full",
  windows: "rounded-[10px]",
} satisfies Record<BlueCtaPlatform, string>

// The macOS capsule, for consumers that compose their own button (navbar,
// sticky bars) and never switch platform.
const blueCtaClassName = `${blueCtaBaseClassName} ${blueCtaPlatformClassNames.macos}`

const blueCtaStyle = {
  fontFamily: '-apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif',
} satisfies React.CSSProperties

function AppleMark({ className }: { className?: string }) {
  return (
    <svg
      aria-hidden="true"
      className={className}
      fill="currentColor"
      viewBox="0 0 814 1000"
    >
      <path d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76.5 0-103.7 40.8-165.9 40.8s-105.6-57.8-155.5-127.4c-58.3-81.3-105.9-207.6-105.9-329.1 0-193.9 126.1-296.6 250.1-296.6 65.9 0 120.9 43.3 162.2 43.3 39.5 0 101.1-45.9 176.3-45.9 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 103.5-30.4 135.5-71.3z" />
    </svg>
  )
}

// The Windows 11 mark: four equal panes, no perspective. It stays legible at
// 15px, where the tilted Windows 8/10 logo turns to mush.
function WindowsMark({ className }: { className?: string }) {
  return (
    <svg
      aria-hidden="true"
      className={className}
      fill="currentColor"
      viewBox="0 0 24 24"
    >
      <path d="M1 1h9.7v9.7H1zM13.3 1H23v9.7h-9.7zM1 13.3h9.7V23H1zM13.3 13.3H23V23h-9.7z" />
    </svg>
  )
}

function PlatformMark({
  platform,
  className,
}: {
  platform: BlueCtaPlatform
  className?: string
}) {
  return platform === "windows" ? (
    <WindowsMark className={className} />
  ) : (
    <AppleMark className={className} />
  )
}

function BlueCtaButton({
  children = "Get SessionWatcher",
  className,
  icon,
  platform = "macos",
  style,
  tone = "blue",
  type = "button",
  ...props
}: BlueCtaButtonProps) {
  return (
    <button
      type={type}
      className={[
        blueCtaBaseClassName,
        blueCtaPlatformClassNames[platform],
        className,
      ]
        .filter(Boolean)
        .join(" ")}
      style={{
        ...blueCtaStyle,
        ...blueCtaToneStyles[tone],
        ...style,
      }}
      {...props}
    >
      {icon === undefined ? (
        <PlatformMark platform={platform} className="size-[15px]" />
      ) : (
        icon
      )}
      {children}
    </button>
  )
}

export {
  AppleMark,
  BlueCtaButton,
  blueCtaBaseClassName,
  blueCtaClassName,
  blueCtaPlatformClassNames,
  blueCtaPlatforms,
  blueCtaStyle,
  blueCtaTones,
  PlatformMark,
  WindowsMark,
}
export type { BlueCtaButtonProps, BlueCtaPlatform, BlueCtaTone }

More from starck

Browse all components in this library →