feat(landing): smooth sliding pill for hero service icons#3469
feat(landing): smooth sliding pill for hero service icons#3469adithyaakrishna wants to merge 3 commits intosimstudioai:mainfrom
Conversation
PR SummaryLow Risk Overview Refactors Written by Cursor Bugbot for commit b4b7a86. This will update automatically on new commits. Configure here. |
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Greptile SummaryThis PR replaces per-icon CSS hover styling on the landing hero service icons with a Confidence Score: 3/5
Sequence DiagramsequenceDiagram
participant Timer as Auto-Hover Timer
participant State as React State
participant LayoutEffect as useLayoutEffect
participant Pill as motion.div (Pill)
participant Button as IconButton (isAutoHovered)
Timer->>State: setAutoHoverIndex(next)
State->>State: activeIconIndex = next
State->>LayoutEffect: trigger (activeIconIndex changed)
LayoutEffect->>LayoutEffect: measure buttonRefs[activeIconIndex].getBoundingClientRect()
LayoutEffect->>State: setPillLayout({left, top, width, height})
State->>Pill: animate to new pillLayout (spring: stiffness=325, damping=33)
Note over Pill: Pill slides smoothly over ~300ms
State->>Button: isAutoHovered=true → border-[#E5E5E5] applied immediately (CSS transition 300ms)
Note over Pill,Button: ⚠️ Both pill (mid-slide) AND button border (static at new icon) visible simultaneously
Last reviewed commit: 782e9f6 |
| <IconButton | ||
| aria-label={service.label} | ||
| onClick={() => handleServiceClick(service.key as keyof typeof SERVICE_TEMPLATES)} | ||
| onMouseEnter={() => setLastHoveredIndex(index)} | ||
| style={service.style} | ||
| isAutoHovered={!isUserHovering && index === autoHoverIndex} | ||
| > | ||
| <Icon className='h-5 w-5 sm:h-6 sm:w-6' /> | ||
| </IconButton> |
There was a problem hiding this comment.
IconButton applies border-[#E5E5E5] shadow-[0_2px_4px_0_rgba(0,0,0,0.08)] immediately when isAutoHovered=true (with a 300ms CSS transition). The sliding pill carries the same border/shadow. During the spring animation from icon A to icon B:
- Icon B's button immediately renders its own border (because
isAutoHoveredflipped totrue) - The pill is still mid-slide between A and B
This creates two visible bordered highlights simultaneously — one static at B (the button's own border) and one sliding (the pill) — which defeats the purpose of the smooth transition.
Since the pill is now the sole source of the highlight, consider suppressing the isAutoHovered border/shadow on IconButton:
| <IconButton | |
| aria-label={service.label} | |
| onClick={() => handleServiceClick(service.key as keyof typeof SERVICE_TEMPLATES)} | |
| onMouseEnter={() => setLastHoveredIndex(index)} | |
| style={service.style} | |
| isAutoHovered={!isUserHovering && index === autoHoverIndex} | |
| > | |
| <Icon className='h-5 w-5 sm:h-6 sm:w-6' /> | |
| </IconButton> | |
| <IconButton | |
| aria-label={service.label} | |
| onClick={() => handleServiceClick(service.key as keyof typeof SERVICE_TEMPLATES)} | |
| onMouseEnter={() => setLastHoveredIndex(index)} | |
| style={service.style} | |
| isAutoHovered={false} | |
| > | |
| <Icon className='h-5 w-5 sm:h-6 sm:w-6' /> | |
| </IconButton> |
Alternatively, update IconButton to not apply the border/shadow when isAutoHovered=true so the pill is the only visual indicator.
apps/sim/app/(landing)/components/hero/components/icon-button.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| setSelectedIconIndex((idx) => | ||
| idx !== null ? Math.min(idx, maxIndex) : null | ||
| ) | ||
| }, [visibleIconCount]) |
There was a problem hiding this comment.
Clamped selectedIconIndex mismatches textarea template content
Low Severity
When visibleIconCount shrinks (e.g., resizing from desktop to mobile), selectedIconIndex is clamped to maxIndex but textValue is left unchanged. This causes the sliding pill to highlight a different service icon than the one whose template is displayed in the textarea. For instance, clicking icon 10 (Google Sheets) then resizing to mobile clamps selectedIconIndex to 5 (Supabase), so the pill highlights Supabase while the textarea still shows the Google Sheets template.


Summary
Fixes #3468
Type of Change
Testing
Checklist
Screenshots/Videos
HeroBeforeAfter.mp4