Skip to main content
Glama
template.tsx.j28.6 kB
{/* chuk-motion/src/chuk_motion/components/content/StylizedWebPage/template.tsx.j2 */} import React from 'react'; import { useCurrentFrame, interpolate, spring, useVideoConfig } from 'remotion'; interface StylizedWebPageProps { title?: string; subtitle?: string; showHeader?: boolean; showSidebar?: boolean; showFooter?: boolean; headerText?: string; sidebarItems?: string[]; contentLines?: string[]; footerText?: string; theme?: 'light' | 'dark'; accentColor?: 'primary' | 'accent' | 'secondary'; startFrame?: number; durationInFrames?: number; } export const StylizedWebPage: React.FC<StylizedWebPageProps> = ({ title = 'Website Title', subtitle = 'Tagline or description', showHeader = true, showSidebar = false, showFooter = false, headerText = 'Navigation', sidebarItems = ['Dashboard', 'Analytics', 'Settings'], contentLines = ['Welcome to our site', 'Explore our features', 'Get started today'], footerText = '© 2024 Company', theme = 'light', accentColor = 'primary', startFrame = 0, durationInFrames = 150 }) => { const frame = useCurrentFrame(); const { fps } = useVideoConfig(); // Don't render if outside the time range if (frame < startFrame || frame >= startFrame + durationInFrames) { return null; } const relativeFrame = frame - startFrame; // Entrance animation const entrance = spring({ frame: relativeFrame, fps: fps, config: { damping: [[ motion.default_spring.config.damping ]], stiffness: [[ motion.default_spring.config.stiffness ]], }, }); const opacity = interpolate(relativeFrame, [0, 20], [0, 1], { extrapolateRight: 'clamp' }); // Theme colors const isDark = theme === 'dark'; const accentColorMap = { primary: '[[ colors.primary[0] ]]', accent: '[[ colors.accent[0] ]]', secondary: '[[ colors.primary[2] ]]' }; const accent = accentColorMap[accentColor]; return ( <div style={{ width: '100%', height: '100%', backgroundColor: isDark ? '[[ colors.background.dark ]]' : '[[ colors.background.light ]]', display: 'flex', flexDirection: 'column', opacity, transform: `scale(${entrance})`, }} > {/* Header/Navbar */} {showHeader && ( <div style={{ height: '[[ spacing.spacing['4xl'] ]]', backgroundColor: isDark ? '[[ colors.background.darker ]]' : accent, borderBottom: `1px solid ${isDark ? '[[ colors.border.subtle ]]' : '[[ colors.border.light ]]'}`, display: 'flex', alignItems: 'center', padding: '0 [[ spacing.spacing.xl ]]', justifyContent: 'space-between', boxShadow: '0 2px 8px [[ colors.shadow.light ]]', }} > <div style={{ fontSize: parseInt('[[ typography.font_sizes[typography.default_resolution].xl ]]'), fontWeight: '[[ typography.font_weights.bold ]]', color: '[[ colors.text.on_dark ]]', fontFamily: "'[[ "', '".join(typography.primary_font.fonts) ]]'", letterSpacing: '-0.5px', }} > {title} </div> <div style={{ fontSize: parseInt('[[ typography.font_sizes[typography.default_resolution].sm ]]'), color: '[[ colors.text.on_dark ]]', opacity: 0.95, fontFamily: "'[[ "', '".join(typography.body_font.fonts) ]]'", fontWeight: '[[ typography.font_weights.medium ]]', }} > {headerText} </div> </div> )} {/* Main content area */} <div style={{ flex: 1, display: 'flex', overflow: 'hidden' }}> {/* Sidebar */} {showSidebar && ( <div style={{ width: '220px', backgroundColor: isDark ? '[[ colors.background.darker ]]' : '[[ colors.background.light ]]', borderRight: `1px solid ${isDark ? '[[ colors.border.subtle ]]' : '[[ colors.border.subtle ]]'}`, padding: '[[ spacing.spacing.lg ]] [[ spacing.spacing.md ]]', display: 'flex', flexDirection: 'column', gap: '[[ spacing.spacing.xxs ]]', }} > {sidebarItems.map((item, index) => ( <div key={index} style={{ padding: '[[ spacing.spacing.sm ]] [[ spacing.spacing.md ]]', backgroundColor: index === 0 ? (isDark ? '[[ colors.border.light ]]' : accent) : 'transparent', color: index === 0 ? '[[ colors.text.on_dark ]]' : (isDark ? '[[ colors.text.muted ]]' : '[[ colors.text.muted ]]'), borderRadius: '[[ spacing.border_radius.md ]]', fontSize: parseInt('[[ typography.font_sizes[typography.default_resolution].sm ]]'), fontFamily: "'[[ "', '".join(typography.body_font.fonts) ]]'", fontWeight: index === 0 ? '[[ typography.font_weights.semibold ]]' : '[[ typography.font_weights.medium ]]', cursor: 'pointer', transition: 'all 0.2s ease', }} > {item} </div> ))} </div> )} {/* Main content */} <div style={{ flex: 1, padding: '[[ spacing.spacing['2xl'] ]]', display: 'flex', flexDirection: 'column', gap: '[[ spacing.spacing.lg ]]', overflowY: 'auto', }} > {/* Hero section */} <div style={{ marginBottom: '16px', }} > <div style={{ fontSize: parseInt('[[ typography.font_sizes[typography.default_resolution]['2xl'] ]]'), fontWeight: '[[ typography.font_weights.bold ]]', color: isDark ? '[[ colors.text.on_dark ]]' : '[[ colors.text.on_light ]]', marginBottom: '8px', fontFamily: "'[[ "', '".join(typography.primary_font.fonts) ]]'", letterSpacing: '-0.5px', }} > {subtitle} </div> </div> {/* Content blocks */} {contentLines.map((line, index) => { // Skip empty lines - they just add spacing if (!line || line.trim() === '') { return null; } return ( <div key={index} style={{ padding: '20px [[ spacing.spacing.lg ]]', backgroundColor: isDark ? '[[ colors.background.glass ]]' : '[[ colors.background.light ]]', border: `1px solid ${isDark ? '[[ colors.border.subtle ]]' : '[[ colors.border.subtle ]]'}`, borderRadius: '[[ spacing.border_radius.lg ]]', fontSize: parseInt('[[ typography.font_sizes[typography.default_resolution].base ]]'), color: isDark ? '[[ colors.text.on_dark ]]' : '[[ colors.text.on_light ]]', fontFamily: "'[[ "', '".join(typography.body_font.fonts) ]]'", fontWeight: '[[ typography.font_weights.regular ]]', lineHeight: '1.6', opacity: interpolate(relativeFrame, [20 + index * 5, 30 + index * 5], [0, 1], { extrapolateRight: 'clamp' }), transition: 'all 0.2s ease', }} > {line} </div> ); })} </div> </div> {/* Footer */} {showFooter && ( <div style={{ height: parseInt('[[ spacing.spacing['2xl'] ]]'), backgroundColor: isDark ? '[[ colors.background.darker ]]' : '[[ colors.background.overlay ]]', borderTop: `[[ spacing.border_width.medium ]] solid [[ colors.border.medium ]]`, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: parseInt('[[ typography.font_sizes[typography.default_resolution].sm ]]'), color: isDark ? '[[ colors.text.muted ]]' : '[[ colors.text.on_light ]]', fontFamily: "'[[ "', '".join(typography.body_font.fonts) ]]'", }} > {footerText} </div> )} </div> ); };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/chrishayuk/chuk-mcp-remotion'

If you have feedback or need assistance with the MCP directory API, please join our Discord server