Shiny Button

Button with a glossy gradient sheen that sweeps on a loop.

Report a bug

Preview

Switch between light and dark to inspect the embedded Storybook preview.

Installation

pnpm dlx shadcn@latest add https://ui.vllnt.ai/r/shiny-button.json

Storybook

Explore all variants, controls, and accessibility checks in the interactive Storybook playground.

View in Storybook

Code

import * as React from "react"; import { cn } from "../../lib/utils"; /** Props for {@link ShinyButton}. */ export type ShinyButtonProps = React.ComponentPropsWithoutRef<"button">; /** * Secondary button with a slow sheen drifting across its surface on a loop. * * Respects `prefers-reduced-motion`: the sheen stays parked off-screen. * * @example * ```tsx * <ShinyButton>Learn more</ShinyButton> * ``` */ export const ShinyButton = ({ children, className, ref, ...props }: ShinyButtonProps & { ref?: React.Ref<HTMLButtonElement> }) => { return ( <button className={cn( "relative inline-flex items-center justify-center overflow-hidden rounded-md border border-border bg-secondary px-4 py-2 text-sm font-medium text-secondary-foreground transition-colors hover:bg-secondary/80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", className, )} ref={ref} type="button" {...props} > <span aria-hidden="true" className="pointer-events-none absolute inset-0 -translate-x-full animate-shimmer motion-reduce:animate-none" style={{ animationDuration: "3s", background: "linear-gradient(90deg, transparent, oklch(var(--foreground) / 0.15), transparent)", }} /> <span className="relative z-10 inline-flex items-center gap-2"> {children} </span> </button> ); }; ShinyButton.displayName = "ShinyButton";

Dependencies

  • @vllnt/ui@^0.2.1