From 68b5598167f67f54306aa622baca4d4d6591809a Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Fri, 15 Nov 2024 17:05:41 +0800 Subject: [PATCH] Fix binding aria-labelledby --- .../mui-base/src/Tabs/Root/TabsRoot.test.tsx | 2 +- packages/mui-base/src/Tabs/Root/TabsRoot.tsx | 3 + .../mui-base/src/Tabs/Root/TabsRootContext.ts | 1 + .../mui-base/src/Tabs/Root/useTabsRoot.ts | 61 ++++++++++---- packages/mui-base/src/Tabs/Tab/Tab.test.tsx | 2 +- packages/mui-base/src/Tabs/Tab/useTab.ts | 3 +- .../src/Tabs/TabIndicator/TabIndicator.tsx | 18 ++-- .../src/Tabs/TabIndicator/useTabIndicator.ts | 10 +-- .../src/Tabs/TabPanel/TabPanel.test.tsx | 14 +--- .../mui-base/src/Tabs/TabPanel/useTabPanel.ts | 34 +++----- .../src/Tabs/TabsList/TabsList.test.tsx | 1 + .../mui-base/src/Tabs/TabsList/TabsList.tsx | 2 + .../src/Tabs/TabsList/TabsListContext.ts | 1 - .../mui-base/src/Tabs/TabsList/useTabsList.ts | 82 ++++--------------- 14 files changed, 99 insertions(+), 135 deletions(-) diff --git a/packages/mui-base/src/Tabs/Root/TabsRoot.test.tsx b/packages/mui-base/src/Tabs/Root/TabsRoot.test.tsx index 7fdbcecdb6..b18f83af0c 100644 --- a/packages/mui-base/src/Tabs/Root/TabsRoot.test.tsx +++ b/packages/mui-base/src/Tabs/Root/TabsRoot.test.tsx @@ -275,7 +275,7 @@ describe('', () => { ].forEach((entry) => { const [orientation, direction, previousItemKey, nextItemKey] = entry; - describe(`when focus is on a tab element in a ${orientation} ${direction} tablist`, () => { + describe(`when focus is on a tab element in a ${orientation} ${direction ?? ''} tablist`, () => { describe(previousItemKey ?? '', () => { describe('with `activateOnFocus = false`', () => { it('moves focus to the last tab without activating it if focus is on the first tab', async () => { diff --git a/packages/mui-base/src/Tabs/Root/TabsRoot.tsx b/packages/mui-base/src/Tabs/Root/TabsRoot.tsx index 8b4c6e5c47..0a59c21034 100644 --- a/packages/mui-base/src/Tabs/Root/TabsRoot.tsx +++ b/packages/mui-base/src/Tabs/Root/TabsRoot.tsx @@ -36,6 +36,7 @@ const TabsRoot = React.forwardRef(function TabsRoot( const { getRootProps, direction, + getTabElementBySelectedValue, getTabIdByPanelValueOrIndex, getTabPanelIdByTabValueOrIndex, onValueChange, @@ -55,6 +56,7 @@ const TabsRoot = React.forwardRef(function TabsRoot( const tabsContextValue = React.useMemo( () => ({ direction, + getTabElementBySelectedValue, getTabIdByPanelValueOrIndex, getTabPanelIdByTabValueOrIndex, onValueChange, @@ -66,6 +68,7 @@ const TabsRoot = React.forwardRef(function TabsRoot( }), [ direction, + getTabElementBySelectedValue, getTabIdByPanelValueOrIndex, getTabPanelIdByTabValueOrIndex, onValueChange, diff --git a/packages/mui-base/src/Tabs/Root/TabsRootContext.ts b/packages/mui-base/src/Tabs/Root/TabsRootContext.ts index 464746ca7f..b68d5f128e 100644 --- a/packages/mui-base/src/Tabs/Root/TabsRootContext.ts +++ b/packages/mui-base/src/Tabs/Root/TabsRootContext.ts @@ -28,6 +28,7 @@ export interface TabsRootContext { * Registers a function that returns the id of the tab with the given value. */ // registerGetTabIdByPanelValueOrIndexFn?: (lookupFunction: (id: any) => string | undefined) => void; + getTabElementBySelectedValue: (selectedValue: any | undefined) => HTMLElement | null; /** * Gets the id of the tab with the given value. * @param {any | undefined} value Value to find the tab for. diff --git a/packages/mui-base/src/Tabs/Root/useTabsRoot.ts b/packages/mui-base/src/Tabs/Root/useTabsRoot.ts index 8127e488af..62b757154b 100644 --- a/packages/mui-base/src/Tabs/Root/useTabsRoot.ts +++ b/packages/mui-base/src/Tabs/Root/useTabsRoot.ts @@ -76,24 +76,49 @@ function useTabsRoot(parameters: useTabsRoot.Parameters): useTabsRoot.ReturnValu // get the `id` attribute of to set as the value of `aria-labelledby` on const getTabIdByPanelValueOrIndex = React.useCallback( (tabPanelValue: any | undefined, index: number) => { - // return getTabIdByPanelValueOrIndexRef.current(tabPanelValue); + if (tabPanelValue === undefined && index < 0) { + return undefined; + } + for (const tabMetadata of tabMap.values()) { - console.log(tabPanelValue, index, tabMetadata); + // console.log(tabPanelValue, index, tabMetadata); + + // find by tabPanelValue + if ( + tabPanelValue !== undefined && + index > -1 && + tabPanelValue === (tabMetadata?.value ?? tabMetadata?.index ?? undefined) + ) { + // console.log('found by tabPanelValue', tabMetadata?.id); + return tabMetadata?.id; + } + + // find by index + if ( + tabPanelValue === undefined && + index > -1 && + index === (tabMetadata?.value ?? tabMetadata?.index ?? undefined) + ) { + // console.log('found by tabPanel index', tabMetadata?.id); + return tabMetadata?.id; + } } + return undefined; }, [tabMap], ); + // FIXME // used as a param for `useActivationDirectionDetector` - const getTabElementByPanelValueOrIndex = React.useCallback( - (tabPanelValue: any | undefined, index: number) => { - // return getTabIdByPanelValueOrIndexRef.current(tabPanelValue); - return null; - }, - [], - ); - + // put this into TabsRootContext + // use it in useTabsList + const getTabElementBySelectedValue = React.useCallback((selectedValue: any | undefined) => { + console.log('getTabElementBySelectedValue', selectedValue); + return null; + }, []); + + // TODO: no need to put this in a ref anymore? const registerGetTabIdByPanelValueOrIndexFn = React.useCallback( (lookupFunction: IdLookupFunction) => { getTabIdByPanelValueOrIndexRef.current = lookupFunction; @@ -112,7 +137,7 @@ function useTabsRoot(parameters: useTabsRoot.Parameters): useTabsRoot.ReturnValu return { getRootProps, direction, - getTabElementByPanelValueOrIndex, + getTabElementBySelectedValue, getTabIdByPanelValueOrIndex, getTabPanelIdByTabValueOrIndex, onValueChange, @@ -120,6 +145,7 @@ function useTabsRoot(parameters: useTabsRoot.Parameters): useTabsRoot.ReturnValu setTabMap, setTabPanelMap, tabActivationDirection, + tabMap, tabPanelRefs, value, }; @@ -155,14 +181,16 @@ namespace useTabsRoot { * The direction of the text. */ direction: 'ltr' | 'rtl'; - getTabElementByPanelValueOrIndex: ( - panelValue: any | undefined, - index: number, - ) => HTMLElement | null; /** - * Gets the id of the tab with the given value. + * Gets the underlying element of the Tab with the given value. * @param value Value to find the tab for. */ + getTabElementBySelectedValue: (panelValue: any | undefined) => HTMLElement | null; + /** + * Gets the `id` attribute of the Tab with the given value. + * @param (any | undefined) panelValue Value to find the Tab for. + * @param (number) index The index of the Tab to look for. + */ getTabIdByPanelValueOrIndex: (panelValue: any | undefined, index: number) => string | undefined; /** * Gets the id of the tab panel with the given value. @@ -192,6 +220,7 @@ namespace useTabsRoot { * The position of the active tab relative to the previously active tab. */ tabActivationDirection: TabActivationDirection; + tabMap: Map; tabPanelRefs: React.RefObject<(HTMLElement | null)[]>; /** * The currently selected tab's value. diff --git a/packages/mui-base/src/Tabs/Tab/Tab.test.tsx b/packages/mui-base/src/Tabs/Tab/Tab.test.tsx index 71ba7fe7b9..6b139a01b1 100644 --- a/packages/mui-base/src/Tabs/Tab/Tab.test.tsx +++ b/packages/mui-base/src/Tabs/Tab/Tab.test.tsx @@ -16,7 +16,6 @@ describe('', () => { const testTabsListContext: TabsListContext = { activateOnFocus: true, - getTabElement: () => null, highlightedTabIndex: 0, onTabActivation: NOOP, setHighlightedTabIndex: NOOP, @@ -29,6 +28,7 @@ describe('', () => { value: 0, onValueChange() {}, setTabMap() {}, + getTabElementBySelectedValue: () => null, getTabIdByPanelValueOrIndex: () => '', getTabPanelIdByTabValueOrIndex: () => '', orientation: 'horizontal', diff --git a/packages/mui-base/src/Tabs/Tab/useTab.ts b/packages/mui-base/src/Tabs/Tab/useTab.ts index 7dac5ad155..f4699009cf 100644 --- a/packages/mui-base/src/Tabs/Tab/useTab.ts +++ b/packages/mui-base/src/Tabs/Tab/useTab.ts @@ -13,6 +13,7 @@ import type { TabsList } from '../TabsList/TabsList'; export interface TabMetadata { disabled: boolean; id: string | undefined; + value: any | undefined; } function useTab(parameters: useTab.Parameters): useTab.ReturnValue { @@ -45,7 +46,7 @@ function useTab(parameters: useTab.Parameters): useTab.ReturnValue { const tabValue = valueParam ?? index; // the `selected` state isn't set on the server (it relies on effects to be calculated), - // so we fall back to checking the `value` param with the selectedValue from the TabsContext + // so we fall back to checking the `value` param with the selectedTabValue from the TabsContext const selected = React.useMemo(() => { if (valueParam === undefined) { return index < 0 ? false : index === selectedTabValue; diff --git a/packages/mui-base/src/Tabs/TabIndicator/TabIndicator.tsx b/packages/mui-base/src/Tabs/TabIndicator/TabIndicator.tsx index ce07f6eae6..9a12d65bc4 100644 --- a/packages/mui-base/src/Tabs/TabIndicator/TabIndicator.tsx +++ b/packages/mui-base/src/Tabs/TabIndicator/TabIndicator.tsx @@ -1,14 +1,14 @@ 'use client'; import * as React from 'react'; -import { ActiveTabPosition, useTabIndicator } from './useTabIndicator'; -import { script as prehydrationScript } from './prehydrationScript.min'; +import { useComponentRenderer } from '../../utils/useComponentRenderer'; +import { useOnMount } from '../../utils/useOnMount'; +import type { BaseUIComponentProps } from '../../utils/types'; import type { TabsDirection, TabsOrientation, TabsRoot } from '../Root/TabsRoot'; import { useTabsRootContext } from '../Root/TabsRootContext'; import { tabsStyleHookMapping } from '../Root/styleHooks'; import { useTabsListContext } from '../TabsList/TabsListContext'; -import { useComponentRenderer } from '../../utils/useComponentRenderer'; -import { useOnMount } from '../../utils/useOnMount'; -import type { BaseUIComponentProps } from '../../utils/types'; +import { ActiveTabPosition, useTabIndicator } from './useTabIndicator'; +import { script as prehydrationScript } from './prehydrationScript.min'; const noop = () => null; @@ -26,8 +26,10 @@ const TabIndicator = React.forwardRef( function TabIndicator(props, forwardedRef) { const { className, render, renderBeforeHydration = false, ...other } = props; - const { orientation, direction, value, tabActivationDirection } = useTabsRootContext(); - const { tabsListRef, getTabElement } = useTabsListContext(); + const { direction, getTabElementBySelectedValue, orientation, tabActivationDirection, value } = + useTabsRootContext(); + + const { tabsListRef } = useTabsListContext(); const [instanceId] = React.useState(() => Math.random().toString(36).slice(2)); const [isMounted, setIsMounted] = React.useState(false); @@ -36,7 +38,7 @@ const TabIndicator = React.forwardRef( useOnMount(() => setIsMounted(true)); const { getRootProps, activeTabPosition: selectedTabPosition } = useTabIndicator({ - getTabElement, + getTabElementBySelectedValue, tabsListRef, value, }); diff --git a/packages/mui-base/src/Tabs/TabIndicator/useTabIndicator.ts b/packages/mui-base/src/Tabs/TabIndicator/useTabIndicator.ts index 3d49a93d36..8e0b45f981 100644 --- a/packages/mui-base/src/Tabs/TabIndicator/useTabIndicator.ts +++ b/packages/mui-base/src/Tabs/TabIndicator/useTabIndicator.ts @@ -12,7 +12,7 @@ function round(value: number) { export function useTabIndicator( parameters: useTabIndicator.Parameters, ): useTabIndicator.ReturnValue { - const { value, tabsListRef, getTabElement } = parameters; + const { value, tabsListRef, getTabElementBySelectedValue } = parameters; const rerender = useForcedRerendering(); React.useEffect(() => { @@ -41,7 +41,7 @@ export function useTabIndicator( let isTabSelected = false; if (value != null && tabsListRef.current != null) { - const selectedTabElement = null; /*getTabElement(value)*/ + const selectedTabElement = getTabElementBySelectedValue(value); isTabSelected = true; if (selectedTabElement != null) { @@ -120,9 +120,9 @@ export interface ActiveTabPosition { } export namespace useTabIndicator { - export interface Parameters extends Pick { - value: TabsRootContext['value']; - } + export interface Parameters + extends Pick, + Pick {} export interface ReturnValue { getRootProps: ( diff --git a/packages/mui-base/src/Tabs/TabPanel/TabPanel.test.tsx b/packages/mui-base/src/Tabs/TabPanel/TabPanel.test.tsx index 2c89ee1494..90c3263ae3 100644 --- a/packages/mui-base/src/Tabs/TabPanel/TabPanel.test.tsx +++ b/packages/mui-base/src/Tabs/TabPanel/TabPanel.test.tsx @@ -1,22 +1,16 @@ import * as React from 'react'; import { Tabs } from '@base_ui/react/Tabs'; import { createRenderer, describeConformance } from '#test-utils'; -import { CompoundComponentContext } from '../../useCompound'; import { TabsRootContext } from '../Root/TabsRootContext'; describe('', () => { const { render } = createRenderer(); - const compoundContextValue = { - getItemIndex: () => 0, - registerItem: () => ({ id: 0, deregister: () => {} }), - totalSubitemCount: 1, - }; - const tabsContextDefaultValue: TabsRootContext = { value: '1', onValueChange: () => {}, setTabMap() {}, + getTabElementBySelectedValue: () => null, getTabIdByPanelValueOrIndex: () => '', getTabPanelIdByTabValueOrIndex: () => '', direction: 'ltr', @@ -27,11 +21,7 @@ describe('', () => { describeConformance(, () => ({ render: (node) => { return render( - - - {node} - - , + {node}, ); }, refInstanceof: window.HTMLDivElement, diff --git a/packages/mui-base/src/Tabs/TabPanel/useTabPanel.ts b/packages/mui-base/src/Tabs/TabPanel/useTabPanel.ts index c199e284e7..f35be421a6 100644 --- a/packages/mui-base/src/Tabs/TabPanel/useTabPanel.ts +++ b/packages/mui-base/src/Tabs/TabPanel/useTabPanel.ts @@ -4,7 +4,6 @@ import type { TabsRootContext } from '../Root/TabsRootContext'; import { useId } from '../../utils/useId'; import { useForkRef } from '../../utils/useForkRef'; import { mergeReactProps } from '../../utils/mergeReactProps'; -import { useCompositeListContext } from '../../Composite/List/CompositeListContext'; import { useCompositeListItem } from '../../Composite/List/useCompositeListItem'; export interface TabPanelMetadata { @@ -13,7 +12,12 @@ export interface TabPanelMetadata { } function useTabPanel(parameters: useTabPanel.Parameters): useTabPanel.ReturnValue { - const { rootRef: externalRef, selectedValue, value: valueParam } = parameters; + const { + getTabIdByPanelValueOrIndex, + rootRef: externalRef, + selectedValue, + value: valueParam, + } = parameters; const id = useId(); @@ -25,9 +29,6 @@ function useTabPanel(parameters: useTabPanel.Parameters): useTabPanel.ReturnValu [id, valueParam], ); - // tabPanelCompositeMap - const { map: tabPanelCompositeMap } = useCompositeListContext(); - const { ref: listItemRef, index } = useCompositeListItem({ metadata, }); @@ -39,29 +40,16 @@ function useTabPanel(parameters: useTabPanel.Parameters): useTabPanel.ReturnValu const hidden = tabPanelValue !== selectedValue; - // const correspondingTabId = tabPanelValue !== undefined ? getTabId(tabPanelValue) : undefined; - - const tabId = React.useMemo(() => { - if (index < 0) { - return undefined; - } - - // TODO: this is incorrect, should be tabButtonMap - for (const value of tabPanelCompositeMap.values()) { - if (value.index > -1 && value.index === index) { - return value.id; - } - } - - return undefined; - }, [index, tabPanelCompositeMap]); + const correspondingTabId = React.useMemo(() => { + return getTabIdByPanelValueOrIndex(valueParam, index); + }, [getTabIdByPanelValueOrIndex, index, valueParam]); const getRootProps = React.useCallback( ( externalProps: React.ComponentPropsWithoutRef<'div'> = {}, ): React.ComponentPropsWithRef<'div'> => { return mergeReactProps(externalProps, { - 'aria-labelledby': undefined, + 'aria-labelledby': correspondingTabId, hidden, id: id ?? undefined, role: 'tabpanel', @@ -70,7 +58,7 @@ function useTabPanel(parameters: useTabPanel.Parameters): useTabPanel.ReturnValu 'data-index': index, }); }, - [handleRef, hidden, id, index], + [correspondingTabId, handleRef, hidden, id, index], ); return { diff --git a/packages/mui-base/src/Tabs/TabsList/TabsList.test.tsx b/packages/mui-base/src/Tabs/TabsList/TabsList.test.tsx index 03addd7c20..ae85aea16a 100644 --- a/packages/mui-base/src/Tabs/TabsList/TabsList.test.tsx +++ b/packages/mui-base/src/Tabs/TabsList/TabsList.test.tsx @@ -16,6 +16,7 @@ describe('', () => { value: '1', onValueChange: () => {}, setTabMap() {}, + getTabElementBySelectedValue: () => null, getTabIdByPanelValueOrIndex: () => '', getTabPanelIdByTabValueOrIndex: () => '', orientation: 'horizontal', diff --git a/packages/mui-base/src/Tabs/TabsList/TabsList.tsx b/packages/mui-base/src/Tabs/TabsList/TabsList.tsx index e70413d4e1..993654b963 100644 --- a/packages/mui-base/src/Tabs/TabsList/TabsList.tsx +++ b/packages/mui-base/src/Tabs/TabsList/TabsList.tsx @@ -27,6 +27,7 @@ const TabsList = React.forwardRef(function TabsList( const { direction = 'ltr', + getTabElementBySelectedValue, onValueChange, orientation = 'horizontal', value, @@ -39,6 +40,7 @@ const TabsList = React.forwardRef(function TabsList( const tabsListRef = React.useRef(null); const { getRootProps, onTabActivation } = useTabsList({ + getTabElementBySelectedValue, onValueChange, orientation, rootRef: forwardedRef, diff --git a/packages/mui-base/src/Tabs/TabsList/TabsListContext.ts b/packages/mui-base/src/Tabs/TabsList/TabsListContext.ts index fc32651eb7..c633fbf979 100644 --- a/packages/mui-base/src/Tabs/TabsList/TabsListContext.ts +++ b/packages/mui-base/src/Tabs/TabsList/TabsListContext.ts @@ -3,7 +3,6 @@ import * as React from 'react'; export interface TabsListContext { activateOnFocus: boolean; - getTabElement: (value: any) => HTMLElement | null; highlightedTabIndex: number; onTabActivation: (newValue: any, event: Event) => void; setHighlightedTabIndex: (index: number) => void; diff --git a/packages/mui-base/src/Tabs/TabsList/useTabsList.ts b/packages/mui-base/src/Tabs/TabsList/useTabsList.ts index 40bc3ffbdc..3caaa9bc69 100644 --- a/packages/mui-base/src/Tabs/TabsList/useTabsList.ts +++ b/packages/mui-base/src/Tabs/TabsList/useTabsList.ts @@ -6,70 +6,23 @@ import { useForkRef } from '../../utils/useForkRef'; import { mergeReactProps } from '../../utils/mergeReactProps'; import { useEnhancedEffect } from '../../utils/useEnhancedEffect'; import { useEventCallback } from '../../utils/useEventCallback'; -// import { TabsListContext } from './TabsListContext'; function useTabsList(parameters: useTabsList.Parameters): useTabsList.ReturnValue { const { + getTabElementBySelectedValue, onValueChange, orientation, - // registerGetTabIdByPanelValueOrIndexFn, rootRef: externalRef, tabsListRef, value: selectedTabValue, } = parameters; - // subitems are s, their Composite parent is - // const { subitems } = useCompoundParent(); - - // DON"T NEED THIS ANYMORE - // - // get id attribute of a Tab by tab value - // for binding aria attributes - // this function needs to be registered to the context - // - // const tabIdLookup = React.useCallback( - // (tabValue: any) => { - // return subitems.get(tabValue)?.id; - // }, - // [subitems], - // ); - - // registerGetTabIdByPanelValueOrIndexFn(tabIdLookup); - - // this is a param for useList - // const subitemKeys = React.useMemo(() => Array.from(subitems.keys()), [subitems]); - - // get the element/node of a tab by tab value - // used as a param for `useActivationDirectionDetector` - // TODO: move this to useTabsRoot since tabMap is there - const getTabElement = React.useCallback( - (tabValue: any) => { - if (tabValue == null) { - return null; - } - - // subitems are s, their Composite parent is - // return subitems.get(tabValue)?.ref.current ?? null; - return null; - }, - [ - /* subitems */ - ], - ); - - // let listOrientation: UseListParameters['orientation']; - // if (orientation === 'vertical') { - // listOrientation = 'vertical'; - // } else { - // listOrientation = direction === 'rtl' ? 'horizontal-rtl' : 'horizontal-ltr'; - // } - - // const tabsListRef = React.useRef(null); const detectActivationDirection = useActivationDirectionDetector( + // the old value selectedTabValue, orientation, tabsListRef, - getTabElement, + getTabElementBySelectedValue, ); const onTabActivation = useEventCallback((newValue: any, event: Event) => { @@ -80,15 +33,6 @@ function useTabsList(parameters: useTabsList.Parameters): useTabsList.ReturnValu } }); - // const controlledProps = React.useMemo(() => { - // return value != null ? { selectedValues: [value] } : { selectedValues: [] }; - // }, [value]); - - // const isItemDisabled = React.useCallback( - // (item: any) => subitems.get(item)?.disabled ?? false, - // [subitems], - // ); - // React.useEffect(() => { // if (value === undefined) { // return; @@ -134,21 +78,22 @@ function getInset(tab: HTMLElement, tabsList: HTMLElement) { } function useActivationDirectionDetector( - value: any, + // the old value + selectedTabValue: any, orientation: TabsOrientation, tabsListRef: React.RefObject, - getTabElement: (tabValue: any) => HTMLElement | null, + getTabElement: (selectedValue: any) => HTMLElement | null, ): (newValue: any) => TabActivationDirection { const previousTabEdge = React.useRef(null); useEnhancedEffect(() => { // Whenever orientation changes, reset the state. - if (value == null || tabsListRef.current == null) { + if (selectedTabValue == null || tabsListRef.current == null) { previousTabEdge.current = null; return; } - const activeTab = getTabElement(value); + const activeTab = getTabElement(selectedTabValue); if (activeTab == null) { previousTabEdge.current = null; return; @@ -156,11 +101,11 @@ function useActivationDirectionDetector( const { left, top } = getInset(activeTab, tabsListRef.current); previousTabEdge.current = orientation === 'horizontal' ? left : top; - }, [orientation, getTabElement, tabsListRef, value]); + }, [orientation, getTabElement, tabsListRef, selectedTabValue]); return React.useCallback( (newValue: any) => { - if (newValue === value) { + if (newValue === selectedTabValue) { return 'none'; } @@ -201,13 +146,16 @@ function useActivationDirectionDetector( return 'none'; }, - [getTabElement, orientation, previousTabEdge, tabsListRef, value], + [getTabElement, orientation, previousTabEdge, tabsListRef, selectedTabValue], ); } namespace useTabsList { export interface Parameters - extends Pick { + extends Pick< + TabsRootContext, + 'getTabElementBySelectedValue' | 'onValueChange' | 'orientation' | 'setTabMap' | 'value' + > { /** * Ref to the root element. */