@lumx/react 3.1.4 → 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 (144) hide show
  1. package/_internal/types.d.ts +16 -5
  2. package/index.d.ts +51 -4
  3. package/index.js +621 -417
  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 +132 -240
  19. package/src/components/dialog/Dialog.test.tsx +6 -30
  20. package/src/components/dialog/Dialog.tsx +17 -3
  21. package/src/components/dropdown/Dropdown.stories.tsx +1 -186
  22. package/src/components/flag/Flag.stories.tsx +33 -18
  23. package/src/components/flag/Flag.test.tsx +1 -8
  24. package/src/components/flex-box/FlexBox.stories.tsx +151 -238
  25. package/src/components/flex-box/FlexBox.test.tsx +9 -49
  26. package/src/components/generic-block/GenericBlock.stories.jsx +1 -1
  27. package/src/components/grid-column/GridColumn.stories.tsx +46 -0
  28. package/src/components/heading/Heading.stories.tsx +57 -95
  29. package/src/components/icon/Icon.stories.tsx +67 -70
  30. package/src/components/image-block/ImageBlock.stories.tsx +103 -47
  31. package/src/components/image-block/ImageBlock.test.tsx +12 -17
  32. package/src/components/inline-list/InlineList.stories.tsx +45 -29
  33. package/src/components/input-helper/InputHelper.stories.tsx +31 -25
  34. package/src/components/input-label/InputLabel.stories.tsx +33 -10
  35. package/src/components/lightbox/Lightbox.stories.tsx +39 -77
  36. package/src/components/lightbox/Lightbox.test.tsx +12 -17
  37. package/src/components/link/Link.stories.tsx +98 -128
  38. package/src/components/link-preview/LinkPreview.stories.tsx +48 -75
  39. package/src/components/list/List.stories.tsx +59 -84
  40. package/src/components/list/List.test.tsx +8 -17
  41. package/src/components/list/ListDivider.stories.tsx +9 -4
  42. package/src/components/list/ListDivider.test.tsx +12 -17
  43. package/src/components/list/ListItem.stories.tsx +97 -59
  44. package/src/components/list/ListItem.test.tsx +12 -17
  45. package/src/components/list/ListSubheader.stories.tsx +8 -5
  46. package/src/components/list/ListSubheader.test.tsx +12 -18
  47. package/src/components/message/Message.stories.tsx +51 -22
  48. package/src/components/mosaic/Mosaic.stories.tsx +78 -74
  49. package/src/components/mosaic/Mosaic.test.tsx +0 -31
  50. package/src/components/navigation/Navigation.stories.tsx +67 -0
  51. package/src/components/navigation/Navigation.test.tsx +58 -0
  52. package/src/components/navigation/Navigation.tsx +62 -0
  53. package/src/components/navigation/NavigationItem.test.tsx +37 -0
  54. package/src/components/navigation/NavigationItem.tsx +89 -0
  55. package/src/components/navigation/NavigationSection.test.tsx +126 -0
  56. package/src/components/navigation/NavigationSection.tsx +109 -0
  57. package/src/components/navigation/context.tsx +6 -0
  58. package/src/components/navigation/index.ts +1 -0
  59. package/src/components/notification/Notifications.stories.tsx +52 -47
  60. package/src/components/popover/Popover.stories.tsx +68 -201
  61. package/src/components/popover-dialog/PopoverDialog.stories.tsx +26 -65
  62. package/src/components/post-block/PostBlock.test.tsx +12 -17
  63. package/src/components/progress/ProgressCircular.stories.tsx +24 -12
  64. package/src/components/progress/ProgressLinear.stories.tsx +6 -2
  65. package/src/components/radio-button/RadioButton.stories.tsx +35 -24
  66. package/src/components/select/Select.stories.tsx +19 -23
  67. package/src/components/skeleton/SkeletonCircle.stories.tsx +37 -21
  68. package/src/components/skeleton/SkeletonCircle.test.tsx +12 -17
  69. package/src/components/skeleton/SkeletonRectangle.stories.tsx +74 -99
  70. package/src/components/skeleton/SkeletonRectangle.test.tsx +12 -17
  71. package/src/components/skeleton/SkeletonTypography.test.tsx +12 -17
  72. package/src/components/slider/Slider.stories.tsx +41 -25
  73. package/src/components/slider/Slider.test.tsx +12 -18
  74. package/src/components/slideshow/Slideshow.stories.tsx +31 -61
  75. package/src/components/slideshow/Slideshow.test.tsx +15 -23
  76. package/src/components/slideshow/SlideshowControls.stories.tsx +4 -6
  77. package/src/components/switch/Switch.stories.tsx +35 -32
  78. package/src/components/table/Table.test.tsx +12 -17
  79. package/src/components/tabs/Tabs.stories.tsx +4 -3
  80. package/src/components/text/Text.stories.tsx +130 -0
  81. package/src/components/text-field/TextField.stories.tsx +114 -148
  82. package/src/components/thumbnail/Thumbnail.stories.tsx +106 -255
  83. package/src/components/thumbnail/Thumbnail.test.tsx +12 -35
  84. package/src/components/tooltip/Tooltip.stories.tsx +51 -136
  85. package/src/components/user-block/UserBlock.stories.tsx +67 -56
  86. package/src/components/user-block/UserBlock.test.tsx +1 -5
  87. package/src/index.ts +1 -0
  88. package/src/stories/controls/color.ts +6 -0
  89. package/src/stories/controls/element.ts +6 -0
  90. package/src/stories/controls/focusPoint.ts +1 -0
  91. package/src/stories/controls/icons.ts +6 -0
  92. package/src/stories/{knobs → controls}/image.ts +6 -16
  93. package/src/stories/controls/selectArgType.ts +4 -0
  94. package/src/stories/controls/theme.ts +3 -0
  95. package/src/stories/controls/typography.ts +5 -0
  96. package/src/stories/controls/withUndefined.ts +1 -0
  97. package/src/stories/decorators/withChromaticForceScreenSize.tsx +8 -0
  98. package/src/stories/decorators/withCombinations.tsx +99 -0
  99. package/src/stories/decorators/withNestedProps.tsx +23 -0
  100. package/src/stories/{withResizableBox.tsx → decorators/withResizableBox.tsx} +6 -10
  101. package/src/stories/decorators/withValueOnChange.tsx +18 -0
  102. package/src/stories/decorators/withWrapper.tsx +19 -0
  103. package/src/stories/utils/CustomLink.tsx +8 -2
  104. package/src/stories/{knobs → utils}/lorem.ts +9 -9
  105. package/src/testing/utils/commonTestsSuiteRTL.ts +2 -3
  106. package/src/testing/utils/index.ts +0 -2
  107. package/src/untypped-modules.d.ts +0 -2
  108. package/src/utils/MaterialThemeSwitcher/MaterialThemeSwitcher.tsx +1 -1
  109. package/src/utils/ThemeContext.ts +4 -0
  110. package/src/utils/forwardRefPolymorphic.ts +9 -0
  111. package/src/utils/type.ts +28 -4
  112. package/src/components/alert-dialog/__snapshots__/AlertDialog.test.tsx.snap +0 -551
  113. package/src/components/avatar/__snapshots__/Avatar.test.tsx.snap +0 -681
  114. package/src/components/comment-block/__snapshots__/CommentBlock.test.tsx.snap +0 -92
  115. package/src/components/dialog/__snapshots__/Dialog.test.tsx.snap +0 -960
  116. package/src/components/expansion-panel/ExpansionPanel.stories.tsx +0 -65
  117. package/src/components/flag/__snapshots__/Flag.test.tsx.snap +0 -133
  118. package/src/components/flex-box/__snapshots__/FlexBox.test.tsx.snap +0 -492
  119. package/src/components/grid-column/GridColumn.stories.jsx +0 -56
  120. package/src/components/image-block/__snapshots__/ImageBlock.test.tsx.snap +0 -64
  121. package/src/components/lightbox/__snapshots__/Lightbox.test.tsx.snap +0 -194
  122. package/src/components/list/__snapshots__/List.test.tsx.snap +0 -360
  123. package/src/components/list/__snapshots__/ListDivider.test.tsx.snap +0 -7
  124. package/src/components/list/__snapshots__/ListItem.test.tsx.snap +0 -160
  125. package/src/components/list/__snapshots__/ListSubheader.test.tsx.snap +0 -9
  126. package/src/components/mosaic/__snapshots__/Mosaic.test.tsx.snap +0 -357
  127. package/src/components/post-block/__snapshots__/PostBlock.test.tsx.snap +0 -139
  128. package/src/components/skeleton/__snapshots__/SkeletonCircle.test.tsx.snap +0 -54
  129. package/src/components/skeleton/__snapshots__/SkeletonRectangle.test.tsx.snap +0 -177
  130. package/src/components/skeleton/__snapshots__/SkeletonTypography.test.tsx.snap +0 -174
  131. package/src/components/slider/__snapshots__/Slider.test.tsx.snap +0 -122
  132. package/src/components/slideshow/__snapshots__/Slideshow.test.tsx.snap +0 -157
  133. package/src/components/table/__snapshots__/Table.test.tsx.snap +0 -263
  134. package/src/components/text/Text.stories.jsx +0 -75
  135. package/src/components/thumbnail/__snapshots__/Thumbnail.test.tsx.snap +0 -130
  136. package/src/components/user-block/__snapshots__/UserBlock.test.tsx.snap +0 -362
  137. package/src/stories/chromaticForceScreenSize.tsx +0 -7
  138. package/src/stories/knobs/buttonKnob.ts +0 -9
  139. package/src/stories/knobs/emphasisKnob.ts +0 -8
  140. package/src/stories/knobs/enumKnob.ts +0 -14
  141. package/src/stories/knobs/focusKnob.ts +0 -3
  142. package/src/stories/knobs/sizeKnob.ts +0 -5
  143. package/src/stories/knobs/thumbnailsKnob.ts +0 -9
  144. 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({});