Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Apply best practices for creating programmatic videos with Remotion and React.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
rules/assets/charts-bar-chart.tsx
1import {loadFont} from '@remotion/google-fonts/Inter';2import {AbsoluteFill, spring, useCurrentFrame, useVideoConfig} from 'remotion';34const {fontFamily} = loadFont();56const COLOR_BAR = '#D4AF37';7const COLOR_TEXT = '#ffffff';8const COLOR_MUTED = '#888888';9const COLOR_BG = '#0a0a0a';10const COLOR_AXIS = '#333333';1112// Ideal composition size: 1280x7201314const Title: React.FC<{children: React.ReactNode}> = ({children}) => (15<div style={{textAlign: 'center', marginBottom: 40}}>16<div style={{color: COLOR_TEXT, fontSize: 48, fontWeight: 600}}>17{children}18</div>19</div>20);2122const YAxis: React.FC<{steps: number[]; height: number}> = ({23steps,24height,25}) => (26<div27style={{28display: 'flex',29flexDirection: 'column',30justifyContent: 'space-between',31height,32paddingRight: 16,33}}34>35{steps36.slice()37.reverse()38.map((step) => (39<div40key={step}41style={{42color: COLOR_MUTED,43fontSize: 20,44textAlign: 'right',45}}46>47{step.toLocaleString()}48</div>49))}50</div>51);5253const Bar: React.FC<{54height: number;55progress: number;56}> = ({height, progress}) => (57<div58style={{59flex: 1,60display: 'flex',61flexDirection: 'column',62justifyContent: 'flex-end',63}}64>65<div66style={{67width: '100%',68height,69backgroundColor: COLOR_BAR,70borderRadius: '8px 8px 0 0',71opacity: progress,72}}73/>74</div>75);7677const XAxis: React.FC<{78children: React.ReactNode;79labels: string[];80height: number;81}> = ({children, labels, height}) => (82<div style={{flex: 1, display: 'flex', flexDirection: 'column'}}>83<div84style={{85display: 'flex',86alignItems: 'flex-end',87gap: 16,88height,89borderLeft: `2px solid ${COLOR_AXIS}`,90borderBottom: `2px solid ${COLOR_AXIS}`,91paddingLeft: 16,92}}93>94{children}95</div>96<div97style={{98display: 'flex',99gap: 16,100paddingLeft: 16,101marginTop: 12,102}}103>104{labels.map((label) => (105<div106key={label}107style={{108flex: 1,109textAlign: 'center',110color: COLOR_MUTED,111fontSize: 20,112}}113>114{label}115</div>116))}117</div>118</div>119);120121export const MyAnimation = () => {122const frame = useCurrentFrame();123const {fps, height} = useVideoConfig();124125const data = [126{month: 'Jan', price: 2039},127{month: 'Mar', price: 2160},128{month: 'May', price: 2327},129{month: 'Jul', price: 2426},130{month: 'Sep', price: 2634},131{month: 'Nov', price: 2672},132];133134const minPrice = 2000;135const maxPrice = 2800;136const priceRange = maxPrice - minPrice;137const chartHeight = height - 280;138const yAxisSteps = [2000, 2400, 2800];139140return (141<AbsoluteFill142style={{143backgroundColor: COLOR_BG,144padding: 60,145display: 'flex',146flexDirection: 'column',147fontFamily,148}}149>150<Title>Gold Price 2024</Title>151152<div style={{display: 'flex', flex: 1}}>153<YAxis steps={yAxisSteps} height={chartHeight} />154<XAxis height={chartHeight} labels={data.map((d) => d.month)}>155{data.map((item, i) => {156const progress = spring({157frame: frame - i * 5 - 10,158fps,159config: {damping: 18, stiffness: 80},160});161162const barHeight =163((item.price - minPrice) / priceRange) * chartHeight * progress;164165return (166<Bar key={item.month} height={barHeight} progress={progress} />167);168})}169</XAxis>170</div>171</AbsoluteFill>172);173};174