Skip to content

Commit

Permalink
feat: add fluid tabs component (#351)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rudra-Sankha-Sinhamahapatra authored Oct 15, 2024
1 parent a1d8297 commit 46ce9d9
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 0 deletions.
19 changes: 19 additions & 0 deletions animata/card/fluid-tabs.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import FluidTabs from "@/animata/card/fluid-tabs";
import { Meta, StoryObj } from "@storybook/react";

const meta = {
title: "Tabs/Fluid Tabs",
component: FluidTabs,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
argTypes: {},
} satisfies Meta<typeof FluidTabs>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Primary: Story = {
args: {},
};
82 changes: 82 additions & 0 deletions animata/card/fluid-tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"use client";

import { useEffect, useRef, useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { Inbox, Landmark, PieChart } from "lucide-react";

const tabs = [
{
id: "accounts",
label: "Accounts",
icon: <Landmark size={18} />,
},
{
id: "deposits",
label: "Deposits",
icon: <Inbox size={18} />,
},
{
id: "funds",
label: "Funds",
icon: <PieChart size={18} />,
},
];

export default function FluidTabs() {
const [activeTab, setActiveTab] = useState("funds");
const [touchedTab, setTouchedTab] = useState<string | null>(null);
const [prevActiveTab, setPrevActiveTab] = useState("funds");
const timeoutRef = useRef<NodeJS.Timeout | null>(null);

useEffect(() => {
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
};
}, []);

const handleTabClick = (tabId: string) => {
setPrevActiveTab(activeTab);
setActiveTab(tabId);
setTouchedTab(tabId);

if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
timeoutRef.current = setTimeout(() => {
setTouchedTab(null);
}, 300);
};

const getTabIndex = (tabId: string) => tabs.findIndex((tab) => tab.id === tabId);

return (
<div className="flex items-center justify-center py-4">
<div className="relative flex w-full max-w-md space-x-2 overflow-hidden rounded-full bg-[#f5f1eb] p-1 shadow-lg">
<AnimatePresence initial={false}>
<motion.div
key={activeTab}
className="absolute inset-y-0 my-1 rounded-full bg-white"
initial={{ x: `${getTabIndex(prevActiveTab) * 100}%` }}
animate={{ x: `${getTabIndex(activeTab) * 100}%` }}
transition={{ type: "spring", stiffness: 300, damping: 30 }}
style={{ width: `${100 / tabs.length}%` }}
/>
</AnimatePresence>
{tabs.map((tab) => (
<motion.button
key={tab.id}
className={`relative z-10 flex w-full items-center justify-center gap-1.5 px-5 py-3 text-sm font-bold transition-colors duration-300 ${
activeTab === tab.id ? "font-bold text-black" : "text-gray-500"
} ${touchedTab === tab.id ? "blur-sm" : ""}`}
onClick={() => handleTabClick(tab.id)}
>
{tab.icon}
{tab.label}
</motion.button>
))}
</div>
</div>
);
}
52 changes: 52 additions & 0 deletions content/docs/card/fluid-tabs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
title: Fluid Tabs
description: The component is a sliding animation card
author: RudraSankha
---

<ComponentPreview name="tabs-fluid-tabs--primary" />

## Installation

<Steps>
<Step>Install dependencies</Step>

```bash
npm install framer-motion lucide-react
```

<Step>Update `tailwind.config.js`</Step>

Add the following to your tailwind.config.js file.

```json
module.exports = {
theme: {
extend: {
}
}
}
```

<Step>Run the following command</Step>

It will create a new file `fluid-tabs.tsx` inside the `components/animata/card` directory.

```bash
mkdir -p components/animata/card && touch components/animata/card/fluid-tabs.tsx
```

<Step>Paste the code</Step>{" "}

Open the newly created file and paste the following code:

```jsx file=<rootDir>/animata/card/fluid-tabs.tsx

```

</Steps>

## Credits

Built by [Rudra Sankha Sinhamahapatra](https://github.com/Rudra-Sankha-Sinhamahapatra)
Twitter Handle [Rudra Sankha](https://x.com/RudraSankha)

0 comments on commit 46ce9d9

Please sign in to comment.