glide-design-system
Version:
Glide design system is an open-source React component library. It offers numerous benefits that make them essential tools for design and development teams.
120 lines (113 loc) • 4.11 kB
JavaScript
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
/**
* tab component
* @param {*} indicatorStyle The style of the tab indicator.
* @param {*} activeIndex The index of the active tab. It represents the initially selected tab when the component is rendered.
* @param {*} children The content of the Tab component, which should be one or more TabItem components.
* @param {*} onTabChange A function to be called when the active tab is changed. It is typically used to handle tab change events and update the activeIndex accordingly.
* @param {*} iconPosition The position of the tab icon relative to the tab label. It can be set to "start" (before the label) or "end" (after the label).
* @param {*} disabled A boolean flag to disable all the tabs if set to true. When disabled,
* @param {string} className - custom class for styles
*/
export const Tab = ({
indicatorStyle = "simple",
activeIndex = 0,
children,
onTabChange,
iconPosition = "start",
disabled = false,
className,
style,
containerClass,
showIndicator = true,
}) => {
const [header, setHeader] = useState([]);
const [currentIndex, setCurrentIndex] = useState(
activeIndex ? activeIndex : 0
);
useEffect(() => {
//changing whether there is array of children or single children and convert to array
const tabsItems = children instanceof Array ? children : [children];
//for displaying the tab icon,labelor diabled we are mapping the tabItems
const tabs = tabsItems.map((el) => ({
label: el?.props?.label,
icon: el?.props?.icon,
disabled: el?.props?.disabled,
}));
if (activeIndex > tabs.length - 1 || activeIndex < 0)
throw new Error(`Invalid range for value ${activeIndex}`);
setHeader(tabs);
}, [children]);
const TabHandler = (i) => {
setCurrentIndex(i);
if (onTabChange) onTabChange(i);
};
return (
<div
className={`tabContainer ${containerClass ? containerClass : ""}`}
style={{
border: indicatorStyle === "simple" ? "1px solid #d7d7d7" : "none",
}}
>
{header?.map((el, i) => {
return (
<div
style={{
borderRight:
i !== header.length - 1 && indicatorStyle === "simple"
? "1px solid #d7d7d7"
: "none",
}}
>
<button
id={`tab-${i}`}
data-testid={`tab-${i}`}
key={i}
className={
i === currentIndex && indicatorStyle === "simple"
? `TabButton tabActiveEffects ${className ? className : ""}`
: `TabButton tabEffects ${className ? className : ""}`
}
style={{
color:
i === currentIndex && indicatorStyle === "simple"
? "white"
: indicatorStyle === "bottomLine"
? "#1b3764"
: "black",
borderTopLeftRadius: i === 0 ? "5px" : "0px",
borderTopRightRadius: i === header.length - 1 ? "5px" : "0px",
cursor: disabled ? "not-allowed" : "pointer",
opacity: disabled ? "0.2" : "1",
...style,
}}
onClick={() => {
if (!disabled) TabHandler(i);
}}
>
<div
className="tabItem"
style={{
flexDirection: iconPosition === "end" ? "row-reverse" : "",
}}
>
<div className="tabIcon">{el?.icon}</div>
<div>{el?.label}</div>
</div>
</button>
{i === currentIndex &&
indicatorStyle === "bottomLine" &&
showIndicator && <div className="tabIndicator"></div>}
</div>
);
})}
</div>
);
};
Tab.propTypes = {
indicatorStyle: PropTypes.string,
onTabChange: PropTypes.func,
iconPosition: PropTypes.string,
disabled: PropTypes.bool,
};