-
Notifications
You must be signed in to change notification settings - Fork 3.4k
feat: updated design for blog and blog details page w dynamic og generation #3625
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: staging
Are you sure you want to change the base?
Changes from all commits
7c6333e
b697772
ffdefcd
fcba27a
6893a1c
0a88400
e5f3a36
7289353
b03d655
73608ad
80c3ae8
ac966fb
969b141
f741c5b
76f4f1b
58fc6cd
debbdff
efb87af
33e6b91
07da8fd
c0c4988
84f7c86
a9ce0db
2812ab9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,16 @@ | ||
| 'use client' | ||
|
|
||
| import { useCallback, useEffect, useRef, useState } from 'react' | ||
| import { createLogger } from '@sim/logger' | ||
| import { AnimatePresence, type MotionValue, motion, useScroll, useTransform } from 'framer-motion' | ||
| import { type MotionValue, motion, useScroll, useTransform } from 'framer-motion' | ||
| import dynamic from 'next/dynamic' | ||
| import { useRouter } from 'next/navigation' | ||
| import Link from 'next/link' | ||
| import { Badge, ChevronDown } from '@/components/emcn' | ||
| import { LandingWorkflowSeedStorage } from '@/lib/core/utils/browser-storage' | ||
|
|
||
| import { cn } from '@/lib/core/utils/cn' | ||
| import { TEMPLATE_WORKFLOWS } from '@/app/(home)/components/templates/template-workflows' | ||
|
|
||
| import { createLogger } from '@sim/logger' | ||
| import { useRouter } from 'next/navigation' | ||
| const logger = createLogger('LandingTemplates') | ||
|
|
||
| const LandingPreviewWorkflow = dynamic( | ||
|
|
@@ -337,7 +338,7 @@ function DotGrid({ className, cols, rows, gap = 0 }: DotGridProps) { | |
| }} | ||
| > | ||
| {Array.from({ length: cols * rows }, (_, i) => ( | ||
| <div key={i} className='h-[1.5px] w-[1.5px] rounded-full bg-[#2A2A2A]' /> | ||
| <div key={i} className='h-[2px] w-[2px] rounded-full bg-[#2A2A2A]' /> | ||
| ))} | ||
| </div> | ||
| ) | ||
|
|
@@ -424,8 +425,8 @@ export default function Templates() { | |
|
|
||
| <div className='bg-[#1C1C1C]'> | ||
| <DotGrid | ||
| className='overflow-hidden border-[#2A2A2A] border-y bg-[#1C1C1C] p-[6px]' | ||
| cols={160} | ||
| className='border-[#2A2A2A] border-y bg-[#1C1C1C] p-[6px]' | ||
| cols={120} | ||
| rows={1} | ||
| gap={6} | ||
| /> | ||
|
|
@@ -449,7 +450,7 @@ export default function Templates() { | |
| </svg> | ||
| </div> | ||
|
|
||
| <div className='px-[20px] pt-[60px] lg:px-[80px] lg:pt-[100px]'> | ||
| <div className='px-[80px] pt-[100px]'> | ||
| <div className='flex flex-col items-start gap-[20px]'> | ||
| <Badge | ||
| variant='blue' | ||
|
|
@@ -466,132 +467,107 @@ export default function Templates() { | |
|
|
||
| <h2 | ||
| id='templates-heading' | ||
| className='font-[430] font-season text-[28px] text-white leading-[100%] tracking-[-0.02em] lg:text-[40px]' | ||
| className='font-[430] font-season text-[40px] text-white leading-[100%] tracking-[-0.02em]' | ||
| > | ||
| Ship your agent in minutes | ||
| </h2> | ||
|
|
||
| <p className='font-[430] font-season text-[#F6F6F0]/50 text-[15px] leading-[150%] tracking-[0.02em] lg:text-[18px]'> | ||
| <p className='font-[430] font-season text-[#F6F6F0]/50 text-[16px] leading-[125%] tracking-[0.02em]'> | ||
| Pre-built templates for every use case—pick one, swap{' '} | ||
| <br className='hidden lg:inline' /> | ||
| models and tools to fit your stack, and deploy. | ||
| </p> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div className='mt-[40px] flex border-[#2A2A2A] border-y lg:mt-[73px]'> | ||
| <div className='shrink-0'> | ||
| <div className='h-full lg:hidden'> | ||
| <DotGrid | ||
| className='h-full w-[24px] overflow-hidden border-[#2A2A2A] border-r p-[4px]' | ||
| cols={2} | ||
| rows={55} | ||
| gap={4} | ||
| /> | ||
| </div> | ||
| <div className='hidden h-full lg:block'> | ||
| <DotGrid | ||
| className='h-full w-[80px] overflow-hidden border-[#2A2A2A] border-r p-[6px]' | ||
| cols={8} | ||
| rows={55} | ||
| gap={6} | ||
| /> | ||
| </div> | ||
| </div> | ||
| <div className='mt-[73px] flex border-[#2A2A2A] border-y'> | ||
| <DotGrid | ||
| className='w-[80px] shrink-0 overflow-hidden border-[#2A2A2A] border-r p-[6px]' | ||
| cols={6} | ||
| rows={55} | ||
| gap={6} | ||
| /> | ||
|
|
||
| <div className='flex min-w-0 flex-1 flex-col lg:flex-row'> | ||
| <div className='flex min-w-0 flex-1'> | ||
| <div | ||
| role='tablist' | ||
| aria-label='Workflow templates' | ||
| className='flex w-full shrink-0 flex-col border-[#2A2A2A] lg:w-[300px] lg:border-r' | ||
| className='flex w-[300px] shrink-0 flex-col border-[#2A2A2A] border-r' | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mobile responsiveness removed from templates sectionHigh Severity The templates section removed all mobile-responsive variants. Padding, font sizes, and layout classes now use fixed desktop values (e.g., Additional Locations (1) |
||
| > | ||
| {TEMPLATE_WORKFLOWS.map((workflow, index) => { | ||
| const isActive = index === activeIndex | ||
| const depth = DEPTH_CONFIGS[workflow.id] | ||
| return ( | ||
| <div key={workflow.id}> | ||
| <button | ||
| id={`template-tab-${index}`} | ||
| type='button' | ||
| role='tab' | ||
| aria-selected={isActive} | ||
| aria-controls={TEMPLATES_PANEL_ID} | ||
| onClick={() => setActiveIndex(index)} | ||
| className={cn( | ||
| 'relative w-full text-left', | ||
| isActive | ||
| ? 'z-10' | ||
| : cn( | ||
| 'flex items-center px-[12px] py-[10px] hover:bg-[#232323]/50', | ||
| index < TEMPLATE_WORKFLOWS.length - 1 && | ||
| 'shadow-[inset_0_-1px_0_0_#2A2A2A]' | ||
| ) | ||
| )} | ||
| <button | ||
| key={workflow.id} | ||
| id={`template-tab-${index}`} | ||
| type='button' | ||
| role='tab' | ||
| aria-selected={isActive} | ||
| aria-controls={TEMPLATES_PANEL_ID} | ||
| onClick={() => setActiveIndex(index)} | ||
| className={cn( | ||
| 'relative text-left', | ||
| isActive | ||
| ? 'z-10' | ||
| : 'shadow-[inset_0_-1px_0_0_#2A2A2A] last:shadow-none hover:bg-[#232323]/50' | ||
| )} | ||
| > | ||
| <div | ||
| className='pointer-events-none absolute top-[-8px] bottom-0 left-0 w-2' | ||
| style={{ | ||
| clipPath: LEFT_WALL_CLIP, | ||
| backgroundColor: hexToRgba(depth.color, 0.63), | ||
| opacity: isActive ? 1 : 0, | ||
| transition: isActive | ||
| ? 'opacity 250ms cubic-bezier(0.2, 0, 0, 1) 50ms' | ||
| : 'opacity 200ms cubic-bezier(0.4, 0, 1, 1)', | ||
| }} | ||
| /> | ||
| <div | ||
| className='pointer-events-none absolute right-[-8px] bottom-0 left-2 h-2' | ||
| style={{ | ||
| ...buildBottomWallStyle(depth), | ||
| opacity: isActive ? 1 : 0, | ||
| transition: isActive | ||
| ? 'opacity 250ms cubic-bezier(0.2, 0, 0, 1) 50ms' | ||
| : 'opacity 200ms cubic-bezier(0.4, 0, 1, 1)', | ||
| }} | ||
| /> | ||
| <div | ||
| className='relative flex items-center px-[12px] py-[10px]' | ||
| style={{ | ||
| transform: isActive ? 'translate(8px, -8px)' : 'translate(0px, 0px)', | ||
| backgroundColor: isActive ? '#242424' : 'transparent', | ||
| boxShadow: isActive | ||
| ? 'inset 0 0 0 1.5px #3E3E3E' | ||
| : 'inset 0 0 0 1.5px transparent', | ||
| transition: isActive | ||
| ? 'transform 350ms cubic-bezier(0.34, 1.4, 0.64, 1), background-color 250ms ease 30ms, box-shadow 250ms ease 30ms' | ||
| : 'transform 300ms cubic-bezier(0.4, 0, 0.2, 1), background-color 200ms ease, box-shadow 200ms ease', | ||
| }} | ||
| > | ||
| {isActive ? ( | ||
| (() => { | ||
| const depth = DEPTH_CONFIGS[workflow.id] | ||
| return ( | ||
| <> | ||
| <div | ||
| className='absolute top-[-8px] bottom-0 left-0 w-2' | ||
| style={{ | ||
| clipPath: LEFT_WALL_CLIP, | ||
| backgroundColor: hexToRgba(depth.color, 0.63), | ||
| }} | ||
| /> | ||
| <div | ||
| className='absolute right-[-8px] bottom-0 left-2 h-2' | ||
| style={buildBottomWallStyle(depth)} | ||
| /> | ||
| <div className='-translate-y-2 relative flex translate-x-2 items-center bg-[#242424] px-[12px] py-[10px] shadow-[inset_0_0_0_1.5px_#3E3E3E]'> | ||
| <span className='flex-1 font-[430] font-season text-[16px] text-white'> | ||
| {workflow.name} | ||
| </span> | ||
| <ChevronDown | ||
| className='-rotate-90 h-[11px] w-[11px] shrink-0' | ||
| style={{ color: depth.color }} | ||
| /> | ||
| </div> | ||
| </> | ||
| ) | ||
| })() | ||
| ) : ( | ||
| <span className='font-[430] font-season text-[#F6F6F0]/50 text-[16px]'> | ||
| {workflow.name} | ||
| </span> | ||
| )} | ||
| </button> | ||
|
|
||
| <AnimatePresence> | ||
| {isActive && isMobile && ( | ||
| <motion.div | ||
| initial={{ height: 0, opacity: 0 }} | ||
| animate={{ height: 'auto', opacity: 1 }} | ||
| exit={{ height: 0, opacity: 0 }} | ||
| transition={{ duration: 0.25, ease: [0.4, 0, 0.2, 1] }} | ||
| className='overflow-hidden' | ||
| > | ||
| <div className='aspect-[16/10] w-full border-[#2A2A2A] border-y bg-[#1b1b1b]'> | ||
| <LandingPreviewWorkflow | ||
| workflow={workflow} | ||
| animate | ||
| fitViewOptions={{ padding: 0.15, maxZoom: 1.3 }} | ||
| /> | ||
| </div> | ||
| <div className='p-[12px]'> | ||
| <button | ||
| type='button' | ||
| onClick={handleUseTemplate} | ||
| disabled={isPreparingTemplate} | ||
| className='inline-flex h-[32px] w-full cursor-pointer items-center justify-center gap-[6px] rounded-[5px] border border-[#FFFFFF] bg-[#FFFFFF] font-[430] font-season text-[14px] text-black transition-colors active:bg-[#E0E0E0]' | ||
| > | ||
| {isPreparingTemplate ? 'Preparing...' : 'Use template'} | ||
| </button> | ||
| </div> | ||
| </motion.div> | ||
| )} | ||
| </AnimatePresence> | ||
| </div> | ||
| <span | ||
| className='flex-1 font-[430] font-season text-[16px]' | ||
| style={{ | ||
| color: isActive ? '#FFFFFF' : 'rgba(246, 246, 240, 0.5)', | ||
| transition: 'color 250ms ease', | ||
| }} | ||
| > | ||
| {workflow.name} | ||
| </span> | ||
| <ChevronDown | ||
| className='-rotate-90 h-[11px] w-[11px] shrink-0' | ||
| style={{ | ||
| color: depth.color, | ||
| opacity: isActive ? 1 : 0, | ||
| transition: isActive | ||
| ? 'opacity 200ms ease 150ms' | ||
| : 'opacity 150ms ease', | ||
| }} | ||
| /> | ||
| </div> | ||
| </button> | ||
| ) | ||
| })} | ||
| </div> | ||
|
|
@@ -610,13 +586,11 @@ export default function Templates() { | |
| fitViewOptions={{ padding: 0.15, maxZoom: 1.3 }} | ||
| /> | ||
| </div> | ||
| <button | ||
| type='button' | ||
| onClick={handleUseTemplate} | ||
| disabled={isPreparingTemplate} | ||
| className='group/cta absolute top-[16px] right-[16px] z-10 inline-flex h-[32px] cursor-pointer items-center gap-[6px] rounded-[5px] border border-[#FFFFFF] bg-[#FFFFFF] px-[10px] font-[430] font-season text-[14px] text-black transition-colors hover:border-[#E0E0E0] hover:bg-[#E0E0E0]' | ||
| <Link | ||
| href='/signup' | ||
| className='group/cta absolute top-[16px] right-[16px] z-10 inline-flex h-[32px] items-center gap-[6px] rounded-[5px] border border-[#33C482] bg-[#33C482] px-[10px] font-[430] font-season text-[14px] text-black transition-[filter] hover:brightness-110' | ||
| > | ||
| {isPreparingTemplate ? 'Preparing...' : 'Use template'} | ||
| Use template | ||
| <span className='relative h-[10px] w-[10px] shrink-0'> | ||
| <ChevronDown className='-rotate-90 absolute inset-0 h-[10px] w-[10px] transition-opacity duration-150 group-hover/cta:opacity-0' /> | ||
| <svg | ||
|
|
@@ -635,31 +609,19 @@ export default function Templates() { | |
| /> | ||
| </svg> | ||
| </span> | ||
| </button> | ||
| </Link> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div className='shrink-0'> | ||
| <div className='h-full lg:hidden'> | ||
| <DotGrid | ||
| className='h-full w-[24px] overflow-hidden border-[#2A2A2A] border-l p-[4px]' | ||
| cols={2} | ||
| rows={55} | ||
| gap={4} | ||
| /> | ||
| </div> | ||
| <div className='hidden h-full lg:block'> | ||
| <DotGrid | ||
| className='h-full w-[80px] overflow-hidden border-[#2A2A2A] border-l p-[6px]' | ||
| cols={8} | ||
| rows={55} | ||
| gap={6} | ||
| /> | ||
| </div> | ||
| </div> | ||
| <DotGrid | ||
| className='w-[80px] shrink-0 overflow-hidden border-[#2A2A2A] border-l p-[6px]' | ||
| cols={6} | ||
| rows={55} | ||
| gap={6} | ||
| /> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </section> | ||
| ) | ||
| } | ||
| } | ||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused state and logic after template button replacement
Low Severity
isPreparingTemplate,handleUseTemplate, andisMobileare now dead code. The diff replaced the template button with a simpleLinkto/signupand removed the mobile inline preview, but the state variables, theuseEffectfor media query detection, theuseRouterimport, and thehandleUseTemplatecallback all remain. This also keeps unnecessary dependencies likecreateLoggerandLandingWorkflowSeedStoragein scope.Additional Locations (1)
apps/sim/app/(home)/components/templates/templates.tsx#L371-L409