Skip to content

Instantly share code, notes, and snippets.

@sebastiandedeyne
Created September 27, 2019 12:08
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sebastiandedeyne/cbea6985ef1ca6c9b238be453854f633 to your computer and use it in GitHub Desktop.
Save sebastiandedeyne/cbea6985ef1ca6c9b238be453854f633 to your computer and use it in GitHub Desktop.
.linechart {
font-size: 10px;
height: 200px;
position: relative;
width: 100%;
font-variant-numeric: tabular-nums;
}
.linechart-x-line {
background-color: var(--secondary);
bottom: 0;
position: absolute;
top: 0;
width: 1px;
}
.linechart-x-label {
bottom: -20px;
left: 50%;
position: absolute;
transform: translateX(-50%);
}
.linechart-x-value {
background-color: var(--primary);
border-radius: 4px;
color: white;
font-weight: 600;
left: 50%;
padding: 0 3px;
position: absolute;
text-align: center;
transform: translateX(-50%) translateY(6px);
z-index: 10;
}
.linechart-y-line {
position: absolute;
left: 0;
right: 0;
height: 1px;
background-color: var(--secondary);
font-size: 10px;
}
.linechart-y-label {
transform: translateX(-15px) translateY(-7px);
}
.linechart-chart {
height: 100%;
position: relative;
width: 100%;
}
import React from 'react';
type Props = {
data: Array<[number, string]>;
};
export default function LineChart({ data }: Props) {
if (!data.length) {
return null;
}
const maxValue = Math.max(...data.map(([value]) => value));
const points = data
.map(([value], index) => {
return `L ${index} ${maxValue - value}`;
})
.join(' ');
return (
<div className="linechart">
{data.map(([value, label], index) => (
<div key={index} className="linechart-x-line" style={{ left: `${(index / (data.length - 1)) * 100}%` }}>
<div className="linechart-x-label">{label}</div>
<div className="linechart-x-value" style={{ bottom: `${(value / maxValue) * 100}%` }}>
{value}
</div>
</div>
))}
<div className="linechart-y-line" style={{ bottom: '100%' }}>
<div className="linechart-y-label">{maxValue}</div>
</div>
<div className="linechart-y-line" style={{ bottom: '50%' }} />
<div className="linechart-y-line" style={{ bottom: '0' }} />
<svg className="linechart-chart" viewBox={`0 0 ${data.length - 1} ${maxValue}`} preserveAspectRatio="none">
<defs>
<linearGradient id="background" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style={{ stopColor: '#5d78ff', stopOpacity: 0.4 }} />
<stop offset="100%" style={{ stopColor: '#5d78ff', stopOpacity: 0 }} />
</linearGradient>
</defs>
<path d={`M 0 ${maxValue + 1} ${points} L 23 ${maxValue + 1} Z`} fill="url(#background)" />
<path
d={points.replace('L', 'M')}
fill="none"
stroke="#5d78ff"
strokeOpacity="0.3"
strokeWidth="1"
strokeLinecap="round"
vectorEffect="non-scaling-stroke"
/>
</svg>
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment