Skip to content

Shimmer Border

Highlight a container or button with light that travels along its border.

import { ShimmerBorder, ShimmerButton } from '@youj/motion/interactions'

Installation & usage

npm i @youj/motion

For an app already set up with npx @youj/cli init, which installs the peers (@youj/core, @youj/motion, motion and Base UI) and wires the provider. New app? Start at Installation.

Use it for the one place a screen invites input or an upgrade: an AI composer, a featured plan, a trial call to action. One shimmer draws the eye, and two compete, so use one per screen. ShimmerBorder and ShimmerButton are the Shimmer effect with a surface and a button look. Reach for the effect when the element already has its own look.

ShimmerBorder is a container with a 12px radius, the surface color and the traveling light on its border. Keep its content above the light with relative z-2.

import { ShimmerBorder } from '@youj/motion/interactions'

export function Composer() {
  return (
    <ShimmerBorder className="rounded-2xl">
      <div className="relative z-2">
        <label htmlFor="prompt" className="sr-only">Ask the assistant</label>
        <textarea id="prompt" rows={3} placeholder="Ask anything about your workspace…" />
        <ComposerToolbar />
      </div>
    </ShimmerBorder>
  )
}

Focus the prompt in the preview: focus inside the container intensifies the light exactly like hover does.

Reference

Propsidle, intensify, speed… (10)

Props

ShimmerBorder

ShimmerBorder props
PropType
childrenReactNode–
idle'subtle' | 'visible' | 'hidden'

How visible the light is at rest. 'hidden' only shows it on hover / focus.

default 'subtle'

'subtle'
intensifyboolean

Lengthen the comet and add a bloom on hover and keyboard focus.

default true

true
speed'slow' | 'base' | 'fast'

One lap of the border.

default 'base'

'base'
borderWidthnumber

Border width in px.

default 1

1

Other props pass through to the container's div.

ShimmerButton

ShimmerButton props
PropType
childrenReactNode–
idle'subtle' | 'visible' | 'hidden'

How visible the light is at rest. 'hidden' only shows it on hover / focus.

default 'subtle'

'subtle'
intensifyboolean

Lengthen the comet and add a bloom on hover and keyboard focus.

default true

true
speed'slow' | 'base' | 'fast'

One lap of the border.

default 'base'

'base'
borderWidthnumber

Border width in px.

default 1

1
Other props pass through: extends ButtonHTMLAttributes<HTMLButtonElement>.
MotionLap, intensify, press · reduced motion

Motion

Motion tokens
MomentTokens
Lapspeed: slow, base, fast
ease.linear

cubic-bezier(0, 0, 1, 1) · deliberate × 10, × 6, × 3.5

cubic-bezier(0, 0, 1, 1)deliberate × 10, × 6, × 3.5
Intensifyon hover and keyboard focus
duration.slowease.standard

340ms · cubic-bezier(0.2, 0, 0, 1)

340mscubic-bezier(0.2, 0, 0, 1)
PressShimmerButton scales to 0.98
duration.fastease.standard

140ms · cubic-bezier(0.2, 0, 0, 1)

140mscubic-bezier(0.2, 0, 0, 1)

Reduced motion

The light is parked at a fixed point on the border and doesn't travel. Hover and focus still intensify it, instantly.

The loop is pure CSS on a registered @property angle, so it costs no JavaScript per frame, and it pauses while the element is offscreen or the tab is hidden.

Reduced motion

The light stops at a fixed point on the border, so the container keeps its accent glint without movement, and hover or focus still brightens it instantly.

AccessibilityKeyboard, ARIA, focus

Accessibility

  • ShimmerButton is a native button, type="button" unless you pass another type, with a visible focus ring.
  • The light's layers are aria-hidden. In ShimmerBorder, label the controls inside it as you would anywhere else, like the visually hidden label on the prompt in the demo.
  • Keyboard focus intensifies the light like hover, so the emphasis never depends on a pointer.