1 звезда на GitHub = 1 новый компонент.

Поставить звезду
Графики и статистикаdataanalyticschartareapremium

Area Chart

Интерактивный график областей с мягкими градиентами и временными рядами данных.

Живое превью

Loading Chart...

Использование

Скопируйте и вставьте этот код в ваш React-компонент:

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

<AreaChart title="Monthly Sales" categories={categories} series={series} variant="primary" />

Ручная установка

Если вы не используете пакет npm, создайте файл и вставьте следующий код: src/components/AreaChart.tsx + AreaChart.css:

AreaChart.tsx
'use client';

import { useEffect, useRef } from 'react';
import './AreaChart.css';

/**
 * AreaChart — A premium, smooth area chart component.
 */
export interface AreaChartProps {
  title?: string;
  subtitle?: string;
  categories?: any[];
  series?: any[];
  height?: number | string;
  colors?: string[];
  showGrid?: boolean;
  className?: string;
}

export function AreaChart({
  title,
  subtitle,
  categories = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  series = [{ name: 'Data', data: [31, 40, 28, 51, 42, 109, 100] }],
  height = 350,
  colors = ['var(--c-accent, #b8860b)', 'var(--c-primary, #1e40af)', '#3b82f6'],
  showGrid = true,
  className = '',
}: AreaChartProps) {
  const chartConfig = {
    categories,
    series,
    height,
    colors,
    showGrid,
  };

  // Ported from the Astro <script>: runs once after mount (DOM logic kept as in the Astro kit).
  const mounted = useRef(false);
  useEffect(() => {
    if (mounted.current) return;
    mounted.current = true;
    async function initCharts() {
        const charts = document.querySelectorAll('.premium-chart-card[data-chart-type="area"]');
        if (charts.length === 0) return;
    
        // Dynamic import to handle SSR and bundling better in production
        let ApexChartsModule;
        try {
          ApexChartsModule = await import('apexcharts');
        } catch (e) {
          console.error('ApexCharts failed to load:', e);
          return;
        }
        
        const ApexCharts = ApexChartsModule.default || ApexChartsModule;
        
        charts.forEach(container => {
          if (container.getAttribute('data-initialized')) return;
          
          const configStr = container.getAttribute('data-config');
          if (!configStr) return;
          
          const config = JSON.parse(configStr);
          config.colors = (config.colors || []).map((c: string) => {
            const m = /^var\((--[\w-]+)\s*(?:,\s*([^)]+))?\)$/.exec(String(c).trim());
            return m ? getComputedStyle(container as Element).getPropertyValue(m[1]).trim() || (m[2] || '').trim() : c;
          });
          const target = container.querySelector('.chart-container');
          const fallback = container.querySelector('.chart-fallback');
          
          if (!target) return;
    
          const options = {
            series: config.series,
            chart: {
              type: 'area',
              height: config.height,
              toolbar: { show: false },
              zoom: { enabled: false },
              background: 'transparent',
              fontFamily: 'Inter, sans-serif',
              animations: {
                enabled: true,
                easing: 'easeinout',
                speed: 800,
              }
            },
            colors: config.colors,
            dataLabels: { enabled: false },
            stroke: { curve: 'smooth', width: 3 },
            fill: {
              type: 'gradient',
              gradient: {
                shadeIntensity: 1,
                opacityFrom: 0.45,
                opacityTo: 0.05,
                stops: [20, 100],
              },
            },
            xaxis: {
              categories: config.categories,
              axisBorder: { show: false },
              axisTicks: { show: false },
              labels: { style: { colors: '#64748b', fontSize: '12px' } },
            },
            yaxis: {
              labels: { style: { colors: '#64748b', fontSize: '12px' } },
            },
            grid: {
              show: config.showGrid,
              borderColor: 'rgba(148, 163, 184, 0.12)',
              strokeDashArray: 4,
            },
            legend: {
              show: true,
              position: 'top',
              horizontalAlign: 'right',
              labels: { colors: '#94a3b8' },
            },
            tooltip: { theme: 'dark' },
            theme: { mode: 'dark' }
          };
    
          try {
            const chart = new ApexCharts(target, options);
            chart.render().then(() => {
              if (fallback) (fallback as HTMLElement).style.display = 'none';
            });
            container.setAttribute('data-initialized', 'true');
          } catch (err) {
            console.error('Failed to render chart:', err);
            if (fallback) fallback.textContent = 'Failed to load chart';
          }
        });
      }
    
      // Initial load
      initCharts();
    
      // Handle navigations
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <>
      <div className={`premium-chart-card ${className}`} data-chart-type="area" data-config={JSON.stringify(chartConfig)} data-rk-163adb="">
        {(title || subtitle) && (
          <div className="premium-chart-card__header" data-rk-163adb="">
            {title && <h3 className="premium-chart-card__title" data-rk-163adb="">{title}</h3>}
            {subtitle && <p className="premium-chart-card__subtitle" data-rk-163adb="">{subtitle}</p>}
          </div>
        )}
        <div className="premium-chart-card__body" data-rk-163adb="">
          <div className="chart-container" data-rk-163adb=""></div>
          <div className="chart-fallback" data-rk-163adb="">Loading Chart...</div>
        </div>
      </div>
    </>
  );
}

export default AreaChart;
AreaChart.css
/* AreaChart — ported from astro-component-kit (charts/AreaChart.astro) */

.premium-chart-card:where([data-rk-163adb]) {
  background: rgb(var(--ink-rgb, 255 255 255) / 0.03);
  backdrop-filter: blur(12px);
  border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08);
  border-radius: var(--r-xl, 24px);
  padding: var(--sp-6, 24px);
  overflow: hidden;
  width: 100%;
  min-width: 300px;
  color: white;
}

.premium-chart-card__header:where([data-rk-163adb]) {
  margin-bottom: var(--sp-6, 24px);
}

.premium-chart-card__title:where([data-rk-163adb]) {
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--c-text-1, #ffffff);
  margin: 0;
}

.premium-chart-card__subtitle:where([data-rk-163adb]) {
  font-size: 0.875rem;
  color: var(--c-text-2, #94a3b8);
  margin: var(--sp-1, 4px) 0 0;
}

.premium-chart-card__body:where([data-rk-163adb]) {
  width: 100%;
  position: relative;
  min-height: 200px;
}

.chart-container:where([data-rk-163adb]) {
  width: 100%;
  position: relative;
  z-index: 2;
}

.chart-fallback:where([data-rk-163adb]) {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8rem;
  color: var(--c-text-3, #64748b);
  z-index: 1;
}

.apexcharts-tooltip {
  background: rgba(15, 23, 42, 0.9) !important;
  backdrop-filter: blur(8px) !important;
  border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.1) !important;
  border-radius: 12px !important;
  color: #fff !important;
  box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3) !important;
}

Краткая информация

Категория
Графики и статистика
Имя файла
AreaChart.tsx
Зависимости
Нет — чистый React + CSS
Теги
dataanalyticschartareapremium