index.tsx 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import 'intersection-observer'; // polyfill
  2. import {createContext, useState} from 'react';
  3. import styled from '@emotion/styled';
  4. import {AriaTabListProps} from '@react-aria/tabs';
  5. import {Item} from '@react-stately/collections';
  6. import {TabListProps, TabListState} from '@react-stately/tabs';
  7. import {ItemProps, Orientation} from '@react-types/shared';
  8. import {TabList} from './tabList';
  9. import {TabPanels} from './tabPanels';
  10. const _Item = Item as (
  11. props: ItemProps<any> & {disabled?: boolean; hidden?: boolean}
  12. ) => JSX.Element;
  13. export {_Item as Item, TabList, TabPanels};
  14. export interface TabsProps
  15. extends Omit<TabListProps<any>, 'children'>,
  16. Omit<AriaTabListProps<any>, 'children'> {
  17. children?: React.ReactNode;
  18. className?: string;
  19. /**
  20. * [Uncontrolled] Default selected tab. Must match the `key` prop on the
  21. * selected tab item.
  22. */
  23. defaultValue?: TabListProps<any>['defaultSelectedKey'];
  24. disabled?: boolean;
  25. /**
  26. * Callback when the selected tab changes.
  27. */
  28. onChange?: TabListProps<any>['onSelectionChange'];
  29. /**
  30. * [Controlled] Selected tab . Must match the `key` prop on the selected tab
  31. * item.
  32. */
  33. value?: TabListProps<any>['selectedKey'];
  34. }
  35. interface TabContext {
  36. rootProps: TabsProps & {orientation: Orientation};
  37. setTabListState: (state: TabListState<any>) => void;
  38. tabListState?: TabListState<any>;
  39. }
  40. export const TabsContext = createContext<TabContext>({
  41. rootProps: {orientation: 'horizontal', children: []},
  42. setTabListState: () => {},
  43. });
  44. /**
  45. * Root tabs component. Provides the necessary data (via React context) for
  46. * child components (TabList and TabPanels) to work together. See example
  47. * usage in tabs.stories.js
  48. */
  49. export function Tabs({orientation = 'horizontal', className, ...props}: TabsProps) {
  50. const [tabListState, setTabListState] = useState<TabListState<any>>();
  51. return (
  52. <TabsContext.Provider
  53. value={{rootProps: {...props, orientation}, tabListState, setTabListState}}
  54. >
  55. <TabsWrap orientation={orientation} className={className}>
  56. {props.children}
  57. </TabsWrap>
  58. </TabsContext.Provider>
  59. );
  60. }
  61. const TabsWrap = styled('div')<{orientation: Orientation}>`
  62. display: flex;
  63. flex-direction: ${p => (p.orientation === 'horizontal' ? 'column' : 'row')};
  64. ${p =>
  65. p.orientation === 'vertical' &&
  66. `
  67. height: 100%;
  68. align-items: stretch;
  69. `};
  70. `;