1 estrella en GitHub = 1 componente nuevo.

Dar una estrella
Gráficos y Estadísticaschartsvgzero-dependencyrankbumpleaderboardtime-series

Bump Chart

Gráfico de ranking en el tiempo que sigue la posición de cada entidad con nodos numerados.

Vista Previa en Vivo

Framework popularity rank

Developer survey position by year

  • Astro
  • Next
  • Svelte
  • Nuxt
  • Remix
202120222023202420252026543211AstroAstro111122NextNext322334SvelteSvelte234453NuxtNuxt455545RemixRemix
View data
Name202120222023202420252026
Astro#5#4#3#2#1#1
Next#1#1#1#1#2#2
Svelte#3#2#2#3#3#4
Nuxt#2#3#4#4#5#3
Remix#4#5#5#5#4#5

Uso

Copia y pega este código directamente en tu componente React:

tsx
import { BumpChart } from 'react-component-kit-ui/charts';

<BumpChart periods={['2024', '2025', '2026']} series={[
    { name: 'React', ranks: [3, 2, 1] },
    { name: 'Next', ranks: [1, 1, 2] },
    { name: 'Svelte', ranks: [2, 3, 3] },
  ]} />

Instalación Manual

Si no estás usando el paquete npm, crea un archivo nuevo y pega el siguiente código: src/components/BumpChart.tsx + BumpChart.css:

BumpChart.tsx
'use client';

import ChartFrame from './ChartFrame';
import { colorAt, smoothPath, type Point } from './chart-utils';

/**
 * BumpChart — Rank-over-time chart. Each line tracks one entity's position
 * (1 = top) across periods, with labels at both ends.
 *
 * @param {string[]} periods - X-axis labels.
 * @param {Array<{name: string, ranks: number[]}>} series - Rank per period (1-based), max 8.
 * @param {string[]} colors - Optional per-series colors.
 * @param {string} variant - Card style (glass|solid|ghost).
 * @param {string} size - Density (sm|md|lg).
 */
export interface BumpChartProps {
  title?: string;
  subtitle?: string;
  periods?: string[];
  series?: Array<{ name: string; ranks: number[] }>;
  colors?: string[];
  variant?: 'glass' | 'solid' | 'ghost';
  size?: 'sm' | 'md' | 'lg';
  className?: string;
}

export function BumpChart({
  title = 'Framework popularity rank',
  subtitle = 'Developer survey position by year',
  periods = ['2021', '2022', '2023', '2024', '2025', '2026'],
  series = [
    { name: 'Astro', ranks: [5, 4, 3, 2, 1, 1] },
    { name: 'Next', ranks: [1, 1, 1, 1, 2, 2] },
    { name: 'Svelte', ranks: [3, 2, 2, 3, 3, 4] },
    { name: 'Nuxt', ranks: [2, 3, 4, 4, 5, 3] },
    { name: 'Remix', ranks: [4, 5, 5, 5, 4, 5] },
  ],
  colors,
  variant = 'glass',
  size = 'md',
  className = '',
}: BumpChartProps) {
  const W = 640;
  const maxRank = Math.max(...series.flatMap((s) => s.ranks));
  const rowH = 44;
  const H = maxRank * rowH + 36;
  const m = { t: 30, l: 80, r: 80 };
  const n = periods.length;
  const x = (i: number) => m.l + (i / Math.max(1, n - 1)) * (W - m.l - m.r);
  const y = (r: number) => m.t + (r - 1) * rowH + 8;
  const lines = series.slice(0, 8).map((s, si) => ({
    ...s,
    color: colorAt(si, colors),
    pts: s.ranks.map((r, i): Point => [x(i), y(r)]),
  }));
  return (
    <>
      <ChartFrame title={title} subtitle={subtitle} variant={variant} size={size} className={className} legend={lines.map((l) => ({ label: l.name, color: l.color }))} table={{ headers: ['Name', ...periods], rows: series.map((s) => [s.name, ...s.ranks.map((r) => `#${r}`)]) }}>
        <svg viewBox={`0 0 ${W} ${H}`} role="img" aria-label={`${title}: bump chart of ranks over ${n} periods`}>
          {periods.map((p, i) => (
            <g key={i}>
              <line className="cf-grid" x1={x(i)} x2={x(i)} y1={m.t - 6} y2={H - 10} />
              <text className="cf-label" x={x(i)} y={14} textAnchor="middle">{p}</text>
            </g>
          ))}
          {lines.map((l, __i: number) => (
            <g key={__i} className="cf-mark cf-dim" tabIndex={0} role="img" aria-label={`${l.name}: ${l.ranks.map((r, i) => `${periods[i]} #${r}`).join(', ')}`} data-tip-title={l.name} data-tip={l.ranks.map((r, i) => `${periods[i]}: #${r}`).join('|')}>
              <path d={smoothPath(l.pts)} fill="none" stroke={l.color} strokeWidth="3" strokeLinecap="round" />
              <path d={smoothPath(l.pts)} fill="none" stroke="transparent" strokeWidth="16" />
              {l.pts.map(([px, py], i) => (
                <g key={i}>
                  <circle cx={px} cy={py} r="11" fill={l.color} stroke="var(--chart-surface, #0d0d0f)" strokeWidth="2" />
                  <text x={px} y={py + 4} textAnchor="middle" fontSize="10" fontWeight="700" fill="#fff">{l.ranks[i]}</text>
                </g>
              ))}
              <text className="cf-label cf-label--strong" x={m.l - 18} y={l.pts[0][1] + 4} textAnchor="end">{l.name}</text>
              <text className="cf-label cf-label--strong" x={W - m.r + 18} y={l.pts[n - 1][1] + 4}>{l.name}</text>
            </g>
          ))}
        </svg>
      </ChartFrame>
    </>
  );
}

export default BumpChart;

Información Rápida

Categoría
Gráficos y Estadísticas
Nombre de archivo
BumpChart.tsx
Dependencias
Ninguna — React + CSS puro
Etiquetas
chartsvgzero-dependencyrankbumpleaderboardtime-series