Design
Tabs
Line Tab

Line Tab

Implement a Line tab component using Next.js, Tailwind CSS, and Framer Motion.

Preview

Installation

Install dependencies

pnpm add clsx tailwind-merge framer-motion

Add util file

utils/cn.ts
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
 
export function cn(...inputs: ClassValue[]): string {
  return twMerge(clsx(inputs));
}

Copy the source code

components/ui/lineTab.tsx
"use client";
import { motion } from "framer-motion";
import React, { useState } from "react";
import { cn } from "@/util/cn";
 
interface TabProps {
  text: string;
  selected: boolean;
  setSelected: React.Dispatch<React.SetStateAction<string>>;
  customID: string;
}
 
function Tab({
  text,
  selected,
  setSelected,
  customID,
}: TabProps): React.JSX.Element {
  return (
    <button
      type="button"
      onClick={() => {
        setSelected(text);
      }}
      className={`${
        selected ? "text-blue-500" : "hover:text-gray-600"
      } relative rounded-md px-2 py-1 text-sm font-medium text-gray-500 transition-colors duration-300`}
    >
      <span className="relative z-10">{text}</span>
      {selected ? (
        <motion.div
          className="absolute left-0 top-0 flex size-full items-end justify-center"
          layoutId={`${customID}linetab`}
          transition={{ type: "spring", duration: 0.4, bounce: 0, delay: 0.1 }}
        >
          <span className="z-0 h-[3px] w-[60%] rounded-t-full bg-blue-500" />
        </motion.div>
      ) : null}
    </button>
  );
}
 
interface LineTabsProps {
  customID: string;
  tabs: string[];
}
 
function LineTab({ customID, tabs }: LineTabsProps): React.JSX.Element {
  const [selected, setSelected] = useState(tabs[0]);
  return (
    <div
      className={cn(
        "border-black-500/25 mb-8 flex flex-wrap items-center gap-2",
      )}
    >
      {tabs.map((tab) => (
        <Tab
          text={tab}
          selected={selected === tab}
          setSelected={setSelected}
          key={tab}
          customID={customID}
        />
      ))}
    </div>
  );
}
 
export default LineTab;

Use the component

import { LineTab } from "@/components/ui/lineTab";
 
function LineTabDemo(): React.JSX.Element {
	const tabs = ["Home", "Docs", "Components", "Hooks"];
	return (
		<div className="w-[300px]">
			<LineTab tabs={tabs} customID="linetab" />
		</div>
	);
	
}
 
export default LineTabDemo;
 

File Structure of the project

        • lineTab.tsx
      • cn.ts