Skip to content

Commit

Permalink
feat(tabs): add the ability to hide a tab, maintain index
Browse files Browse the repository at this point in the history
  • Loading branch information
mikeldking committed May 22, 2023
1 parent 4240a41 commit d42b87b
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 5 deletions.
35 changes: 31 additions & 4 deletions src/tabs/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ const tabListCSS = css`
gap: var(--ac-global-dimension-static-size-65);
}
button[data-is-hidden='true'] {
display: none;
}
&[data-orientation='horizontal'] {
flex-direction: row;
border-bottom: 1px solid var(--tab-border-color);
Expand Down Expand Up @@ -120,6 +124,7 @@ export function Tabs({
className={`ac-tabs ${className}`}
data-orientation={orientation}
css={tabsContainerCSS}
data-selected-tab-index={selectedIndex}
>
<div role="tablist" data-orientation={orientation} css={tabListCSS}>
{tabs.map((tab, index) => {
Expand All @@ -128,6 +133,8 @@ export function Tabs({
<button
key={tab.key}
data-selected={isSelected}
data-tab-index={index}
data-is-hidden={tab.hidden}
role="tab"
onClick={e => {
e.preventDefault();
Expand All @@ -153,6 +160,7 @@ export function Tabs({
if (isValidElement(child)) {
return cloneElement(child as ReactElement<TabPaneChildFCProps>, {
isSelected: index === selectedIndex,
index,
});
}
return null;
Expand All @@ -162,7 +170,16 @@ export function Tabs({
);
}

type TabPaneChildFCProps = { isSelected: boolean };
type TabPaneChildFCProps = {
/**
* Whether or not the tab is selected
*/
isSelected: boolean;
/**
* The numeric index managed by the Tabs component. If a tab is hidden, it will still count towards the index
*/
index: number;
};
/**
* Function component child for lazy loading support. See storybook
*/
Expand All @@ -177,28 +194,38 @@ interface TabPaneProps
* Props for the tablist item. Use for data-testid etc.
*/
tabListItemProps?: { [`data-testid`]: string };
/**
* Whether or not the tab should be conditionally hidden or not.
* Useful when trying to hide a tab based on permissions or some other hueristic
* @default false
*/
hidden?: boolean;
}

export const TabPane = ({
name,
children,
className,
isSelected = false,
hidden = false,
index,
...divProps
}: TabPaneProps & { isSelected?: boolean }) => {
}: TabPaneProps & { isSelected?: boolean; index?: number }) => {
return (
<div
data-tab-name={name}
{...divProps}
hidden={!isSelected}
hidden={!isSelected || hidden}
role="tabpanel"
className={className}
tabIndex={isSelected ? 0 : -1}
css={css`
outline: none;
`}
>
{typeof children === 'function' ? children({ isSelected }) : children}
{typeof children === 'function'
? children({ isSelected, index: index! })
: children}
</div>
);
};
Expand Down
33 changes: 32 additions & 1 deletion stories/Tabs.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export const WithExtra: Story<TabsProps> = args => (
<LazyLoadingTabContents isSelected={isSelected} />
)}
</TabPane>
<TabPane name="Tab 2" extra={<Counter>2</Counter>}>
<TabPane name="Tab 3" extra={<Counter>2</Counter>}>
{({ isSelected }) => (
<LazyLoadingTabContents isSelected={isSelected} />
)}
Expand All @@ -100,6 +100,37 @@ export const WithExtra: Story<TabsProps> = args => (
</Provider>
);

export const WithHidden: Story<TabsProps> = args => (
<Provider>
<div style={{ width: 500 }} css={tabContentCSS}>
<Tabs {...args}>
<TabPane name="Tab 1" extra={<Counter>12</Counter>}>
{({ isSelected }) => (
<LazyLoadingTabContents isSelected={isSelected} />
)}
</TabPane>
<TabPane
name="Tab 2"
hidden={true}
extra={<Counter variant="danger">23</Counter>}
>
{({ isSelected }) => (
<LazyLoadingTabContents isSelected={isSelected} />
)}
</TabPane>
<TabPane name="Tab 3">
{({ isSelected, index }) => (
<div data-testid={'should-be-tab-3'} css={tabContentCSS}>
<Heading level={2}>{`Tab content for index: ${index}`}</Heading>
<LazyLoadingTabContents isSelected={isSelected} />
</div>
)}
</TabPane>
</Tabs>
</div>
</Provider>
);

export const Gallery: Story<TabsProps> = args => (
<div style={{ width: 500 }}>
<section>
Expand Down

0 comments on commit d42b87b

Please sign in to comment.