Glin UI
Signature / Atom

Magnetic CTA

Call-to-action button with subtle cursor-attraction on hover.

New: scheduled deploys

Ship on your own schedule

Queue a release for Tuesday morning and let the pipeline handle the rest. Rollbacks stay one click away.

Installation$

Install from
pnpm dlx @glinui/cli@latest add magnetic-cta

Prefer the package?

Usage$

MagneticCTA wraps a Button and pulls it toward the cursor inside the magnetic radius. The default is a crisp glinr surface that adapts to the theme scope, so it looks right on every stage backdrop. The button stays fully accessible; the pull is a decorative transform.

Examples$

Variants$

Every variant of the shared vocabulary works, and the motion effect adapts to the surface colour. Omit variant for the ambient default (glinr).

import { MagneticCTA } from "@glinui/ui"
export function MagneticCTAVariantsDemo() {
return (
<div className="flex flex-wrap items-center gap-3">
<MagneticCTA variant="glinr">glinr</MagneticCTA>
<MagneticCTA variant="solid">solid</MagneticCTA>
<MagneticCTA variant="plain">plain</MagneticCTA>
<MagneticCTA variant="soft">soft</MagneticCTA>
<MagneticCTA variant="outline">outline</MagneticCTA>
<MagneticCTA variant="ghost">ghost</MagneticCTA>
<MagneticCTA variant="gradient">gradient</MagneticCTA>
</div>
)
}

Glass (opt-in)$

glass is never the default. It needs a colorful or photographic backdrop to read, so place it over imagery or inside a ThemeScope with a backdrop.

import { MagneticCTA } from "@glinui/ui"
export function MagneticCTAGlassDemo() {
return (
<MagneticCTA variant="glass">Glass</MagneticCTA>
)
}

Custom offset and radius$

Increase maxOffset for a stronger pull and magnetRadius to activate the effect from further away.

import { MagneticCTA } from "@glinui/ui"
export function MagneticCTAStrongDemo() {
return (
<div className="flex flex-wrap gap-6">
<MagneticCTA variant="solid" maxOffset={14} magnetRadius={180}>
Strong pull
</MagneticCTA>
<MagneticCTA variant="outline" maxOffset={4} magnetRadius={80}>
Subtle pull
</MagneticCTA>
</div>
)
}

Container class$

Use containerClassName to control the layout of the magnetic wrapper.

import { MagneticCTA } from "@glinui/ui"
export function MagneticCTAContainerDemo() {
return (
<MagneticCTA containerClassName="flex justify-center w-full">
Centered CTA
</MagneticCTA>
)
}

Accessibility$

  • Renders through Button: native <button>, 2px accent focus ring with offset, disabled and aria-busy states.
  • Accessible name comes from the label. Decorative effect layers are aria-hidden and pointer-events-none.
  • The focus ring stays on the button and is not hidden by the offset.

Reduced Motion$

The pull is disabled under prefers-reduced-motion and data-glin-motion="none": the offset resets to zero.

API Reference$

PropTypeRequiredDefaultDescription
containerClassNamestringNo-Auto-generated from TypeScript source.
magnetRadiusnumberNo140Auto-generated from TypeScript source.
maxOffsetnumberNo8Auto-generated from TypeScript source.

Source$

import { MagneticCTA } from "@glinui/ui"
packages/ui/src/components/magnetic-cta.tsx

Generated API Snapshot

Beta

Auto-extracted from TypeScript source in packages/ui/src/components/magnetic-cta.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

MagneticCTAProps

MagneticCTAProps

PropTypeRequiredDefaultDescription
containerClassNamestringNo--
magnetRadiusnumberNo140-
maxOffsetnumberNo8-