diff --git a/libraries/core-react/src/Tabs/Tab.jsx b/libraries/core-react/src/Tabs/Tab.jsx
index c5b56ecf15..32ae194f84 100644
--- a/libraries/core-react/src/Tabs/Tab.jsx
+++ b/libraries/core-react/src/Tabs/Tab.jsx
@@ -78,9 +78,24 @@ const StyledTab = styled.button.attrs(({ active, disabled }) => ({
}
`
-export const Tab = forwardRef(function Tab(props, ref) {
- return
-})
+/**
+ * @typedef {object} Props
+ * @prop {boolean} [active] If `true`, the tab will be active.
+ * @prop {boolean} [disabled] If `true`, the tab will be disabled.
+ * @prop {string} [className]
+ * @prop {React.ReactNode} children
+ */
+
+export const Tab = forwardRef(
+ /**
+ * @param {Props} props
+ * @param {React.Ref} ref
+ * @returns {React.ReactElement}
+ */
+ function Tab(props, ref) {
+ return
+ },
+)
Tab.propTypes = {
/** If `true`, the tab will be active. */
diff --git a/libraries/core-react/src/Tabs/TabList.jsx b/libraries/core-react/src/Tabs/TabList.jsx
index 526ddf0966..92793981db 100644
--- a/libraries/core-react/src/Tabs/TabList.jsx
+++ b/libraries/core-react/src/Tabs/TabList.jsx
@@ -25,81 +25,98 @@ const StyledTabList = styled.div.attrs(() => ({
grid-auto-columns: ${({ variant }) => variants[variant]};
`
-const TabList = forwardRef(function TabsList({ children, ...props }, ref) {
- const { activeTab, handleChange, tabsId, variant } = useContext(TabsContext)
+/**
+ * @typedef {object} Props
+ * @prop {string} [className]
+ * @prop {import('./Tabs').TabsVariant} [variant] Sets the width of the tabs
+ * @prop {Tab | Tab[]} children
+ */
+
+const TabList = forwardRef(
+ /**
+ * @param {Props} props
+ * @param {React.Ref} ref
+ * @returns {React.ReactElement}
+ */
+ function TabsList({ children, ...rest }, ref) {
+ const { activeTab, handleChange, tabsId, variant } = useContext(TabsContext)
+
+ const currentTab = useRef(activeTab)
+
+ const [focusVisible, setFocusVisible] = useState(false)
+
+ const selectedTabRef = useCallback((node) => {
+ if (node !== null) {
+ node.focus()
+ }
+ }, [])
+
+ useEffect(() => {
+ currentTab.current = activeTab
+ }, [activeTab])
+
+ const Tabs = React.Children.map(children, (child, index) => {
+ const tabRef =
+ index === activeTab
+ // @ts-ignore
+ ? useCombinedRefs(child.ref, selectedTabRef)
+ // @ts-ignore
+ : child.ref
+
+ // @ts-ignore
+ return React.cloneElement(child, {
+ id: `${tabsId}-tab-${index + 1}`,
+ 'aria-controls': `${tabsId}-panel-${index + 1}`,
+ active: index === activeTab,
+ index,
+ onClick: () => handleChange(index),
+ ref: tabRef,
+ focusVisible,
+ })
+ })
- const currentTab = useRef(activeTab)
+ const focusableChildren = Tabs.filter((child) => !child.props.disabled).map(
+ (child) => child.props.index,
+ )
- const [focusVisible, setFocusVisible] = useState(false)
+ const firstFocusableChild = focusableChildren[0]
+ const lastFocusableChild = focusableChildren[focusableChildren.length - 1]
- const selectedTabRef = useCallback((node) => {
- if (node !== null) {
- node.focus()
+ const handleTabsChange = (direction, fallbackTab) => {
+ const i = direction === 'left' ? 1 : -1
+ const nextTab =
+ focusableChildren[focusableChildren.indexOf(currentTab.current) - i]
+ handleChange(nextTab === undefined ? fallbackTab : nextTab)
}
- }, [])
-
- useEffect(() => {
- currentTab.current = activeTab
- }, [activeTab])
-
- const Tabs = React.Children.map(children, (child, index) => {
- const tabRef =
- index === activeTab
- ? useCombinedRefs(child.ref, selectedTabRef)
- : child.ref
-
- return React.cloneElement(child, {
- id: `${tabsId}-tab-${index + 1}`,
- 'aria-controls': `${tabsId}-panel-${index + 1}`,
- active: index === activeTab,
- index,
- onClick: () => handleChange(index),
- ref: tabRef,
- focusVisible,
- })
- })
-
- const focusableChildren = Tabs.filter((child) => !child.props.disabled).map(
- (child) => child.props.index,
- )
-
- const firstFocusableChild = focusableChildren[0]
- const lastFocusableChild = focusableChildren[focusableChildren.length - 1]
-
- const handleTabsChange = (direction, fallbackTab) => {
- const i = direction === 'left' ? 1 : -1
- const nextTab =
- focusableChildren[focusableChildren.indexOf(currentTab.current) - i]
- handleChange(nextTab === undefined ? fallbackTab : nextTab)
- }
-
- const handleKeyPress = (event) => {
- const { key } = event
- setFocusVisible(true)
- if (key === 'ArrowLeft') {
- handleTabsChange('left', lastFocusableChild)
+
+ const handleKeyPress = (event) => {
+ const { key } = event
+ setFocusVisible(true)
+ if (key === 'ArrowLeft') {
+ handleTabsChange('left', lastFocusableChild)
+ }
+ if (key === 'ArrowRight') {
+ handleTabsChange('right', firstFocusableChild)
+ }
}
- if (key === 'ArrowRight') {
- handleTabsChange('right', firstFocusableChild)
+
+ const handleMouseDown = () => {
+ setFocusVisible(false)
}
- }
-
- const handleMouseDown = () => {
- setFocusVisible(false)
- }
-
- return (
-
- {Tabs}
-
- )
-})
+
+ return (
+
+ {Tabs}
+
+ )
+ },
+)
const tabType = PropTypes.shape({
type: PropTypes.oneOf([Tab]),
@@ -109,14 +126,17 @@ TabList.propTypes = {
/** @ignore */
className: PropTypes.string,
/** Sets the width of the tabs */
+ // @ts-ignore
variant: PropTypes.oneOf(['fullWidth', 'minWidth']),
/** @ignore */
+ // @ts-ignore
children: PropTypes.oneOfType([PropTypes.arrayOf(tabType), tabType])
.isRequired,
}
TabList.defaultProps = {
className: null,
+ // @ts-ignore
variant: 'minWidth',
}
diff --git a/libraries/core-react/src/Tabs/TabPanel.jsx b/libraries/core-react/src/Tabs/TabPanel.jsx
index d097f30601..ac382a4e89 100644
--- a/libraries/core-react/src/Tabs/TabPanel.jsx
+++ b/libraries/core-react/src/Tabs/TabPanel.jsx
@@ -15,13 +15,27 @@ const StyledTabPanel = styled.div.attrs(() => ({
paddingBottom,
})
-const TabPanel = forwardRef(function TabPanel({ ...props }, ref) {
- return (
-
- {props.children}
-
- )
-})
+/**
+ * @typedef {object} Props
+ * @prop {React.ReactNode} children
+ * @prop {string} [className]
+ * @prop {boolean} [hidden] If `true`, the panel will be hidden.
+ */
+
+const TabPanel = forwardRef(
+ /**
+ * @param {Props} props
+ * @param {React.Ref} ref
+ * @returns {React.ReactElement}
+ */
+ function TabPanel({ ...props }, ref) {
+ return (
+
+ {props.children}
+
+ )
+ },
+)
TabPanel.propTypes = {
/** @ignore */
diff --git a/libraries/core-react/src/Tabs/TabPanels.jsx b/libraries/core-react/src/Tabs/TabPanels.jsx
index d74a2cf695..8ceb69236f 100644
--- a/libraries/core-react/src/Tabs/TabPanels.jsx
+++ b/libraries/core-react/src/Tabs/TabPanels.jsx
@@ -3,22 +3,36 @@ import PropTypes from 'prop-types'
import { TabsContext } from './Tabs.context'
import { TabPanel } from './TabPanel'
-const TabPanels = forwardRef(function TabPanels({ children, ...props }, ref) {
- const { activeTab, tabsId } = useContext(TabsContext)
+/**
+ * @typedef {object} Props
+ * @prop {string} [className]
+ * @prop {TabPanel | TabPanel[]} children
+ */
- const Panels = React.Children.map(children, (child, index) =>
- React.cloneElement(child, {
- id: `${tabsId}-panel-${index + 1}`,
- 'aria-labelledby': `${tabsId}-tab-${index + 1}`,
- hidden: activeTab !== index,
- }),
- )
- return (
-
- {Panels}
-
- )
-})
+const TabPanels = forwardRef(
+ /**
+ * @param {Props} props
+ * @param {React.Ref} ref
+ * @returns {React.ReactElement}
+ */
+ function TabPanels({ children, ...rest }, ref) {
+ const { activeTab, tabsId } = useContext(TabsContext)
+
+ const Panels = React.Children.map(children, (child, index) =>
+ // @ts-ignore
+ React.cloneElement(child, {
+ id: `${tabsId}-panel-${index + 1}`,
+ 'aria-labelledby': `${tabsId}-tab-${index + 1}`,
+ hidden: activeTab !== index,
+ }),
+ )
+ return (
+
+ {Panels}
+
+ )
+ },
+)
const panelType = PropTypes.shape({
type: PropTypes.oneOf([TabPanel]),
@@ -28,6 +42,7 @@ TabPanels.propTypes = {
/** @ignore */
className: PropTypes.string,
/** @ignore */
+ // @ts-ignore
children: PropTypes.oneOfType([PropTypes.arrayOf(panelType), panelType])
.isRequired,
}
diff --git a/libraries/core-react/src/Tabs/Tabs.context.js b/libraries/core-react/src/Tabs/Tabs.context.js
index 8b61312c8a..6b4c739fb6 100644
--- a/libraries/core-react/src/Tabs/Tabs.context.js
+++ b/libraries/core-react/src/Tabs/Tabs.context.js
@@ -2,7 +2,8 @@ import React, { createContext } from 'react'
const TabsContext = createContext({
variant: '',
- handleChange: () => {},
+ /** @param {number} index */
+ handleChange: (index) => {},
activeTab: 0,
tabsId: '',
})
diff --git a/libraries/core-react/src/Tabs/Tabs.jsx b/libraries/core-react/src/Tabs/Tabs.jsx
index f8149f947c..6cfab0384f 100644
--- a/libraries/core-react/src/Tabs/Tabs.jsx
+++ b/libraries/core-react/src/Tabs/Tabs.jsx
@@ -3,25 +3,41 @@ import PropTypes from 'prop-types'
import createId from 'lodash.uniqueid'
import { TabsProvider } from './Tabs.context'
-const Tabs = forwardRef(function Tabs(
- { activeTab, onChange, variant, ...props },
- ref,
-) {
- const tabsId = useMemo(() => createId('tabs-'), [])
+/**
+ * @typedef {'fullWidth' | 'minWidth'} TabsVariant
+ */
- return (
-
-
-
- )
-})
+/**
+ * @typedef {object} Props
+ * @prop {number} [activeTab] The index of the active tab
+ * @prop {() => void} [onChange] The callback function for selecting a tab
+ * @prop {TabsVariant} [variant] Sets the width of the tabs
+ * @prop {React.ReactNode} children
+ */
+
+const Tabs = forwardRef(
+ /**
+ * @param {Props} props
+ * @param {React.Ref} ref
+ * @returns {React.ReactElement}
+ */
+ function Tabs({ activeTab, onChange, variant, ...rest }, ref) {
+ const tabsId = useMemo(() => createId('tabs-'), [])
+
+ return (
+
+
+
+ )
+ },
+)
Tabs.propTypes = {
/** The index of the active tab */
@@ -29,6 +45,7 @@ Tabs.propTypes = {
/** The callback function for selecting a tab */
onChange: PropTypes.func,
/** Sets the width of the tabs */
+ // @ts-ignore
variant: PropTypes.oneOf(['fullWidth', 'minWidth']),
/** @ignore */
children: PropTypes.node.isRequired,
@@ -37,6 +54,7 @@ Tabs.propTypes = {
Tabs.defaultProps = {
activeTab: 0,
onChange: () => {},
+ // @ts-ignore
variant: 'minWidth',
}