Shared: Components: Tabs: Added multiple mode for the component.

This commit is contained in:
Tatiana Lopaeva 2024-06-28 10:33:38 +03:00
parent d2d7d535d1
commit 24d7b695ab
3 changed files with 100 additions and 43 deletions

View File

@ -31,9 +31,14 @@ import { TabsTypes } from "./Tabs.enums";
export const StyledTabs = styled.div<{
stickyTop?: string;
multiple: boolean;
}>`
${(props) =>
props.multiple &&
css`
display: flex;
flex-direction: column;
`};
.sticky {
height: 33px;
@ -128,6 +133,7 @@ export const ScrollbarTabs = styled(Scrollbar)<{
export const TabList = styled.div<{
$type?: TabsTypes;
multiple: boolean;
}>`
display: flex;
align-items: center;
@ -136,6 +142,13 @@ export const TabList = styled.div<{
width: 100%;
height: 32px;
${(props) =>
props.multiple &&
css`
flex-wrap: wrap;
height: fit-content;
`};
gap: ${(props) => (props.$type === TabsTypes.Primary ? "20px" : "8px")};
border-bottom: ${(props) =>

View File

@ -39,26 +39,26 @@ import {
} from "./Tabs.styled";
import { TabsProps, TTabItem } from "./Tabs.types";
import { TabsTypes } from "./Tabs.enums";
import { OFFSET_RIGHT, OFFSET_LEFT, INDEX_NOT_FOUND } from "./Tabs.constants";
import { OFFSET_RIGHT, OFFSET_LEFT } from "./Tabs.constants";
const Tabs = (props: TabsProps) => {
const {
items,
selectedItemId,
selectedItems = [],
type = TabsTypes.Primary,
stickyTop,
onSelect,
multiple = false,
...rest
} = props;
let selectedItemIndex = items.findIndex((item) => item.id === selectedItemId);
if (selectedItemIndex === INDEX_NOT_FOUND) {
selectedItemIndex = 0;
}
const selectedItemIndex = !selectedItemId
? 0
: items.findIndex((item) => item.id === selectedItemId);
const [currentItem, setCurrentItem] = useState<TTabItem>(
items[selectedItemIndex],
);
const [currentItem, setCurrentItem] = useState(selectedItemIndex);
const [multipleItems, setMultipleItems] = useState(selectedItems);
const tabsRef = useRef<HTMLDivElement>(null);
const scrollRef = useRef<ScrollbarType>(null);
@ -67,8 +67,8 @@ const Tabs = (props: TabsProps) => {
const isViewLastTab = useViewTab(scrollRef, tabsRef, items.length - 1);
useEffect(() => {
setCurrentItem(items[selectedItemIndex]);
}, [selectedItemIndex, items]);
if (!multiple) setCurrentItem(selectedItemIndex);
}, [selectedItemIndex, items, multiple]);
const scrollToTab = (index: number): void => {
if (!scrollRef.current || !tabsRef.current) return;
@ -95,19 +95,42 @@ const Tabs = (props: TabsProps) => {
};
const setSelectedItem = (selectedTabItem: TTabItem, index: number): void => {
setCurrentItem(selectedTabItem);
scrollToTab(index);
onSelect?.(selectedTabItem);
if (multiple) {
const indexOperation = () => {
const newArray = [...multipleItems];
const deletionIndex = newArray.indexOf(index);
if (deletionIndex !== -1) {
newArray.splice(deletionIndex, 1);
return newArray;
}
newArray.push(index);
return newArray;
};
return (
<StyledTabs {...rest} stickyTop={stickyTop}>
<div className="sticky">
{!isViewFirstTab && <div className="blur-ahead" />}
<ScrollbarTabs ref={scrollRef} autoHide={false} noScrollY $type={type}>
<TabList ref={tabsRef} $type={type}>
const updatedActiveTab = indexOperation();
setMultipleItems(updatedActiveTab);
onSelect?.(selectedTabItem);
return;
}
setCurrentItem(index);
onSelect?.(selectedTabItem);
scrollToTab(index);
};
const renderContent = (
<TabList ref={tabsRef} $type={type} multiple={multiple}>
{items.map((item, index) => {
const isActive = item.id === currentItem.id;
const isActive = multiple
? multipleItems.indexOf(index) !== -1
: index === currentItem;
return (
<Tab
key={item.id}
@ -125,13 +148,31 @@ const Tabs = (props: TabsProps) => {
);
})}
</TabList>
);
return (
<StyledTabs {...rest} stickyTop={stickyTop} multiple={multiple}>
{multiple && renderContent}
{!multiple && (
<div className="sticky">
{!isViewFirstTab && <div className="blur-ahead" />}
<ScrollbarTabs
ref={scrollRef}
autoHide={false}
noScrollY
$type={type}
>
{renderContent}
</ScrollbarTabs>
{!isViewLastTab && <div className="blur-back" />}
</div>
)}
<div className="sticky-indent" />
<div className="tabs-body">{currentItem?.content}</div>
{!multiple && (
<div className="tabs-body">{items[currentItem]?.content}</div>
)}
</StyledTabs>
);
};

View File

@ -44,10 +44,13 @@ export interface TabsProps {
items: TTabItem[];
/** Selected item of tabs. */
selectedItemId?: number | string;
selectedItems?: number[];
/** Theme for displaying tabs. */
type?: TabsTypes;
/** Tab indentation for sticky positioning. */
stickyTop?: string;
/** Enables multiple select */
multiple?: boolean;
/** Sets a callback function that is triggered when the tab is selected. */
onSelect?: (element: TTabItem) => void;
}