Buttonsbuttonanimatedattention
Pulse Button
A button with a persistent circular pulse effect to draw attention.
Live Preview
Usage
Copy and paste this code into your React component:
tsx
import { PulseButton } from 'react-component-kit-ui/buttons';
<PulseButton color="#8b5cf6">Join live</PulseButton>Manual Installation
If you are not using the npm package, create a new file and paste the following code: src/components/PulseButton.tsx + PulseButton.css:
PulseButton.tsx
'use client';
import type { CSSProperties, ElementType, HTMLAttributes, ReactNode } from 'react';
import './PulseButton.css';
/**
* PulseButton โ A button with a persistent circular pulse effect to draw attention.
*
* @param color - Optional. Pulse color. Default '#8b5cf6'.
*/
export interface PulseButtonProps extends HTMLAttributes<HTMLElement> {
href?: string;
target?: string;
rel?: string;
type?: 'button' | 'submit' | 'reset';
variant?: 'primary' | 'secondary' | 'ghost';
size?: 'sm' | 'md' | 'lg';
color?: string;
disabled?: boolean;
children?: ReactNode;
}
export function PulseButton({
href,
type = 'button',
variant = 'primary',
size = 'md',
color = '#8b5cf6',
disabled = false,
className,
style,
children,
...rest
}: PulseButtonProps) {
const Tag: ElementType = href ? 'a' : 'button';
return (
<Tag
{...rest}
href={href}
type={href ? undefined : type}
disabled={href ? undefined : disabled}
aria-disabled={href && disabled ? true : undefined}
className={['pulse-btn', `pulse-btn--${variant}`, `pulse-btn--${size}`, className].filter(Boolean).join(' ')}
style={{ '--pulse-color': color, ...style } as CSSProperties}
>
{children}
</Tag>
);
}
export default PulseButton;PulseButton.css
/* PulseButton โ ported from astro-component-kit (buttons/PulseButton.astro) */
.pulse-btn {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.7rem 1.6rem;
background: var(--pulse-color);
color: white;
border: none;
border-radius: var(--r-full, 9999px);
cursor: pointer;
text-decoration: none;
font-weight: 600;
transition: transform 0.2s ease, box-shadow 0.2s ease;
user-select: none;
white-space: nowrap;
font-family: var(--font-sans, inherit);
isolation: isolate;
box-shadow: 0 10px 26px -18px color-mix(in srgb, var(--pulse-color), black 10%);
}
.pulse-btn::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
box-shadow: 0 0 0 0 var(--pulse-color);
animation: pulse-button-pulse-ring 2s infinite;
z-index: -1;
pointer-events: none;
}
@keyframes pulse-button-pulse-ring {
0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--pulse-color), transparent 30%); }
70% { box-shadow: 0 0 0 15px color-mix(in srgb, var(--pulse-color), transparent 100%); }
100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--pulse-color), transparent 100%); }
}
.pulse-btn:hover:not(:disabled) {
transform: scale(1.05);
filter: brightness(110%);
}
.pulse-btn:active:not(:disabled) {
transform: scale(0.98);
}
.pulse-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
animation: none;
filter: grayscale(1);
}
.pulse-btn:disabled::after {
animation: none;
box-shadow: none;
}
/* Variants */
.pulse-btn--secondary {
background: #0f172a;
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 10px 26px -20px rgba(15, 23, 42, 0.95);
}
.pulse-btn--ghost {
background: transparent;
border: 1px solid var(--pulse-color);
color: var(--pulse-color);
box-shadow: none;
}
/* Sizes */
.pulse-btn--sm { padding: 0.4rem 1.1rem; font-size: 0.8rem; }
.pulse-btn--md { padding: 0.7rem 1.6rem; font-size: 0.95rem; }
.pulse-btn--lg { padding: 1rem 2.2rem; font-size: 1.1rem; }Quick Info
- Category
- Buttons
- Filename
PulseButton.tsx- Dependencies
- None โ pure React + CSS
- Tags
- buttonanimatedattention