123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- import {Fragment, useState} from 'react';
- import range from 'lodash/range';
- import JSXNode from 'sentry/components/stories/jsxNode';
- import Matrix from 'sentry/components/stories/matrix';
- import SideBySide from 'sentry/components/stories/sideBySide';
- import SizingWindow from 'sentry/components/stories/sizingWindow';
- import {TabList, TabListProps, TabPanels, Tabs, TabsProps} from 'sentry/components/tabs';
- import storyBook from 'sentry/stories/storyBook';
- export default storyBook(Tabs, story => {
- const TABS = [
- {key: 'one', label: 'One', content: 'This is the first Panel.'},
- {key: 'two', label: 'Two', content: 'This is the second panel'},
- {key: 'three', label: 'Three', content: 'This is the third panel'},
- ];
- story('Default', () => (
- <Fragment>
- <p>
- You should be using all of <JSXNode name="Tabs" />, <JSXNode name="TabList" />,{' '}
- <JSXNode name="TabList.Item" />, <JSXNode name="TabPanels" /> and
- <JSXNode name="TabPanels.Item" /> components.
- </p>
- <p>
- This will give you all kinds of accessibility and state tracking out of the box.
- But you will have to render all tab content, including hooks, upfront.
- </p>
- <SizingWindow>
- <Tabs>
- <TabList>
- {TABS.map(tab => (
- <TabList.Item key={tab.key}>{tab.label}</TabList.Item>
- ))}
- </TabList>
- <TabPanels>
- {TABS.map(tab => (
- <TabPanels.Item key={tab.key}>{tab.content}</TabPanels.Item>
- ))}
- </TabPanels>
- </Tabs>
- </SizingWindow>
- </Fragment>
- ));
- story('Items Overflow', () => {
- const tabs = range(65, 75).map(i => ({
- key: 'i' + i,
- label: String.fromCharCode(i, i, i, i),
- content: String.fromCharCode(i, i, i, i),
- }));
- return (
- <Fragment>
- <p>When there are many items, they will overflow into a dropdown menu.</p>
- <SizingWindow display="block" style={{height: '210px', width: '400px'}}>
- <Tabs defaultValue="two">
- <TabList>
- {tabs.map(tab => (
- <TabList.Item key={tab.key}>{tab.label}</TabList.Item>
- ))}
- </TabList>
- </Tabs>
- </SizingWindow>
- </Fragment>
- );
- });
- story('Default Value', () => (
- <Fragment>
- <p>
- Set <JSXNode name="Tabs" props={{defaultValue: String}} />
- </p>
- <SizingWindow>
- <Tabs defaultValue="two">
- <TabList>
- {TABS.map(tab => (
- <TabList.Item key={tab.key}>{tab.label}</TabList.Item>
- ))}
- </TabList>
- <TabPanels>
- {TABS.map(tab => (
- <TabPanels.Item key={tab.key}>{tab.content}</TabPanels.Item>
- ))}
- </TabPanels>
- </Tabs>
- </SizingWindow>
- </Fragment>
- ));
- story('Controlled Value', () => {
- const [selected, setSelected] = useState('two');
- return (
- <Fragment>
- <p>
- If you want to control the state of the tabs from outside, you can call{' '}
- <var>{'useState()'}</var> and set{' '}
- <JSXNode name="Tabs" props={{value: String, onChange: Function}} /> manually.
- </p>
- <p>
- This is useful if you want to detect button clicks and do something different.{' '}
- The <JSXNode name="Tabs" /> context wrapper is not required in this case.
- </p>
- <p>selected={selected}</p>
- <SizingWindow>
- <Tabs value={selected} onChange={setSelected}>
- <TabList>
- {TABS.map(tab => (
- <TabList.Item key={tab.key}>{tab.label}</TabList.Item>
- ))}
- </TabList>
- <TabPanels>
- {TABS.map(tab => (
- <TabPanels.Item key={tab.key}>{tab.content}</TabPanels.Item>
- ))}
- </TabPanels>
- </Tabs>
- </SizingWindow>
- </Fragment>
- );
- });
- story('Rendering', () => (
- <Matrix<TabsProps<string> & TabListProps>
- render={props => (
- <Tabs orientation={props.orientation}>
- <TabList hideBorder={props.hideBorder}>
- {TABS.map(tab => (
- <TabList.Item key={tab.key}>{tab.label}</TabList.Item>
- ))}
- </TabList>
- <TabPanels>
- {TABS.map(tab => (
- <TabPanels.Item key={tab.key}>{tab.content}</TabPanels.Item>
- ))}
- </TabPanels>
- </Tabs>
- )}
- propMatrix={{
- orientation: ['horizontal', 'vertical'],
- hideBorder: [false, true],
- }}
- selectedProps={['orientation', 'hideBorder']}
- />
- ));
- story('Disabled', () => (
- <SideBySide>
- <div>
- <p>
- Use <JSXNode name="Tabs" props={{disabled: true}} /> to disable everything.
- </p>
- <SizingWindow>
- <Tabs disabled>
- <TabList>
- {TABS.map(tab => (
- <TabList.Item key={tab.key}>{tab.label}</TabList.Item>
- ))}
- </TabList>
- <TabPanels>
- {TABS.map(tab => (
- <TabPanels.Item key={tab.key}>{tab.content}</TabPanels.Item>
- ))}
- </TabPanels>
- </Tabs>
- </SizingWindow>
- </div>
- <div>
- <p>
- Use <JSXNode name="TabList" props={{disabledKeys: Array}} /> to disable
- individual <JSXNode name="TabList.Item" /> children.
- </p>
- <SizingWindow>
- <Tabs>
- <TabList disabledKeys={['two']}>
- {TABS.map(tab => (
- <TabList.Item key={tab.key}>{tab.label}</TabList.Item>
- ))}
- </TabList>
- <TabPanels>
- {TABS.map(tab => (
- <TabPanels.Item key={tab.key}>{tab.content}</TabPanels.Item>
- ))}
- </TabPanels>
- </Tabs>
- </SizingWindow>
- </div>
- </SideBySide>
- ));
- });
|