shineBorder
A Effects block/component from Magic UI — clean-room reimplemented for Domphy (see methodology). Call shineBorder() with no arguments for a working demo, or edit the code below live.
Props
| Prop | Type | Description |
|---|---|---|
thickness | number | Ring thickness in pixels. Defaults to 1. |
duration | number | One full rotation, in seconds — slower/calmer than borderBeam's comet. Defaults to 14. |
colors | ThemeColor[] | Colors the shine band blends through, in order. Defaults to a single subtle hue ["neutral"] (upstream's #000000). |
borderRadius | number | Corner radius in pixels, should roughly match the host card's own rounding. Defaults to 16. |
children | DomphyElement[] | Card content rendered inside the shined container. Defaults to a small demo card body. |
Implementation notes
Implemented as a full-perimeter SVG ring (not a dashed comet, unlike borderBeam) whose gradient orientation is continuously rotated by a native SMIL <animateTransform attributeName="gradientTransform" type="rotate">. This was chosen over CSS custom-property (@property) angle interpolation because Domphy's core CSS-in-JS compiler (packages/core/src/classes/StyleRule.ts) only recognizes @media/@supports/@container/@layer/@keyframes/@font-face as hoistable at-rules — an inline [@property ...] style key would silently be dropped, not registered — so a Houdini-typed-property rotation isn't reachable from Domphy's style object grammar today. SMIL animateTransform is native declarative SVG markup (already in @domphy/core's SvgTags list) with solid support across evergreen browsers and needs no JS/rAF at all, matching the spec's 'always-on, no interaction' requirement and giving a seamless loop for free (0deg and 360deg are visually identical). A second, wider, blurred duplicate ring is layered underneath for the described soft shimmer. Doctor-clean.
Status: ported · Reference: Magic UI original
// Magic UI "Shine Border" — clean-room reimplementation.
//
// A decorative animated border: a vivid multi-hue shine band that
// continuously sweeps around a container's rounded outline (contrast with
// `borderBeam`, which animates a single traveling comet). Implemented as a
// full-perimeter SVG ring stroked with a gradient — transparent flanks around
// the shine color, matching upstream's `radial-gradient(transparent,
// transparent, shineColor, transparent, transparent)` — whose orientation is
// continuously rotated by a native SMIL `<animateTransform>`. Pure declarative
// markup: no JS timers, resize listeners, or measurement, so it degrades to a
// static gradient ring wherever SMIL is unavailable, and to a static ring for
// users with `prefers-reduced-motion: reduce` (upstream's `motion-safe:` gate).
//
// Defaults and reduced-motion behavior verified against the real upstream
// source (registry/magicui/shine-border.tsx, MIT-licensed); the SMIL ring is a
// technique substitution for upstream's CSS `animate-shine` (see SOURCES.md).
import type { DomphyElement } from "@domphy/core";
import type { ThemeColor } from "@domphy/theme";
import { themeColor, themeSpacing } from "@domphy/theme";
import { heading, paragraph } from "@domphy/ui";
export interface ShineBorderProps {
/** Ring thickness in pixels. Defaults to `1`. */
thickness?: number;
/** One full rotation, in seconds — slower/calmer than `borderBeam`'s comet. Defaults to `14`. */
duration?: number;
/** Colors the shine band blends through, in order. Defaults to a vivid three-hue gradient `["primary", "secondary", "warning"]` — the animated multicolor shine is the point of the component (mirrors the upstream docs demo's `#A07CFE/#FE8FB5/#FFBE7B` trio within the theme's own families). */
colors?: ThemeColor[];
/** Corner radius in pixels, should roughly match the host card's own rounding. Defaults to `16`. */
borderRadius?: number;
/** Card content rendered inside the shined container. Defaults to a small demo card body. */
children?: DomphyElement[];
}
let shineBorderInstanceCounter = 0;
/**
* A card-like container whose border ring continuously shimmers through a
* rotating color gradient — an always-on ambient "premium" highlight. Call
* with no arguments for a working demo card.
*/
function shineBorder(props: ShineBorderProps = {}): DomphyElement<"div"> {
const {
thickness = 1,
duration = 14,
colors = ["primary", "secondary", "warning"],
borderRadius = 16,
children = [
{ h3: "Shine Border", $: [heading()] },
{
p: "A rotating gradient ring shimmers around this card as a calm, always-on premium highlight.",
$: [paragraph({ color: "neutral" })],
},
],
} = props;
const instanceId = ++shineBorderInstanceCounter;
const gradientId = `domphy-shine-border-gradient-${instanceId}`;
// `<stop>` is a paint-server node, not text — it has no `color` to follow the
// tone context, so the `missing-color` doctor rule is a false positive here.
//
// Upstream flanks the shine color(s) with transparent on both ends
// (`radial-gradient(transparent, transparent, <shineColor>, transparent,
// transparent)`), so even a single subtle hue reads as a moving band rather
// than a flat uniform ring. Mirror that: transparent → color(s) across the
// middle → transparent, with the SMIL rotation below sweeping the band around.
const transparentStop = (offset: string, key: string): DomphyElement =>
({
stop: null,
offset,
style: { stopColor: "transparent" },
_doctorDisable: "missing-color",
_key: key,
}) as DomphyElement;
const stops: DomphyElement[] = [
transparentStop("0%", "stop-start"),
...(colors.map((color, index) => ({
stop: null,
offset: `${((index + 1) / (colors.length + 1)) * 100}%`,
style: {
stopColor: (listener) => themeColor(listener, "shift-9", color),
},
_doctorDisable: "missing-color",
_key: `stop-${index}`,
})) as DomphyElement[]),
transparentStop("100%", "stop-end"),
];
const ringRect = (
strokeWidth: number,
blur: number,
opacity: number,
): DomphyElement =>
({
rect: null,
x: "1",
y: "1",
width: "calc(100% - 2px)",
height: "calc(100% - 2px)",
rx: String(Math.max(borderRadius - 1, 0)),
ry: String(Math.max(borderRadius - 1, 0)),
fill: "none",
stroke: `url(#${gradientId})`,
strokeWidth: String(strokeWidth),
style: {
opacity,
...(blur > 0 ? { filter: `blur(${blur}px)` } : {}),
},
}) as DomphyElement;
// Upstream gates the shine behind `motion-safe:animate-shine`, so users who
// request `prefers-reduced-motion: reduce` get a static ring. SMIL can't be
// gated by a CSS media query, so snapshot the preference at build time and
// omit the `<animateTransform>` entirely — leaving the same static gradient
// ring upstream's `motion-safe:` gate leaves. (Build-time snapshot, not a live
// listener; a mid-session OS toggle takes effect on the next render.)
const prefersReducedMotion =
typeof window !== "undefined" &&
typeof window.matchMedia === "function" &&
window.matchMedia("(prefers-reduced-motion: reduce)").matches;
return {
div: [
{
div: children,
style: {
position: "relative",
zIndex: 1,
padding: themeSpacing(6),
},
} as DomphyElement,
{
svg: [
{
defs: [
{
linearGradient: [
...stops,
...(prefersReducedMotion
? []
: [
{
animateTransform: null,
attributeName: "gradientTransform",
type: "rotate",
from: "0 0.5 0.5",
to: "360 0.5 0.5",
dur: `${duration}s`,
repeatCount: "indefinite",
} as DomphyElement,
]),
],
id: gradientId,
gradientUnits: "objectBoundingBox",
x1: "0%",
y1: "0%",
x2: "100%",
y2: "0%",
} as DomphyElement,
],
} as DomphyElement,
// A wider, blurred duplicate underneath gives the ring a soft shimmer.
ringRect(thickness * 2.5, 3, 0.45),
ringRect(thickness, 0, 1),
],
width: "100%",
height: "100%",
xmlns: "http://www.w3.org/2000/svg",
ariaHidden: "true",
style: { position: "absolute", inset: 0, pointerEvents: "none" },
} as DomphyElement,
],
style: {
position: "relative",
overflow: "hidden",
borderRadius: `${borderRadius}px`,
backgroundColor: (listener) => themeColor(listener, "inherit", "neutral"),
color: (listener) => themeColor(listener, "shift-10", "neutral"),
},
};
}
export { shineBorder };