Skip to content

feat:Add macOS-style dock component with animated social icons#87

Merged
Abhijit-Jha merged 3 commits intoitshover:masterfrom
rejioco:dock-component
Jan 18, 2026
Merged

feat:Add macOS-style dock component with animated social icons#87
Abhijit-Jha merged 3 commits intoitshover:masterfrom
rejioco:dock-component

Conversation

@rejioco
Copy link
Copy Markdown
Contributor

@rejioco rejioco commented Jan 16, 2026

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

  • A horizontal dock layout inspired by the macOS Dock
  • Social and utility icons mapped to common actions and platforms
  • Smooth hover-triggered animations using itshover icons, mimicking native dock behavior
  • Scalable and centered positioning suitable for dashboards, landing pages, or portfolios

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

  • New Features
    • Added an animated social media dock with configurable icons (Twitter/X, WhatsApp, GitHub, Facebook, LinkedIn, Instagram), elastic hover layout, and tooltips.
    • Added individual animated icon components for Facebook, GitHub, Instagram, LinkedIn, and WhatsApp with optional hover-animation control.
    • Example showcasing the dock has been added to the examples list.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Jan 16, 2026

@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.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 16, 2026

Note

Other AI code review bot(s) detected

CodeRabbit 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.

📝 Walkthrough

Walkthrough

Adds 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 disableHover prop to the existing GitHub icon. Dock is registered in the examples registry.

Changes

Cohort / File(s) Summary
Dock component & example registration
components/examples/dock.tsx, lib/examples.ts
Adds Dock default export implementing a horizontal social icon dock composed of DockItems with hover-driven elastic layout, icon animation control via refs, and tooltips; registers Dock in EXAMPLE_REGISTRY.
New animated icon components
components/ui/facebook-icon.tsx, components/ui/instagram-icon.tsx, components/ui/linkedin-icon.tsx, components/ui/whatsapp-icon.tsx
Adds four forwardRef SVG icon components exposing imperative handles (startAnimation, stopAnimation) using useAnimate/motion; support props (size, color, strokeWidth, className, disableHover) and optional hover-triggered animations.
Existing icon modification
components/ui/github-icon.tsx
Adds disableHover: boolean prop (default false) and conditions hover handlers on it so hover-driven animations can be disabled.

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰
I hopped to craft a playful dock,
Icons dance and tooltips knock,
Thumps and likes and links that glow,
I twirl the code and watch them show,
Hop—animations on the clock! 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: introducing a macOS-style dock component with animated social icons, which directly matches the changeset's primary deliverable.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

🧹 Recent nitpick comments
components/ui/instagram-icon.tsx (1)

50-83: LGTM! Consider aligning wrapper structure with sibling icons.

The component works correctly. Note that this icon uses motion.div as the outer wrapper with a regular <svg> inside, while FacebookIcon and LinkedinIcon use motion.svg directly. Both approaches function correctly with useAnimate's scope, but aligning the structure would improve consistency across the icon library.


📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 184a122 and 52c2856.

📒 Files selected for processing (5)
  • components/examples/dock.tsx
  • components/ui/facebook-icon.tsx
  • components/ui/instagram-icon.tsx
  • components/ui/linkedin-icon.tsx
  • components/ui/whatsapp-icon.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • components/ui/whatsapp-icon.tsx
  • components/examples/dock.tsx
🔇 Additional comments (2)
components/ui/facebook-icon.tsx (1)

1-90: LGTM!

The component is well-structured with proper use of forwardRef, useImperativeHandle, and useAnimate. The animation sequencing (awaiting the path animation before triggering the emoji) creates a nice staggered effect, and the disableHover prop correctly disables hover handlers when needed.

components/ui/linkedin-icon.tsx (1)

1-93: LGTM!

The component is well-implemented with proper animation logic. The "use client" directive is correctly present, the pathLength animations have appropriate initial values, and the border path correctly sets transformOrigin: "center" for the scale animation.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Jan 16, 2026

Greptile Summary

Added 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:

  • Created new dock component (components/examples/dock.tsx) with animated hover effects
  • Added 5 new social icon components with unique animations (Facebook, Instagram, LinkedIn, WhatsApp, and modified GitHub icon)
  • Updated GitHub icon to support disableHover prop for programmatic animation control
  • Registered dock example in examples registry
  • Updated package name from animated-icons to itshover

Issues found:

  • Incorrect href on line 16 of dock.tsx ("$" instead of "#")
  • Swapped URLs on lines 20-21 (LinkedIn → Instagram URL, Instagram → Facebook URL)
  • Debug console.log statements left in production code
  • Unused helper functions in GitHub icon component

Confidence Score: 3/5

  • This PR has functional bugs that need fixing before merge
  • Score reflects critical logic errors (swapped URLs, typo in href) that would result in incorrect navigation behavior, along with minor code quality issues (debug logs, dead code). The animation and icon implementations are solid, but the navigation bugs must be resolved.
  • Pay close attention to components/examples/dock.tsx - contains typo and incorrect URL mappings that will break navigation

Important Files Changed

Filename Overview
components/examples/dock.tsx New macOS-style dock component with typo in href, swapped URLs, and debug console.logs
components/ui/github-icon.tsx Added disableHover prop support, but left unused helper functions in the code

Sequence Diagram

sequenceDiagram
    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
Loading

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Additional Comments (1)

  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

Edit Code Review Agent Settings | Greptile

Comment thread components/examples/dock.tsx Outdated


const dockItems = [
{ icon: TwitterXIcon, label: "Twitter/X", href: "$" },
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.

syntax: Typo in href - should be "#" not "$"

Suggested change
{ 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.

Comment thread components/examples/dock.tsx Outdated
Comment on lines +20 to +21
{ icon: LinkedinIcon, label: "LinkedIn", href: "https://instagram.com" },
{ icon: InstagramIcon, label: "Instagram", href: "https://facebook.com" },
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.

logic: The hrefs are incorrect - LinkedIn points to Instagram and Instagram points to Facebook

Suggested change
{ 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.

Comment thread components/examples/dock.tsx Outdated
Comment on lines +41 to +50
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();
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.

style: Remove debug console.log statements

Suggested change
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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

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.

handleHoverStart and handleHoverEnd are defined but never used. Lines 45-46 directly reference start and stop instead. Remove these dead functions to clean up the code.

🧹 Proposed fix
-    const handleHoverStart = () => {
-      start();
-    };
-
-    const handleHoverEnd = () => {
-      stop();
-    };
-
     return (

13-27: Consider wrapping start and stop in useCallback for 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 isHovered state tracks hover for the individual DockItem, not the entire dock. The dock-level hover state is in the Dock component (line 99).

🧹 Proposed fix
-    const [isHovered, setIsHovered] = useState(false);  // for entire dock
+    const [isHovered, setIsHovered] = useState(false);

62-66: Consider adding aria-label for accessibility.

The anchor elements link to external sites but rely solely on visual icons. Adding an aria-label would 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 pathLength and scale to both .lines and .border elements. While Framer Motion ignores non-applicable properties, separating the targets would be more explicit and align with the start function'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

📥 Commits

Reviewing files that changed from the base of the PR and between fe0766e and 63729d8.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (7)
  • components/examples/dock.tsx
  • components/ui/facebook-icon.tsx
  • components/ui/github-icon.tsx
  • components/ui/instagram-icon.tsx
  • components/ui/linkedin-icon.tsx
  • components/ui/whatsapp-icon.tsx
  • lib/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, and useCallback. 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: true setting is appropriate for a dock component.

Note: The CI pipeline flagged a Prettier formatting issue. Please run prettier --write on 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 disableHover prop
  • transformOrigin: "center" on the border for correct scale animation

Note: CI flagged Prettier formatting issues. Run prettier --write on this file.


1-3: Imports are valid for the project's Framer Motion version.

The motion/react import path is correctly supported by the project's motion package (v12.23.26).

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread components/examples/dock.tsx
Comment thread components/examples/dock.tsx Outdated
@rejioco rejioco changed the title Add macOS-style dock component with animated social icons feat:Add macOS-style dock component with animated social icons Jan 16, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between 63729d8 and 184a122.

📒 Files selected for processing (7)
  • components/examples/dock.tsx
  • components/ui/facebook-icon.tsx
  • components/ui/github-icon.tsx
  • components/ui/instagram-icon.tsx
  • components/ui/linkedin-icon.tsx
  • components/ui/whatsapp-icon.tsx
  • lib/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.

Comment thread components/examples/dock.tsx
Comment thread components/ui/linkedin-icon.tsx
Comment thread components/ui/whatsapp-icon.tsx
@Abhijit-Jha Abhijit-Jha merged commit 07e5516 into itshover:master Jan 18, 2026
2 of 3 checks passed
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.

2 participants