Line Chart
scificn/line-chartFreeComponent
SVG line chart with multi-series support, animated draw-on, area fill, grid lines, and legend.
Live preview
live · rendered by the registry
Rendered by scificn on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://www.scificn.dev/r/line-chart.jsonSource
1'use client'23import * as React from 'react'4import { cn } from '@/lib/utils'56export type LineChartVariant = 'DEFAULT' | 'ACTIVE' | 'WARNING' | 'CRITICAL'78export interface LineChartSeries {9 id: string10 label: string11 data: number[]12 variant?: LineChartVariant13}1415export interface LineChartProps extends React.HTMLAttributes<HTMLDivElement> {16 series: LineChartSeries[]17 labels: string[]18 title?: string19 height?: number20 min?: number21 max?: number22 showDots?: boolean23 showArea?: boolean24 showGrid?: boolean25 showLegend?: boolean26 animated?: boolean27}2829const LEFT = 4030const RIGHT = 831const TOP = 832const BOTTOM = 243334const SERIES_COLORS = [35 'var(--color-green)',36 'var(--color-amber)',37 'var(--color-red)',38 'var(--color-blue)',39]4041const VARIANT_COLORS: Record<LineChartVariant, string> = {42 DEFAULT: 'var(--text-secondary)',43 ACTIVE: 'var(--color-green)',44 WARNING: 'var(--color-amber)',45 CRITICAL: 'var(--color-red)',46}4748function seriesColor(s: LineChartSeries, idx: number): string {49 if (s.variant) return VARIANT_COLORS[s.variant]50 return SERIES_COLORS[idx % SERIES_COLORS.length]51}5253const LineChart = React.forwardRef<HTMLDivElement, LineChartProps>(54 (55 {56 className,57 series,58 labels,59 title,60 height = 160,61 min,62 max,63 showDots = true,64 showArea = false,65 showGrid = true,66 showLegend,67 animated = true,68 style,69 ...props70 },71 ref72 ) => {73 const containerRef = React.useRef<HTMLDivElement>(null)74 const [svgW, setSvgW] = React.useState(500)75 const [drawn, setDrawn] = React.useState(false)7677 React.useEffect(() => {78 if (!containerRef.current) return79 const ro = new ResizeObserver(entries => {80 setSvgW(entries[0].contentRect.width)81 })82 ro.observe(containerRef.current)83 return () => ro.disconnect()84 }, [])8586 React.useEffect(() => {87 const id = requestAnimationFrame(() => setDrawn(true))88 return () => cancelAnimationFrame(id)89 }, [])9091 const allValues = series.flatMap(s => s.data)92 const dataMin = allValues.length > 0 ? Math.min(...allValues) : 093 const dataMax = allValues.length > 0 ? Math.max(...allValues) : 10094 const minV = min ?? dataMin95 const maxV = max ?? dataMax96 const range = Math.max(maxV - minV, 1)9798 const plotW = svgW - LEFT - RIGHT99 const plotH = height - TOP - BOTTOM100 const n = labels.length101102 function xPos(i: number) {103// … truncated
More from scificn
All 33 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Alertalert | scificn | Components | Free | 1 dep | |
| Badgebadge | scificn | Components | Free | 1 dep | |
| Bar Chartbar-chart | scificn | Components | Free | no deps | |
| Breadcrumbbreadcrumb | scificn | Components | Free | no deps | |
| Buttonbutton | scificn | Components | Free | 2 deps | |
| Cardcard | scificn | Components | Free | no deps | |
| Checkboxcheckbox | scificn | Components | Free | 1 dep | |
| Dialogdialog | scificn | Components | Free | 1 dep |
