diff --git a/static/app/components/tabs/index.stories.tsx b/static/app/components/tabs/index.stories.tsx new file mode 100644 index 00000000000000..f586bd86a6bf6f --- /dev/null +++ b/static/app/components/tabs/index.stories.tsx @@ -0,0 +1,191 @@ +import {Fragment, useState} from 'react'; +import range from 'lodash/range'; + +import Matrix from 'sentry/components/stories/matrix'; +import SideBySide from 'sentry/components/stories/sideBySide'; +import SizingWindow from 'sentry/components/stories/sizingWindow'; +import {TabList, TabPanels, Tabs} 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', () => ( + +

+ You should be using all of {''}, {''},{' '} + {''}, {''} and + {''} components. +

+

+ 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. +

+ + + + {TABS.map(tab => ( + {tab.label} + ))} + + + {TABS.map(tab => ( + {tab.content} + ))} + + + +
+ )); + + 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 ( + +

When there are many items, they will overflow into a dropdown menu.

+ + {/* The inner
is needed because SizingWindow has overflow:hidden */} +
+ + + {tabs.map(tab => ( + {tab.label} + ))} + + +
+ + + ); + }); + + story('Default Value', () => ( + +

+ Set {''} +

+ + + + {TABS.map(tab => ( + {tab.label} + ))} + + + {TABS.map(tab => ( + {tab.content} + ))} + + + +
+ )); + + story('Controlled Value', () => { + const [selected, setSelected] = useState('two'); + return ( + +

+ If you want to control the state of the tabs from outside, you can call{' '} + {'useState()'} and set{' '} + {' ...}>'} manually. +

+

+ This is useful if you want to detect button clicks and do something different.{' '} + The {''} context wrapper is not required in this case. +

+

selected={selected}

+ + + + {TABS.map(tab => ( + {tab.label} + ))} + + + {TABS.map(tab => ( + {tab.content} + ))} + + + +
+ ); + }); + + story('Rendering', () => ( + ( + + + {TABS.map(tab => ( + {tab.label} + ))} + + + {TABS.map(tab => ( + {tab.content} + ))} + + + )} + propMatrix={{ + orientation: ['horizontal', 'vertical'], + hideBorder: [false, true], + }} + selectedProps={['orientation', 'hideBorder']} + /> + )); + + story('Disabled', () => ( + +
+

+ Use <Tabs disabled> to disable everything. +

+ + + + {TABS.map(tab => ( + {tab.label} + ))} + + + {TABS.map(tab => ( + {tab.content} + ))} + + + +
+
+

+ Use {''} to disable individual{' '} + {''} children. +

+ + + + {TABS.map(tab => ( + {tab.label} + ))} + + + {TABS.map(tab => ( + {tab.content} + ))} + + + +
+
+ )); +}); diff --git a/static/app/stories/storyBook.tsx b/static/app/stories/storyBook.tsx index 31e142985dd039..1a247a2a2969cd 100644 --- a/static/app/stories/storyBook.tsx +++ b/static/app/stories/storyBook.tsx @@ -45,6 +45,10 @@ export default function storyBook(rootName: string, setup: SetupFn) { const Story = styled('section')` margin-bottom: ${space(4)}; + + & > p { + margin: ${space(3)} 0; + } `; const StoryTitle = styled('h4')`