A band of light that sweeps across a card or an image when the pointer or keyboard focus reaches it.
Optional, and kept apart.
Nothing here is included in a project unless you add it, and the plain component it builds on is unchanged. This effect is decoration: it is hidden from screen readers, stands still for visitors who prefer reduced motion, and can be paused. Use Still on a preview to see that version.
import { GlareHover } from "@rdloom/react";
// The default glare is a soft tint of the action colour, so it shows on a light card.
export default function GlareHoverBasicExample() {
return (
<div className="flex w-full justify-center py-6">
<GlareHover
tabIndex={0}
className="w-80 rounded-[var(--rd-radius-overlay)] border border-[var(--rd-color-border-default)] bg-[var(--rd-color-surface-default)] p-6 outline-none focus-visible:ring-2 focus-visible:ring-[var(--rd-color-focus-ring)]"
>
<h3 className="text-lg font-semibold">Pro plan</h3>
<p className="mt-1 text-sm text-[var(--rd-color-text-muted)]">Hover or focus this card to see the glare.</p>
</GlareHover>
</div>
);
}Installation
npx rdloom add glare-hoverCopies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes.
It also adds rdloom-motion.css next to your tokens and imports it from the tokens file, once: no setup, and no inline styles. The plain components you already use are untouched.
Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/glare-hover.jsonWorks, but without upgrade tracking, and you import the motion CSS yourself.
Usage
import { GlareHover } from "@rdloom/react";
<div className="flex w-full justify-center py-6">
<GlareHover
tabIndex={0}
className="w-80 rounded-[var(--rd-radius-overlay)] border border-[var(--rd-color-border-default)] bg-[var(--rd-color-surface-default)] p-6 outline-none focus-visible:ring-2 focus-visible:ring-[var(--rd-color-focus-ring)]"
>
<h3 className="text-lg font-semibold">Pro plan</h3>
<p className="mt-1 text-sm text-[var(--rd-color-text-muted)]">Hover or focus this card to see the glare.</p>
</GlareHover>
</div>On image
import { GlareHover } from "@rdloom/react";
// On a photo or a dark surface, set the glare to white at low strength.
export default function GlareHoverOnImageExample() {
return (
<div className="flex w-full justify-center py-4">
<GlareHover angle={-30} duration={0.9} color="rgb(255 255 255 / 0.45)" className="h-56 w-full max-w-md rounded-[var(--rd-radius-overlay)]">
<img
src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?auto=format&fit=crop&w=1200&q=80"
alt="Green highlands under a cloudy sunrise with a winding road"
className="size-full object-cover"
/>
</GlareHover>
</div>
);
}API Reference
Defined by the spec. Components also accept the props of the React Aria component they wrap.
| Prop | Type | Default |
|---|---|---|
childrenrequiredThe content to sweep across. | node | none |
angleTilt of the band in degrees. | number | -20 |
durationSeconds for one sweep. | number | 0.7 |
colorColour of the glare, any CSS colour. Defaults to a soft tint of the action colour, which shows on light and dark surfaces. Use white at low strength on a dark card. | string | none |
isPausedStops the effect and shows it still. | boolean | false |
Accessibility
Role group, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.
Keyboard
Not interactive.
Screen readers announce
- Read as ordinary content: the glare is not announced
What your code must do
- The glare is decoration: aria-hidden and never blocks the pointer
- It sweeps once on hover and once on focus-within, so keyboard users see the same effect, and it is not a way to show state
- Off for reduced motion, inside rdm-still and with isPaused
- The glare is a faint tint, so the text or image underneath keeps its contrast
- In forced-colors (high contrast) mode the band is removed
Guidelines
Use it when
- Product images and feature cards
- A hover accent on a photo
Avoid it when
- Text the reader must keep reading while the band crosses it
Don't
- Using the glare as the only sign that something is clickable
- Strong, opaque glare colours
Design tokens
The semantic tokens this component uses. Change them once and every component follows; see Design tokens.
--rd-radius-overlay--rd-color-border-default