Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: restore design system Tabs api #4949

Merged
merged 4 commits into from
Oct 23, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat: restore old apis
jmfrancois committed Oct 23, 2023
commit ac3f39c1ff87f9a8fa1473612450e5b293ac4ecf
4 changes: 1 addition & 3 deletions packages/design-system/src/components/Tabs/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
export * from './Primitive/TabsProvider';
export * from './Primitive/Tabs';
export * from './Primitive/TabPanel';
export * from './variants/Tabs';
67 changes: 67 additions & 0 deletions packages/design-system/src/components/Tabs/variants/Tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { TabsProvider } from './Primitive/TabsProvider';
import { Tabs as TabList, Tab } from './Primitive/Tabs';
import { TabPanel } from './Primitive/TabPanel';

type TabTitlePropTypes = {
id?: string;
title: string;
icon?: string;
tag?: string | number;
tooltip?: string;
disabled?: boolean;
};
type TabItemPropTypes = {
tabTitle: string | TabTitlePropTypes;
tabContent: React.ReactNode;
};

export type TabsProps = {
tabs: TabItemPropTypes[];
defaultActiveKey?: string;
size?: 'S' | 'M' | 'L';
};

export function Tabs(props: TabsProps) {
if (props.tabs) {
return (
<TabsProvider
size={props.size}
defaultActiveKey={
props.defaultActiveKey || props.tabs[0].tabTitle?.id || props.tabs[0].tabTitle
}
>
<TabList>
{props.tabs.map((tab: TabItemPropTypes, index: number) => (
<Tab
key={index}
aria-controls={tab.tabTitle?.id || tab.tabTitle}
title={tab.tabTitle?.title || tab.tabTitle}
icon={tab.tabTitle?.icon}
tag={tab.tabTitle?.tag}
tooltip={tab.tabTitle?.tooltip}
disabled={tab.tabTitle?.disabled}
/>
))}
</TabList>
{props.tabs.map((tab: TabItemPropTypes, index: number) => (
<TabPanel key={index} id={tab.tabTitle?.id || tab.tabTitle}>
{tab.tabContent}
</TabPanel>
))}
</TabsProvider>
);
}
return null;
}

Tabs as typeof Tabs & {
Container: typeof TabsProvider;
List: typeof TabList;
Panel: typeof TabPanel;
Tab: typeof Tab;
};

Tabs.Container = TabsProvider;
Tabs.List = TabList;
Tabs.Panel = TabPanel;
Tabs.Tab = Tab;
142 changes: 82 additions & 60 deletions packages/design-system/src/stories/navigation/Tabs.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,102 +1,124 @@
import { useState } from 'react';
import { StackHorizontal, StackVertical, Tabs, TabsProvider, Tab, TabPanel } from '../../';
import { StackHorizontal, StackVertical, Tabs } from '../../';

export default { component: Tabs, title: 'Navigation/Tabs' };

export const Styles = () => (
<StackHorizontal gap="M" justify="spaceBetween">
<StackVertical gap="S" align="center">
<h2>Default</h2>
<TabsProvider defaultActiveKey="profile">
<Tabs>
<Tab aria-controls="home" title="Home" />
<Tab aria-controls="profile" title="Profile" />
<Tab aria-controls="contact" title="Contact" disabled />
</Tabs>
<TabPanel id="home">Tab content for Home</TabPanel>
<TabPanel id="profile">Tab content for Profile</TabPanel>
<TabPanel id="contact">Tab content for Contact</TabPanel>
</TabsProvider>
<Tabs.Container defaultActiveKey="profile">
<Tabs.List>
<Tabs.Tab aria-controls="home" title="Home" />
<Tabs.Tab aria-controls="profile" title="Profile" />
<Tabs.Tab aria-controls="contact" title="Contact" disabled />
</Tabs.List>
<Tabs.Panel id="home">Tab content for Home</Tabs.Panel>
<Tabs.Panel id="profile">Tab content for Profile</Tabs.Panel>
<Tabs.Panel id="contact">Tab content for Contact</Tabs.Panel>
</Tabs.Container>
</StackVertical>
<StackVertical gap="S" align="center">
<h2>Large</h2>
<TabsProvider size="L" defaultActiveKey="profile">
<Tabs>
<Tab aria-controls="home" title="Home" />
<Tab aria-controls="profile" title="Profile" />
<Tab aria-controls="contact" title="Contact" disabled />
</Tabs>
<TabPanel id="home">Tab content for Home</TabPanel>
<TabPanel id="profile">Tab content for Profile</TabPanel>
<TabPanel id="contact">Tab content for Contact</TabPanel>
</TabsProvider>
<Tabs.Container size="L" defaultActiveKey="profile">
<Tabs.List>
<Tabs.Tab aria-controls="home" title="Home" />
<Tabs.Tab aria-controls="profile" title="Profile" />
<Tabs.Tab aria-controls="contact" title="Contact" disabled />
</Tabs.List>
<Tabs.Panel id="home">Tab content for Home</Tabs.Panel>
<Tabs.Panel id="profile">Tab content for Profile</Tabs.Panel>
<Tabs.Panel id="contact">Tab content for Contact</Tabs.Panel>
</Tabs.Container>
</StackVertical>
</StackHorizontal>
);

export const TabsWithIcon = () => (
<TabsProvider defaultActiveKey="profile">
<Tabs>
<Tab aria-controls="user" title="User" icon="user" />
<Tab aria-controls="calendar" title="Calendar" icon="calendar" />
<Tab aria-controls="favorite" title="Favorite" icon="star" disabled />
</Tabs>
<TabPanel id="user">Users tab content</TabPanel>
<TabPanel id="calendar">Calendar tab content</TabPanel>
<TabPanel id="favorite">Favorite tab content</TabPanel>
</TabsProvider>
<Tabs.Container defaultActiveKey="profile">
<Tabs.List>
<Tabs.Tab aria-controls="user" title="User" icon="user" />
<Tabs.Tab aria-controls="calendar" title="Calendar" icon="calendar" />
<Tabs.Tab aria-controls="favorite" title="Favorite" icon="star" disabled />
</Tabs.List>
<Tabs.Panel id="user">Users tab content</Tabs.Panel>
<Tabs.Panel id="calendar">Calendar tab content</Tabs.Panel>
<Tabs.Panel id="favorite">Favorite tab content</Tabs.Panel>
</Tabs.Container>
);

export const TabsWithTag = () => (
<TabsProvider defaultActiveKey="profile">
<Tabs>
<Tab aria-controls="user" title="User" icon="user" tag={13} />
<Tab aria-controls="calendar" title="Calendar" icon="calendar" tag={54} />
<Tab
<Tabs.Container defaultActiveKey="profile">
<Tabs.List>
<Tabs.Tab aria-controls="user" title="User" icon="user" tag={13} />
<Tabs.Tab aria-controls="calendar" title="Calendar" icon="calendar" tag={54} />
<Tabs.Tab
aria-controls="favorite"
title="Favorite"
icon="star"
tag="999+"
tooltip="1534 Favorite items"
/>
</Tabs>
<TabPanel id="user">Users tab content</TabPanel>
<TabPanel id="calendar">Calendar tab content</TabPanel>
<TabPanel id="favorite">Favorite tab content</TabPanel>
</TabsProvider>
</Tabs.List>
<Tabs.Panel id="user">Users tab content</Tabs.Panel>
<Tabs.Panel id="calendar">Calendar tab content</Tabs.Panel>
<Tabs.Panel id="favorite">Favorite tab content</Tabs.Panel>
</Tabs.Container>
);

export const TabsWithLongTitles = () => (
<TabsProvider defaultActiveKey="user">
<Tabs>
<Tab aria-controls="user" title="User" icon="user" tag={13} />
<Tab
<Tabs.Container defaultActiveKey="user">
<Tabs.List>
<Tabs.Tab aria-controls="user" title="User" icon="user" tag={13} />
<Tabs.Tab
aria-controls="notification"
title="A much too long title that will trigger the overflow limit"
icon="information-stroke"
tag="999+"
tooltip="1239 notifications - A much too long title that will trigger the overflow limit"
/>
</Tabs>
<TabPanel id="user">Users tab content</TabPanel>
<TabPanel id="notification">
</Tabs.List>
<Tabs.Panel id="user">Users tab content</Tabs.Panel>
<Tabs.Panel id="notification">
<h2>About tab content</h2>
</TabPanel>
</TabsProvider>
</Tabs.Panel>
</Tabs.Container>
);

export const TabStandaloneControlled = () => {
const [key, setKey] = useState<string>('home');
return (
<TabsProvider activeKey={key} onSelect={(e, k) => setKey(k)}>
<Tabs>
<Tab aria-controls="home" title="Home" />
<Tab aria-controls="profile" title="Profile" />
<Tab aria-controls="contact" title="Contact" disabled />
</Tabs>
<TabPanel id="home">Tab content for Home</TabPanel>
<TabPanel id="profile">Tab content for Profile</TabPanel>
<TabPanel id="contact">Tab content for Contact</TabPanel>
</TabsProvider>
<Tabs.Container activeKey={key} onSelect={(e, k) => setKey(k)}>
<Tabs.List>
<Tabs.Tab aria-controls="home" title="Home" />
<Tabs.Tab aria-controls="profile" title="Profile" />
<Tabs.Tab aria-controls="contact" title="Contact" disabled />
</Tabs.List>
<Tabs.Panel id="home">Tab content for Home</Tabs.Panel>
<Tabs.Panel id="profile">Tab content for Profile</Tabs.Panel>
<Tabs.Panel id="contact">Tab content for Contact</Tabs.Panel>
</Tabs.Container>
);
};

export const TabAPI = () => (
<Tabs
tabs={[
{
tabTitle: 'Tabs 1',
tabContent: <>Tab 1</>,
},
{
tabTitle: 'Tabs 2',
tabContent: <>Tab 2</>,
},
{
tabTitle: {
title: 'Tabs 3',
icon: 'user',
},
tabContent: <>Tab 3</>,
},
]}
/>
);