Skip to content

Commit

Permalink
feat(APP-3954): Update Tab component to hide the TabList when used wi…
Browse files Browse the repository at this point in the history
…th only one tab (#407)
  • Loading branch information
shan8851 authored Feb 18, 2025
1 parent 4771aa6 commit 236b7e6
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

### Changed

- Update `Tabs.List` component to only render when used with multiple tabs
- Bump `elliptic` to 6.6.1

## [1.0.66] - 2025-02-11
Expand Down
26 changes: 17 additions & 9 deletions src/core/components/tabs/tabsList/tabsList.test.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,34 @@
// TabsRoot.test.tsx
import { render, screen } from '@testing-library/react';
import { Tabs, type ITabsListProps } from '../../tabs';
import { type ITabsListProps, Tabs } from '../../tabs';

describe('<Tabs.Root /> component', () => {
describe('<Tabs.List /> component', () => {
const createTestComponent = (props?: Partial<ITabsListProps>) => {
const completeProps: ITabsListProps = {
...props,
};

return (
<Tabs.Root>
<Tabs.List {...completeProps}>
<Tabs.Trigger label="Tab 1" value="1" />
<Tabs.Trigger label="Tab 2" value="2" />
</Tabs.List>
<Tabs.List {...completeProps} />
</Tabs.Root>
);
};

it('should render multiple tab triggers without crashing', () => {
render(createTestComponent());
it('renders multiple tab triggers', () => {
const children = [
<Tabs.Trigger key="1" label="Tab 1" value="1" />,
<Tabs.Trigger key="2" label="Tab 2" value="2" />,
];
render(createTestComponent({ children }));

expect(screen.getByText('Tab 1')).toBeInTheDocument();
expect(screen.getByText('Tab 2')).toBeInTheDocument();
});

it('renders null when only a single tab trigger is present', () => {
const children = <Tabs.Trigger label="Tab 1" value="1" />;
render(createTestComponent({ children }));

expect(screen.queryByText('Tab 1')).not.toBeInTheDocument();
});
});
7 changes: 6 additions & 1 deletion src/core/components/tabs/tabsList/tabsList.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TabsList as RadixTabsList } from '@radix-ui/react-tabs';
import classNames from 'classnames';
import { useContext, type ComponentProps } from 'react';
import { Children, useContext, type ComponentProps } from 'react';
import { TabsContext } from '../tabsRoot/tabsRoot';

export interface ITabsListProps extends ComponentProps<'div'> {}
Expand All @@ -11,6 +11,11 @@ export const TabsList: React.FC<ITabsListProps> = (props) => {

const tabsListClassNames = classNames('flex gap-x-6', { 'border-b border-neutral-100': isUnderlined }, className);

// If there is only a single child then the tabs are redundant and we just show the content
if (Children.count(children) === 1) {
return null;
}

return (
<RadixTabsList className={tabsListClassNames} {...otherProps}>
{children}
Expand Down
20 changes: 20 additions & 0 deletions src/core/components/tabs/tabsRoot/tabsRoot.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,24 @@ export const InsideCard: Story = {
render: (args) => <Card className="p-6">{reusableStoryComponent(args)}</Card>,
};

/**
* Usage example of a Tabs component with a single tab with the default value.
* Make sure to set the `defaultValue` or `value` property to select and show the content of the tab.
*/
export const SingleTab: Story = {
args: { defaultValue: '1' },
render: (args) => (
<Tabs.Root {...args}>
<Tabs.List>
<Tabs.Trigger label="Default Tab" value="1" />
</Tabs.List>
<Tabs.Content value="1">
<div className="flex h-24 w-96 items-center justify-center border border-dashed border-info-300 bg-info-100">
Item 1 Content
</div>
</Tabs.Content>
</Tabs.Root>
),
};

export default meta;
15 changes: 8 additions & 7 deletions src/core/components/tabs/tabsTrigger/tabsTrigger.test.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TabsList as RadixTabsList, Tabs as RadixTabsRoot } from '@radix-ui/react-tabs';
import { render, screen } from '@testing-library/react';
import { IconType } from '../../icon';
import { Tabs, type ITabsTriggerProps } from '../../tabs';
Expand All @@ -11,11 +12,11 @@ describe('<Tabs.Trigger /> component', () => {
};

return (
<Tabs.Root>
<Tabs.List>
<RadixTabsRoot>
<RadixTabsList>
<Tabs.Trigger {...completeProps} />
</Tabs.List>
</Tabs.Root>
</RadixTabsList>
</RadixTabsRoot>
);
};

Expand All @@ -33,8 +34,8 @@ describe('<Tabs.Trigger /> component', () => {
});

it('disables the tab when the disabled property is set to true', () => {
const disabled = true;
render(createTestComponent({ disabled }));
expect(screen.getByRole('tab').getAttribute('disabled')).toEqual('');
render(createTestComponent({ disabled: true }));
const tab = screen.getByRole('tab');
expect(tab.getAttribute('disabled')).toEqual('');
});
});

0 comments on commit 236b7e6

Please sign in to comment.