Primary Button

Free

The default call to action, solid fill with hover and focus states.

npx shadcn@latest add @ui-shrushank/primary-button

The install writes a single file to components/ui/PrimaryButton.tsx, which exports PrimaryButton.

tsx
import { PrimaryButton } from "@/components/ui/PrimaryButton";
tsx
<PrimaryButton>Label</PrimaryButton>

Needs framer-motion installed. The shadcn CLI adds it for you.

The default call-to-action; every library needs the anchor case.

Solid fill, explicit hover and focus-visible states, one accent token.

Every line below was read out of the file you are about to copy, so you can check each one against the source at the bottom of this page.

  • Has an explicit prefers-reduced-motion branch: the animation is dropped for an instant state change, and the component stays fully usable without it.
  • Draws a focus-visible ring that is separate from its hover treatment, so keyboard users get an affordance mouse users do not take away.

Focus state is separate from hover so keyboard users get the same affordance mouse users get; a CTA with no visible focus ring is the most common a11y failure in button kits.

1 required, 0 optional.

childrenrequired
React.ReactNode

One file, no runtime package. Copy it, or install it with the command at the top of this page.

PrimaryButton.tsx
"use client";import { motion, useReducedMotion } from "framer-motion";export function PrimaryButton({ children }: { children: React.ReactNode }) {  const shouldReduceMotion = useReducedMotion();  return (    <motion.button      whileHover={shouldReduceMotion ? undefined : { y: -2 }}      whileTap={{ scale: 0.96, y: 0 }}      transition={{ type: "spring", stiffness: 500, damping: 30 }}      className="group relative inline-flex items-center justify-center overflow-hidden rounded-lg bg-emerald-700 px-5 py-2.5 text-sm font-medium text-white shadow-[0_1px_2px_rgba(4,120,87,0.3)] transition-[box-shadow,background-color] duration-300 hover:bg-emerald-800 hover:shadow-[0_12px_24px_-8px_rgba(4,120,87,0.65)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-emerald-700 active:bg-emerald-800 dark:bg-emerald-700 dark:shadow-[0_1px_2px_rgba(16,185,129,0.35)] dark:hover:bg-emerald-600 dark:hover:shadow-[0_12px_24px_-8px_rgba(16,185,129,0.55)] dark:focus-visible:outline-emerald-400 dark:active:bg-emerald-700"    >      <span        aria-hidden        className="pointer-events-none absolute inset-0 -translate-x-full bg-gradient-to-r from-transparent via-white/30 to-transparent transition-transform duration-700 ease-out group-hover:translate-x-full motion-reduce:hidden"      />      <span className="relative">{children}</span>    </motion.button>  );}