Skip to main content

Horizontal Bar Chart

horizontal-bar-chart.tsx
import {loadFont} from '@remotion/google-fonts/Inter'; import React from 'react'; import {Easing, Interactive, interpolate, useCurrentFrame} from 'remotion'; const {fontFamily} = loadFont('normal', { subsets: ['latin'], weights: ['700', '800'], }); const data = [ {highlighted: true, label: 'Jonny', value: 18}, {highlighted: false, label: 'Igor', value: 17}, {highlighted: false, label: 'Mehmet', value: 10}, ]; const HEIGHT = Math.round(400 / data.length); const maxValue = Math.max(...data.map(({value}) => value)); const Bar: React.FC<{ readonly highlighted: boolean; readonly label: string; readonly value: number; readonly showInTimeline: boolean; }> = ({highlighted, label, showInTimeline, value}) => { const frame = useCurrentFrame(); return ( <Interactive.Div cropRight={interpolate(frame, [14, 47], [1, 0], { easing: [Easing.bezier(0, 0, 0.58, 1)], extrapolateLeft: 'clamp', extrapolateRight: 'clamp', })} name={'Bar'} showInTimeline={showInTimeline} style={{ alignItems: 'center', backgroundColor: highlighted ? '#2858e8' : '#d1d5db', borderRadius: 12, boxSizing: 'border-box', color: highlighted ? '#ffffff' : '#111827', display: 'flex', height: '100%', justifyContent: 'space-between', overflow: 'hidden', padding: '0 34px', width: '100%', }} > <Interactive.Div name={'Label'} showInTimeline={showInTimeline} style={{ fontSize: 40, fontWeight: 700, lineHeight: 1, opacity: interpolate(frame, [26, 32], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }), whiteSpace: 'nowrap', }} > {label} </Interactive.Div> <Interactive.Div name={`${label} value`} showInTimeline={showInTimeline} style={{ fontSize: 48, fontWeight: 800, letterSpacing: -1.6, lineHeight: 1, opacity: interpolate(frame, [32, 38], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }), whiteSpace: 'nowrap', }} > {value} </Interactive.Div> </Interactive.Div> ); }; export const HorizontalBarChart: React.FC = () => { return ( <Interactive.Div name="Chart" style={{ fontFamily, fontVariantNumeric: 'tabular-nums', height: '100%', display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: 42, }} > <Interactive.H1 name="Title" style={{ fontSize: 76, fontWeight: 800, letterSpacing: -3.8, lineHeight: 0.95, margin: 0, color: '#111827', }} > Team member pull-ups </Interactive.H1> {data.map(({highlighted, label, value}, index) => ( <div key={label} style={{ height: HEIGHT, }} > <Interactive.Div from={8 + index * 6} style={{width: `${(value / maxValue) * 100}%`, height: '100%'}} showInTimeline={false} > <Bar highlighted={highlighted} label={label} showInTimeline={index === 0} value={value} /> </Interactive.Div> </div> ))} </Interactive.Div> ); };