Tabs
Benefits of City Life:
- Access to better job opportunities and higher salaries.
- More diverse options for dining, shopping, and entertainment.
- Greater access to healthcare and educational institutions.
- Enhanced public transportation and infrastructure.
<Tabs defaultActiveKey={"x"}>
<TabList className={'bg-gray-900 rounded-lg p-1 grid grid-cols-2 '}>
<TabTrigger tabKey={"x"}>City</TabTrigger>
<TabTrigger tabKey={"y"}>Village</TabTrigger>
</TabList>
<TabContent tabKey={"x"} className='bg-gray-900 rounded-lg p-4'>
<p className="text-gray-200 text-lg">
<strong>Benefits of City Life:</strong>
</p>
<ul className="list-disc pl-5 mt-2 text-gray-400">
<li>Access to better job opportunities and higher salaries.</li>
<li>More diverse options for dining, shopping, and entertainment.</li>
<li>Greater access to healthcare and educational institutions.</li>
<li>Enhanced public transportation and infrastructure.</li>
</ul>
</TabContent>
<TabContent tabKey={"y"} className='bg-gray-900 rounded-lg p-4'>
<p className="text-gray-200 text-lg">
<strong>Benefits of Village Life:</strong>
</p>
<ul className="list-disc pl-5 mt-2 text-gray-400">
<li>Closer connection with nature and a cleaner environment.</li>
<li>Lower cost of living and affordable housing.</li>
<li>More space and a slower, peaceful lifestyle.</li>
<li>Stronger sense of community and local support.</li>
</ul>
</TabContent>
</Tabs>
// components/Tabs.js
"use client";
import React, { useState, createContext, useContext } from "react";
/**
* @typedef {Object} TabsContextValue
* @property {number} activeKey - The currently active tab's key.
* @property {function(number): void} handleTabClick - Function to handle tab clicks and update the active tab.
*/
/**
* @context TabsContext
* @description Context for managing tab state and behavior.
*/
const TabsContext = createContext();
/**
* Tabs component for creating a tabbed interface.
*
* @component
* @param {Object} props - Component props.
* @param {React.ReactNode} props.children - Child components representing tabs and their content.
* @param {number} [props.defaultActiveKey=0] - The key of the tab that should be active by default.
* @returns {JSX.Element} The rendered Tabs component.
*
* @example
* ```jsx
* <Tabs defaultActiveKey={1}>
* <TabList>
* <TabTrigger tabKey={0}>Tab 1</TabTrigger>
* <TabTrigger tabKey={1}>Tab 2</TabTrigger>
* </TabList>
* <TabContent tabKey={0}>Content for Tab 1</TabContent>
* <TabContent tabKey={1}>Content for Tab 2</TabContent>
* </Tabs>
* ```
*/
export default function Tabs({ children, defaultActiveKey = 0, className }) {
const [activeKey, setActiveKey] = useState(defaultActiveKey);
/**
* Handles tab clicks and updates the active tab.
*
* @param {number} key - The key of the clicked tab.
*/
const handleTabClick = (key) => {
setActiveKey(key);
};
return (
<TabsContext.Provider value={{ activeKey, handleTabClick }}>
<div className={`w-full mx-auto ${className}`}>{children}</div>
</TabsContext.Provider>
);
}
/**
* TabList component for grouping TabTrigger components.
*
* @component
* @param {Object} props - Component props.
* @param {React.ReactNode} props.children - Child TabTrigger components.
* @param {string} [props.className] - Additional CSS class names to apply to the TabList container.
* @returns {JSX.Element} The rendered TabList component.
*/
export function TabList({ children, className }) {
return <div className={` flex gap-1 mb-4 ${className}`}>{children}</div>;
}
/**
* TabTrigger component representing a single tab that can be clicked to activate its corresponding TabContent.
*
* @component
* @param {Object} props - Component props.
* @param {React.ReactNode} props.children - The content to display within the tab trigger.
* @param {number} props.tabKey - A unique key to identify the tab and associate it with its content.
* @param {string} [props.className] - Additional CSS class names to apply to the TabTrigger button.
* @returns {JSX.Element} The rendered TabTrigger component.
*
* @throws {Error} If the `tabKey` prop is not provided.
*/
export function TabTrigger({ children, tabKey, className }) {
if (tabKey === undefined) {
throw new Error("TabTrigger component requires a 'tabKey' prop.");
}
const { activeKey, handleTabClick } = useContext(TabsContext);
return (
<button
onClick={() => handleTabClick(tabKey)}
className={` rounded-lg transition-colors duration-200 bg-gray-900 border border-gray-900 hover:border-transparent px-3 py-1.5 text-base font-medium hover:bg-opacity-70 ${activeKey === tabKey ? "bg-gray-950 text-white" : "bg-gray-900 text-gray-400"} ${className}`}
>
{children}
</button>
);
}
/**
* TabContent component representing the content associated with a specific tab.
*
* @component
* @param {Object} props - Component props.
* @param {React.ReactNode} props.children - The content to display when the associated tab is active.
* @param {number} props.tabKey - A unique key to identify the tab content and associate it with its trigger.
* @param {string} [props.className] - Additional CSS class names to apply to the TabContent container.
* @returns {JSX.Element|null} The rendered TabContent component or null if the tab is not active.
*
* @throws {Error} If the `tabKey` prop is not provided.
*/
export function TabContent({ children, tabKey, className }) {
if (tabKey === undefined) {
throw new Error("TabContent component requires a 'tabKey' prop.");
}
const { activeKey } = useContext(TabsContext);
return (
activeKey === tabKey && (
<div className={`${className}`}>{children}</div>
)
);
}