|
1 |
| -import { Button, Dialog, Tab, TabList, TabPanel, TabProvider } from '@lumx/react'; |
| 1 | +/* eslint-disable react-hooks/rules-of-hooks */ |
| 2 | + |
| 3 | +import { Alignment, Button, Dialog, Tab, TabList, TabListLayout, TabPanel, TabProvider } from '@lumx/react'; |
| 4 | +import { iconArgType } from '@lumx/react/stories/controls/icons'; |
| 5 | +import { getSelectArgType } from '@lumx/react/stories/controls/selectArgType'; |
| 6 | +import { withNestedProps } from '@lumx/react/stories/decorators/withNestedProps'; |
| 7 | +import { toFlattenProps } from '@lumx/react/stories/utils/toFlattenProps'; |
| 8 | +import { withCategory } from '@lumx/react/stories/utils/withCategory'; |
2 | 9 | import get from 'lodash/get';
|
3 | 10 | import times from 'lodash/times';
|
4 | 11 | import React, { useState } from 'react';
|
5 | 12 |
|
6 |
| -export default { title: 'LumX components/tabs' }; |
| 13 | +export default { |
| 14 | + title: 'LumX components/tabs', |
| 15 | + decorators: [withNestedProps()], |
| 16 | + parameters: { controls: { sort: 'alpha' } }, |
| 17 | +}; |
| 18 | + |
| 19 | +/** Default tab behavior with some controllable args */ |
| 20 | +export const Default = { |
| 21 | + render: ({ theme, tabProviderProps, tabListProps, tabProps }: any) => ( |
| 22 | + <TabProvider {...tabProviderProps}> |
| 23 | + <TabList theme={theme} aria-label="Tab list" {...tabListProps}> |
| 24 | + <Tab {...tabProps[0]} /> |
| 25 | + <Tab {...tabProps[1]} /> |
| 26 | + <Tab {...tabProps[2]} /> |
| 27 | + </TabList> |
| 28 | + <TabPanel className="lumx-spacing-padding-huge">{tabProps[0].label} content</TabPanel> |
| 29 | + <TabPanel className="lumx-spacing-padding-huge">{tabProps[1].label} content</TabPanel> |
| 30 | + <TabPanel className="lumx-spacing-padding-huge">{tabProps[2].label} content</TabPanel> |
| 31 | + </TabProvider> |
| 32 | + ), |
| 33 | + args: toFlattenProps({ |
| 34 | + tabProps: [ |
| 35 | + { label: 'Tab 1' }, |
| 36 | + { |
| 37 | + label: 'Tab 2', |
| 38 | + isDisabled: true, |
| 39 | + }, |
| 40 | + { label: 'Tab 3' }, |
| 41 | + ], |
| 42 | + }), |
| 43 | + argTypes: toFlattenProps({ |
| 44 | + tabProviderProps: withCategory('Tab Provider', { |
| 45 | + isLazy: { control: 'boolean' }, |
| 46 | + shouldActivateOnFocus: { control: 'boolean' }, |
| 47 | + }), |
| 48 | + tabListProps: withCategory('Tab List', { |
| 49 | + layout: getSelectArgType(TabListLayout), |
| 50 | + position: getSelectArgType([Alignment.left, Alignment.center, Alignment.right]), |
| 51 | + }), |
| 52 | + tabProps: times(3, (index) => |
| 53 | + withCategory(`Tab ${index + 1}`, { |
| 54 | + label: { control: 'text' }, |
| 55 | + icon: iconArgType, |
| 56 | + isDisabled: { control: 'boolean' }, |
| 57 | + }), |
| 58 | + ), |
| 59 | + }), |
| 60 | +}; |
7 | 61 |
|
8 | 62 | /* Control active tab externally (with activate tab on focus). */
|
9 |
| -export const Controlled = ({ theme }: any) => { |
10 |
| - const [activeTab, setActiveTab] = useState(1); |
11 |
| - const changeActiveTabIndex = (evt: any) => setActiveTab(parseInt(get(evt, 'target.value', '0'), 10)); |
| 63 | +export const Controlled = { |
| 64 | + render({ theme }: any) { |
| 65 | + const [activeTab, setActiveTab] = useState(1); |
| 66 | + const changeActiveTabIndex = (evt: any) => setActiveTab(parseInt(get(evt, 'target.value', '0'), 10)); |
12 | 67 |
|
13 |
| - const [isLazy, setIsLazy] = useState(true); |
14 |
| - const changeIsLazy = (evt: any) => setIsLazy(get(evt, 'target.checked')); |
| 68 | + const [isLazy, setIsLazy] = useState(true); |
| 69 | + const changeIsLazy = (evt: any) => setIsLazy(get(evt, 'target.checked')); |
15 | 70 |
|
16 |
| - const [shouldActivateOnFocus, setShouldActivateOnFocus] = useState(true); |
17 |
| - const changeShouldActivateOnFocus = (evt: any) => setShouldActivateOnFocus(get(evt, 'target.checked')); |
| 71 | + const [shouldActivateOnFocus, setShouldActivateOnFocus] = useState(true); |
| 72 | + const changeShouldActivateOnFocus = (evt: any) => setShouldActivateOnFocus(get(evt, 'target.checked')); |
18 | 73 |
|
19 |
| - return ( |
20 |
| - <> |
21 |
| - <div> |
22 |
| - Active tab index: |
23 |
| - <input type="number" min={0} max={2} value={activeTab} onChange={changeActiveTabIndex} /> |
24 |
| - </div> |
| 74 | + return ( |
| 75 | + <> |
| 76 | + <div> |
| 77 | + Active tab index: |
| 78 | + <input type="number" min={0} max={2} value={activeTab} onChange={changeActiveTabIndex} /> |
| 79 | + </div> |
25 | 80 |
|
26 |
| - <div> |
27 |
| - Lazy render tab panel content: |
28 |
| - <input type="checkbox" checked={isLazy} onChange={changeIsLazy} /> |
29 |
| - </div> |
| 81 | + <div> |
| 82 | + Lazy render tab panel content: |
| 83 | + <input type="checkbox" checked={isLazy} onChange={changeIsLazy} /> |
| 84 | + </div> |
30 | 85 |
|
31 |
| - <div> |
32 |
| - Activate tab on focus: |
33 |
| - <input type="checkbox" checked={shouldActivateOnFocus} onChange={changeShouldActivateOnFocus} /> |
34 |
| - </div> |
35 |
| - <TabProvider |
36 |
| - activeTabIndex={activeTab} |
37 |
| - onChange={setActiveTab} |
38 |
| - isLazy={isLazy} |
39 |
| - shouldActivateOnFocus={shouldActivateOnFocus} |
40 |
| - > |
41 |
| - <TabList theme={theme} aria-label="Tab list"> |
42 |
| - <Tab label="Tab a" /> |
43 |
| - <Tab label="Tab b" /> |
44 |
| - <Tab label="Tab c" /> |
45 |
| - </TabList> |
| 86 | + <div> |
| 87 | + Activate tab on focus: |
| 88 | + <input type="checkbox" checked={shouldActivateOnFocus} onChange={changeShouldActivateOnFocus} /> |
| 89 | + </div> |
| 90 | + <TabProvider |
| 91 | + activeTabIndex={activeTab} |
| 92 | + onChange={setActiveTab} |
| 93 | + isLazy={isLazy} |
| 94 | + shouldActivateOnFocus={shouldActivateOnFocus} |
| 95 | + > |
| 96 | + <TabList theme={theme} aria-label="Tab list"> |
| 97 | + <Tab label="Tab a" /> |
| 98 | + <Tab label="Tab b" /> |
| 99 | + <Tab label="Tab c" /> |
| 100 | + </TabList> |
46 | 101 |
|
47 |
| - <TabPanel className="lumx-spacing-padding-huge">Tab a content</TabPanel> |
48 |
| - <TabPanel className="lumx-spacing-padding-huge">Tab b content</TabPanel> |
49 |
| - <TabPanel className="lumx-spacing-padding-huge">Tab c content</TabPanel> |
50 |
| - </TabProvider> |
51 |
| - </> |
52 |
| - ); |
| 102 | + <TabPanel className="lumx-spacing-padding-huge">Tab a content</TabPanel> |
| 103 | + <TabPanel className="lumx-spacing-padding-huge">Tab b content</TabPanel> |
| 104 | + <TabPanel className="lumx-spacing-padding-huge">Tab c content</TabPanel> |
| 105 | + </TabProvider> |
| 106 | + </> |
| 107 | + ); |
| 108 | + }, |
| 109 | + chromatic: { disable: true }, |
53 | 110 | };
|
54 | 111 |
|
55 | 112 | /* Display tabs far from their tab panels. */
|
56 |
| -export const SplitTabListAndTabPanels = ({ theme }: any) => { |
57 |
| - const [isOpen, setOpen] = useState(true); |
58 |
| - const [activeTabIndex, onChange] = useState(1); |
| 113 | +export const SplitTabListAndTabPanels = { |
| 114 | + render({ theme }: any) { |
| 115 | + const [isOpen, setOpen] = useState(true); |
| 116 | + const [activeTabIndex, onChange] = useState(1); |
59 | 117 |
|
60 |
| - return ( |
61 |
| - <TabProvider activeTabIndex={activeTabIndex} onChange={onChange} isLazy={false}> |
62 |
| - <Button |
63 |
| - onClick={() => { |
64 |
| - setOpen(!isOpen); |
65 |
| - onChange(1); |
66 |
| - }} |
67 |
| - > |
68 |
| - Open dialog with tabs in footer |
69 |
| - </Button> |
70 |
| - <Dialog isOpen={isOpen} forceFooterDivider onClose={() => setOpen(false)}> |
71 |
| - <TabPanel className="lumx-spacing-padding-huge">Tab 1 content</TabPanel> |
72 |
| - <TabPanel className="lumx-spacing-padding-huge">Tab 2 content</TabPanel> |
73 |
| - <TabPanel className="lumx-spacing-padding-huge">Tab 3 content</TabPanel> |
| 118 | + return ( |
| 119 | + <TabProvider activeTabIndex={activeTabIndex} onChange={onChange} isLazy={false}> |
| 120 | + <Button |
| 121 | + onClick={() => { |
| 122 | + setOpen(!isOpen); |
| 123 | + onChange(1); |
| 124 | + }} |
| 125 | + > |
| 126 | + Open dialog with tabs in footer |
| 127 | + </Button> |
| 128 | + <Dialog isOpen={isOpen} forceFooterDivider onClose={() => setOpen(false)}> |
| 129 | + <TabPanel className="lumx-spacing-padding-huge">Tab 1 content</TabPanel> |
| 130 | + <TabPanel className="lumx-spacing-padding-huge">Tab 2 content</TabPanel> |
| 131 | + <TabPanel className="lumx-spacing-padding-huge">Tab 3 content</TabPanel> |
74 | 132 |
|
75 |
| - <footer> |
76 |
| - <TabList theme={theme} aria-label="Tab list"> |
77 |
| - <Tab label="Tab 1" /> |
78 |
| - <Tab label="Tab 2" /> |
79 |
| - <Tab label="Tab 3" /> |
80 |
| - </TabList> |
81 |
| - </footer> |
82 |
| - </Dialog> |
83 |
| - </TabProvider> |
84 |
| - ); |
| 133 | + <footer> |
| 134 | + <TabList theme={theme} aria-label="Tab list"> |
| 135 | + <Tab label="Tab 1" /> |
| 136 | + <Tab label="Tab 2" /> |
| 137 | + <Tab label="Tab 3" /> |
| 138 | + </TabList> |
| 139 | + </footer> |
| 140 | + </Dialog> |
| 141 | + </TabProvider> |
| 142 | + ); |
| 143 | + }, |
| 144 | + chromatic: { disable: true }, |
85 | 145 | };
|
86 | 146 |
|
87 | 147 | /* Dynamically generate tabs. */
|
88 |
| -export const DynamicTabs = ({ theme, tabCount }: any) => { |
89 |
| - return ( |
90 |
| - <TabProvider> |
91 |
| - <TabList theme={theme} aria-label="Tab list"> |
| 148 | +export const DynamicTabs = { |
| 149 | + render({ theme, tabCount }: any) { |
| 150 | + return ( |
| 151 | + <TabProvider> |
| 152 | + <TabList theme={theme} aria-label="Tab list"> |
| 153 | + {times(tabCount, (tabNumber) => ( |
| 154 | + <Tab key={tabNumber} label={`Tab ${tabNumber}`} /> |
| 155 | + ))} |
| 156 | + </TabList> |
| 157 | + |
92 | 158 | {times(tabCount, (tabNumber) => (
|
93 |
| - <Tab key={tabNumber} label={`Tab ${tabNumber}`} /> |
| 159 | + <TabPanel key={tabNumber} className="lumx-spacing-padding-huge"> |
| 160 | + Tab {tabNumber} content |
| 161 | + </TabPanel> |
94 | 162 | ))}
|
95 |
| - </TabList> |
96 |
| - |
97 |
| - {times(tabCount, (tabNumber) => ( |
98 |
| - <TabPanel key={tabNumber} className="lumx-spacing-padding-huge"> |
99 |
| - Tab {tabNumber} content |
100 |
| - </TabPanel> |
101 |
| - ))} |
102 |
| - </TabProvider> |
103 |
| - ); |
104 |
| -}; |
105 |
| -DynamicTabs.args = { |
106 |
| - tabCount: 3, |
| 163 | + </TabProvider> |
| 164 | + ); |
| 165 | + }, |
| 166 | + args: { |
| 167 | + tabCount: 3, |
| 168 | + }, |
| 169 | + chromatic: { disable: true }, |
107 | 170 | };
|
0 commit comments