Alert Pulse
Superposition d'anneau pulsant pour alerter les objets du canevas, avec des tons de gravite. Installez Alert Pulse depuis le registre VLLNT UI avec la CLI shadcn.
Superposition d'anneau pulsant pour alerter les objets du canevas, avec des tons de gravite. Fait partie de la famille utility dans VLLNT UI, il est publie comme entree de registre lisible par machine — copiez la source directement dans votre application avec la CLI shadcn et possedez-la, sans dependance d'execution a une bibliotheque de composants.
Apercu
Basculez entre clair et sombre pour inspecter l'apercu Storybook integre.
Installation
Ajoutez Alert Pulse a votre projet avec la CLI shadcn. La source arrive dans votre code, prete a etre adaptee :
pnpm dlx shadcn@latest add https://ui.vllnt.ai/r/alert-pulse.jsonSource
"use client";
import type { ComponentPropsWithoutRef } from "react";
import { cn } from "../../lib/utils";
/**
* Severity tone of an alert pulse — drives the ring color.
*
* @public
*/
export type AlertPulseSeverity = "error" | "info" | "warn";
const SEVERITY_STROKE: Record<AlertPulseSeverity, string> = {
error: "stroke-red-500",
info: "stroke-blue-500",
warn: "stroke-amber-500",
};
const SEVERITY_FILL: Record<AlertPulseSeverity, string> = {
error: "fill-red-500/20",
info: "fill-blue-500/20",
warn: "fill-amber-500/20",
};
const SEVERITY_LABEL: Record<AlertPulseSeverity, string> = {
error: "Error",
info: "Info",
warn: "Warning",
};
/**
* Localizable strings.
*
* @public
*/
export type AlertPulseLabels = {
/** Override for the aria-label. Defaults to severity name. */
region?: string;
};
/**
* Props for {@link AlertPulse}.
*
* @public
*/
export type AlertPulseProps = {
/** Center X of the pulse in canvas pixels. */
cx: number;
/** Center Y of the pulse in canvas pixels. */
cy: number;
/** Localizable strings. */
labels?: AlertPulseLabels;
/** Outer ring radius in pixels. Defaults to `36`. */
radius?: number;
/** Disable the pulse animation. Useful for snapshots. Defaults to `false`. */
reducedMotion?: boolean;
/** Severity tone. Defaults to `"warn"`. */
severity?: AlertPulseSeverity;
} & ComponentPropsWithoutRef<"svg">;
const safeRadius = (value: number): number => (value < 6 ? 6 : value);
/**
* Pulsing ring overlay drawn around an alerting canvas object. The
* outer ring expands and fades to communicate "attention here";
* the inner ring stays put so the object remains anchored. Pure
* presentation; the host computes the center + severity from the
* runtime alert stream.
*
* Render inside a `position: relative` parent that shares the canvas
* pixel coordinate space; the SVG is `pointer-events: none` so host
* gestures pass through.
*
* @example
* ```tsx
* <div className="relative h-screen w-screen">
* <Canvas />
* <AlertPulse cx={480} cy={320} severity="error" />
* </div>
* ```
*
* @public
*/
export const AlertPulse = ({
ref,
...props
}: AlertPulseProps & { ref?: React.Ref<SVGSVGElement> }) => {
const {
className,
cx,
cy,
labels,
radius = 36,
reducedMotion = false,
severity = "warn",
...rest
} = props;
const r = safeRadius(radius);
const ariaLabel = labels?.region ?? SEVERITY_LABEL[severity];
const size = r * 2 + 24;
return (
<svg
aria-label={ariaLabel}
className={cn(
"pointer-events-none absolute z-20 overflow-visible",
className,
)}
data-alert-pulse
data-alert-severity={severity}
height={size}
ref={ref}
role="img"
style={{
left: cx - size / 2,
top: cy - size / 2,
}}
width={size}
{...rest}
>
<circle
className={cn("origin-center", SEVERITY_STROKE[severity])}
cx={size / 2}
cy={size / 2}
fill="none"
r={r}
strokeOpacity={0.7}
strokeWidth={2}
/>
<circle
className={cn(
"origin-center",
SEVERITY_STROKE[severity],
SEVERITY_FILL[severity],
reducedMotion ? null : "animate-ping",
)}
cx={size / 2}
cy={size / 2}
data-alert-pulse-ring
r={r}
strokeOpacity={0.4}
strokeWidth={2}
/>
</svg>
);
};
AlertPulse.displayName = "AlertPulse";
Stories
Explorez chaque variante et etat dans le Storybook interactif :
Apercu
Basculez entre clair et sombre pour inspecter l'apercu Storybook integre.