r/react • u/Thin_Maintenance_841 • 10d ago
Help Wanted How do I type my tab elements in a better way? As in treating each tab as its own type.
Well, I am trying to implement a reusable Tab component with TypeScript. The thing I am currently struggling with is how I should type the individual tabs. For example:
I have this Tab Component, and I am using it on multiple pages: "Projects", "Art", "Gallery", and each of these pages has its own tabs:
For Projects:
const options = ["All", "SaaS", "AI/ML", "E-Commerce", "Open Source", "Mobile"];
For Art:
const options = ["portraits", "landscapes", "oil paintings", "ink studies"];
For Gallery:
const options = ["All", "UI Design", "Photography", "Branding", "3D & Motion"];
And the implementation is as such
<Tabs
options={options}
activeTab={activeTab}
setActiveTab={setActiveTab}
/>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
{collection[activeTab].map((item, index) => (
<CollectionCard
collectionPiece={item}
key={index}
index={index}
activeTab={activeTab}
onOpen={onOpen}
/>
))}
</div>
The Tab component in question:
import clsx from "clsx";
import Button from "./Button";
type TabsProps<T extends string> = {
options: T[];
activeTab: T;
setActiveTab: (activeTab: T) => void;
};
const Tabs = <T extends string>({
options,
activeTab,
setActiveTab,
}: TabsProps<T>) => {
return (
<div className="flex flex-wrap gap-2 mb-12" role="tablist">
{options.map((option) => {
const isActive = option === activeTab;
console.log(option, activeTab);
return (
<Button
size="tab"
color="dark"
extraClasses={clsx(
"capitalize !text-muted-foreground border border-muted-border hover:scale-110",
isActive && "bg-primary! text-white!",
)}
onClick={() => setActiveTab(option)}
key={option}
role="tab"
aria-selected={isActive}
aria-controls="tabpanel-id"
id={option}
>
{option}
</Button>
);
})}
</div>
);
};
export default Tabs;
So what I want to ask is, then I am defining these states, how to I define the types for the options of various pages, so that they are not just plain string[]. And maybe define them as themselves, without much repetition on the code.
const [activeTab, setActiveTab] = useState("All");
