Skip to content

Commit

Permalink
Expose activeId/defaultActiveId/setActiveId on Tabs
Browse files Browse the repository at this point in the history
  • Loading branch information
ciampo committed Oct 15, 2024
1 parent ddf3bb4 commit 566d43f
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 8 deletions.
41 changes: 33 additions & 8 deletions packages/components/src/tabs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,52 @@ import { Tab } from './tab';
import { TabList } from './tablist';
import { TabPanel } from './tabpanel';

function externalToInternalTabId(
externalId: string | undefined | null,
instanceId: string
) {
return externalId && `${ instanceId }-${ externalId }`;
}

function internalToExternalTabId(
internalId: string | undefined | null,
instanceId: string
) {
return typeof internalId === 'string'
? internalId.replace( `${ instanceId }-`, '' )
: internalId;
}

function Tabs( {
selectOnMove = true,
defaultTabId,
orientation = 'horizontal',
onSelect,
children,
selectedTabId,
activeTabId,
defaultActiveTabId,
onActiveTabIdChange,
}: TabsProps ) {
const instanceId = useInstanceId( Tabs, 'tabs' );
const store = Ariakit.useTabStore( {
selectOnMove,
orientation,
defaultSelectedId: defaultTabId && `${ instanceId }-${ defaultTabId }`,
setSelectedId: ( selectedId ) => {
const strippedDownId =
typeof selectedId === 'string'
? selectedId.replace( `${ instanceId }-`, '' )
: selectedId;
onSelect?.( strippedDownId );
defaultSelectedId: externalToInternalTabId( defaultTabId, instanceId ),
setSelectedId: ( newSelectedId ) => {
onSelect?.( internalToExternalTabId( newSelectedId, instanceId ) );
},
selectedId: externalToInternalTabId( selectedTabId, instanceId ),
defaultActiveId: externalToInternalTabId(
defaultActiveTabId,
instanceId
),
setActiveId: ( newActiveId ) => {
onActiveTabIdChange?.(
internalToExternalTabId( newActiveId, instanceId )
);
},
selectedId: selectedTabId && `${ instanceId }-${ selectedTabId }`,
activeId: externalToInternalTabId( activeTabId, instanceId ),
} );

const { items, activeId } = Ariakit.useStoreState( store );
Expand Down
21 changes: 21 additions & 0 deletions packages/components/src/tabs/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,27 @@ export type TabsProps = {
* When in controlled mode, the `null` value will result in no tab being selected.
*/
selectedTabId?: string | null;
/**
* The current active tab `id`. The active tab is the tab element within the
* tablist widget that has DOM focus.
* - `null` represents the tablist (ie. the base composite element). Users
* will be able to navigate out of it using arrow keys.
* - If `activeId` is initially set to `null`, the base composite element
* itself will have focus and users will be able to navigate to it using
* arrow keys.
*/
activeTabId?: Ariakit.TabStoreProps[ 'activeId' ];
/**
* The tab id that should be active by default when the composite widget is
* rendered. If `null`, the tablist element itself will have focus
* and users will be able to navigate to it using arrow keys. If `undefined`,
* the first enabled item will be focused.
*/
defaultActiveTabId?: Ariakit.CompositeStoreProps[ 'defaultActiveId' ];
/**
* A callback that gets called when the `activeId` state changes.
*/
onActiveTabIdChange?: Ariakit.TabStoreProps[ 'setActiveId' ];
};

export type TabListProps = {
Expand Down

0 comments on commit 566d43f

Please sign in to comment.