A premium call-to-action whose body is flowing liquid metal: it surges toward the pointer, dimples and ripples when pressed, and can swell past its border.

  • shader
  • webgl
  • button
  • metal
  • chrome
  • cta
  • hover
  • ripple
Preset

Installation

Pro — coming soon

The source and installation instructions for this item ship with Kagadmodyaa Pro.

Usage

Use it like any other component. Choose a theme with preset; any prop you pass as well overrides the preset.

import { LiquidMetalButton } from '@/components/effects/liquid-metal-button/liquid-metal-button'

export function Hero() {
  return (
    <div className="flex items-center gap-4 p-6">
      {/* the molten edge swells a few px past the border: give it room, and avoid overflow: hidden parents */}
      <LiquidMetalButton preset="Gold" size="lg" iconEnd={<ArrowRight />} onClick={() => signUp()}>
        Start for free
      </LiquidMetalButton>
      <LiquidMetalButton preset="Gunmetal" size="sm" label="Learn more" />
      <LiquidMetalButton loading>Saving</LiquidMetalButton>
      <LiquidMetalButton iconStart={<Plus />} aria-label="Add" />
    </div>
  )
}

// A normal <button>: type, disabled, ref, aria-* and every event prop work as usual.
// Presets: Chrome, Gold, Rose Gold, Gunmetal, Oil Slick. Any prop you pass (metalTint, roughness, studio...) overrides the preset.
// The stage above is <LiquidMetalButtonShowcase />, also exported, if you want the same hero composition.
<LiquidMetalButton preset="Gold" size={"lg"} />

Presets

  • Chrome
  • Gold
  • Rose Gold
  • Gunmetal
  • Oil Slick

Props

NameTypeDefaultDescription
preset'Chrome' | 'Gold' | 'Rose Gold' | 'Gunmetal' | 'Oil Slick'none (the defaults below)A named theme. Any prop you pass as well overrides the preset’s value.
size'sm' | 'md' | 'lg''lg'Size of the button: sm 38px, md 48px, lg 62px tall.
label'Start for free' | 'Get early access' | 'Book a demo' | 'Continue' | 'Join the waitlist''Start for free'The label, when you do not pass children. Always real text, never part of the shader.
tone'auto' | 'dark' | 'light''auto'Which surface the button sits on. auto follows the page theme.
studio'chrome' | 'gold' | 'rose' | 'gunmetal' | 'oil''chrome'Which room the metal reflects: its sky, horizon, ground and light colours. Oil adds thin-film iridescence.
metalTintstring'#eef2f8'The colour of the mirror at normal incidence. A hex colour.
roughnessnumber0.10 is a mirror, 1 is satin: how soft the reflections are. Range 0 to 1.
intensitynumber1Strength of the reflections and highlights. Range 0 to 1.5.
speednumber1How fast the metal flows at rest. 0 freezes it. Range 0 to 2.
surgenumber1How hard the metal swells toward the pointer on hover. Range 0 to 2.
ripplenumber1How strong the ripple rings are when you press. Range 0 to 2.
moltenEdgebooleantrueLet the metal swell and drip a little past the border on hover, inside a small margin so layout never shifts.
classNamestring—Extra class on the root element. The effect fills its parent: give the parent a height.
styleCSSProperties—Inline style on the root element.

Behaviour

  • A real <button>: Enter and Space activate it, Tab focuses it, and a crisp focus-visible ring shows on keyboard focus. The label is ordinary text above the canvas, engraved into the metal with a text-shadow; the metal under it is calmed so it always reads.
  • At rest the metal flows slowly. On hover it surges toward the pointer, brightens and a highlight follows the cursor; on press the surface dimples under your finger and a ripple ring expands from the press point, then it rebounds and settles (spring physics). Enter and Space ripple from the centre.
  • Molten edge: on hover the metal swells and drips a few pixels past the border. It lives inside the button's own canvas margin so layout never shifts, but a parent with overflow: hidden will clip it. Turn it off for a clean pill.
  • disabled dims it and freezes the metal; loading swirls the metal around a spinner, sets aria-busy and ignores clicks while keeping focus. Icons go in iconStart and iconEnd (decorative); a button with only an icon needs an aria-label.
  • The canvas is created only while the button is near the viewport, and at most eight draw at once on a page. Beyond that a button keeps its CSS metal. It pauses off screen and in a background tab, lowers its resolution automatically if frames run slow, and draws one still frame under prefers-reduced-motion.
  • Without WebGL, and before the first frame, you see a CSS metallic gradient in the same colours. Tone is 'auto' by default: it follows a dark or light class on <html> (or the OS setting) and re-reads it when the theme changes.

See all effects