bottega

primitives

Neu Fill Button

A neumorphic soft button with a raised shadow surface derived entirely from design tokens. On hover, two overlapping ovals sweep upward from below the button face to flood it with the primary color — text flips to primary-foreground as the fill completes. Pressing triggers a concave inset shadow for tactile depth. Fully accessible: native button semantics, focus-visible ring, keyboard operable.

Ported from shah1345 (MIT)


Install

1. Register the namespace (once per project):

json
// components.json — register the @bottega namespace once
{
  "registries": {
    "@bottega": { "url": "https://bottega.ariacode.ca/r/{name}.json" }
  }
}

2. Add the component:

bash
npx shadcn add @bottega/neu-fill-button

Usage

Usagetsx
<NeuFillButton />

Props

Standard props — see source.


Source

neu-fill-button.tsxtsx
"use client";

import type React from "react";
import styles from "./neu-fill-button.module.css";

export type NeuFillButtonProps = React.ComponentProps<"button">;

/**
 * NeuFillButton — neumorphic soft button with a hover fill-expand sweep.
 *
 * Pure CSS interaction (no motion dep): two oval pseudo-elements start below
 * the button and sweep upward on hover to flood the face with `--primary`.
 * `:active` inverts shadows to a concave press.
 *
 * Pass any native `<button>` prop; `children` defaults to "Hover me" so the
 * preview renders standalone.
 */
export function NeuFillButton({
  children = "Hover me",
  className,
  type = "button",
  ...props
}: NeuFillButtonProps) {
  return (
    <button
      type={type}
      className={[styles.button, className].filter(Boolean).join(" ")}
      {...props}
    >
      {children}
    </button>
  );
}

Dependencies

  • @bottega/tokens