diff --git a/libs/core/src/Tabs.tsx b/libs/core/src/Tabs.tsx index 0360b18..23671c0 100644 --- a/libs/core/src/Tabs.tsx +++ b/libs/core/src/Tabs.tsx @@ -28,10 +28,20 @@ type TabsProps = { children: React.ReactNode; /** - * Sets a tab with the corresponding index as an active tab on component render. + * Sets a tab with the corresponding index as default selected tab on component render. */ defaultIndex?: number; + /** + * Sets a tab with the corresponding index as an active tab on component render. + */ + index?: number; + + /** + * Callback function that is called on all tab changes + */ + onTabChange?: (index: number) => void; + /** * Determines the placement of the icon. * Defaults to 'leading'. @@ -205,6 +215,8 @@ function Tabs({ fullWidth, children, defaultIndex, + index, + onTabChange, className, iconPlacement = "leading", scrollButtons = false, @@ -235,7 +247,7 @@ function Tabs({ ); }), - [childrenArray] + [childrenArray], ); const tabPanels = React.useMemo( @@ -245,12 +257,12 @@ function Tabs({ {child.props.children} )), - [childrenArray] + [childrenArray], ); return ( - + @@ -381,7 +393,7 @@ function CustomTab({ "flex justify-center items-center h-full", { [tokens.Tab.withIcon.leading]: icon !== null && iconPlacement === "leading" }, { [tokens.Tab.withIcon.trailing]: icon !== null && iconPlacement === "trailing" }, - { "flex-row-reverse text-end": iconPlacement === "trailing" } + { "flex-row-reverse text-end": iconPlacement === "trailing" }, ); const tabClassName = cx( @@ -398,14 +410,14 @@ function CustomTab({ tokens.Tab.base.master, tokens.Tab.base.borderBottomWidth, tokens.Tab.base.fontWeight, - tokens.Tab.base.fontSize + tokens.Tab.base.fontSize, ); const iconClassName = cx( { [tokens.Icon.base.leading]: iconPlacement === "leading" }, { [tokens.Icon.base.trailing]: iconPlacement === "trailing" }, { [tokens.Icon.active]: index === selectedIndex }, - { [tokens.Icon.inactive]: index !== selectedIndex } + { [tokens.Icon.inactive]: index !== selectedIndex }, ); const handleClick = () => { diff --git a/storybook/src/core/Tabs.mdx b/storybook/src/core/Tabs.mdx index 6e8dfc2..9bebe22 100644 --- a/storybook/src/core/Tabs.mdx +++ b/storybook/src/core/Tabs.mdx @@ -17,6 +17,8 @@ You can also define the icon placement to be before or after the label via `icon (see the [leading icons](#with-leading-icons) or [trailing icons](#with-trailing-icons) stories). Furthermore, the `defaultIndex` prop allows you to specify which tab is the default one on component render. +If you wish to have more control over your Tabs you can use `index` prop to set currently selected tab, +note that if you use `index` prop you also need to handle index changes so prop `onTabChange` must also be present ## Usage diff --git a/storybook/src/core/Tabs.stories.tsx b/storybook/src/core/Tabs.stories.tsx index 7b50dff..6ef628e 100644 --- a/storybook/src/core/Tabs.stories.tsx +++ b/storybook/src/core/Tabs.stories.tsx @@ -19,7 +19,7 @@ import * as React from "react"; import { withDesign } from "storybook-addon-designs"; -import { Tabs } from "@tiller-ds/core"; +import { Button, Tabs } from "@tiller-ds/core"; import { Icon } from "@tiller-ds/icons"; import { defaultThemeConfig } from "@tiller-ds/theme"; @@ -203,6 +203,20 @@ export const ScrollButtons = () => ( ); +export const WithIndex = () => { + const [index, setIndex] = React.useState(0); + + return ( +
+ + {billingTab} + {companyTab} + + +
+ ); +}; + const HideControls = { children: { control: { disable: true } }, iconPlacement: { control: { disable: true } },