Skip to content

improvement(home): redesign workspace home template experience#3880

Closed
ananmaysharan wants to merge 1 commit intosimstudioai:mainfrom
ananmaysharan:improvement/home-template-redesign
Closed

improvement(home): redesign workspace home template experience#3880
ananmaysharan wants to merge 1 commit intosimstudioai:mainfrom
ananmaysharan:improvement/home-template-redesign

Conversation

@ananmaysharan
Copy link
Copy Markdown

Summary

  • Replace vertical scroll-all template layout with category-based pill navigation.
  • Adds responsive horizontal scrolling with gradient fade indicators on mobile, natural wrapping on desktop.
  • Template cards now show integration icon stacks and anchor preview images from top-left.
  • Fixes dark and light mode hover colors and behaviours on template cards.

Screenshots/Videos

Before:

before.mp4

After:

after.mp4

Design Decisions

I chose to focus on redesigning the template card experience into a pill based navigation to help users quickly navigate and explore the existing pre-built templates that could be useful to them, based on already existing category variable within the templates. I focused on making it work across dark and light modes and different viewport sizes. In addition, I redesigned the card title to include all of the integrations a particular template uses, in order to show the breadth of capabilities and integrations Sim has, as well as for users looking for a particular integration to be able to scan the templates section for it quickly. Finally, I made some small fixes to layout, color and hover states in the home page.

Next Steps

Given more time, my focus would go to the contents of the cards themselves. They are generic and repeated for many of the templates, and inconsistent light and dark backgrounds for the templates in the featured section. Future work could go into making the content dynamic and representative of each template exactly as well as showing more information about the types of modules as well as the integrations. Beyond that, adding some more interaction/details/animation into the card and pill hover states as well as diversifying the icon set used to make them more representative of the template purpose. Finally, there are some color contrast/accessibility issues with some logos in the integrations in dark/light mode, work is needed to ensure the use of correct color/monochrome logo versions for integrations in the right contexts.

Replace vertical scroll-all template layout with category-based pill
navigation. Adds responsive horizontal scrolling with gradient fade
indicators on mobile, natural wrapping on desktop. Template cards now
show integration icon stacks and anchor preview images from top-left.
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 1, 2026

@ananmaysharan is attempting to deploy a commit to the Sim Team on Vercel.

A member of the Team first needs to authorize it.

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 1, 2026

PR Summary

Low Risk
Primarily UI/UX changes to template browsing and card presentation; risk is limited to potential layout/scroll/animation regressions across breakpoints and reduced-motion settings.

Overview
Reworks the home "Start with a template" section to use category pill navigation (horizontal scroll on mobile with gradient fade indicators) instead of rendering all templates in grouped vertical sections.

Template cards now show a right-aligned IntegrationIconStack derived from integrationBlockTypes, and card visuals are tweaked (top-left image anchoring, truncated titles, and updated hover surface colors) for more consistent light/dark behavior.

Template/category metadata is updated so CATEGORY_META includes icons, and many template icon assignments are swapped from integration logos to the shared emcn icon set.

Written by Cursor Bugbot for commit 5e4fac7. This will update automatically on new commits. Configure here.

@ananmaysharan ananmaysharan deleted the improvement/home-template-redesign branch April 1, 2026 05:44
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 1, 2026

Greptile Summary

This PR redesigns the workspace home template section, replacing a flat vertical-scroll layout with a category-based pill navigation, responsive horizontal scrolling on mobile, and template cards that now surface integration icon stacks alongside the card title.

Key changes:

  • template-prompts.tsx — new pill nav with scroll-fade indicators; TemplateCard now renders IntegrationIconStack in the card footer; preview images anchor from top-left.
  • consts.tsCATEGORY_META entries gain icon fields; all templates gain integrationBlockTypes arrays; template icon fields switched from branded integration icons to generic UI icons.
  • integration-icon-stack.tsx (new) — memoised component rendering overlapping circular integration icons with a framer-motion spring-scale hover effect.

One P1 issue found: showRightFade is initialised to true without a mount-time DOM check, so the right scroll-gradient may appear incorrectly on mobile viewports where the pill row does not overflow. One P2 suggestion: the animate prop should use framer-motion's individual scale property rather than a raw CSS transform string.

Confidence Score: 4/5

Safe to merge after addressing the incorrect initial showRightFade state on mobile.

One P1 visual defect (right gradient indicator appearing when there is no overflowing content on certain mobile viewports) should be fixed before merging. The two P2 findings are non-blocking style improvements.

apps/sim/app/workspace/[workspaceId]/home/components/template-prompts/template-prompts.tsx (showRightFade init), apps/sim/app/workspace/[workspaceId]/home/components/template-prompts/components/integration-icon-stack.tsx (animate prop)

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/home/components/template-prompts/components/integration-icon-stack.tsx New component rendering overlapping integration icons with spring-scale hover animation; animation uses raw CSS transform string instead of framer-motion's individual scale property, and the icon map belongs in a dedicated config file per project conventions.
apps/sim/app/workspace/[workspaceId]/home/components/template-prompts/consts.ts Adds icons to CATEGORY_META, adds integrationBlockTypes arrays to all templates, and replaces branded integration icons with generic UI icons for template cards — all straightforward and correct.
apps/sim/app/workspace/[workspaceId]/home/components/template-prompts/template-prompts.tsx Replaces vertical scroll layout with category-based pill navigation and responsive card grid; showRightFade initialised to true without a mount-time scroll check, causing the right gradient to display incorrectly on some mobile viewports.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[TemplatePrompts] --> B{activeCategory}
    B -->|popular| C[TEMPLATES filtered by featured]
    B -->|other| D[TEMPLATES filtered by category]
    C --> E[grid of TemplateCard]
    D --> E
    E --> F{template.image?}
    F -->|yes| G[Next/Image anchored top-left]
    F -->|no| H[TemplatePreview\ntable / knowledge / file / workflow]
    E --> I[IntegrationIconStack\nhovering spring-scales icons]
    A --> J[pill nav]
    J --> K[scroll fade L/R indicators\nmobile only]
    K --> L[handleNavScroll\nupdates showLeftFade / showRightFade]
Loading

Reviews (1): Last reviewed commit: "improvement(home): redesign workspace ho..." | Re-trigger Greptile

Comment on lines +294 to +295
const [showLeftFade, setShowLeftFade] = useState(false)
const [showRightFade, setShowRightFade] = useState(true)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Right fade gradient shown incorrectly on initial render

showRightFade is initialised to true unconditionally. On mobile screens where all 7 category pills fit without overflowing (e.g. wider phones in landscape mode, ~430–767 px), the right gradient indicator is displayed even though there is no additional content to scroll to. The handleNavScroll handler is only called when the user scrolls, so the flag is never corrected after mount if the element does not overflow.

Add a useLayoutEffect (or useEffect) to run the scroll check once on mount:

Suggested change
const [showLeftFade, setShowLeftFade] = useState(false)
const [showRightFade, setShowRightFade] = useState(true)
const [showLeftFade, setShowLeftFade] = useState(false)
const [showRightFade, setShowRightFade] = useState(false)
useLayoutEffect(() => {
handleNavScroll()
}, [handleNavScroll])

Also import useLayoutEffect at the top:

import { type ComponentType, memo, type SVGProps, useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react'

Comment on lines +130 to +140
animate={{
transform: `scale(${getScale(index)})`,
}}
transition={{ type: 'spring', bounce: 0.15, duration: 0.25 }}
style={{ zIndex: hoveredIndex === index ? 50 : icons.length - index }}
className='-ml-1 flex h-5 w-5 origin-bottom items-center justify-center rounded-full border border-[var(--border-1)] bg-[var(--white)] first:ml-0 dark:bg-[var(--surface-4)]'
>
<Icon aria-hidden='true' className='h-3 w-3' />
</motion.div>
))}
</div>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Use individual framer-motion transform property instead of CSS string

Passing a raw CSS transform string to framer-motion's animate prop (transform: \scale(…)`) is not the recommended pattern. Framer-motion's interpolation engine works most reliably with individual transform keys (scale, x, y, etc.), not composite CSS strings. Using individual keys also gives you correct origin-bottom` behaviour from the Tailwind class already applied.

Suggested change
animate={{
transform: `scale(${getScale(index)})`,
}}
transition={{ type: 'spring', bounce: 0.15, duration: 0.25 }}
style={{ zIndex: hoveredIndex === index ? 50 : icons.length - index }}
className='-ml-1 flex h-5 w-5 origin-bottom items-center justify-center rounded-full border border-[var(--border-1)] bg-[var(--white)] first:ml-0 dark:bg-[var(--surface-4)]'
>
<Icon aria-hidden='true' className='h-3 w-3' />
</motion.div>
))}
</div>
animate={{ scale: getScale(index) }}

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +52 to +94
const INTEGRATION_BLOCK_ICONS: Record<string, IconComponent> = {
airtable: AirtableIcon,
amplitude: AmplitudeIcon,
apollo: ApolloIcon,
asana: AsanaIcon,
calendly: CalendlyIcon,
confluence: ConfluenceIcon,
datadog: DatadogIcon,
discord: DiscordIcon,
firecrawl: FirecrawlIcon,
github: GithubIcon,
gmail: GmailIcon,
gong: GongIcon,
google_calendar: GoogleCalendarIcon,
google_docs: GoogleDocsIcon,
google_drive: GoogleDriveIcon,
google_sheets: GoogleSheetsIcon,
greenhouse: GreenhouseIcon,
hubspot: HubspotIcon,
intercom: IntercomIcon,
jira: JiraIcon,
lemlist: LemlistIcon,
linear: LinearIcon,
linkedin: LinkedInIcon,
mailchimp: MailchimpIcon,
microsoft_teams: MicrosoftTeamsIcon,
notion: NotionIcon,
obsidian: ObsidianIcon,
pagerduty: PagerDutyIcon,
reddit: RedditIcon,
salesforce: SalesforceIcon,
sentry: SentryIcon,
shopify: ShopifyIcon,
slack: SlackIcon,
stripe: StripeIcon,
twilio_sms: TwilioIcon,
typeform: TypeformIcon,
webflow: WebflowIcon,
wordpress: WordpressIcon,
x: xIcon,
youtube: YouTubeIcon,
zendesk: ZendeskIcon,
} as const
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Config map should live in a dedicated config file

Per the project's component convention, component configuration (like INTEGRATION_BLOCK_ICONS) should be placed in a dedicated .ts config file rather than inline in the component file. This also mirrors how the icon maps were previously organised in consts.ts.

Consider extracting it to a sibling file such as components/integration-icon-config.ts and importing the map into integration-icon-stack.tsx.

Rule Used: When defining properties for components, use a ded... (source)

Learnt From
simstudioai/sim#367

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

if (!el) return
setShowLeftFade(el.scrollLeft > 2)
setShowRightFade(el.scrollLeft < el.scrollWidth - el.clientWidth - 2)
}, [])
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right fade gradient shows when nav doesn't overflow

Low Severity

showRightFade is initialized to true, but it's only corrected by the handleNavScroll callback on onScroll events. If the category pills fit within the viewport without overflowing (e.g., wider mobile screens or landscape), no scroll event ever fires, so the right gradient fade indicator remains permanently visible despite there being nothing to scroll to. A useEffect (or ResizeObserver) that checks el.scrollWidth > el.clientWidth after mount and on resize is needed to set the correct initial state.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant