diff --git a/packages/@react-aria/tabs/src/index.ts b/packages/@react-aria/tabs/src/index.ts index 903442d05fa..6908022969f 100644 --- a/packages/@react-aria/tabs/src/index.ts +++ b/packages/@react-aria/tabs/src/index.ts @@ -10,4 +10,6 @@ * governing permissions and limitations under the License. */ -export * from './useTabs'; +export * from './useTab'; +export * from './useTabPanel'; +export * from './useTabList'; diff --git a/packages/@react-aria/tabs/src/useTab.ts b/packages/@react-aria/tabs/src/useTab.ts new file mode 100644 index 00000000000..abac01f391f --- /dev/null +++ b/packages/@react-aria/tabs/src/useTab.ts @@ -0,0 +1,59 @@ +/* + * Copyright 2020 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {AriaTabProps} from '@react-types/tabs'; +import {generateId} from './utils'; +import {HTMLAttributes, RefObject} from 'react'; +import {SingleSelectListState} from '@react-stately/list'; +import {usePress} from '@react-aria/interactions'; +import {useSelectableItem} from '@react-aria/selection'; + +interface TabAria { + /** Props for the tab element. */ + tabProps: HTMLAttributes +} + +export function useTab( + props: AriaTabProps, + state: SingleSelectListState, + ref: RefObject +): TabAria { + let {key, isDisabled: propsDisabled} = props; + let {selectionManager: manager, selectedKey} = state; + + let isSelected = key === selectedKey; + + let {itemProps} = useSelectableItem({ + selectionManager: manager, + key, + ref + }); + let isDisabled = propsDisabled || state.disabledKeys.has(key); + + let {pressProps} = usePress({...itemProps, isDisabled}); + let tabId = generateId(state, key, 'tab'); + let tabPanelId = generateId(state, key, 'tabpanel'); + let {tabIndex} = pressProps; + + return { + tabProps: { + ...pressProps, + id: tabId, + 'aria-selected': isSelected, + 'aria-disabled': isDisabled || undefined, + 'aria-controls': isSelected ? tabPanelId : undefined, + tabIndex: isDisabled ? undefined : tabIndex, + role: 'tab' + } + }; +} + diff --git a/packages/@react-aria/tabs/src/useTabList.ts b/packages/@react-aria/tabs/src/useTabList.ts new file mode 100644 index 00000000000..386c0b9fbb6 --- /dev/null +++ b/packages/@react-aria/tabs/src/useTabList.ts @@ -0,0 +1,66 @@ +/* +* Copyright 2020 Adobe. All rights reserved. +* This file is licensed to you under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. You may obtain a copy +* of the License at http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software distributed under +* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +* OF ANY KIND, either express or implied. See the License for the specific language +* governing permissions and limitations under the License. +*/ + +import {AriaTabListProps} from '@react-types/tabs'; +import {HTMLAttributes, useMemo} from 'react'; +import {mergeProps, useId, useLabels} from '@react-aria/utils'; +import {TabListState} from '@react-stately/tabs'; +import {tabsIds} from './utils'; +import {TabsKeyboardDelegate} from './TabsKeyboardDelegate'; +import {useLocale} from '@react-aria/i18n'; +import {useSelectableCollection} from '@react-aria/selection'; + +interface TabListAria { + /** Props for the tablist container. */ + tabListProps: HTMLAttributes +} + +export function useTabList(props: AriaTabListProps, state: TabListState, ref): TabListAria { + let { + orientation = 'horizontal', + keyboardActivation = 'automatic' + } = props; + let { + collection, + selectionManager: manager, + disabledKeys + } = state; + let {direction} = useLocale(); + let delegate = useMemo(() => new TabsKeyboardDelegate( + collection, + direction, + orientation, + disabledKeys), [collection, disabledKeys, orientation, direction]); + + let {collectionProps} = useSelectableCollection({ + ref, + selectionManager: manager, + keyboardDelegate: delegate, + selectOnFocus: keyboardActivation === 'automatic', + disallowEmptySelection: true + }); + + // Compute base id for all tabs + let tabsId = useId(); + tabsIds.set(state, tabsId); + + let tabListLabelProps = useLabels({...props, id: tabsId}); + + return { + tabListProps: { + ...mergeProps(collectionProps, tabListLabelProps), + role: 'tablist', + 'aria-orientation': orientation, + tabIndex: undefined + } + }; +} diff --git a/packages/@react-aria/tabs/src/useTabPanel.ts b/packages/@react-aria/tabs/src/useTabPanel.ts new file mode 100644 index 00000000000..ffcc6f334ac --- /dev/null +++ b/packages/@react-aria/tabs/src/useTabPanel.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2020 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {AriaTabPanelProps} from '@react-types/tabs'; +import {generateId} from './utils'; +import {HTMLAttributes} from 'react'; +import {mergeProps} from '@react-aria/utils'; +import {TabListState} from '@react-stately/tabs'; + +interface TabPanelAria { + /** Props for the tab panel element. */ + tabPanelProps: HTMLAttributes +} + +export function useTabPanel(props: AriaTabPanelProps, state: TabListState): TabPanelAria { + return { + tabPanelProps: mergeProps(props, { + id: generateId(state, state?.selectedKey, 'tabpanel'), + 'aria-labelledby': generateId(state, state?.selectedKey, 'tab'), + tabIndex: 0, + role: 'tabpanel' + }) + }; +} diff --git a/packages/@react-aria/tabs/src/useTabs.ts b/packages/@react-aria/tabs/src/useTabs.ts deleted file mode 100644 index 2684c889786..00000000000 --- a/packages/@react-aria/tabs/src/useTabs.ts +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2020 Adobe. All rights reserved. - * This file is licensed to you under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - * OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - */ - -import {AriaTabProps, AriaTabsProps} from '@react-types/tabs'; -import {HTMLAttributes, Key, RefObject, useMemo} from 'react'; -import {mergeProps, useId, useLabels} from '@react-aria/utils'; -import {SingleSelectListState} from '@react-stately/list'; -import {TabsKeyboardDelegate} from './TabsKeyboardDelegate'; -import {TabsState} from '@react-stately/tabs'; -import {useLocale} from '@react-aria/i18n'; -import {usePress} from '@react-aria/interactions'; -import {useSelectableCollection, useSelectableItem} from '@react-aria/selection'; - -interface TabsAria { - /** Props for the tablist container. */ - tabListProps: HTMLAttributes, - /** Props for the associated tabpanel element. */ - tabPanelProps: HTMLAttributes -} - -const tabsIds = new WeakMap, string>(); - -export function useTabs(props: AriaTabsProps, state: TabsState, ref): TabsAria { - let { - orientation = 'horizontal', - keyboardActivation = 'automatic' - } = props; - let { - collection, - selectionManager: manager, - disabledKeys, - selectedKey - } = state; - let {direction} = useLocale(); - let delegate = useMemo(() => new TabsKeyboardDelegate( - collection, - direction, - orientation, - disabledKeys), [collection, disabledKeys, orientation, direction]); - - let {collectionProps} = useSelectableCollection({ - ref, - selectionManager: manager, - keyboardDelegate: delegate, - selectOnFocus: keyboardActivation === 'automatic', - disallowEmptySelection: true - }); - - // Compute base id for all tabs - let tabsId = useId(); - tabsIds.set(state, tabsId); - - let tabListLabelProps = useLabels({...props, id: tabsId}); - - return { - tabListProps: { - ...mergeProps(collectionProps, tabListLabelProps), - role: 'tablist', - 'aria-orientation': orientation, - tabIndex: undefined - }, - tabPanelProps: { - id: generateId(state, selectedKey, 'tabpanel'), - 'aria-labelledby': generateId(state, selectedKey, 'tab'), - tabIndex: 0, - role: 'tabpanel' - } - }; -} - -interface TabAria { - /** Props for the tab element. */ - tabProps: HTMLAttributes -} - -export function useTab( - props: AriaTabProps, - state: SingleSelectListState, - ref: RefObject -): TabAria { - let {item, isDisabled: propsDisabled} = props; - let {key} = item; - let {selectionManager: manager, selectedKey} = state; - - let isSelected = key === selectedKey; - - let {itemProps} = useSelectableItem({ - selectionManager: manager, - key, - ref - }); - let isDisabled = propsDisabled || state.disabledKeys.has(key); - - let {pressProps} = usePress({...itemProps, isDisabled}); - let tabId = generateId(state, key, 'tab'); - let tabPanelId = generateId(state, key, 'tabpanel'); - let {tabIndex} = pressProps; - - // selected tab should have tabIndex=0, when it initializes - if (isSelected && !isDisabled) { - tabIndex = 0; - } - - return { - tabProps: { - ...pressProps, - id: tabId, - 'aria-selected': isSelected, - 'aria-disabled': isDisabled || undefined, - 'aria-controls': isSelected ? tabPanelId : undefined, - tabIndex: isDisabled ? undefined : tabIndex, - role: 'tab' - } - }; -} - -function generateId(state: SingleSelectListState, key: Key, role: string) { - if (typeof key === 'string') { - key = key.replace(/\s+/g, ''); - } - - let baseId = tabsIds.get(state); - return `${baseId}-${role}-${key}`; -} diff --git a/packages/@react-aria/tabs/src/utils.ts b/packages/@react-aria/tabs/src/utils.ts new file mode 100644 index 00000000000..3c125a0d303 --- /dev/null +++ b/packages/@react-aria/tabs/src/utils.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2020 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {Key} from 'react'; +import {SingleSelectListState} from '@react-stately/list'; + +export const tabsIds = new WeakMap, string>(); + +export function generateId(state: SingleSelectListState, key: Key, role: string) { + if (typeof key === 'string') { + key = key.replace(/\s+/g, ''); + } + + let baseId = tabsIds.get(state); + return `${baseId}-${role}-${key}`; +} + diff --git a/packages/@react-spectrum/tabs/src/Tabs.tsx b/packages/@react-spectrum/tabs/src/Tabs.tsx index 75f188dbe5e..b65b270b6b9 100644 --- a/packages/@react-spectrum/tabs/src/Tabs.tsx +++ b/packages/@react-spectrum/tabs/src/Tabs.tsx @@ -14,26 +14,44 @@ import {classNames, SlotProvider, unwrapDOMRef, useDOMRef, useStyleProps, useVal import {DOMProps, DOMRef, Node, Orientation} from '@react-types/shared'; import {FocusRing} from '@react-aria/focus'; import {Item, Picker} from '@react-spectrum/picker'; +import {ListCollection, SingleSelectListState} from '@react-stately/list'; import {mergeProps, useId, useLayoutEffect} from '@react-aria/utils'; -import React, {HTMLAttributes, Key, MutableRefObject, ReactElement, useCallback, useEffect, useRef, useState} from 'react'; -import {SingleSelectListState} from '@react-stately/list'; +import React, {Key, MutableRefObject, ReactElement, useCallback, useContext, useEffect, useRef, useState} from 'react'; import {SpectrumPickerProps} from '@react-types/select'; -import {SpectrumTabsProps} from '@react-types/tabs'; +import {SpectrumTabListProps, SpectrumTabPanelsProps, SpectrumTabsProps} from '@react-types/tabs'; import styles from '@adobe/spectrum-css-temp/components/tabs/vars.css'; +import {TabListState, useTabListState} from '@react-stately/tabs'; import {Text} from '@react-spectrum/text'; +import {useCollection} from '@react-stately/collections'; import {useHover} from '@react-aria/interactions'; import {useLocale} from '@react-aria/i18n'; import {useProvider, useProviderProps} from '@react-spectrum/provider'; import {useResizeObserver} from '@react-aria/utils'; -import {useTab, useTabs} from '@react-aria/tabs'; -import {useTabsState} from '@react-stately/tabs'; +import {useTab, useTabList, useTabPanel} from '@react-aria/tabs'; + +interface TabsContext { + tabProps: SpectrumTabsProps, + tabState: { + tabListState: TabListState, + setTabListState: (state: TabListState) => void, + selectedTab: HTMLElement, + collapse: boolean + }, + refs: { + wrapperRef: MutableRefObject, + tablistRef: MutableRefObject + }, + tabPanelProps: { + 'aria-labelledby': string + } +} + +const TabContext = React.createContext>(null); function Tabs(props: SpectrumTabsProps, ref: DOMRef) { props = useProviderProps(props); let { orientation = 'horizontal' as Orientation, - isDisabled, - isQuiet, density = 'regular', children, ...otherProps @@ -42,24 +60,23 @@ function Tabs(props: SpectrumTabsProps, ref: DOMRef(); let wrapperRef = useRef(); - let state = useTabsState(props); let {direction} = useLocale(); let {styleProps} = useStyleProps(otherProps); - let {tabListProps, tabPanelProps} = useTabs(props, state, tablistRef); let [collapse, setCollapse] = useValueEffect(false); let [selectedTab, setSelectedTab] = useState(); + const [tabListState, setTabListState] = useState>(null); useEffect(() => { if (tablistRef.current) { - let selectedTab: HTMLElement = tablistRef.current.querySelector(`[data-key="${state.selectedKey}"]`); + let selectedTab: HTMLElement = tablistRef.current.querySelector(`[data-key="${tabListState?.selectedKey}"]`); if (selectedTab != null) { setSelectedTab(selectedTab); } } // collapse is in the dep array so selectedTab can be updated for TabLine positioning - }, [children, state.selectedKey, collapse, tablistRef]); + }, [children, tabListState?.selectedKey, collapse, tablistRef]); let checkShouldCollapse = useCallback(() => { let computeShouldCollapse = () => { @@ -94,48 +111,35 @@ function Tabs(props: SpectrumTabsProps, ref: DOMRef - {orientation === 'vertical' && - - } - {orientation !== 'vertical' && - - } -
- {state.selectedItem && state.selectedItem.props.children} + +
+ {props.children}
-
+ ); } @@ -146,13 +150,14 @@ interface TabProps extends DOMProps { orientation?: Orientation } -export function Tab(props: TabProps) { +// @private +function Tab(props: TabProps) { let {item, state, isDisabled: propsDisabled} = props; let {key, rendered} = item; let isDisabled = propsDisabled || state.disabledKeys.has(key); let ref = useRef(); - let {tabProps} = useTab({item, isDisabled}, state, ref); + let {tabProps} = useTab({key, isDisabled}, state, ref); let {hoverProps, isHovered} = useHover({ ...props @@ -198,6 +203,7 @@ interface TabLineProps { selectedKey?: Key } +// @private function TabLine(props: TabLineProps) { let { orientation, @@ -238,77 +244,31 @@ function TabLine(props: TabLineProps) { return
; } -interface CollapsibleTabListProps extends TabListProps, TabPickerProps { - tabListProps?: HTMLAttributes, - wrapperRef: MutableRefObject, - collapse?: boolean, - tabListclassName?: string -} - -const CollapsibleTabList = React.forwardRef(function (props: CollapsibleTabListProps, ref: MutableRefObject) { - let { - tabListProps, - density, - isQuiet, - isDisabled, - state, - selectedTab, - wrapperRef, - collapse - } = props; - - let tabListclassName = classNames(styles, 'spectrum-TabsPanel-tabs'); - - return ( -
- {collapse && } - {!collapse && ( - - )} -
- ); -}); +/** + * A TabList is used within Tabs to group tabs that a user can switch between. + * The keys of the items within the must match up with a corresponding item inside the . + */ +export function TabList(props: SpectrumTabListProps) { + const tabContext = useContext(TabContext); + const {refs, tabState, tabProps, tabPanelProps} = tabContext; + const {isQuiet, density, isDisabled, orientation} = tabProps; + const {selectedTab, collapse, setTabListState} = tabState; + const {tablistRef, wrapperRef} = refs; + // Pass original Tab props but override children to create the collection. + const state = useTabListState({...tabProps, children: props.children}); -interface TabListProps { - isQuiet?: boolean, - density?: 'compact' | 'regular', - isDisabled?: boolean, - orientation?: Orientation, - state: SingleSelectListState, - selectedTab: HTMLElement, - className?: string -} + const {tabListProps} = useTabList({...tabProps, ...props}, state, tablistRef); -const TabList = React.forwardRef(function (props: TabListProps, ref: MutableRefObject) { - let { - isQuiet, - density, - state, - isDisabled, - orientation, - selectedTab, - className, - ...otherProps - } = props; + useEffect(() => { + // Passing back to root as useTabPanel needs the TabListState + setTabListState(state); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [state.disabledKeys, state.selectedItem, state.selectedKey, props.children]); - return ( + const tabContent = (
(props: TabListProps, ref: Muta { 'spectrum-Tabs--quiet': isQuiet, ['spectrum-Tabs--compact']: density === 'compact' - }, - className - )}> + })}> {[...state.collection].map((item) => ( ))}
); -}); + + + if (orientation === 'vertical') { + return tabContent; + } else { + let tabListclassName = classNames(styles, 'spectrum-TabsPanel-tabs'); + return ( +
+ {collapse ? : tabContent} +
+ ); + } +} + +/** + * TabPanels is used within Tabs as a container for the content of each tab. + * The keys of the items within the must match up with a corresponding item inside the . + */ +export function TabPanels(props: SpectrumTabPanelsProps) { + const {tabState, tabProps, tabPanelProps: ctxTabPanelProps} = useContext(TabContext); + const {tabListState} = tabState; + const {tabPanelProps} = useTabPanel(props, tabListState); + + if (ctxTabPanelProps['aria-labelledby']) { + tabPanelProps['aria-labelledby'] = ctxTabPanelProps['aria-labelledby']; + } + + const factory = nodes => new ListCollection(nodes); + const collection = useCollection({items: tabProps.items, ...props}, factory); + const selectedItem = tabListState ? collection.getItem(tabListState.selectedKey) : null; + + return ( +
+ {selectedItem && selectedItem.props.children} +
+ ); +} interface TabPickerProps extends SpectrumPickerProps { density?: 'compact' | 'regular', diff --git a/packages/@react-spectrum/tabs/stories/Tabs.stories.js b/packages/@react-spectrum/tabs/stories/Tabs.stories.js index 87a3ba006c4..8aaaff3d958 100644 --- a/packages/@react-spectrum/tabs/stories/Tabs.stories.js +++ b/packages/@react-spectrum/tabs/stories/Tabs.stories.js @@ -11,13 +11,13 @@ */ import {action} from '@storybook/addon-actions'; +import {ActionGroup, Content, Flex, Heading, Text} from '@adobe/react-spectrum'; import Bookmark from '@spectrum-icons/workflow/Bookmark'; import {Button} from '@react-spectrum/button'; import {ButtonGroup} from '@react-spectrum/buttongroup'; import Calendar from '@spectrum-icons/workflow/Calendar'; -import {Content, Flex, Heading, Text} from '@adobe/react-spectrum'; import Dashboard from '@spectrum-icons/workflow/Dashboard'; -import {Item, Tabs} from '..'; +import {Item, TabList, TabPanels, Tabs} from '..'; import React from 'react'; import {storiesOf} from '@storybook/react'; @@ -118,16 +118,22 @@ storiesOf('Tabs', module) () => ( - - - Hello World - - - - - Goodbye World - - + + + + + + + + Hello World + + + + + Goodbye World + + + ) @@ -137,74 +143,97 @@ storiesOf('Tabs', module) () => ( ( - - - Text - - - - - Text 2 - - + + + Tab 1 long long long name + + + Tab 2 + + + + + + Text + + + + + Text 2 + + + ) ) + ) + .add( + 'Tab with flex container in between', + () => ); function render(props = {}) { return ( - - - Tab Body 1 - - Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. - Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. - Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. - - - - - - Tab Body 2 - - Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. - Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. - Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. - - - - - - Tab Body 3 - - Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. - Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. - Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. - - - - - - Tab Body 4 - - Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. - Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. - Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. - - - - - - Tab Body 5 - - Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. - Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. - Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. - - - + + + + + + + + + + + Tab Body 1 + + Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. + Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. + Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. + + + + + + Tab Body 2 + + Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. + Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. + Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. + + + + + + Tab Body 3 + + Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. + Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. + Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. + + + + + + Tab Body 4 + + Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. + Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. + Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. + + + + + + Tab Body 5 + + Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. + Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. + Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. + + + + ); } @@ -212,60 +241,52 @@ function render(props = {}) { function renderWithIcons(props = {}) { return ( - - - Dashboard - - }> - - Dashboard - - Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. - Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. - Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. - - - - - - Calendar - - }> - - Calendar - - Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. - Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. - Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. - - - - - - Bookmark - - }> - - Bookmark - - Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. - Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. - Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. - - - + + + + Dashboard + + + + Calendar + + + + Bookmark + + + + + + Dashboard + + Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. + Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. + Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. + + + + + + Calendar + + Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. + Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. + Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. + + + + + + Bookmark + + Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. + Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. + Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. + + + + ); } @@ -273,56 +294,65 @@ function renderWithIcons(props = {}) { function renderWithFalsyKey(props = {}) { return ( - - - Tab Body 1 - - Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. - Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. - Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. - - - - - - Tab Body 2 - - Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. - Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. - Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. - - - - - - Tab Body 3 - - Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. - Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. - Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. - - - - - - Tab Body 4 - - Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. - Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. - Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. - - - - - - Tab Body 5 - - Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. - Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. - Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. - - - + + + + + + + + + + + Tab Body 1 + + Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. + Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. + Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. + + + + + + Tab Body 2 + + Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. + Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. + Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. + + + + + + Tab Body 3 + + Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. + Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. + Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. + + + + + + Tab Body 4 + + Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. + Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. + Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. + + + + + + Tab Body 5 + + Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. + Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. + Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. + + + + ); } @@ -358,26 +388,28 @@ let DynamicTabs = (props = {}) => { return (
- {item => ( - - {item.icon} - {item.name} - - }> - - {item.children} - - Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. - Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. - Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. - - - - )} + + {item => ( + + {item.icon} + {item.name} + + )} + + + {item => ( + + + {item.children} + + Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. + Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. + Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. + + + + )} +
); }; + + +let DynamicTabsWithDecoration = (props = {}) => { + + let [tabs, setTabs] = React.useState(items); + let addTab = () => { + let newTabs = [...tabs]; + newTabs.push({ + name: `Tab ${tabs.length + 1}`, + children: `Tab Body ${tabs.length + 1}` + }); + + setTabs(newTabs); + }; + + let removeTab = () => { + if (tabs.length > 1) { + let newTabs = [...tabs]; + newTabs.pop(); + setTabs(newTabs); + } + }; + + return ( +
+ + + + + {item => ( + + {item.icon} + {item.name} + + )} + + + val === 'add' ? addTab() : removeTab()}> + + Add Tab + + + Remove Tab + + + + + + {item => ( + + + {item.children} + + Dolore ex esse laboris elit magna esse sunt. Pariatur in veniam Lorem est occaecat do magna nisi mollit ipsum sit adipisicing fugiat ex. Pariatur ullamco exercitation ea qui adipisicing. + Id cupidatat aute id ut excepteur exercitation magna pariatur. Mollit irure irure reprehenderit pariatur eiusmod proident Lorem deserunt duis cillum mollit. Do reprehenderit sit cupidatat quis laborum in do culpa nisi ipsum. Velit aliquip commodo ea ipsum incididunt culpa nostrud deserunt incididunt exercitation. In quis proident sit ad dolore tempor. Eiusmod pariatur quis commodo labore cupidatat cillum enim eiusmod voluptate laborum culpa. Laborum cupidatat incididunt velit voluptate incididunt occaecat quis do. + Consequat adipisicing irure Lorem commodo officia sint id. Velit sit magna aliquip eiusmod non id deserunt. Magna veniam ad consequat dolor cupidatat esse enim Lorem ullamco. Anim excepteur consectetur id in. Mollit laboris duis labore enim duis esse reprehenderit. + + + + )} + + + +
+ ); +}; diff --git a/packages/@react-spectrum/tabs/test/Tabs.test.js b/packages/@react-spectrum/tabs/test/Tabs.test.js index 1819ff52442..ee948e4a48e 100644 --- a/packages/@react-spectrum/tabs/test/Tabs.test.js +++ b/packages/@react-spectrum/tabs/test/Tabs.test.js @@ -11,7 +11,7 @@ */ import {act, fireEvent, render, within} from '@testing-library/react'; -import {Item, Tabs} from '../src'; +import {Item, TabList, TabPanels, Tabs} from '../src'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {theme} from '@react-spectrum/theme-default'; @@ -28,11 +28,18 @@ function renderComponent(props) { return render( - {item => ( - - {item.children} - - )} + + {item => ( + + )} + + + {item => ( + + {item.children} + + )} + ); @@ -217,18 +224,32 @@ describe('Tabs', function () { let tree = render( - {items.map(item => ( - - {item.children} - - ))} + + {items.map(item => ( + + ))} + + + {items.map(item => ( + + {item.children} + + ))} + - {items.map(item => ( - - {item.children} - - ))} + + {items.map(item => ( + + ))} + + + {items.map(item => ( + + {item.children} + + ))} + ); @@ -369,11 +390,18 @@ describe('Tabs', function () { let {getByRole, rerender} = render( - {item => ( - - {item.children} - - )} + + {item => ( + + )} + + + {item => ( + + {item.children} + + )} + ); @@ -400,11 +428,18 @@ describe('Tabs', function () { rerender( - {item => ( - - {item.children} - - )} + + {item => ( + + )} + + + {item => ( + + {item.children} + + )} + ); @@ -420,12 +455,19 @@ describe('Tabs', function () { rerender( - - {item => ( - - {item.children} - - )} + + + {item => ( + + )} + + + {item => ( + + {item.children} + + )} + ); @@ -458,11 +500,18 @@ describe('Tabs', function () { rerender( - {item => ( - - {item.children} - - )} + + {item => ( + + )} + + + {item => ( + + {item.children} + + )} + ); diff --git a/packages/@react-stately/tabs/src/useTabsState.ts b/packages/@react-stately/tabs/src/useTabsState.ts index 76aa68a9aa3..4701194ba4c 100644 --- a/packages/@react-stately/tabs/src/useTabsState.ts +++ b/packages/@react-stately/tabs/src/useTabsState.ts @@ -11,18 +11,24 @@ */ import {SingleSelectListState, useSingleSelectListState} from '@react-stately/list'; -import {TabsProps} from '@react-types/tabs'; +import {TabListProps} from '@react-types/tabs'; import {useEffect} from 'react'; -export interface TabsState extends SingleSelectListState {} +export interface TabListState extends SingleSelectListState {} -export function useTabsState(props: TabsProps): TabsState { +export function useTabListState(props: TabListProps): TabListState { let state = useSingleSelectListState(props); useEffect(() => { // Ensure a tab is always selected (in case no selected key was specified or if selected item was deleted from collection) - if (state.selectionManager.isEmpty || !state.collection.getItem(state.selectedKey)) { - state.selectionManager.replaceSelection(state.collection.getFirstKey()); + let selectedKey = state.selectedKey; + if (state.selectionManager.isEmpty || !state.collection.getItem(selectedKey)) { + selectedKey = state.collection.getFirstKey(); + state.selectionManager.replaceSelection(selectedKey); + } + + if (state.selectionManager.focusedKey == null) { + state.selectionManager.setFocusedKey(selectedKey); } }, [state.selectionManager, state.selectedKey, state.collection]); diff --git a/packages/@react-types/tabs/src/index.d.ts b/packages/@react-types/tabs/src/index.d.ts index 0b98768684a..97062165775 100644 --- a/packages/@react-types/tabs/src/index.d.ts +++ b/packages/@react-types/tabs/src/index.d.ts @@ -13,24 +13,24 @@ import { AriaLabelingProps, CollectionBase, + CollectionChildren, DOMProps, - Node, Orientation, SingleSelection, StyleProps } from '@react-types/shared'; import {Key} from 'react'; -export interface AriaTabProps { - /** Collection node for the tab. */ - item: Node, +export interface AriaTabProps { + /** The key of the tab. */ + key: Key, /** Whether the tab should be disabled. */ isDisabled?: boolean } -export interface TabsProps extends CollectionBase, SingleSelection {} +export interface TabListProps extends CollectionBase, SingleSelection {} -export interface AriaTabsProps extends TabsProps, DOMProps, AriaLabelingProps { +export interface AriaTabListProps extends TabListProps, DOMProps, AriaLabelingProps { /** * Whether tabs are activated automatically on focus or manually. * @default 'automatic' @@ -48,22 +48,23 @@ export interface AriaTabsProps extends TabsProps, DOMProps, AriaLabelingPr isDisabled?: boolean } -export interface SpectrumTabsProps extends AriaTabsProps, StyleProps { - /** Whether the Tabs should be displayed with a quiet style. */ +export interface AriaTabPanelProps extends DOMProps, AriaLabelingProps {} + +interface SpectrumTabsProps extends SingleSelection, DOMProps, StyleProps { + items?: Iterable, + keyboardActivation?: 'automatic' | 'manual', + orientation?: Orientation, + isDisabled?: boolean, + disabledKeys?: Iterable, isQuiet?: boolean, - /** - * Sets the amount of space between the Tab and the Tab rail. - * @default 'regular' - */ density?: 'compact' | 'regular', - // overflowMode?: 'dropdown' | 'scrolling', - // isEmphasized?: boolean, - /** Whether Tabs are disabled. */ - isDisabled?: boolean, - /** Handler that is called when the tab selection changes. */ - onSelectionChange?: (selectedItem: Key) => void, - /** The currently selected Tab key in the collection (controlled). */ - selectedKey?: Key, - /** The initial selected Tab key in the collection (uncontrolled). */ - defaultSelectedKey?: Key + children: any +} + +export interface SpectrumTabListProps extends DOMProps, StyleProps { + children: CollectionChildren +} + +export interface SpectrumTabPanelsProps extends DOMProps, StyleProps { + children: CollectionChildren }