1
1
'use client' ;
2
2
import * as React from 'react' ;
3
- import { useTabsPanel } from './useTabsPanel' ;
3
+ import { useBaseUiId } from '../../utils/useBaseUiId' ;
4
+ import { useRenderElement } from '../../utils/useRenderElement' ;
5
+ import type { BaseUIComponentProps } from '../../utils/types' ;
6
+ import { useCompositeListItem } from '../../composite/list/useCompositeListItem' ;
4
7
import { tabsStyleHookMapping } from '../root/styleHooks' ;
5
8
import { useTabsRootContext } from '../root/TabsRootContext' ;
6
- import { useComponentRenderer } from '../../utils/useComponentRenderer' ;
7
- import { TabsRoot , type TabValue } from '../root/TabsRoot' ;
8
- import type { BaseUIComponentProps } from '../../utils/types' ;
9
+ import type { TabsRoot , TabValue } from '../root/TabsRoot' ;
10
+ import { TabsPanelDataAttributes } from './TabsPanelDataAttributes' ;
11
+
12
+ export interface TabPanelMetadata {
13
+ id ?: string ;
14
+ value : TabValue ;
15
+ }
9
16
10
17
/**
11
18
* A panel displayed when the corresponding tab is active.
@@ -14,10 +21,17 @@ import type { BaseUIComponentProps } from '../../utils/types';
14
21
* Documentation: [Base UI Tabs](https://base-ui.com/react/components/tabs)
15
22
*/
16
23
export const TabsPanel = React . forwardRef ( function TabPanel (
17
- props : TabsPanel . Props ,
24
+ componentProps : TabsPanel . Props ,
18
25
forwardedRef : React . ForwardedRef < HTMLDivElement > ,
19
26
) {
20
- const { children, className, value : valueProp , render, keepMounted = false , ...other } = props ;
27
+ const {
28
+ children,
29
+ className,
30
+ value : valueProp ,
31
+ render,
32
+ keepMounted = false ,
33
+ ...elementProps
34
+ } = componentProps ;
21
35
22
36
const {
23
37
value : selectedValue ,
@@ -26,13 +40,28 @@ export const TabsPanel = React.forwardRef(function TabPanel(
26
40
tabActivationDirection,
27
41
} = useTabsRootContext ( ) ;
28
42
29
- const { hidden, getRootProps } = useTabsPanel ( {
30
- getTabIdByPanelValueOrIndex,
31
- rootRef : forwardedRef ,
32
- selectedValue,
33
- value : valueProp ,
43
+ const id = useBaseUiId ( ) ;
44
+
45
+ const metadata = React . useMemo (
46
+ ( ) => ( {
47
+ id,
48
+ value : valueProp ,
49
+ } ) ,
50
+ [ id , valueProp ] ,
51
+ ) ;
52
+
53
+ const { ref : listItemRef , index } = useCompositeListItem < TabPanelMetadata > ( {
54
+ metadata,
34
55
} ) ;
35
56
57
+ const tabPanelValue = valueProp ?? index ;
58
+
59
+ const hidden = tabPanelValue !== selectedValue ;
60
+
61
+ const correspondingTabId = React . useMemo ( ( ) => {
62
+ return getTabIdByPanelValueOrIndex ( valueProp , index ) ;
63
+ } , [ getTabIdByPanelValueOrIndex , index , valueProp ] ) ;
64
+
36
65
const state : TabsPanel . State = React . useMemo (
37
66
( ) => ( {
38
67
hidden,
@@ -42,12 +71,21 @@ export const TabsPanel = React.forwardRef(function TabPanel(
42
71
[ hidden , orientation , tabActivationDirection ] ,
43
72
) ;
44
73
45
- const { renderElement } = useComponentRenderer ( {
46
- propGetter : getRootProps ,
47
- render : render ?? 'div' ,
48
- className,
74
+ const renderElement = useRenderElement ( 'div' , componentProps , {
49
75
state,
50
- extraProps : { ...other , children : hidden && ! keepMounted ? undefined : children } ,
76
+ ref : [ forwardedRef , listItemRef ] ,
77
+ props : [
78
+ {
79
+ 'aria-labelledby' : correspondingTabId ,
80
+ hidden,
81
+ id : id ?? undefined ,
82
+ role : 'tabpanel' ,
83
+ tabIndex : hidden ? - 1 : 0 ,
84
+ [ TabsPanelDataAttributes . index as string ] : index ,
85
+ } ,
86
+ elementProps ,
87
+ { children : hidden && ! keepMounted ? undefined : children } ,
88
+ ] ,
51
89
customStyleHookMapping : tabsStyleHookMapping ,
52
90
} ) ;
53
91
0 commit comments