@indico-data/design-system 2.19.0 → 2.20.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 (38) hide show
  1. package/lib/index.css +55 -0
  2. package/lib/index.d.ts +18 -1
  3. package/lib/index.esm.css +55 -0
  4. package/lib/index.esm.js +1567 -8
  5. package/lib/index.esm.js.map +1 -1
  6. package/lib/index.js +1567 -6
  7. package/lib/index.js.map +1 -1
  8. package/lib/src/components/index.d.ts +2 -0
  9. package/lib/src/components/menu/Menu.d.ts +5 -0
  10. package/lib/src/components/menu/Menu.stories.d.ts +6 -0
  11. package/lib/src/components/menu/Menu.test.d.ts +1 -0
  12. package/lib/src/components/menu/index.d.ts +1 -0
  13. package/lib/src/components/popper/Popper.d.ts +12 -0
  14. package/lib/src/components/popper/Popper.stories.d.ts +6 -0
  15. package/lib/src/components/popper/Popper.test.d.ts +1 -0
  16. package/lib/src/components/popper/index.d.ts +1 -0
  17. package/lib/src/hooks/useClickOutside.d.ts +2 -0
  18. package/lib/src/index.d.ts +2 -0
  19. package/package.json +2 -1
  20. package/src/components/index.ts +2 -0
  21. package/src/components/menu/Menu.mdx +15 -0
  22. package/src/components/menu/Menu.stories.tsx +56 -0
  23. package/src/components/menu/Menu.test.tsx +88 -0
  24. package/src/components/menu/Menu.tsx +20 -0
  25. package/src/components/menu/index.ts +1 -0
  26. package/src/components/menu/styles/Menu.scss +19 -0
  27. package/src/components/menu/styles/_variables.scss +15 -0
  28. package/src/components/popper/Popper.mdx +79 -0
  29. package/src/components/popper/Popper.stories.tsx +161 -0
  30. package/src/components/popper/Popper.test.tsx +68 -0
  31. package/src/components/popper/Popper.tsx +57 -0
  32. package/src/components/popper/index.ts +1 -0
  33. package/src/components/popper/styles/Popper.scss +11 -0
  34. package/src/components/popper/styles/_variables.scss +15 -0
  35. package/src/hooks/useClickOutside.tsx +22 -0
  36. package/src/index.ts +2 -0
  37. package/src/legacy/components/buttons/commonStyles.ts +0 -4
  38. package/src/styles/index.scss +2 -0
@@ -12,3 +12,5 @@ export { Select } from './forms/select';
12
12
  export { Form } from './forms/form';
13
13
  export { Skeleton } from './skeleton';
14
14
  export { Card } from './card';
15
+ export { Popper } from './popper';
16
+ export { Menu } from './menu';
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ export type MenuProps = {
3
+ children: React.ReactNode;
4
+ };
5
+ export declare function Menu({ children }: MenuProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { Menu, MenuProps } from './Menu';
3
+ declare const meta: Meta<typeof Menu>;
4
+ export default meta;
5
+ type Story = StoryObj<MenuProps>;
6
+ export declare const Default: Story;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export { Menu } from './Menu';
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { Placement } from '@floating-ui/react-dom';
3
+ export type PopperProps = {
4
+ children: React.ReactNode;
5
+ referenceElement: HTMLElement | null;
6
+ isOpen: boolean;
7
+ onClose: () => void;
8
+ ariaLabel: string;
9
+ placement?: Placement;
10
+ offsetValue?: number;
11
+ };
12
+ export declare function Popper({ children, referenceElement, isOpen, onClose, ariaLabel, placement, offsetValue, }: PopperProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,6 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { Popper, PopperProps } from './Popper';
3
+ declare const meta: Meta<typeof Popper>;
4
+ export default meta;
5
+ type Story = StoryObj<PopperProps>;
6
+ export declare const Default: Story;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export { Popper } from './Popper';
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const useClickOutside: (ref: React.MutableRefObject<HTMLElement>, handler: (e: MouseEvent | TouchEvent) => void) => void;
@@ -17,3 +17,5 @@ export { Select as SelectInput } from './components/forms/select';
17
17
  export { Form } from './components/forms/form';
18
18
  export { Skeleton } from './components/skeleton';
19
19
  export { Card } from './components/card';
20
+ export { Popper } from './components/popper';
21
+ export { Menu } from './components/menu';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indico-data/design-system",
3
- "version": "2.19.0",
3
+ "version": "2.20.0",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "main": "lib/index.js",
@@ -28,6 +28,7 @@
28
28
  "**/*": "prettier --write --ignore-unknown"
29
29
  },
30
30
  "dependencies": {
31
+ "@floating-ui/react-dom": "^2.1.1",
31
32
  "@fortawesome/fontawesome-svg-core": "^6.5.2",
32
33
  "@fortawesome/free-regular-svg-icons": "^6.5.2",
33
34
  "@fortawesome/free-solid-svg-icons": "^6.5.2",
@@ -12,3 +12,5 @@ export { Select } from './forms/select';
12
12
  export { Form } from './forms/form';
13
13
  export { Skeleton } from './skeleton';
14
14
  export { Card } from './card';
15
+ export { Popper } from './popper';
16
+ export { Menu } from './menu';
@@ -0,0 +1,15 @@
1
+ import { Canvas, Meta, Controls, Story } from '@storybook/blocks';
2
+ import * as Menu from './Menu.stories';
3
+ import { Col, Row } from '@/components';
4
+
5
+ <Meta title="Components/Menu" of={Menu} />
6
+
7
+ # Menu
8
+
9
+ The Menu component is used to display a list of actionable items. Typically used in dropdowns, poppers, or sidebars.
10
+
11
+ <Canvas of={Menu.Default} />
12
+
13
+ ### The following props are available for the Menu component:
14
+
15
+ <Controls of={Menu.Default} />
@@ -0,0 +1,56 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { Menu, MenuProps } from './Menu';
3
+ import { Button } from '../button';
4
+
5
+ const meta: Meta<typeof Menu> = {
6
+ title: 'Components/Menu',
7
+ component: Menu,
8
+ argTypes: {
9
+ children: {
10
+ control: 'text',
11
+ description:
12
+ 'The children of the Menu component, which will be automatically styled as menu-items.',
13
+ table: {
14
+ category: 'Props',
15
+ type: {
16
+ summary: 'React.ReactNode',
17
+ },
18
+ },
19
+ },
20
+ },
21
+ };
22
+
23
+ export default meta;
24
+
25
+ type Story = StoryObj<MenuProps>;
26
+
27
+ export const Default: Story = {
28
+ render: (args) => (
29
+ <Menu {...args}>
30
+ <Button
31
+ data-testid="refresh-library"
32
+ ariaLabel="Refresh Data"
33
+ iconName="retrain"
34
+ onClick={() => console.log('Refresh Data')}
35
+ >
36
+ Refresh Data
37
+ </Button>
38
+ <Button
39
+ data-testid="configure-fields"
40
+ ariaLabel="Configure Fields"
41
+ iconName="edit"
42
+ onClick={() => console.log('Configure Fields')}
43
+ >
44
+ Configure Fields
45
+ </Button>
46
+ <Button
47
+ data-testid="delete-library"
48
+ ariaLabel="Delete Library"
49
+ iconName="trash"
50
+ onClick={() => console.log('Delete Library')}
51
+ >
52
+ Delete Library
53
+ </Button>
54
+ </Menu>
55
+ ),
56
+ };
@@ -0,0 +1,88 @@
1
+ import React from 'react';
2
+ import { render, screen, fireEvent } from '@testing-library/react';
3
+ import { Menu } from './Menu';
4
+ import { Button } from '../button';
5
+
6
+ describe('Menu Component', () => {
7
+ it('renders children inside of the menu', () => {
8
+ render(
9
+ <Menu>
10
+ <Button data-testid="refresh-library" ariaLabel="Refresh Data" iconName="retrain">
11
+ Refresh Data
12
+ </Button>
13
+ <Button data-testid="configure-fields" ariaLabel="Configure Fields" iconName="edit">
14
+ Configure Fields
15
+ </Button>
16
+ <Button data-testid="delete-library" ariaLabel="Delete Library" iconName="trash">
17
+ Delete Library
18
+ </Button>
19
+ </Menu>,
20
+ );
21
+ expect(screen.getByText('Refresh Data')).toBeInTheDocument();
22
+ expect(screen.getByText('Configure Fields')).toBeInTheDocument();
23
+ expect(screen.getByText('Delete Library')).toBeInTheDocument();
24
+ });
25
+
26
+ it('applies the menu-item class to its children', () => {
27
+ render(
28
+ <Menu>
29
+ <Button data-testid="refresh-library" ariaLabel="Refresh Data" iconName="retrain">
30
+ Refresh Data
31
+ </Button>
32
+ <Button data-testid="configure-fields" ariaLabel="Configure Fields" iconName="edit">
33
+ Configure Fields
34
+ </Button>
35
+ <Button data-testid="delete-library" ariaLabel="Delete Library" iconName="trash">
36
+ Delete Library
37
+ </Button>
38
+ </Menu>,
39
+ );
40
+ const menuItems = screen.getAllByRole('button');
41
+ menuItems.forEach((item) => {
42
+ expect(item).toHaveClass('menu-item');
43
+ });
44
+ });
45
+
46
+ it('handles click events for its children', () => {
47
+ const mockRefresh = jest.fn();
48
+ const mockConfigure = jest.fn();
49
+ const mockDelete = jest.fn();
50
+
51
+ render(
52
+ <Menu>
53
+ <Button
54
+ data-testid="refresh-library"
55
+ ariaLabel="Refresh Data"
56
+ iconName="retrain"
57
+ onClick={mockRefresh}
58
+ >
59
+ Refresh Data
60
+ </Button>
61
+ <Button
62
+ data-testid="configure-fields"
63
+ ariaLabel="Configure Fields"
64
+ iconName="edit"
65
+ onClick={mockConfigure}
66
+ >
67
+ Configure Fields
68
+ </Button>
69
+ <Button
70
+ data-testid="delete-library"
71
+ ariaLabel="Delete Library"
72
+ iconName="trash"
73
+ onClick={mockDelete}
74
+ >
75
+ Delete Library
76
+ </Button>
77
+ </Menu>,
78
+ );
79
+
80
+ fireEvent.click(screen.getByText('Refresh Data'));
81
+ fireEvent.click(screen.getByText('Configure Fields'));
82
+ fireEvent.click(screen.getByText('Delete Library'));
83
+
84
+ expect(mockRefresh).toHaveBeenCalledTimes(1);
85
+ expect(mockConfigure).toHaveBeenCalledTimes(1);
86
+ expect(mockDelete).toHaveBeenCalledTimes(1);
87
+ });
88
+ });
@@ -0,0 +1,20 @@
1
+ import React, { ReactElement } from 'react';
2
+ import classNames from 'classnames';
3
+
4
+ export type MenuProps = {
5
+ children: React.ReactNode;
6
+ };
7
+
8
+ export function Menu({ children }: MenuProps) {
9
+ return (
10
+ <div className="menu">
11
+ {React.Children.map(children, (child) =>
12
+ React.isValidElement(child)
13
+ ? React.cloneElement(child as ReactElement, {
14
+ className: classNames((child as ReactElement).props.className, 'menu-item'),
15
+ })
16
+ : child,
17
+ )}
18
+ </div>
19
+ );
20
+ }
@@ -0,0 +1 @@
1
+ export { Menu } from './Menu';
@@ -0,0 +1,19 @@
1
+ @import './variables.scss';
2
+
3
+ .menu {
4
+ border-radius: var(--pf-menu-rounded);
5
+
6
+ .menu-item {
7
+ width: 100%;
8
+ background: var(--pf-menu-item-background-color);
9
+ color: var(--pf-menu-item-color);
10
+ display: block;
11
+ width: 100%;
12
+ text-align: left;
13
+ border: none;
14
+
15
+ &:hover {
16
+ background: var(--pf-menu-item-hover-color);
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,15 @@
1
+ :root,
2
+ :root [data-theme='light'],
3
+ :root [data-theme='dark'] {
4
+ --pf-menu-rounded: var(--pf-rounded);
5
+ --pf-menu-item-hover-color: var(--pf-primary-color-100);
6
+ --pf-menu-item-background-color: var(--pf-white-color);
7
+ --pf-menu-item-color: var(--pf-gray-color);
8
+ }
9
+
10
+ // Dark Theme Specific Variables
11
+ :root [data-theme='dark'] {
12
+ --pf-menu-item-hover-color: var(--pf-primary-color-300);
13
+ --pf-menu-item-background-color: var(--pf-primary-color-600);
14
+ --pf-menu-item-color: var(--pf-gray-color-100);
15
+ }
@@ -0,0 +1,79 @@
1
+ import { Canvas, Meta, Controls } from '@storybook/blocks';
2
+ import * as PopperStories from './Popper.stories';
3
+ import { Col, Row } from '@/components';
4
+
5
+ <Meta title="Components/Popper" of={PopperStories} />
6
+
7
+ # Popper
8
+
9
+ The Popper component is used to display content relative to another element. It can be used for tooltips, dropdowns, and other floating elements. The Popper is positioned using the `@floating-ui/react-dom` library.
10
+
11
+ <Canvas
12
+ of={PopperStories.Default}
13
+ source={{
14
+ code: `
15
+ import React, { useState, useRef } from 'react';
16
+ import { Popper } from '@/components/Popper';
17
+ import { Button } from '@/components/Button';
18
+ import { Menu } from '@/components/Menu';
19
+
20
+ const Example = () => {
21
+ const [isOpen, setIsOpen] = useState(false);
22
+ const buttonRef = useRef<HTMLDivElement | null>(null);
23
+
24
+ return (
25
+ <div>
26
+ <div ref={buttonRef}>
27
+ <Button
28
+ onClick={() => setIsOpen((prev) => !prev)}
29
+ iconName="kabob"
30
+ ariaLabel="Toggle Popper"
31
+ />
32
+ </div>
33
+ <Popper
34
+ referenceElement={buttonRef.current}
35
+ isOpen={isOpen}
36
+ onClose={() => setIsOpen(false)}
37
+ ariaLabel="Example Popper"
38
+ placement="bottom-start"
39
+ offsetValue={5}
40
+ >
41
+ <Menu>
42
+ <Button
43
+ data-testid="refresh-library"
44
+ ariaLabel="Refresh Data"
45
+ iconName="retrain"
46
+ onClick={() => console.log('Refresh Data')}
47
+ >
48
+ Refresh Data
49
+ </Button>
50
+ <Button
51
+ data-testid="configure-fields"
52
+ ariaLabel="Configure Fields"
53
+ iconName="edit"
54
+ onClick={() => console.log('Configure Fields')}
55
+ >
56
+ Configure Fields
57
+ </Button>
58
+ <Button
59
+ data-testid="delete-library"
60
+ ariaLabel="Delete Library"
61
+ iconName="trash"
62
+ onClick={() => console.log('Delete Library')}
63
+ >
64
+ Delete Library
65
+ </Button>
66
+ </Menu>
67
+ </Popper>
68
+ </div>
69
+ );
70
+ };
71
+
72
+ export default Example;
73
+ `,
74
+ }}
75
+ />
76
+
77
+ ### The following props are available for the Popper component:
78
+
79
+ <Controls of={PopperStories.Default} />
@@ -0,0 +1,161 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { useState, useRef } from 'react';
3
+ import { Popper, PopperProps } from './Popper';
4
+ import { Button } from '../button';
5
+ import { Menu } from '../menu';
6
+
7
+ const meta: Meta<typeof Popper> = {
8
+ title: 'Components/Popper',
9
+ component: Popper,
10
+ argTypes: {
11
+ children: {
12
+ control: 'object',
13
+ description: 'The content of the popper.',
14
+ table: {
15
+ category: 'Props',
16
+ type: {
17
+ summary: 'React.ReactNode',
18
+ },
19
+ },
20
+ },
21
+ referenceElement: {
22
+ control: 'object',
23
+ description: 'The element to which the popper is attached.',
24
+ table: {
25
+ category: 'Props',
26
+ type: {
27
+ summary: 'HTMLElement | null',
28
+ },
29
+ },
30
+ },
31
+ isOpen: {
32
+ control: 'boolean',
33
+ description: 'Controls the visibility of the popper.',
34
+ table: {
35
+ category: 'Props',
36
+ type: {
37
+ summary: 'boolean',
38
+ },
39
+ defaultValue: { summary: 'false' },
40
+ },
41
+ },
42
+ onClose: {
43
+ action: 'closed',
44
+ description: 'Callback function when the popper closes.',
45
+ table: { category: 'callbacks' },
46
+ },
47
+ ariaLabel: {
48
+ control: 'text',
49
+ description: 'Sets the aria-label attribute for the popper.',
50
+ table: {
51
+ category: 'Props',
52
+ type: {
53
+ summary: 'string',
54
+ },
55
+ },
56
+ },
57
+ placement: {
58
+ control: 'select',
59
+ options: [
60
+ 'top',
61
+ 'top-start',
62
+ 'top-end',
63
+ 'right',
64
+ 'right-start',
65
+ 'right-end',
66
+ 'bottom',
67
+ 'bottom-start',
68
+ 'bottom-end',
69
+ 'left',
70
+ 'left-start',
71
+ 'left-end',
72
+ ],
73
+ description: 'Sets the placement of the popper.',
74
+ table: {
75
+ category: 'Props',
76
+ type: {
77
+ summary: 'string',
78
+ },
79
+ defaultValue: { summary: 'bottom-start' },
80
+ },
81
+ },
82
+ offsetValue: {
83
+ control: 'number',
84
+ description: 'Sets the offset value for the popper.',
85
+ table: {
86
+ category: 'Props',
87
+ type: {
88
+ summary: 'number',
89
+ },
90
+ defaultValue: { summary: '5' },
91
+ },
92
+ },
93
+ },
94
+ decorators: [
95
+ (Story: React.ComponentType) => (
96
+ <div
97
+ style={{
98
+ height: '160px',
99
+ }}
100
+ >
101
+ <Story />
102
+ </div>
103
+ ),
104
+ ],
105
+ };
106
+
107
+ export default meta;
108
+
109
+ type Story = StoryObj<PopperProps>;
110
+
111
+ export const Default: Story = {
112
+ render: (args) => {
113
+ const [isOpen, setIsOpen] = useState(false);
114
+ const buttonRef = useRef<HTMLDivElement | null>(null);
115
+
116
+ return (
117
+ <div>
118
+ <div ref={buttonRef}>
119
+ <Button
120
+ onClick={() => setIsOpen((prev) => !prev)}
121
+ iconName="kabob"
122
+ ariaLabel="Toggle Popper"
123
+ />
124
+ </div>
125
+ <Popper
126
+ {...args}
127
+ referenceElement={buttonRef.current}
128
+ isOpen={isOpen || args.isOpen}
129
+ onClose={() => setIsOpen(false)}
130
+ >
131
+ <Menu>
132
+ <Button
133
+ data-testid="refresh-library"
134
+ ariaLabel="Refresh Data"
135
+ iconName="retrain"
136
+ onClick={() => console.log('Refresh Data')}
137
+ >
138
+ Refresh Data
139
+ </Button>
140
+ <Button
141
+ data-testid="configure-fields"
142
+ ariaLabel="Configure Fields"
143
+ iconName="edit"
144
+ onClick={() => console.log('Configure Fields')}
145
+ >
146
+ Configure Fields
147
+ </Button>
148
+ <Button
149
+ data-testid="delete-library"
150
+ ariaLabel="Delete Library"
151
+ iconName="trash"
152
+ onClick={() => console.log('Delete Library')}
153
+ >
154
+ Delete Library
155
+ </Button>
156
+ </Menu>
157
+ </Popper>
158
+ </div>
159
+ );
160
+ },
161
+ };
@@ -0,0 +1,68 @@
1
+ import React from 'react';
2
+ import { render, screen, fireEvent } from '@testing-library/react';
3
+ import { Popper } from './Popper';
4
+ import { Menu } from '../menu';
5
+ import { Button } from '../button';
6
+
7
+ describe('Popper Component', () => {
8
+ it('renders without display when isOpen is false', () => {
9
+ render(
10
+ <Popper referenceElement={null} isOpen={false} onClose={jest.fn()} ariaLabel="Example Popper">
11
+ <div>Popper Content</div>
12
+ </Popper>,
13
+ );
14
+ expect(screen.queryByText('Popper Content')).not.toBeInTheDocument();
15
+ });
16
+
17
+ it('displays the popper content when isOpen is true', () => {
18
+ render(
19
+ <Popper referenceElement={null} isOpen={true} onClose={jest.fn()} ariaLabel="Example Popper">
20
+ <div>Popper Content</div>
21
+ </Popper>,
22
+ );
23
+ expect(screen.getByText('Popper Content')).toBeInTheDocument();
24
+ });
25
+
26
+ it('calls onClose when clicked outside', () => {
27
+ const mockOnClose = jest.fn();
28
+
29
+ render(
30
+ <div>
31
+ <div data-testid="outside">Outside Element</div>
32
+ <Popper
33
+ referenceElement={null}
34
+ isOpen={true}
35
+ onClose={mockOnClose}
36
+ ariaLabel="Example Popper"
37
+ >
38
+ <div>Popper Content</div>
39
+ </Popper>
40
+ </div>,
41
+ );
42
+
43
+ fireEvent.mouseDown(screen.getByTestId('outside'));
44
+ expect(mockOnClose).toHaveBeenCalledTimes(1);
45
+ });
46
+
47
+ it('renders children inside the popper', () => {
48
+ render(
49
+ <Popper referenceElement={null} isOpen={true} onClose={jest.fn()} ariaLabel="Example Popper">
50
+ <Menu>
51
+ <Button ariaLabel="Refresh Data" iconName="retrain">
52
+ Refresh Data
53
+ </Button>
54
+ <Button ariaLabel="Configure Fields" iconName="edit">
55
+ Configure Fields
56
+ </Button>
57
+ <Button ariaLabel="Delete Library" iconName="trash">
58
+ Delete Library
59
+ </Button>
60
+ </Menu>
61
+ </Popper>,
62
+ );
63
+
64
+ expect(screen.getByText('Refresh Data')).toBeInTheDocument();
65
+ expect(screen.getByText('Configure Fields')).toBeInTheDocument();
66
+ expect(screen.getByText('Delete Library')).toBeInTheDocument();
67
+ });
68
+ });
@@ -0,0 +1,57 @@
1
+ import React, { useRef } from 'react';
2
+ import { useFloating, offset, flip, shift, Placement } from '@floating-ui/react-dom';
3
+ import { useClickOutside } from '@/hooks/useClickOutside';
4
+
5
+ export type PopperProps = {
6
+ children: React.ReactNode;
7
+ referenceElement: HTMLElement | null;
8
+ isOpen: boolean;
9
+ onClose: () => void;
10
+ ariaLabel: string;
11
+ placement?: Placement;
12
+ offsetValue?: number;
13
+ };
14
+
15
+ export function Popper({
16
+ children,
17
+ referenceElement,
18
+ isOpen,
19
+ onClose,
20
+ ariaLabel,
21
+ placement = 'bottom-start',
22
+ offsetValue = 5,
23
+ }: PopperProps) {
24
+ const popperContentRef = useRef() as React.MutableRefObject<HTMLDivElement>;
25
+
26
+ const { x, y, strategy, refs } = useFloating({
27
+ placement,
28
+ middleware: [offset(offsetValue), flip(), shift()],
29
+ elements: {
30
+ reference: referenceElement,
31
+ },
32
+ });
33
+
34
+ useClickOutside(popperContentRef, onClose);
35
+
36
+ if (!isOpen) {
37
+ return null;
38
+ }
39
+
40
+ return (
41
+ <div
42
+ ref={refs.setFloating}
43
+ style={{
44
+ position: strategy,
45
+ top: y ?? '',
46
+ left: x ?? '',
47
+ }}
48
+ role="dialog"
49
+ aria-label={ariaLabel}
50
+ className="popper-container"
51
+ >
52
+ <div ref={popperContentRef} className="popper-content">
53
+ {children}
54
+ </div>
55
+ </div>
56
+ );
57
+ }
@@ -0,0 +1 @@
1
+ export { Popper } from './Popper';