1 estrella en GitHub = 1 componente nuevo.

Dar una estrella
Tipografíatypographymarqueegradientloopticker

Gradient Text Marquee

Marquesina continua de texto en degradado que se desplaza infinitamente en bucle.

Vista Previa en Vivo

PERFORMANCE FIRSTZERO DEPENDENCIESACCESSIBLE WCAG AAASTRO 5 READYDARK 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