Tipografíatypographymarqueegradientloopticker
Gradient Text Marquee
Marquesina continua de texto en degradado que se desplaza infinitamente en bucle.
Vista Previa en Vivo
PERFORMANCE FIRST✦ZERO DEPENDENCIES✦ACCESSIBLE WCAG AA✦ASTRO 5 READY✦DARK GLASS MORPHISM✦PERFORMANCE FIRST✦ZERO DEPENDENCIES✦ACCESSIBLE WCAG AA✦ASTRO 5 READY✦DARK GLASS MORPHISM✦
Uso
Copia y pega este código directamente en tu componente React:
tsx
import { GradientTextMarquee } from 'react-component-kit-ui/typography';
<GradientTextMarquee text="ASTRO COMPONENTS • MODERN UI • ZERO RUNTIME • ACCESSIBLE • " speed="normal" />Instalación Manual
Si no estás usando el paquete npm, crea un archivo nuevo y pega el siguiente código: src/components/GradientTextMarquee.tsx + GradientTextMarquee.css:
GradientTextMarquee.tsx
'use client';
import type { CSSProperties } from 'react';
import './GradientTextMarquee.css';
/** class:list → className */
function cx(...args: unknown[]): string {
const out: string[] = [];
const walk = (v: unknown) => {
if (!v) return;
if (typeof v === 'string' || typeof v === 'number') out.push(String(v));
else if (Array.isArray(v)) v.forEach(walk);
else if (typeof v === 'object') for (const [k, on] of Object.entries(v as Record<string, unknown>)) if (on) out.push(k);
};
args.forEach(walk);
return out.join(' ');
}
/** "a: b; --c: d" → style object */
function st(css: string | undefined): CSSProperties {
const o: Record<string, string> = {};
for (const decl of String(css ?? '').split(';')) {
const i = decl.indexOf(':');
if (i < 0) continue;
const k = decl.slice(0, i).trim();
if (k) o[k.startsWith('--') ? k : k.replace(/-([a-z])/g, (_, c) => c.toUpperCase())] = decl.slice(i + 1).trim();
}
return o as CSSProperties;
}
/**
* GradientTextMarquee — Continuous kinetic typographic marquee banner with background-clip gold gradient.
*
* @param {string[]} phrases - Array of words or slogans to scroll continuously.
* @param {string} speed - Animation duration string (e.g. '25s'). Default is '20s'.
* @param {boolean} reverse - Whether the marquee moves in reverse direction.
*/
export interface GradientTextMarqueeProps {
phrases?: string[];
speed?: string;
reverse?: boolean;
}
export function GradientTextMarquee({
phrases = [
'PERFORMANCE FIRST',
'ZERO DEPENDENCIES',
'ACCESSIBLE WCAG AA',
'ASTRO 5 READY',
'DARK GLASS MORPHISM',
],
speed = '20s',
reverse = false,
}: GradientTextMarqueeProps) {
return (
<>
<div className="grad-marquee" style={st(`--marquee-speed: ${speed};`)} aria-label="Animated slogan marquee" data-rk-48dfb7="">
<div className={cx(['grad-marquee__track', { 'is-reverse': reverse }])} data-rk-48dfb7="">
{phrases.map((phrase, __i: number) => (
<span key={__i} className="grad-marquee__item" data-rk-48dfb7="">
<span className="text" data-rk-48dfb7="">{phrase}</span>
<span className="dot" aria-hidden="true" data-rk-48dfb7="">✦</span>
</span>
))}
{/* Duplicate loop */}
{phrases.map((phrase, __i: number) => (
<span key={__i} className="grad-marquee__item" aria-hidden="true" data-rk-48dfb7="">
<span className="text" data-rk-48dfb7="">{phrase}</span>
<span className="dot" aria-hidden="true" data-rk-48dfb7="">✦</span>
</span>
))}
</div>
</div>
</>
);
}
export default GradientTextMarquee;GradientTextMarquee.css
/* GradientTextMarquee — ported from astro-component-kit (typography/GradientTextMarquee.astro) */
.grad-marquee:where([data-rk-48dfb7]) {
position: relative;
width: 100%;
overflow: hidden;
padding: var(--sp-4, 1rem) 0;
user-select: none;
mask-image: linear-gradient(90deg, transparent, #000 15%, #000 85%, transparent);
-webkit-mask-image: linear-gradient(90deg, transparent, #000 15%, #000 85%, transparent);
font-family: var(--font-sans, system-ui, sans-serif);
}
.grad-marquee__track:where([data-rk-48dfb7]) {
display: flex;
align-items: center;
gap: 2rem;
width: max-content;
animation: gradient-text-marquee-marquee-roll var(--marquee-speed) linear infinite;
}
.grad-marquee__track:hover:where([data-rk-48dfb7]) {
animation-play-state: paused;
}
.grad-marquee__track.is-reverse:where([data-rk-48dfb7]) {
animation-direction: reverse;
}
.grad-marquee__item:where([data-rk-48dfb7]) {
display: inline-flex;
align-items: center;
gap: 2rem;
}
.grad-marquee__item:where([data-rk-48dfb7]) .text:where([data-rk-48dfb7]) {
font-size: clamp(1.8rem, 4vw, 3.2rem);
font-weight: 900;
letter-spacing: 0.05em;
text-transform: uppercase;
background: linear-gradient(135deg, #ffffff 0%, #fef3c7 40%, #d4a017 80%, #b8860b 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
white-space: nowrap;
}
.grad-marquee__item:where([data-rk-48dfb7]) .dot:where([data-rk-48dfb7]) {
color: var(--c-primary-light, #d4a017);
font-size: 1.2rem;
}
@keyframes gradient-text-marquee-marquee-roll {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
.grad-marquee__track:where([data-rk-48dfb7]) { animation: none; overflow-x: auto; }
}Información Rápida
- Categoría
- Tipografía
- Nombre de archivo
GradientTextMarquee.tsx- Dependencias
- Ninguna — React + CSS puro
- Etiquetas
- typographymarqueegradientloopticker