feat:Add macOS-style dock component with animated social icons#87
feat:Add macOS-style dock component with animated social icons#87Abhijit-Jha merged 3 commits intoitshover:masterfrom
Conversation
|
@AyushGuleria2005 is attempting to deploy a commit to the itshover's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 📝 WalkthroughWalkthroughAdds a new Dock React example component rendering an animated horizontal social icon dock with tooltips and hover-elastic layout; introduces four new forwardRef animated SVG icon components (Facebook, Instagram, LinkedIn, WhatsApp), and adds a Changes
Sequence DiagramsequenceDiagram
actor User
participant Dock
participant DockItem
participant Icon
participant Tooltip
User->>Dock: hover over dock area
Dock->>Dock: adjust padding & gap (spring)
User->>DockItem: hover (mouse enter)
activate DockItem
DockItem->>DockItem: setIsHovered(true)
DockItem->>Icon: ref.startAnimation()
activate Icon
Icon->>Icon: animate SVG elements
deactivate Icon
DockItem->>Tooltip: show (animate opacity & position)
deactivate DockItem
User->>DockItem: hover out (mouse leave)
activate DockItem
DockItem->>DockItem: setIsHovered(false)
DockItem->>Icon: ref.stopAnimation()
activate Icon
Icon->>Icon: reset animation state
deactivate Icon
DockItem->>Tooltip: hide
deactivate DockItem
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧹 Recent nitpick comments
📜 Recent review detailsConfiguration used: defaults Review profile: CHILL Plan: Pro 📒 Files selected for processing (5)
🚧 Files skipped from review as they are similar to previous changes (2)
🔇 Additional comments (2)
✏️ Tip: You can disable this entire section by setting Comment |
Greptile SummaryAdded a macOS-style dock component featuring 6 animated social media icons (Twitter/X, WhatsApp, GitHub, Facebook, LinkedIn, Instagram). The component implements smooth hover interactions with icon scaling, tooltip displays, and dynamic spacing using Framer Motion. Major changes:
Issues found:
Confidence Score: 3/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant Dock
participant DockItem
participant Icon
participant MotionSVG
User->>Dock: Hover over dock container
Dock->>Dock: setIsHovered(true)
Dock->>Dock: Animate padding & gap expansion
User->>DockItem: Hover over icon
DockItem->>DockItem: handleMouseEnter()
DockItem->>DockItem: setIsHovered(true)
DockItem->>Icon: iconRef.current?.startAnimation()
Icon->>MotionSVG: animate() with specific animation
MotionSVG-->>User: Show animated icon
DockItem->>DockItem: Show tooltip (opacity: 1, y: -50)
DockItem->>DockItem: Scale icon (scale: 1.2, y: -8)
User->>DockItem: Mouse leave icon
DockItem->>DockItem: handleMouseLeave()
DockItem->>DockItem: setIsHovered(false)
DockItem->>Icon: iconRef.current?.stopAnimation()
Icon->>MotionSVG: Reset animation state
DockItem->>DockItem: Hide tooltip (opacity: 0)
DockItem->>DockItem: Reset scale
User->>Dock: Mouse leave dock
Dock->>Dock: setIsHovered(false)
Dock->>Dock: Reset padding & gap
|
There was a problem hiding this comment.
Additional Comments (1)
-
components/ui/github-icon.tsx, line 34-40 (link)style: Remove unused functions - they're defined but never used
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!
7 files reviewed, 4 comments
|
|
||
|
|
||
| const dockItems = [ | ||
| { icon: TwitterXIcon, label: "Twitter/X", href: "$" }, |
There was a problem hiding this comment.
syntax: Typo in href - should be "#" not "$"
| { icon: TwitterXIcon, label: "Twitter/X", href: "$" }, | |
| { icon: TwitterXIcon, label: "Twitter/X", href: "#" }, |
Prompt To Fix With AI
This is a comment left during a code review.
Path: components/examples/dock.tsx
Line: 16:16
Comment:
**syntax:** Typo in href - should be `"#"` not `"$"`
```suggestion
{ icon: TwitterXIcon, label: "Twitter/X", href: "#" },
```
How can I resolve this? If you propose a fix, please make it concise.| { icon: LinkedinIcon, label: "LinkedIn", href: "https://instagram.com" }, | ||
| { icon: InstagramIcon, label: "Instagram", href: "https://facebook.com" }, |
There was a problem hiding this comment.
logic: The hrefs are incorrect - LinkedIn points to Instagram and Instagram points to Facebook
| { icon: LinkedinIcon, label: "LinkedIn", href: "https://instagram.com" }, | |
| { icon: InstagramIcon, label: "Instagram", href: "https://facebook.com" }, | |
| { icon: LinkedinIcon, label: "LinkedIn", href: "#" }, | |
| { icon: InstagramIcon, label: "Instagram", href: "#" }, |
Prompt To Fix With AI
This is a comment left during a code review.
Path: components/examples/dock.tsx
Line: 20:21
Comment:
**logic:** The hrefs are incorrect - LinkedIn points to Instagram and Instagram points to Facebook
```suggestion
{ icon: LinkedinIcon, label: "LinkedIn", href: "#" },
{ icon: InstagramIcon, label: "Instagram", href: "#" },
```
How can I resolve this? If you propose a fix, please make it concise.| console.log("This was workig even after animation was off -> mouse enter: ", isAnimated) | ||
| iconRef.current?.startAnimation(); | ||
| } | ||
| }; | ||
|
|
||
| const handleMouseLeave = () => { | ||
| setIsHovered(false); | ||
| if (isAnimated) { | ||
| console.log("This was workig even after animation was off -> mouse leave", isAnimated) | ||
| iconRef.current?.stopAnimation(); |
There was a problem hiding this comment.
style: Remove debug console.log statements
| console.log("This was workig even after animation was off -> mouse enter: ", isAnimated) | |
| iconRef.current?.startAnimation(); | |
| } | |
| }; | |
| const handleMouseLeave = () => { | |
| setIsHovered(false); | |
| if (isAnimated) { | |
| console.log("This was workig even after animation was off -> mouse leave", isAnimated) | |
| iconRef.current?.stopAnimation(); | |
| const handleMouseEnter = () => { | |
| setIsHovered(true); | |
| if (isAnimated) { | |
| iconRef.current?.startAnimation(); | |
| } | |
| }; | |
| const handleMouseLeave = () => { | |
| setIsHovered(false); | |
| if (isAnimated) { | |
| iconRef.current?.stopAnimation(); |
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!
Prompt To Fix With AI
This is a comment left during a code review.
Path: components/examples/dock.tsx
Line: 41:50
Comment:
**style:** Remove debug console.log statements
```suggestion
const handleMouseEnter = () => {
setIsHovered(true);
if (isAnimated) {
iconRef.current?.startAnimation();
}
};
const handleMouseLeave = () => {
setIsHovered(false);
if (isAnimated) {
iconRef.current?.stopAnimation();
```
<sub>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!</sub>
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@components/examples/dock.tsx`:
- Around line 41-42: Remove the debug console.log statements that print internal
state (the lines referencing isAnimated) in the dock example: delete the
console.log at the mouse-enter block and the similar debug log at lines 49-50 so
only the intended behavior (calling iconRef.current?.startAnimation() and other
logic such as stopAnimation) remains; search for "console.log" in the component
to ensure no other debug logs remain and keep iconRef.current?.startAnimation()
and related calls unchanged.
- Around line 15-23: The dockItems array contains incorrect hrefs—update the
entries in the dockItems constant: change the Twitter/X item (currently href
"$") to a valid placeholder or URL (e.g., "#"), change the LinkedinIcon item
(label "LinkedIn") from "https://instagram.com" to the correct LinkedIn URL
(e.g., "https://linkedin.com" or "#"), and change the InstagramIcon item (label
"Instagram") from "https://facebook.com" to the correct Instagram URL (e.g.,
"https://instagram.com" or "#"); modify only the href values in the dockItems
array.
🧹 Nitpick comments (6)
components/ui/github-icon.tsx (2)
34-40: Remove unused handler functions.
handleHoverStartandhandleHoverEndare defined but never used. Lines 45-46 directly referencestartandstopinstead. Remove these dead functions to clean up the code.🧹 Proposed fix
- const handleHoverStart = () => { - start(); - }; - - const handleHoverEnd = () => { - stop(); - }; - return (
13-27: Consider wrappingstartandstopinuseCallbackfor consistency.Other icon components in this PR (InstagramIcon, WhatsappIcon, FacebookIcon) wrap their animation handlers in
useCallback. For consistency across the icon component family, consider applying the same pattern here.components/examples/dock.tsx (3)
5-6: Remove commented-out import.The commented import on line 5 is dead code. If the alias path is preferred for future use, add a TODO comment or remove the line entirely.
🧹 Proposed fix
-// import TwitterXIcon from "@/icons/twitter-x-icon"; import TwitterXIcon from "../ui/twitter-x-icon";
36-36: Fix misleading comment.The comment "for entire dock" is inaccurate—this
isHoveredstate tracks hover for the individualDockItem, not the entire dock. The dock-level hover state is in theDockcomponent (line 99).🧹 Proposed fix
- const [isHovered, setIsHovered] = useState(false); // for entire dock + const [isHovered, setIsHovered] = useState(false);
62-66: Consider addingaria-labelfor accessibility.The anchor elements link to external sites but rely solely on visual icons. Adding an
aria-labelwould improve screen reader accessibility.♿ Proposed fix
<motion.a layout href={href} target="_blank" rel="noopener noreferrer" + aria-label={label} className="relative flex items-center justify-center"components/ui/linkedin-icon.tsx (1)
25-31: Consider separating animation targets in stop function.The stop function applies both
pathLengthandscaleto both.linesand.borderelements. While Framer Motion ignores non-applicable properties, separating the targets would be more explicit and align with thestartfunction's structure.♻️ Optional: Separate animation targets
const stop = useCallback(() => { - animate( - ".lines, .border", - { pathLength: 1, scale: 1 }, - { duration: 0.2 }, - ); + animate(".lines", { pathLength: 1 }, { duration: 0.2 }); + animate(".border", { scale: 1 }, { duration: 0.2 }); }, [animate]);
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (7)
components/examples/dock.tsxcomponents/ui/facebook-icon.tsxcomponents/ui/github-icon.tsxcomponents/ui/instagram-icon.tsxcomponents/ui/linkedin-icon.tsxcomponents/ui/whatsapp-icon.tsxlib/examples.ts
🧰 Additional context used
🪛 GitHub Actions: CI
components/examples/dock.tsx
[warning] 1-1: Code style issues detected by Prettier. Run 'prettier --write' to fix formatting in this file.
components/ui/instagram-icon.tsx
[warning] 1-1: Code style issues detected by Prettier. Run 'prettier --write' to fix formatting in this file.
components/ui/github-icon.tsx
[warning] 1-1: Code style issues detected by Prettier. Run 'prettier --write' to fix formatting in this file.
components/ui/whatsapp-icon.tsx
[warning] 1-1: Code style issues detected by Prettier. Run 'prettier --write' to fix formatting in this file.
components/ui/facebook-icon.tsx
[warning] 1-1: Code style issues detected by Prettier. Run 'prettier --write' to fix formatting in this file.
components/ui/linkedin-icon.tsx
[warning] 1-1: Code style issues detected by Prettier. Run 'prettier --write' to fix formatting in this file.
lib/examples.ts
[warning] 1-1: Code style issues detected by Prettier. Run 'prettier --write' to fix formatting in this file.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Greptile Review
🔇 Additional comments (6)
components/ui/instagram-icon.tsx (1)
1-81: LGTM!The component follows the established pattern with proper use of
forwardRef,useImperativeHandle, anduseCallback. The animation sequence for the Instagram icon elements is well-structured.components/ui/whatsapp-icon.tsx (1)
1-72: LGTM!Clean implementation following the established animated icon pattern. The shake animation on the phone icon element is appropriate for a messaging app icon.
components/ui/facebook-icon.tsx (1)
1-83: LGTM!Well-implemented animated icon with a creative like animation using the thumbs-up emoji. The component follows the established pattern correctly.
lib/examples.ts (1)
59-69: LGTM! New Dock entry is well-structured.The registry entry follows the established pattern and includes all required metadata. The
fullWidth: truesetting is appropriate for a dock component.Note: The CI pipeline flagged a Prettier formatting issue. Please run
prettier --writeon this file to resolve.components/ui/linkedin-icon.tsx (2)
38-80: SVG structure and animation bindings look good.The LinkedIn icon is properly structured with:
- Correct viewBox and stroke attributes
- Appropriate use of motion elements for animatable paths
- Proper hover handlers respecting
disableHoverproptransformOrigin: "center"on the border for correct scale animationNote: CI flagged Prettier formatting issues. Run
prettier --writeon this file.
1-3: Imports are valid for the project's Framer Motion version.The
motion/reactimport path is correctly supported by the project'smotionpackage (v12.23.26).
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@components/examples/dock.tsx`:
- Around line 61-93: The anchor rendered as motion.a is icon-only and lacks an
accessible name; update the element to provide a screen-reader label by adding
an aria-label (use the existing label prop or a fallback like href) or include
an SR-only span inside the anchor with the label text; ensure the change targets
the motion.a that wraps the Icon (and keep existing props such as
onMouseEnter/onMouseLeave, whileHover, transition) so screen readers can
identify the link destination.
In `@components/ui/linkedin-icon.tsx`:
- Around line 1-4: This file is using React hooks (useImperativeHandle,
useCallback) and motion's useAnimate, so mark it as a Next.js client component
by adding "use client" as the first line of components/ui/linkedin-icon.tsx;
ensure the directive appears before imports so hooks in the forwardRef component
and types AnimatedIconHandle / AnimatedIconProps work correctly.
In `@components/ui/whatsapp-icon.tsx`:
- Around line 1-4: This component uses client-only hooks (useImperativeHandle,
useCallback, useAnimate) and motion/react JSX; add the "use client" directive as
the very first line of the file so the component is treated as a client
component and hooks work correctly, then ensure exports and forwardRef usage
(forwardRef, AnimatedIconHandle, AnimatedIconProps) remain unchanged.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
components/examples/dock.tsxcomponents/ui/facebook-icon.tsxcomponents/ui/github-icon.tsxcomponents/ui/instagram-icon.tsxcomponents/ui/linkedin-icon.tsxcomponents/ui/whatsapp-icon.tsxlib/examples.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- components/ui/facebook-icon.tsx
- components/ui/instagram-icon.tsx
🔇 Additional comments (2)
components/ui/github-icon.tsx (1)
51-52: Nice addition for opt-in hover behavior.Conditional hover wiring keeps the icon compatible with imperative animation control.
lib/examples.ts (1)
59-69: LGTM — registry entry is well-formed.Metadata and wiring match existing examples.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
This pull request adds a macOS-style dock component to demonstrate real-world usage of itshover animated icons in a familiar, desktop-inspired UI.
What’s included
Purpose
The goal of this example is to show how itshover icons can be used to build
polished, interaction-rich components inspired by real operating system UI patterns.
This dock component serves as a practical reference for integrating animated icons
into modern web interfaces while maintaining a clean, production-ready feel.
Screen Recording
dock-component.mov
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.