Quantum

No dependencies
Code format
React + Tailwind
const css = `
  @keyframes btn-quantum-a {
    0% { translate: -7px 3px; } 20% { translate: 5px -4px; } 45% { translate: -3px -5px; } 70% { translate: 8px 2px; } 100% { translate: -6px 4px; }
  }
  @keyframes btn-quantum-b {
    0% { translate: 6px -3px; } 30% { translate: -8px 2px; } 55% { translate: 3px 5px; } 80% { translate: -4px -3px; } 100% { translate: 7px 1px; }
  }
  @keyframes btn-quantum-c {
    0% { translate: 2px 5px; } 25% { translate: -5px -2px; } 60% { translate: 7px -4px; } 85% { translate: -2px 4px; } 100% { translate: 3px -5px; }
  }
  @keyframes btn-quantum-collapse {
    from { transform: scale(0.85); opacity: 0.9; }
    to { transform: scale(1.5); opacity: 0; }
  }
  .btn-quantum {
    position: relative;
    width: 168px;
    height: 50px;
    padding: 0;
    border: none;
    background: none;
    font-family: inherit;
    cursor: pointer;
  }
  .btn-quantum:focus-visible { outline: 2px solid light-dark(#42454c, #e5e6e9); outline-offset: 5px; border-radius: 999px; }
  .btn-quantum__state {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    border: 1px solid light-dark(#5f626a, #a7abb2);
    border-radius: 999px;
    color: light-dark(#373a40, #f1f2f3);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.08em;
    opacity: 0.38;
    filter: blur(0.6px);
    transition: opacity 0.15s ease, filter 0.15s ease;
  }
  .btn-quantum__state:nth-child(1) { animation: btn-quantum-a 1.1s steps(1, end) infinite; }
  .btn-quantum__state:nth-child(2) { animation: btn-quantum-b 0.83s steps(1, end) infinite; }
  .btn-quantum__state:nth-child(3) { animation: btn-quantum-c 0.97s steps(1, end) infinite; }
  .btn-quantum__state--real {
    background: light-dark(#f3f4f7, #1a1c1f);
    border-color: light-dark(#50535b, #c6c8cd);
    opacity: 0;
    filter: none;
  }
  .btn-quantum__flash {
    position: absolute;
    inset: 0;
    border: 1px solid light-dark(#373a40, #f1f2f3);
    border-radius: 999px;
    opacity: 0;
    pointer-events: none;
  }
  /* Observed: the superposition collapses at once (no tween; that's the point) into one state. */
  .btn-quantum:hover .btn-quantum__state,
  .btn-quantum:focus-visible .btn-quantum__state { animation: none; opacity: 0; }
  .btn-quantum:hover .btn-quantum__state--real,
  .btn-quantum:focus-visible .btn-quantum__state--real { opacity: 1; }
  .btn-quantum:hover .btn-quantum__flash,
  .btn-quantum:focus-visible .btn-quantum__flash { animation: btn-quantum-collapse 0.5s cubic-bezier(0.22, 1, 0.36, 1); }
  @media (prefers-reduced-motion: reduce) {
    .btn-quantum__state { animation: none !important; }
    .btn-quantum__state:nth-child(1) { translate: -4px 2px; }
    .btn-quantum__state:nth-child(2) { translate: 4px -2px; }
    .btn-quantum:hover .btn-quantum__flash { animation: none; }
  }
`;

export function QuantumButton() {
  return (
    <>
      <style>
        {css}
      </style>
      <button type="button" className="btn-quantum">
        <span className="btn-quantum__state" aria-hidden="true">
          Observe
        </span>
        <span className="btn-quantum__state" aria-hidden="true">
          Observe
        </span>
        <span className="btn-quantum__state" aria-hidden="true">
          Observe
        </span>
        <span className="btn-quantum__state btn-quantum__state--real">Observe</span>
        <span className="btn-quantum__flash" aria-hidden="true" />
      </button>
    </>
  );
}

Free to use in any project, commercial included. MIT-0, no attribution required. Licence

Install with shadcn

npx shadcn@latest add @movin/button-quantum
Source on GitHub

About this component

The label sits in superposition: three faint copies of the button jitter between positions out of step. Hover or focus observes it, and they collapse instantly into one solid button with a ring of light.

Dependencies
None
Difficulty
Beginner
Triggers
hover, state change, continuous
Techniques
keyframes, filter, css transition
Reduced motion
Respected
Theme
Light and dark (follows your page's color-scheme)

A real <button>; the jittering copies are aria-hidden and the solid label names it. Focus observes it like hover. Under prefers-reduced-motion the copies sit still and slightly offset.

More buttons

See all
Radar
Reactor
Target Lock
Teleport