-
Notifications
You must be signed in to change notification settings - Fork 4.3k
/
Copy pathtab.tsx
65 lines (57 loc) · 1.74 KB
/
tab.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
* External dependencies
*/
import * as Ariakit from '@ariakit/react';
/**
* WordPress dependencies
*/
import { forwardRef } from '@wordpress/element';
/**
* Internal dependencies
*/
import type { TabProps } from './types';
import warning from '@wordpress/warning';
import { useTabsContext } from './context';
import {
Tab as StyledTab,
TabChildren as StyledTabChildren,
TabChevron as StyledTabChevron,
} from './styles';
import type { WordPressComponentProps } from '../context';
import { chevronRight } from '@wordpress/icons';
export const Tab = forwardRef<
HTMLButtonElement,
Omit< WordPressComponentProps< TabProps, 'button', false >, 'id' >
>( function Tab( { children, tabId, disabled, render, ...otherProps }, ref ) {
const { store, instanceId } = useTabsContext() ?? {};
// If the active item is not connected, the tablist may end up in a state
// where none of the tabs are tabbable. In this case, we force all tabs to
// be tabbable, so that as soon as an item received focus, it becomes active
// and Tablist goes back to working as expected.
// eslint-disable-next-line @wordpress/no-unused-vars-before-return
const tabbable = Ariakit.useStoreState( store, ( state ) => {
return (
state?.activeId !== null &&
! store?.item( state?.activeId )?.element?.isConnected
);
} );
if ( ! store ) {
warning( '`Tabs.Tab` must be wrapped in a `Tabs` component.' );
return null;
}
const instancedTabId = `${ instanceId }-${ tabId }`;
return (
<StyledTab
ref={ ref }
store={ store }
id={ instancedTabId }
disabled={ disabled }
render={ render }
tabbable={ tabbable }
{ ...otherProps }
>
<StyledTabChildren>{ children }</StyledTabChildren>
<StyledTabChevron icon={ chevronRight } />
</StyledTab>
);
} );