Skip to content

Commit

Permalink
feat(Tabs): Added overflowButton property (#1060)
Browse files Browse the repository at this point in the history
Co-authored-by: Greta <[email protected]>
  • Loading branch information
elephantcatdog and gretanausedaite authored May 16, 2023
1 parent 5679f3c commit 6183552
Show file tree
Hide file tree
Showing 19 changed files with 1,067 additions and 40 deletions.
13 changes: 13 additions & 0 deletions .changeset/lovely-poems-remember.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@itwin/itwinui-react': minor
'@itwin/itwinui-css': minor
---

- Added data attribute 'data-iui-overflow' - when true it adds styling for overflow tabs
- Added property 'overflowOptions' - contains `useOverflow`, which when true enables tabs to scroll if there's overflow

```typescript
<Tabs type='default' overflowButton={{ useOverflow: true }}>
{tabs}
</Tabs>
```
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
197 changes: 195 additions & 2 deletions apps/storybook/src/Tabs.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
import SvgStar from '@itwin/itwinui-icons-react/cjs/icons/Star';
import { Meta, Story } from '@storybook/react/';
import React from 'react';
import { Button, Tab } from '@itwin/itwinui-react';
import { Tabs, TabsProps } from '@itwin/itwinui-react/esm/core/Tabs/Tabs';
import { Button, Tab, Tabs, TabsProps } from '@itwin/itwinui-react';

export default {
title: 'Core/Tabs',
Expand Down Expand Up @@ -187,6 +186,200 @@ SublabelsAndIcons.args = {
type: 'borderless',
};

export const HorizontalOverflow: Story<Partial<TabsProps>> = (args) => {
const [activeIndex, setActiveIndex] = React.useState(10);
const getContent = () => {
switch (activeIndex) {
case 0:
return 'Tab Content One';
case 1:
return 'Tab Content Two';
case 2:
return 'Tab Content Three';
case 3:
return 'Tab Content Four';
case 4:
return 'Tab Content Five';
case 5:
return 'Tab Content Six';
case 6:
return 'Tab Content Seven';
case 7:
return 'Tab Content Eight';
case 8:
return 'Tab Content Nine';
case 9:
return 'Tab Content Ten';
case 10:
return 'Tab Content Eleven';
case 11:
return 'Tab Content Twelve';
default:
return 'Tab Content Thirteen';
}
};
const labels = [
<Tab key={1} label='Item 1' />,
<Tab key={2} label='Item 2' />,
<Tab key={3} label='Item 3' />,
<Tab key={4} label='Item 4' />,
<Tab key={5} label='Item 5' />,
<Tab key={6} label='Item 6' disabled />,
<Tab key={7} label='Item 7' />,
<Tab key={8} label='Item 8' />,
<Tab key={9} label='Item 9' disabled />,
<Tab key={10} label='Item 10' />,
<Tab key={11} label='Item 11' />,
<Tab key={12} label='Item 12' />,
<Tab key={13} label='Very long item number thirteen' />,
];

return (
<div
style={{
width: '50%',
maxWidth: 800,
minWidth: 250,
border: '1px solid lightpink',
padding: 8,
}}
>
<Tabs
type='default'
labels={labels}
overflowOptions={{ useOverflow: true }}
{...args}
onTabSelected={setActiveIndex}
activeIndex={activeIndex}
actions={[<Button key={'button'}>Button</Button>]}
>
{getContent()}
</Tabs>
</div>
);
};
HorizontalOverflow.args = {
type: 'default',
labels: [
<Tab key={1} label='Item 1' />,
<Tab key={2} label='Item 2' />,
<Tab key={3} label='Item 3' />,
<Tab key={4} label='Item 4' />,
<Tab key={5} label='Item 5' />,
<Tab key={6} label='Item 6' disabled />,
<Tab key={7} label='Item 7' />,
<Tab key={8} label='Item 8' />,
<Tab key={9} label='Item 9' disabled />,
<Tab key={10} label='Item 10' />,
<Tab key={11} label='Item 11' />,
<Tab key={12} label='Item 12' />,
<Tab key={13} label='Very long item number thirteen' />,
],
};
HorizontalOverflow.argTypes = {
type: { options: ['default', 'borderless'] },
orientation: { control: { disable: true } },
actions: { control: { disable: true } },
};

export const VerticalOverflow: Story<Partial<TabsProps>> = (args) => {
const [activeIndex, setActiveIndex] = React.useState(10);
const getContent = () => {
switch (activeIndex) {
case 0:
return 'Tab Content One';
case 1:
return 'Tab Content Two';
case 2:
return 'Tab Content Three';
case 3:
return 'Tab Content Four';
case 4:
return 'Tab Content Five';
case 5:
return 'Tab Content Six';
case 6:
return 'Tab Content Seven';
case 7:
return 'Tab Content Eight';
case 8:
return 'Tab Content Nine';
case 9:
return 'Tab Content Ten';
case 10:
return 'Tab Content Eleven';
case 11:
return 'Tab Content Twelve';
default:
return 'Tab Content Thirteen';
}
};
const labels = [
<Tab key={1} label='Item 1' />,
<Tab key={2} label='Item 2' />,
<Tab key={3} label='Item 3' />,
<Tab key={4} label='Item 4' />,
<Tab key={5} label='Item 5' />,
<Tab key={6} label='Item 6' disabled />,
<Tab key={7} label='Item 7' />,
<Tab key={8} label='Item 8' />,
<Tab key={9} label='Item 9' disabled />,
<Tab key={10} label='Item 10' />,
<Tab key={11} label='Item 11' />,
<Tab key={12} label='Item 12' />,
<Tab key={13} label='Very long item number thirteen' />,
];

return (
<div
style={{
height: '50vh',
maxHeight: 400,
minHeight: 100,
border: '1px solid lightpink',
padding: 8,
}}
>
<Tabs
orientation='vertical'
type='default'
labels={labels}
overflowOptions={{ useOverflow: true }}
{...args}
onTabSelected={setActiveIndex}
activeIndex={activeIndex}
actions={[<Button key={'button'}>Button</Button>]}
>
{getContent()}
</Tabs>
</div>
);
};
VerticalOverflow.args = {
orientation: 'vertical',
type: 'default',
labels: [
<Tab key={1} label='Item 1' />,
<Tab key={2} label='Item 2' />,
<Tab key={3} label='Item 3' />,
<Tab key={4} label='Item 4' />,
<Tab key={5} label='Item 5' />,
<Tab key={6} label='Item 6' disabled />,
<Tab key={7} label='Item 7' />,
<Tab key={8} label='Item 8' />,
<Tab key={9} label='Item 9' disabled />,
<Tab key={10} label='Item 10' />,
<Tab key={11} label='Item 11' />,
<Tab key={12} label='Item 12' />,
<Tab key={13} label='Very long item number thirteen' />,
],
};
VerticalOverflow.argTypes = {
type: { options: ['default', 'borderless'] },
orientation: { control: { disable: true } },
actions: { control: { disable: true } },
};

export const Vertical: Story<Partial<TabsProps>> = (args) => {
const [index, setIndex] = React.useState(0);
const getContent = () => {
Expand Down
14 changes: 14 additions & 0 deletions apps/storybook/src/Tabs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ describe('Tabs', () => {
'Pill Tabs',
'Sublabels And Icons',
'Vertical',
'Horizontal Overflow',
'Vertical Overflow',
];

tests.forEach((testName) => {
Expand All @@ -18,6 +20,18 @@ describe('Tabs', () => {
cy.visit('iframe', { qs: { id } });
cy.wait(1000); // wait for resize observer to be done
cy.compareSnapshot(testName);

if (testName === 'Horizontal Overflow') {
const tabs = cy.get('li > button.iui-tab').should('have.length', 13);

tabs.last().focus();
cy.compareSnapshot(`${testName} (Scroll end)`);

// cy somehow loses tabs list and does not focus on first element so getting it again.
cy.focused().blur();
cy.get('li > button.iui-tab').first().focus();
cy.compareSnapshot(`${testName} (Scroll start)`);
}
});
});
});
53 changes: 53 additions & 0 deletions apps/website/src/examples/Tabs.overflow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import * as React from 'react';
import { Tabs, Tab } from '@itwin/itwinui-react';

export default () => {
const [index, setIndex] = React.useState(0);
const getContent = () => {
switch (index) {
case 0:
return 'Bentley Systems, Incorporated, is an American-based software development company that develops, manufactures, licenses, sells and supports computer software and services for the design, construction, and operation of infrastructure.';
case 1:
return "The company's software serves the building, plant, civil, and geospatial markets in the areas of architecture, engineering, construction (AEC) and operations.";
case 2:
return 'Their software products are used to design, engineer, build, and operate large constructed assets such as roadways, railways, bridges, buildings, industrial plants, power plants, and utility networks.';
case 3:
return 'The company re-invests 20% of their revenues in research and development.';
case 4:
return 'Bentley Systems is headquartered in Exton, Pennsylvania, United States, but has development, sales and other departments in over 50 countries.';
case 5:
return 'The company had revenues of $700 million in 2018.';
case 6:
return 'Keith A. Bentley and Barry J. Bentley founded Bentley Systems in 1984.';
default:
return 'They introduced the commercial version of PseudoStation in 1985, which allowed users of Intergraphs VAX systems to use low-cost graphics terminals to view and modify the designs on their Intergraph IGDS (Interactive Graphics Design System) installations.';
}
};
const labels = [
<Tab key={1} label='Bentley Overview' />,
<Tab key={2} label='Markets' />,
<Tab key={3} label='Uses' />,
<Tab key={4} label='Reinvestment' />,
<Tab key={5} label='Location' />,
<Tab key={6} label='Revenue' />,
<Tab key={7} label='Founders' />,
<Tab key={8} label='History' />,
];

return (
<div style={{ maxWidth: 425, border: '1px solid lightpink', padding: 8 }}>
<Tabs
labels={labels}
overflowOptions={{ useOverflow: true }}
onTabSelected={setIndex}
activeIndex={index}
>
{getContent()}
</Tabs>
</div>
);
};
1 change: 1 addition & 0 deletions apps/website/src/examples/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ export { default as SurfaceNoPaddingExample } from './Surface.nopadding';
export { default as TableMainExample } from './Table.main';

export { default as TabsMainExample } from './Tabs.main';
export { default as TabsOverflowExample } from './Tabs.overflow';

export { default as TagMainExample } from './Tag.main';
export { default as TagBasicExample } from './Tag.basic';
Expand Down
10 changes: 10 additions & 0 deletions apps/website/src/pages/docs/tabs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ import * as AllExamples from '~/examples';
<AllExamples.TabsMainExample client:load />
</LiveExample>

## Usage

### Overflow

If the available space does not allow all the tabs to be displayed, set `useOverflow` of `OverflowOptions` to true. This allows tabs to be scrollable.

<LiveExample src='Tabs.overflow.tsx'>
<AllExamples.TabsOverflowExample client:load />
</LiveExample>

## Props

<PropsTable path={frontmatter.propsPath} />
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions packages/itwinui-css/backstop/scenarios/tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ module.exports = [
selectors: ['#demo-default-vertical'],
viewports: [{ width: 800, height: 600 }],
}),
scenario('Type Overflow', {
selectors: ['#demo-overflow'],
viewports: [{ width: 800, height: 600 }],
}),
scenario('Type borderless', {
selectors: ['#demo-borderless'],
viewports: [{ width: 800, height: 600 }],
Expand Down
Loading

0 comments on commit 6183552

Please sign in to comment.