Glin UI
Primitive / AtomAdapted from Magic UIbeta

Interactive Hover Button

Pill button whose accent dot floods the surface on hover, focus or press.

Edit on GitHub

Join the beta

Early access to the new analytics workspace. Hover or focus the button to see it fill.

1,240 teams already in

Installation

Install from
pnpm dlx @glinui/cli@latest add interactive-hover-button

Credits. Adapted from Magic UI (MIT, (c) Magic UI). Clip path fill, a single accessible label, focus and press parity, token colors, RTL, sizes, glass and loading states. Attribution details.

Prefer the package?

Usage

Improvements: one accessible label instead of two, a cheap clip-path fill instead of a 100x scaled dot, focus-visible and active parity with hover, logical RTL offsets with a mirrored arrow, sizes, the shared variant vocabulary (glinr default, glass opt-in), loading, asChild and motion levels.

Variants

The shared vocabulary. The accent dot floods whichever surface you pick.

<div className="flex flex-wrap items-center gap-3">
<InteractiveHoverButton variant="glinr">glinr</InteractiveHoverButton>
<InteractiveHoverButton variant="solid">solid</InteractiveHoverButton>
<InteractiveHoverButton variant="plain">plain</InteractiveHoverButton>
<InteractiveHoverButton variant="soft">soft</InteractiveHoverButton>
<InteractiveHoverButton variant="outline">outline</InteractiveHoverButton>
<InteractiveHoverButton variant="ghost">ghost</InteractiveHoverButton>
<InteractiveHoverButton variant="gradient">gradient</InteractiveHoverButton>
</div>

Glass (opt-in)

Glass is never the default. It needs a colorful or photographic backdrop to read.

<InteractiveHoverButton variant="glass">Book a demo</InteractiveHoverButton>

Sizes, icons and states

Leading icon, small and large sizes, and a loading state.

<InteractiveHoverButton size="sm">Small</InteractiveHoverButton>
<InteractiveHoverButton size="lg" leadingIcon={<Plus />}>New project</InteractiveHoverButton>
<InteractiveHoverButton loading>Saving</InteractiveHoverButton>

Accessibility

  • Native button (or your element with asChild) with the Button focus ring.
  • The hover face is aria-hidden, so the label is read once. The original duplicated it.
  • Keyboard focus triggers the same fill as hover, and press fills it on touch.

Keyboard Interactions

KeyAction
EnterActivates the button.
SpaceActivates the button.
TabMoves focus and plays the fill.

ARIA Attributes

  • `aria-busy` while loading
  • `aria-disabled` when disabled or loading
  • Decorative icons and the hover face use `aria-hidden`

Reduced Motion

Motion level full slides the label and floods the surface with a clip-path. Subtle keeps the flood and opacity swap but drops the slide. None, or prefers-reduced-motion, switches state instantly. Hover effects only run on fine pointers.

Affected properties

clip-pathtransformopacity

API Reference

InteractiveHoverButton

PropTypeRequiredDefaultDescription
variant"glinr" | "solid" | "plain" | "soft" | "outline" | "ghost" | "gradient" | "glass"-ambient (glinr)Surface from the shared vocabulary. Omit for the ambient default. Glass is opt-in and needs a backdrop.
tone"neutral" | "accent" | "success" | "warning" | "danger" | "info"-neutralColour axis.
size"xs" | "sm" | "md" | "lg" | "icon"NomdHeight and type size, aligned with Button.
leadingIconReact.ReactNodeNo-Decorative icon before the label.
trailingIconReact.ReactNodeNo-Decorative icon after the label. Replaces the hover arrow.
loadingbooleanNofalseShows a Spinner, sets aria-busy and blocks interaction.
asChildboolean-falseRender onto your own element, for example a router link.
disabledboolean-falseDisables the control.

Source

Import directly from the package or browse the source on GitHub. Click any file to view it.

Import

import { InteractiveHoverButton } from "@glinui/ui"

Dependencies

@glinui/ui@glinui/motionclass-variance-authority@phosphor-icons/react

Generated API Snapshot

Beta

Auto-extracted from TypeScript source in packages/ui/src/components/interactive-hover-button.tsx. This section is in beta and may lag behind hand-curated docs. Regenerate with pnpm --filter @glinui/docs api:generate.

Generated: 2026-10-08T01:41:21.546Z · Full index: /docs/api-metadata

Primary Props Type

InteractiveHoverButtonProps

InteractiveHoverButtonProps

PropTypeRequiredDefaultDescription
leadingIconReact.ReactNodeNo-Icon before the label (decorative).
loadingbooleanNofalseShow a spinner, set aria-busy and block interaction.
size"xs" | "sm" | "md" | "lg" | "icon"No"md"Variant option from interactiveHoverButtonVariants.
trailingIconReact.ReactNodeNo-Icon after the label. Defaults to an arrow that mirrors in RTL on the hover face.