Skip to content

Instantly share code, notes, and snippets.

@ditorodev
Last active April 14, 2025 06:48
import { AnimatePresence, motion } from "motion/react";
import { useRef, useState } from "react";
type TabValue = "free" | "monthly" | "yearly";
export default function App() {
const [value, setValue] = useState<TabValue>("free");
const code = `
// Wrap the Tab component in a div to control its dimensions
<div className="w-[500px] h-14">
<Tab
value={value}
onChange={setValue}
theme={{
selectedBgColor: "black",
unselectedColor: "var(--color-gray-200)", // supports css variables
nestedSelectedBgColor: "#FFF",
nestedSelectedColor: "rgb(0, 0, 0)",
nestedColor: "hsl(0, 0%, 100%)"
}}
/>
</div>`
return (
<div className="bg-gray-100 h-screen w-screen flex flex-col gap-4 items-center justify-center">
<p className="text-xs text-gray-500 font-mono my-10">
[
<a href="https://x.com/KumailNanji/status/1904512842684145854" className="text-blue-500 underline">
design
</a>
]
by: <a href="https://x.com/KumailNanji" className="text-blue-500 underline">@KumailNanji</a>
<br />
<b>code by</b> <a href="https://x.com/ditorodev" className="text-blue-500 underline">@ditorodev</a>
<br />
<i>Copy the code and paste it into your project [<a href="https://gist.github.com/ditorodev/275f90b4e170eaa8f7d572b1268c06cd" className="text-blue-500 underline">here</a>]</i>
</p>
<div className="w-[500px] h-14">
<Tab value={value} onChange={setValue} />
</div>
<div>
<p className="text-xs text-gray-500 font-mono my-10">themed</p>
<div className="w-[500px] h-14">
<Tab value={value} onChange={setValue} theme={{
selectedBgColor: "var(--color-blue-600)",
selectedColor: "var(--color-blue-50)",
unselectedColor: "var(--color-gray-500)",
nestedSelectedBgColor: "var(--color-blue-800)",
nestedSelectedColor: "var(--color-blue-50)",
nestedColor: "var(--color-blue-800)",
baseBgColor: "var(--color-gray-900)",
borderColor: "var(--color-gray-700)",
}} />
</div>
</div>
<div className="flex flex-row gap-4">
<div className="font-mono text-sm text-gray-600 bg-gray-200 p-1 rounded-lg my-10 w-[300px] h-fit">
<p className="text-xs text-gray-500 font-mono p-1">state</p>
<pre className="bg-gray-100 p-4 rounded-md">
{JSON.stringify({
value,
}, null, 2)}
</pre>
</div>
<div className="font-mono text-sm text-gray-600 bg-gray-200 p-1 rounded-lg my-10 min-w-[300px]">
<p className="text-xs text-gray-500 font-mono p-1">usage</p>
<pre className="bg-gray-100 p-4 rounded-md">
{code}
</pre>
</div>
</div>
</div>
);
}
const DEFAULT_THEME = {
selectedBgColor: "black",
unselectedColor: "var(--color-gray-200)",
nestedSelectedBgColor: "white",
nestedSelectedColor: "black",
nestedColor: "white",
selectedColor: "white",
baseBgColor: "var(--color-gray-50)",
borderColor: "var(--color-gray-200)",
};
const Tab = (props: {
value: TabValue;
onChange: (value: TabValue) => void;
theme?: {
selectedBgColor: string;
unselectedColor: string;
nestedSelectedBgColor: string;
nestedSelectedColor: string;
nestedColor: string;
selectedColor: string;
baseBgColor: string;
borderColor: string;
};
}) => {
const { value, onChange, theme = DEFAULT_THEME } = props;
const selectedTab = value === "free" ? "free" : "premium";
const refMonthly = useRef<HTMLDivElement>(null);
const refYearly = useRef<HTMLDivElement>(null);
return (
<div
className="relative flex flex-row justify-between w-full rounded-full h-full bg-[var(--base-bg-color)] shadow-lg border border-[var(--border-color)]"
style={{
"--base-bg-color": theme.baseBgColor,
"--selected-bg-color": theme.selectedBgColor,
"--unselected-color": theme.unselectedColor,
"--nested-selected-bg-color": theme.nestedSelectedBgColor,
"--nested-selected-color": theme.nestedSelectedColor,
"--nested-color": theme.nestedColor,
"--selected-color": theme.selectedColor,
"--border-color": theme.borderColor,
} as React.CSSProperties}
>
<motion.div
className="w-1/2 bg-[var(--selected-bg-color)] absolute top-[2px] bottom-[2px] rounded-full"
initial={false}
animate={{
right: selectedTab === "free" ? "auto" : 2,
left: selectedTab === "free" ? 2 : "auto",
}}
style={{
zIndex: selectedTab === "free" ? 3 : 1,
}}
/>
<div
className="transition-colors relative text-lg w-1/2 text-[var(--unselected-color)] data-[selected]:text-white text-center leading-10 h-full flex items-center justify-center cursor-pointer"
data-selected={selectedTab === "free" ? true : undefined}
onClick={() => onChange("free")}
style={{
zIndex: 3,
}}
>
Free
</div>
<div
className="relative p-[.5px] w-1/2 overflow-clip flex flex-col data-[selected]:text-[var(--selected-color)] items-center justify-center"
data-selected={selectedTab === "premium" ? true : undefined}
>
<AnimatePresence>
<>
<motion.div
style={{
color: selectedTab === "premium" ? "var(--selected-color)" : undefined,
display: selectedTab === "premium" ? "none" : "flex",
zIndex: 2,
}}
animate={{ opacity: 1, y: selectedTab === "premium" ? 20 : 0, scale: 1, filter: "blur(0px)" }}
exit={{ opacity: 0, scale: 0, filter: "blur(4px)" }}
transition={{ duration: 0.15 }}
className="flex flex-col items-center cursor-pointer w-full text-[var(--unselected-color)]"
onClick={() => onChange("monthly")}
>
Premium
<motion.div
className="relative flex flex-row items-center justify-center text-xs"
>
<div className="relative w-fit text-[var(--parent-color)] data-[selected]:text-[var(--parent-selected-color)]" data-selected>
Monthly
</div>
<div className="size-[2px] bg-current rounded-full mx-2" />
<div className="relative w-fit text-[var(--parent-color)] data-[selected]:text-[var(--parent-selected-color)]">Yearly</div>
</motion.div>
</motion.div>
{selectedTab === "premium" && (
<motion.div
className="relative w-full h-[calc(100%-8px)]"
initial={{ opacity: 0, scale: 0 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.3 }}
style={{
zIndex: 1,
pointerEvents: selectedTab === "premium" ? "auto" : "none",
}}
>
<motion.div
id="tab-indicator"
className="bg-[var(--nested-selected-bg-color)] absolute left-0 w-1/2 h-full top-0 bottom-0 rounded-full"
animate={value === "yearly" ? {
left: refYearly.current?.offsetLeft,
width: refYearly.current?.offsetWidth,
} : undefined}
/>
<div className="relative p-1 text-center text-[var(--nested-selected-color)] w-full h-full min-w-0 flex flex-row items-center justify-between text-base">
<div
className="transition-colors w-full text-[var(--nested-color)] data-[selected]:text-[var(--nested-selected-color)] cursor-pointer"
data-selected={value === "monthly" ? true : undefined}
onClick={() => onChange("monthly")}
ref={refMonthly}
>
Monthly
</div>
<div
className="transition-colors w-full text-[var(--nested-color)] data-[selected]:text-[var(--nested-selected-color)] cursor-pointer"
data-selected={value === "yearly" ? true : undefined}
onClick={() => onChange("yearly")}
ref={refYearly}
>
Yearly
</div>
</div>
</motion.div>
)}
</>
</AnimatePresence>
</div>
</div>
);
};
import { AnimatePresence, motion } from "motion/react";
import { useRef, useState } from "react";
type TabValue = "free" | "monthly" | "yearly";
const DEFAULT_THEME = {
selectedBgColor: "black",
unselectedColor: "var(--color-gray-200)",
nestedSelectedBgColor: "white",
nestedSelectedColor: "black",
nestedColor: "white",
selectedColor: "white",
baseBgColor: "var(--color-gray-50)",
borderColor: "var(--color-gray-200)",
};
const Tab = (props: {
value: TabValue;
onChange: (value: TabValue) => void;
theme?: {
selectedBgColor: string;
unselectedColor: string;
nestedSelectedBgColor: string;
nestedSelectedColor: string;
nestedColor: string;
selectedColor: string;
baseBgColor: string;
borderColor: string;
};
}) => {
const { value, onChange, theme = DEFAULT_THEME } = props;
const selectedTab = value === "free" ? "free" : "premium";
const refMonthly = useRef<HTMLDivElement>(null);
const refYearly = useRef<HTMLDivElement>(null);
return (
<div
className="relative flex flex-row justify-between w-full rounded-full h-full bg-[var(--base-bg-color)] shadow-lg border border-[var(--border-color)]"
style={{
"--base-bg-color": theme.baseBgColor,
"--selected-bg-color": theme.selectedBgColor,
"--unselected-color": theme.unselectedColor,
"--nested-selected-bg-color": theme.nestedSelectedBgColor,
"--nested-selected-color": theme.nestedSelectedColor,
"--nested-color": theme.nestedColor,
"--selected-color": theme.selectedColor,
"--border-color": theme.borderColor,
} as React.CSSProperties}
>
<motion.div
className="w-1/2 bg-[var(--selected-bg-color)] absolute top-[2px] bottom-[2px] rounded-full"
initial={false}
animate={{
right: selectedTab === "free" ? "auto" : 2,
left: selectedTab === "free" ? 2 : "auto",
}}
style={{
zIndex: selectedTab === "free" ? 3 : 1,
}}
/>
<div
className="transition-colors relative text-lg w-1/2 text-[var(--unselected-color)] data-[selected]:text-white text-center leading-10 h-full flex items-center justify-center cursor-pointer"
data-selected={selectedTab === "free" ? true : undefined}
onClick={() => onChange("free")}
style={{
zIndex: 3,
}}
>
Free
</div>
<div
className="relative p-[.5px] w-1/2 overflow-clip flex flex-col data-[selected]:text-[var(--selected-color)] items-center justify-center"
data-selected={selectedTab === "premium" ? true : undefined}
>
<AnimatePresence>
<>
<motion.div
style={{
color: selectedTab === "premium" ? "var(--selected-color)" : undefined,
display: selectedTab === "premium" ? "none" : "flex",
zIndex: 2,
}}
animate={{ opacity: 1, y: selectedTab === "premium" ? 20 : 0, scale: 1, filter: "blur(0px)" }}
exit={{ opacity: 0, scale: 0, filter: "blur(4px)" }}
transition={{ duration: 0.15 }}
className="flex flex-col items-center cursor-pointer w-full text-[var(--unselected-color)]"
onClick={() => onChange("monthly")}
>
Premium
<motion.div
className="relative flex flex-row items-center justify-center text-xs"
>
<div className="relative w-fit text-[var(--parent-color)] data-[selected]:text-[var(--parent-selected-color)]" data-selected>
Monthly
</div>
<div className="size-[2px] bg-current rounded-full mx-2" />
<div className="relative w-fit text-[var(--parent-color)] data-[selected]:text-[var(--parent-selected-color)]">Yearly</div>
</motion.div>
</motion.div>
{selectedTab === "premium" && (
<motion.div
className="relative w-full h-[calc(100%-8px)]"
initial={{ opacity: 0, scale: 0 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.3 }}
style={{
zIndex: 1,
pointerEvents: selectedTab === "premium" ? "auto" : "none",
}}
>
<motion.div
id="tab-indicator"
className="bg-[var(--nested-selected-bg-color)] absolute left-0 w-1/2 h-full top-0 bottom-0 rounded-full"
animate={value === "yearly" ? {
left: refYearly.current?.offsetLeft,
width: refYearly.current?.offsetWidth,
} : undefined}
/>
<div className="relative p-1 text-center text-[var(--nested-selected-color)] w-full h-full min-w-0 flex flex-row items-center justify-between text-base">
<div
className="transition-colors w-full text-[var(--nested-color)] data-[selected]:text-[var(--nested-selected-color)] cursor-pointer"
data-selected={value === "monthly" ? true : undefined}
onClick={() => onChange("monthly")}
ref={refMonthly}
>
Monthly
</div>
<div
className="transition-colors w-full text-[var(--nested-color)] data-[selected]:text-[var(--nested-selected-color)] cursor-pointer"
data-selected={value === "yearly" ? true : undefined}
onClick={() => onChange("yearly")}
ref={refYearly}
>
Yearly
</div>
</div>
</motion.div>
)}
</>
</AnimatePresence>
</div>
</div>
);
};
@ditorodev
Copy link
Author

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