@lumx/react 3.1.5 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/_internal/types.d.ts +16 -5
  2. package/index.d.ts +45 -4
  3. package/index.js +609 -411
  4. package/index.js.map +1 -1
  5. package/package.json +3 -3
  6. package/src/components/alert-dialog/AlertDialog.stories.tsx +96 -165
  7. package/src/components/alert-dialog/AlertDialog.test.tsx +15 -23
  8. package/src/components/avatar/Avatar.stories.tsx +91 -62
  9. package/src/components/avatar/Avatar.test.tsx +9 -24
  10. package/src/components/badge/Badge.stories.tsx +63 -38
  11. package/src/components/button/Button.stories.tsx +147 -139
  12. package/src/components/button/IconButton.stories.tsx +45 -0
  13. package/src/components/checkbox/Checkbox.stories.tsx +37 -30
  14. package/src/components/chip/Chip.stories.tsx +77 -15
  15. package/src/components/comment-block/CommentBlock.stories.tsx +90 -25
  16. package/src/components/comment-block/CommentBlock.test.tsx +12 -17
  17. package/src/components/date-picker/DatePickerField.stories.tsx +52 -83
  18. package/src/components/dialog/Dialog.stories.tsx +131 -293
  19. package/src/components/dialog/Dialog.test.tsx +0 -32
  20. package/src/components/dropdown/Dropdown.stories.tsx +1 -186
  21. package/src/components/flag/Flag.stories.tsx +33 -18
  22. package/src/components/flag/Flag.test.tsx +1 -8
  23. package/src/components/flex-box/FlexBox.stories.tsx +151 -238
  24. package/src/components/flex-box/FlexBox.test.tsx +9 -49
  25. package/src/components/generic-block/GenericBlock.stories.jsx +1 -1
  26. package/src/components/grid-column/GridColumn.stories.tsx +46 -0
  27. package/src/components/heading/Heading.stories.tsx +57 -95
  28. package/src/components/icon/Icon.stories.tsx +67 -70
  29. package/src/components/image-block/ImageBlock.stories.tsx +103 -47
  30. package/src/components/image-block/ImageBlock.test.tsx +12 -17
  31. package/src/components/inline-list/InlineList.stories.tsx +45 -29
  32. package/src/components/input-helper/InputHelper.stories.tsx +31 -25
  33. package/src/components/input-label/InputLabel.stories.tsx +33 -10
  34. package/src/components/lightbox/Lightbox.stories.tsx +39 -77
  35. package/src/components/lightbox/Lightbox.test.tsx +12 -17
  36. package/src/components/link/Link.stories.tsx +98 -128
  37. package/src/components/link-preview/LinkPreview.stories.tsx +48 -75
  38. package/src/components/list/List.stories.tsx +59 -84
  39. package/src/components/list/List.test.tsx +8 -17
  40. package/src/components/list/ListDivider.stories.tsx +9 -4
  41. package/src/components/list/ListDivider.test.tsx +12 -17
  42. package/src/components/list/ListItem.stories.tsx +97 -59
  43. package/src/components/list/ListItem.test.tsx +12 -17
  44. package/src/components/list/ListSubheader.stories.tsx +8 -5
  45. package/src/components/list/ListSubheader.test.tsx +12 -18
  46. package/src/components/message/Message.stories.tsx +51 -22
  47. package/src/components/mosaic/Mosaic.stories.tsx +78 -74
  48. package/src/components/mosaic/Mosaic.test.tsx +0 -31
  49. package/src/components/navigation/Navigation.stories.tsx +67 -0
  50. package/src/components/navigation/Navigation.test.tsx +58 -0
  51. package/src/components/navigation/Navigation.tsx +62 -0
  52. package/src/components/navigation/NavigationItem.test.tsx +37 -0
  53. package/src/components/navigation/NavigationItem.tsx +89 -0
  54. package/src/components/navigation/NavigationSection.test.tsx +126 -0
  55. package/src/components/navigation/NavigationSection.tsx +109 -0
  56. package/src/components/navigation/context.tsx +6 -0
  57. package/src/components/navigation/index.ts +1 -0
  58. package/src/components/notification/Notifications.stories.tsx +52 -47
  59. package/src/components/popover/Popover.stories.tsx +68 -201
  60. package/src/components/popover-dialog/PopoverDialog.stories.tsx +26 -65
  61. package/src/components/post-block/PostBlock.test.tsx +12 -17
  62. package/src/components/progress/ProgressCircular.stories.tsx +24 -12
  63. package/src/components/progress/ProgressLinear.stories.tsx +6 -2
  64. package/src/components/radio-button/RadioButton.stories.tsx +35 -24
  65. package/src/components/select/Select.stories.tsx +19 -23
  66. package/src/components/skeleton/SkeletonCircle.stories.tsx +37 -21
  67. package/src/components/skeleton/SkeletonCircle.test.tsx +12 -17
  68. package/src/components/skeleton/SkeletonRectangle.stories.tsx +74 -99
  69. package/src/components/skeleton/SkeletonRectangle.test.tsx +12 -17
  70. package/src/components/skeleton/SkeletonTypography.test.tsx +12 -17
  71. package/src/components/slider/Slider.stories.tsx +41 -25
  72. package/src/components/slider/Slider.test.tsx +12 -18
  73. package/src/components/slideshow/Slideshow.stories.tsx +31 -61
  74. package/src/components/slideshow/Slideshow.test.tsx +15 -23
  75. package/src/components/slideshow/SlideshowControls.stories.tsx +4 -6
  76. package/src/components/switch/Switch.stories.tsx +35 -32
  77. package/src/components/table/Table.test.tsx +12 -17
  78. package/src/components/tabs/Tabs.stories.tsx +4 -3
  79. package/src/components/text/Text.stories.tsx +130 -0
  80. package/src/components/text-field/TextField.stories.tsx +114 -148
  81. package/src/components/thumbnail/Thumbnail.stories.tsx +106 -255
  82. package/src/components/thumbnail/Thumbnail.test.tsx +12 -35
  83. package/src/components/tooltip/Tooltip.stories.tsx +51 -136
  84. package/src/components/user-block/UserBlock.stories.tsx +67 -56
  85. package/src/components/user-block/UserBlock.test.tsx +1 -5
  86. package/src/index.ts +1 -0
  87. package/src/stories/controls/color.ts +6 -0
  88. package/src/stories/controls/element.ts +6 -0
  89. package/src/stories/controls/focusPoint.ts +1 -0
  90. package/src/stories/controls/icons.ts +6 -0
  91. package/src/stories/{knobs → controls}/image.ts +6 -16
  92. package/src/stories/controls/selectArgType.ts +4 -0
  93. package/src/stories/controls/theme.ts +3 -0
  94. package/src/stories/controls/typography.ts +5 -0
  95. package/src/stories/controls/withUndefined.ts +1 -0
  96. package/src/stories/decorators/withChromaticForceScreenSize.tsx +8 -0
  97. package/src/stories/decorators/withCombinations.tsx +99 -0
  98. package/src/stories/decorators/withNestedProps.tsx +23 -0
  99. package/src/stories/{withResizableBox.tsx → decorators/withResizableBox.tsx} +6 -10
  100. package/src/stories/decorators/withValueOnChange.tsx +18 -0
  101. package/src/stories/decorators/withWrapper.tsx +19 -0
  102. package/src/stories/utils/CustomLink.tsx +8 -2
  103. package/src/stories/{knobs → utils}/lorem.ts +9 -9
  104. package/src/testing/utils/commonTestsSuiteRTL.ts +2 -3
  105. package/src/testing/utils/index.ts +0 -2
  106. package/src/untypped-modules.d.ts +0 -2
  107. package/src/utils/MaterialThemeSwitcher/MaterialThemeSwitcher.tsx +1 -1
  108. package/src/utils/ThemeContext.ts +4 -0
  109. package/src/utils/forwardRefPolymorphic.ts +9 -0
  110. package/src/utils/type.ts +28 -4
  111. package/src/components/alert-dialog/__snapshots__/AlertDialog.test.tsx.snap +0 -558
  112. package/src/components/avatar/__snapshots__/Avatar.test.tsx.snap +0 -681
  113. package/src/components/comment-block/__snapshots__/CommentBlock.test.tsx.snap +0 -92
  114. package/src/components/dialog/__snapshots__/Dialog.test.tsx.snap +0 -1133
  115. package/src/components/expansion-panel/ExpansionPanel.stories.tsx +0 -65
  116. package/src/components/flag/__snapshots__/Flag.test.tsx.snap +0 -133
  117. package/src/components/flex-box/__snapshots__/FlexBox.test.tsx.snap +0 -492
  118. package/src/components/grid-column/GridColumn.stories.jsx +0 -56
  119. package/src/components/image-block/__snapshots__/ImageBlock.test.tsx.snap +0 -64
  120. package/src/components/lightbox/__snapshots__/Lightbox.test.tsx.snap +0 -194
  121. package/src/components/list/__snapshots__/List.test.tsx.snap +0 -360
  122. package/src/components/list/__snapshots__/ListDivider.test.tsx.snap +0 -7
  123. package/src/components/list/__snapshots__/ListItem.test.tsx.snap +0 -160
  124. package/src/components/list/__snapshots__/ListSubheader.test.tsx.snap +0 -9
  125. package/src/components/mosaic/__snapshots__/Mosaic.test.tsx.snap +0 -357
  126. package/src/components/post-block/__snapshots__/PostBlock.test.tsx.snap +0 -139
  127. package/src/components/skeleton/__snapshots__/SkeletonCircle.test.tsx.snap +0 -54
  128. package/src/components/skeleton/__snapshots__/SkeletonRectangle.test.tsx.snap +0 -177
  129. package/src/components/skeleton/__snapshots__/SkeletonTypography.test.tsx.snap +0 -174
  130. package/src/components/slider/__snapshots__/Slider.test.tsx.snap +0 -122
  131. package/src/components/slideshow/__snapshots__/Slideshow.test.tsx.snap +0 -157
  132. package/src/components/table/__snapshots__/Table.test.tsx.snap +0 -263
  133. package/src/components/text/Text.stories.jsx +0 -75
  134. package/src/components/thumbnail/__snapshots__/Thumbnail.test.tsx.snap +0 -130
  135. package/src/components/user-block/__snapshots__/UserBlock.test.tsx.snap +0 -362
  136. package/src/stories/chromaticForceScreenSize.tsx +0 -7
  137. package/src/stories/knobs/buttonKnob.ts +0 -9
  138. package/src/stories/knobs/emphasisKnob.ts +0 -8
  139. package/src/stories/knobs/enumKnob.ts +0 -14
  140. package/src/stories/knobs/focusKnob.ts +0 -3
  141. package/src/stories/knobs/sizeKnob.ts +0 -5
  142. package/src/stories/knobs/thumbnailsKnob.ts +0 -9
  143. package/src/testing/utils/itShouldRenderStories.tsx +0 -103
@@ -0,0 +1,109 @@
1
+ import React, { forwardRef, ReactNode, useRef, useState, useMemo, useContext } from 'react';
2
+
3
+ import { mdiChevronDown, mdiChevronUp } from '@lumx/icons';
4
+ import { Icon, Size, Text, Orientation, Popover, Placement, Theme } from '@lumx/react';
5
+ import uniqueId from 'lodash/uniqueId';
6
+ import classNames from 'classnames';
7
+ import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
8
+ import { HasClassName } from '@lumx/react/utils/type';
9
+ import { ThemeContext } from '@lumx/react/utils/ThemeContext';
10
+ import { CLASSNAME as ITEM_CLASSNAME } from './NavigationItem';
11
+ import { NavigationContext } from './context';
12
+
13
+ export interface NavigationSectionProps extends React.ComponentPropsWithoutRef<'li'>, HasClassName {
14
+ /** Items inside the section */
15
+ children: ReactNode;
16
+ /** Icon (SVG path). */
17
+ icon?: string;
18
+ /** Label content. */
19
+ label: string | ReactNode;
20
+ }
21
+
22
+ /**
23
+ * Component display name.
24
+ */
25
+ const COMPONENT_NAME = 'NavigationSection';
26
+
27
+ /**
28
+ * Component default class name and class prefix.
29
+ */
30
+ const CLASSNAME = getRootClassName(COMPONENT_NAME);
31
+
32
+ export const NavigationSection = Object.assign(
33
+ forwardRef<HTMLLIElement, NavigationSectionProps>((props, ref) => {
34
+ const { children, className, label, icon, ...forwardedProps } = props;
35
+ const [isOpen, setIsOpen] = useState(false);
36
+ const buttonRef = useRef<HTMLButtonElement>(null);
37
+ const sectionId = useMemo(() => uniqueId('section'), []);
38
+ const { orientation } = useContext(NavigationContext) || {};
39
+ const theme = useContext(ThemeContext);
40
+ const isDropdown = orientation === Orientation.horizontal;
41
+ return (
42
+ <li
43
+ className={classNames(
44
+ className,
45
+ CLASSNAME,
46
+ ITEM_CLASSNAME,
47
+ handleBasicClasses({
48
+ prefix: ITEM_CLASSNAME,
49
+ theme,
50
+ }),
51
+ )}
52
+ ref={ref}
53
+ {...forwardedProps}
54
+ >
55
+ <button
56
+ aria-controls={sectionId}
57
+ aria-expanded={isOpen}
58
+ className={classNames(`${ITEM_CLASSNAME}__link`)}
59
+ ref={buttonRef}
60
+ onClick={(event) => {
61
+ setIsOpen(!isOpen);
62
+ event.stopPropagation();
63
+ }}
64
+ type="button"
65
+ >
66
+ {icon ? <Icon className={`${ITEM_CLASSNAME}__icon`} icon={icon} size={Size.xs} /> : null}
67
+
68
+ <Text as="span" truncate className={`${ITEM_CLASSNAME}__label`} ref={ref}>
69
+ {label}
70
+ </Text>
71
+ <Icon
72
+ className={classNames(`${ITEM_CLASSNAME}__icon`, `${CLASSNAME}__chevron`)}
73
+ icon={isOpen ? mdiChevronUp : mdiChevronDown}
74
+ />
75
+ </button>
76
+ {isOpen &&
77
+ (isDropdown ? (
78
+ <Popover
79
+ anchorRef={buttonRef}
80
+ isOpen={isOpen}
81
+ placement={Placement.BOTTOM_START}
82
+ usePortal={false}
83
+ closeOnClickAway
84
+ closeOnEscape
85
+ onClick={() => setIsOpen(false)}
86
+ onClose={() => setIsOpen(false)}
87
+ zIndex={996}
88
+ >
89
+ <ThemeContext.Provider value={Theme.light}>
90
+ <ul className={`${CLASSNAME}__drawer--popover`} id={sectionId}>
91
+ <NavigationContext.Provider value={{ orientation: Orientation.vertical }}>
92
+ {children}
93
+ </NavigationContext.Provider>
94
+ </ul>
95
+ </ThemeContext.Provider>
96
+ </Popover>
97
+ ) : (
98
+ <ul className={`${CLASSNAME}__drawer`} id={sectionId}>
99
+ {children}
100
+ </ul>
101
+ ))}
102
+ </li>
103
+ );
104
+ }),
105
+ {
106
+ displayName: COMPONENT_NAME,
107
+ className: CLASSNAME,
108
+ },
109
+ );
@@ -0,0 +1,6 @@
1
+ import { createContext } from 'react';
2
+ import { Orientation } from '..';
3
+
4
+ export const NavigationContext = createContext<{ orientation?: Orientation } | undefined>({
5
+ orientation: Orientation.vertical,
6
+ });
@@ -0,0 +1 @@
1
+ export * from './Navigation';
@@ -1,12 +1,16 @@
1
- import React, { useState } from 'react';
2
-
3
- import { Button, Notification, Kind } from '@lumx/react';
1
+ import { Notification, Kind } from '@lumx/react';
4
2
  import { NOTIFICATION_TRANSITION_DURATION } from '@lumx/core/js/constants';
5
- import { action } from '@storybook/addon-actions';
6
- import { chromaticForceScreenSize } from '../../stories/chromaticForceScreenSize';
3
+ import { getSelectArgType } from '@lumx/react/stories/controls/selectArgType';
4
+ import { withChromaticForceScreenSize } from '../../stories/decorators/withChromaticForceScreenSize';
7
5
 
8
6
  export default {
9
7
  title: 'LumX components/notification/Notification',
8
+ component: Notification,
9
+ args: Notification.defaultProps,
10
+ argTypes: {
11
+ type: getSelectArgType(Kind),
12
+ onClick: { action: true },
13
+ },
10
14
  parameters: {
11
15
  // Delay Chromatic snapshot to wait for notification to open.
12
16
  chromatic: {
@@ -15,63 +19,64 @@ export default {
15
19
  },
16
20
  },
17
21
  // Force minimum chromatic screen size to make sure the dialog appears in view.
18
- decorators: [chromaticForceScreenSize],
22
+ decorators: [withChromaticForceScreenSize()],
19
23
  };
20
24
 
21
- const properties = {
22
- error: {
25
+ /**
26
+ * Error notification
27
+ */
28
+ export const Error = {
29
+ args: {
30
+ type: Kind.error,
23
31
  content: 'Error',
24
- onClick: action('onClick'),
25
32
  isOpen: true,
26
- type: Kind.error,
27
33
  },
28
- info: {
29
- content: 'Info',
30
- onClick: action('onClick'),
31
- isOpen: true,
34
+ };
35
+
36
+ /**
37
+ * Info notification
38
+ */
39
+ export const Info = {
40
+ args: {
32
41
  type: Kind.info,
33
- },
34
- infoWithCallback: {
35
- onActionClick: action('onClick'),
36
- actionLabel: 'Undo',
37
- content: 'Info with callback',
38
- onClick: action('onClick'),
42
+ content: 'Info',
39
43
  isOpen: true,
40
- type: Kind.info,
41
44
  },
42
- success: {
45
+ };
46
+
47
+ /**
48
+ * Success notification
49
+ */
50
+ export const Success = {
51
+ args: {
52
+ type: Kind.success,
43
53
  content: 'Success',
44
- onClick: action('onClick'),
45
54
  isOpen: true,
46
- type: Kind.success,
47
55
  },
56
+ };
48
57
 
49
- warning: {
58
+ /**
59
+ * Warning notification
60
+ */
61
+ export const Warning = {
62
+ args: {
63
+ type: Kind.warning,
50
64
  content: 'Warning',
51
- onClick: action('onClick'),
52
65
  isOpen: true,
53
- type: Kind.warning,
54
66
  },
55
67
  };
56
68
 
57
- export const Error = () => <Notification {...properties.error} />;
58
-
59
- export const Info = () => <Notification {...properties.info} />;
60
-
61
- export const InfoWithCallback = () => <Notification {...properties.infoWithCallback} />;
62
-
63
- export const Success = () => <Notification {...properties.success} />;
64
-
65
- export const Warning = () => <Notification {...properties.warning} />;
66
-
67
- export const OnTrigger = () => {
68
- const [isOpen, setIsOpen] = useState(false);
69
- const onClick = () => setIsOpen(!isOpen);
70
-
71
- return (
72
- <>
73
- <Button onClick={onClick}>{!isOpen ? 'Show Notification' : 'Close Notification'}</Button>,
74
- <Notification {...properties.error} isOpen={isOpen} />,
75
- </>
76
- );
69
+ /**
70
+ * Info notification with action button
71
+ */
72
+ export const InfoWithAction = {
73
+ argTypes: {
74
+ onActionClick: { action: true },
75
+ },
76
+ args: {
77
+ type: Kind.info,
78
+ content: 'InfoWithAction',
79
+ actionLabel: 'Undo',
80
+ isOpen: true,
81
+ },
77
82
  };
@@ -1,132 +1,91 @@
1
- import React, { RefObject, useEffect, useRef, useState } from 'react';
1
+ /* eslint-disable react-hooks/rules-of-hooks */
2
+ import React, { useEffect, useRef, useState } from 'react';
2
3
 
3
4
  import { mdiAccount, mdiBell } from '@lumx/icons';
4
5
  import {
5
- Alignment,
6
6
  Chip,
7
- Button,
8
7
  Emphasis,
9
- FlexBox,
8
+ Text,
10
9
  Icon,
11
10
  IconButton,
12
11
  List,
13
12
  ListItem,
14
- Orientation,
15
13
  Placement,
16
14
  Popover,
17
15
  Size,
16
+ Elevation,
18
17
  } from '@lumx/react';
19
- import { boolean, select } from '@storybook/addon-knobs';
20
18
  import range from 'lodash/range';
21
- import startCase from 'lodash/startCase';
22
-
23
- export default { title: 'LumX components/popover/Popover' };
24
-
25
- const DEFAULT_PROPS = Popover.defaultProps as any;
26
-
27
- export const Positions = ({ theme }: any) => {
28
- const popovers: Array<[Placement, RefObject<any>]> = [
29
- [Placement.LEFT, useRef(null)],
30
- [Placement.TOP, useRef(null)],
31
- [Placement.BOTTOM, useRef(null)],
32
- [Placement.RIGHT, useRef(null)],
33
- ];
34
- const hasArrow = boolean('Has arrow', DEFAULT_PROPS.hasArrow as any);
35
- const elevation: any = select('Elevation', [5, 4, 3, 2, 1], DEFAULT_PROPS.elevation);
36
- const alignOptions = { middle: '', start: '-start', end: '-end' };
37
- const align = select('Placement variant', alignOptions, alignOptions.middle);
38
-
39
- return (
40
- <FlexBox style={{ padding: 80 }} orientation={Orientation.horizontal}>
41
- {popovers.map(([placement, ref]) => {
42
- const placementVariant = (placement + align) as any;
43
- return (
44
- <FlexBox key={placement} fillSpace vAlign={Alignment.center} hAlign={Alignment.center}>
45
- <Chip ref={ref} theme={theme} size={Size.s}>
46
- {startCase(placementVariant).toUpperCase()}
47
- </Chip>
48
-
49
- <Popover
50
- isOpen
51
- theme={theme}
52
- anchorRef={ref}
53
- placement={placementVariant}
54
- elevation={elevation}
55
- hasArrow={hasArrow}
56
- >
57
- <div className="lumx-spacing-margin-huge">Popover</div>
58
- </Popover>
59
- </FlexBox>
60
- );
61
- })}
62
- </FlexBox>
63
- );
19
+ import { withCombinations } from '@lumx/react/stories/decorators/withCombinations';
20
+ import { getSelectArgType } from '@lumx/react/stories/controls/selectArgType';
21
+ import { withChromaticForceScreenSize } from '@lumx/react/stories/decorators/withChromaticForceScreenSize';
22
+
23
+ export default {
24
+ title: 'LumX components/popover/Popover',
25
+ component: Popover,
26
+ args: Popover.defaultProps,
27
+ argTypes: {
28
+ isOpen: { control: 'boolean' },
29
+ hasArrow: { control: 'boolean' },
30
+ placement: getSelectArgType(Placement),
31
+ elevation: getSelectArgType<Elevation>([1, 2, 3, 4, 5]),
32
+ },
33
+ decorators: [
34
+ // Force minimum chromatic screen size to make sure the dialog appears in view.
35
+ withChromaticForceScreenSize(),
36
+ ],
64
37
  };
65
38
 
66
- export const Auto = ({ theme }: any) => {
67
- const demoPopperStyle = {
68
- alignItems: 'center',
69
- display: 'flex',
70
- height: 100,
71
- justifyContent: 'center',
72
- width: 200,
73
- };
74
-
75
- const container = {
76
- width: '200%',
77
- height: '2000px',
78
- alignItems: 'center',
79
- display: 'flex',
80
- justifyContent: 'center',
81
- };
82
-
83
- const anchorRef = useRef(null);
84
-
85
- return (
86
- <div style={container}>
87
- <div>
88
- <Chip ref={anchorRef} theme={theme} size={Size.s}>
39
+ /**
40
+ * Simple
41
+ */
42
+ export const Simple = {
43
+ args: {
44
+ children: (
45
+ <Text as="p" className="lumx-spacing-padding-big">
46
+ Popover
47
+ </Text>
48
+ ),
49
+ },
50
+ render(props: any) {
51
+ const anchorRef = React.useRef(null);
52
+ return (
53
+ <>
54
+ <Chip ref={anchorRef} size="s" className="lumx-spacing-margin-big">
89
55
  Anchor
90
56
  </Chip>
91
- </div>
92
- <Popover theme={theme} anchorRef={anchorRef} placement={Placement.AUTO} isOpen>
93
- <div style={demoPopperStyle}>Popover</div>
94
- </Popover>
95
- </div>
96
- );
57
+ <Popover anchorRef={anchorRef} isOpen {...props} />
58
+ </>
59
+ );
60
+ },
97
61
  };
98
62
 
99
- export const Top = ({ theme }: any) => {
100
- const demoPopperStyle = {
101
- alignItems: 'center',
102
- display: 'flex',
103
- height: 100,
104
- justifyContent: 'center',
105
- width: 200,
106
- };
107
-
108
- const container = {
109
- width: '200%',
110
- height: '2000px',
111
- alignItems: 'center',
112
- display: 'flex',
113
- justifyContent: 'center',
114
- };
115
-
116
- const anchorRef = useRef(null);
117
-
118
- return (
119
- <div style={container}>
120
- <div>
121
- <Chip ref={anchorRef} theme={theme} size={Size.s}>
122
- Anchor
123
- </Chip>
124
- </div>
125
- <Popover theme={theme} anchorRef={anchorRef} placement={Placement.TOP} isOpen>
126
- <div style={demoPopperStyle}>Popover</div>
127
- </Popover>
128
- </div>
129
- );
63
+ /**
64
+ * Popover not using React.createPortal
65
+ */
66
+ export const WithoutPortal = { ...Simple, args: { ...Simple.args, usePortal: false } };
67
+
68
+ /**
69
+ * All base placements
70
+ */
71
+ export const Placements = {
72
+ ...Simple,
73
+ argTypes: {
74
+ placement: { control: false },
75
+ },
76
+ decorators: [
77
+ withCombinations({
78
+ cellStyle: {
79
+ padding: 80,
80
+ },
81
+ combinations: {
82
+ cols: {
83
+ key: 'placement',
84
+ options: [Placement.TOP, Placement.RIGHT, Placement.BOTTOM, Placement.LEFT],
85
+ },
86
+ },
87
+ }),
88
+ ],
130
89
  };
131
90
 
132
91
  export const WithUpdatingChildren = ({ theme }: any) => {
@@ -223,98 +182,6 @@ export const WithScrollingPopover = ({ theme }: any) => {
223
182
  );
224
183
  };
225
184
 
226
- export const WithoutPortal = ({ theme }: any) => {
227
- const popovers: Array<[Placement, RefObject<any>]> = [
228
- [Placement.LEFT, useRef(null)],
229
- [Placement.TOP, useRef(null)],
230
- [Placement.BOTTOM, useRef(null)],
231
- [Placement.RIGHT, useRef(null)],
232
- ];
233
- const hasArrow = boolean('Has arrow', DEFAULT_PROPS.hasArrow as any);
234
- const elevation: any = select('Elevation', [5, 4, 3, 2, 1], DEFAULT_PROPS.elevation);
235
- const alignOptions = { middle: '', start: '-start', end: '-end' };
236
- const align = select('Placement variant', alignOptions, alignOptions.middle);
237
-
238
- return (
239
- <FlexBox style={{ padding: 80 }} orientation={Orientation.horizontal}>
240
- {popovers.map(([placement, ref]) => {
241
- const placementVariant = (placement + align) as any;
242
- return (
243
- <FlexBox key={placement} fillSpace vAlign={Alignment.center} hAlign={Alignment.center}>
244
- <Chip ref={ref} theme={theme} size={Size.s}>
245
- {startCase(placementVariant).toUpperCase()}
246
- </Chip>
247
-
248
- <Popover
249
- isOpen
250
- theme={theme}
251
- anchorRef={ref}
252
- placement={placementVariant}
253
- elevation={elevation}
254
- hasArrow={hasArrow}
255
- usePortal={false}
256
- >
257
- <div className="lumx-spacing-margin-huge">Popover</div>
258
- </Popover>
259
- </FlexBox>
260
- );
261
- })}
262
- </FlexBox>
263
- );
264
- };
265
-
266
- export const NestedWithoutPortal = () => {
267
- const boundaryRef = React.useRef(document.querySelector('body'));
268
-
269
- const Entry = ({ children, placement = Placement.RIGHT_START }: any) => {
270
- const rootButtonRef = React.useRef(null);
271
- const [rootOpen, setRootOpen] = React.useState(false);
272
-
273
- return (
274
- <>
275
- <li ref={rootButtonRef}>
276
- <Button onClick={() => setRootOpen(!rootOpen)}>Click</Button>
277
- </li>
278
- {children && (
279
- <Popover
280
- boundaryRef={boundaryRef}
281
- fitWithinViewportHeight
282
- //offset={{ along: -16 }}
283
- placement={placement}
284
- isOpen={rootOpen}
285
- anchorRef={rootButtonRef}
286
- usePortal={false}
287
- >
288
- <div className="lumx-spacing-margin-huge" style={{ overflowY: 'auto' }}>
289
- <List style={{ minWidth: '150px' }}>{children}</List>
290
- </div>
291
- </Popover>
292
- )}
293
- </>
294
- );
295
- };
296
-
297
- return (
298
- <div style={{ height: '100vh', width: '50px' }}>
299
- <List>
300
- <Entry placement={Placement.BOTTOM_START}>
301
- <Entry />
302
- <Entry />
303
- <Entry>
304
- <Entry />
305
- <Entry />
306
- <Entry>
307
- <Entry>
308
- <Entry />
309
- </Entry>
310
- </Entry>
311
- </Entry>
312
- </Entry>
313
- </List>
314
- </div>
315
- );
316
- };
317
-
318
185
  export const FitToAnchorWidth = ({ theme }: any) => {
319
186
  const demoPopperStyle = {
320
187
  alignItems: 'center',
@@ -1,75 +1,36 @@
1
- import React, { useRef, useState } from 'react';
2
- import { mdiMenu, mdiSettings } from '@lumx/icons';
3
- import { Placement } from '@lumx/react';
1
+ import React from 'react';
2
+ import { useBooleanState } from '@lumx/react/hooks/useBooleanState';
3
+ import { PopoverDialog } from '.';
4
+ import { Button } from '../button';
4
5
 
5
- import { PopoverDialog, PopoverDialogProps } from '.';
6
- import { Emphasis, Orientation, Size, Typography } from '..';
7
- import { Button, IconButton } from '../button';
8
- import { FlexBox } from '../flex-box';
9
- import { Heading } from '../heading';
10
- import { List, ListItem } from '../list';
11
- import { Toolbar } from '../toolbar';
6
+ export default {
7
+ title: 'LumX components/popover-dialog/PopoverDialog',
8
+ component: PopoverDialog,
9
+ };
12
10
 
13
- const WithButton = (Story: any, context: any) => {
14
- const anchorRef = useRef(null);
15
- const [isOpen, setIsOpen] = useState<boolean>(context?.args?.isOpen || false);
11
+ /**
12
+ * Example PopoverDialog using a button as a trigger
13
+ */
14
+ export const WithButtonTrigger = () => {
15
+ const anchorRef = React.useRef(null);
16
+ const [isOpen, close, open] = useBooleanState(true);
16
17
 
17
18
  return (
18
19
  <>
19
- <Button ref={anchorRef} onClick={() => setIsOpen((current) => !current)}>
20
+ <Button id="trigger-button-1" ref={anchorRef} onClick={open}>
20
21
  Open popover
21
22
  </Button>
22
- <Story anchorRef={anchorRef} isOpen={isOpen} onClose={() => setIsOpen(false)} />
23
- </>
24
- );
25
- };
26
-
27
- const dialogHeaderId = 'dialog-header';
28
-
29
- const DemoPopoverContent = () => (
30
- <FlexBox orientation={Orientation.vertical}>
31
- <Toolbar
32
- label={
33
- <Heading id="dialogHeaderId" typography={Typography.headline}>
34
- Title
35
- </Heading>
36
- }
37
- after={<IconButton label="Settings" icon={mdiSettings} emphasis={Emphasis.low} />}
38
- />
39
- <List>
40
- <ListItem size={Size.huge} after={<IconButton label="Menu" icon={mdiMenu} size={Size.s} />}>
41
- List Item With Actions
42
- </ListItem>
43
- <ListItem
44
- size={Size.huge}
45
- linkProps={{
46
- href: 'http://google.com',
47
- }}
23
+ <PopoverDialog
24
+ aria-labelledby="trigger-button-1"
25
+ anchorRef={anchorRef}
26
+ isOpen={isOpen}
27
+ onClose={close}
28
+ placement="bottom"
48
29
  >
49
- Clickable list item
50
- </ListItem>
51
- </List>
52
- </FlexBox>
53
- );
54
-
55
- export default {
56
- title: 'LumX components/popover-dialog/PopoverDialog',
57
- component: PopoverDialog,
58
- decorators: [WithButton],
59
- args: {
60
- children: <DemoPopoverContent />,
61
- 'aria-labelledby': dialogHeaderId,
62
- placement: Placement.BOTTOM,
63
- },
64
- };
65
-
66
- const Template = (args: PopoverDialogProps, context: any) => {
67
- const { anchorRef, isOpen, onClose } = context;
68
- return (
69
- <PopoverDialog {...args} anchorRef={anchorRef} isOpen={isOpen} onClose={onClose}>
70
- {args.children}
71
- </PopoverDialog>
30
+ <Button className="lumx-spacing-margin-huge" onClick={close}>
31
+ Close
32
+ </Button>
33
+ </PopoverDialog>
34
+ </>
72
35
  );
73
36
  };
74
-
75
- export const Default = Template.bind({});