oneslash-design-system 1.1.0 → 1.1.1
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.
- package/components/menuItem.tsx +3 -3
- package/components/popover.tsx +40 -70
- package/package.json +4 -2
package/components/menuItem.tsx
CHANGED
|
@@ -52,13 +52,13 @@ export default function MenuItem({
|
|
|
52
52
|
flex items-center space-x-2 p-2 rounded-[8px] cursor-pointer justify-start
|
|
53
53
|
${isSelected
|
|
54
54
|
? 'bg-light-action-selected dark:bg-dark-action-selected'
|
|
55
|
-
: 'hover:bg-light-
|
|
55
|
+
: 'hover:bg-light-background-accent100 hover:dark:bg-dark-background-accent100'}
|
|
56
56
|
`}
|
|
57
57
|
style={{ width: '100%' }}
|
|
58
58
|
onClick={onClick}
|
|
59
59
|
>
|
|
60
|
-
{Icon && <Icon className="w-
|
|
61
|
-
<span className="whitespace-nowrap text-body1">
|
|
60
|
+
{Icon && <Icon className="w-6 h-6" />}
|
|
61
|
+
<span className="whitespace-nowrap text-body1 px-2">
|
|
62
62
|
{label}
|
|
63
63
|
</span>
|
|
64
64
|
</div>
|
package/components/popover.tsx
CHANGED
|
@@ -1,98 +1,68 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
3
|
+
import { usePopper } from 'react-popper';
|
|
3
4
|
|
|
4
5
|
interface PopoverProps {
|
|
5
6
|
id?: string;
|
|
6
7
|
anchorEl?: HTMLElement | null;
|
|
7
|
-
open
|
|
8
|
-
onClose
|
|
9
|
-
children:
|
|
8
|
+
open: boolean;
|
|
9
|
+
onClose: () => void;
|
|
10
|
+
children: React.ReactNode;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
export default function Popover({
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
export default function Popover({
|
|
14
|
+
id,
|
|
15
|
+
anchorEl,
|
|
16
|
+
open,
|
|
17
|
+
onClose,
|
|
18
|
+
children,
|
|
17
19
|
}: PopoverProps) {
|
|
20
|
+
const [popoverElement, setPopoverElement] = useState<HTMLDivElement | null>(null);
|
|
21
|
+
const [hasMounted, setHasMounted] = useState(false);
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
const
|
|
23
|
+
// Initialize Popper.js
|
|
24
|
+
const { styles, attributes } = usePopper(anchorEl, popoverElement, {
|
|
25
|
+
placement: 'bottom-start', // Default placement, can be customized
|
|
26
|
+
modifiers: [
|
|
27
|
+
{ name: 'offset', options: { offset: [0, 8] } }, // Offset for spacing between anchor and popover
|
|
28
|
+
],
|
|
29
|
+
});
|
|
21
30
|
|
|
22
|
-
//
|
|
23
|
-
|
|
31
|
+
// Handle outside clicks to close the popover
|
|
32
|
+
useEffect(() => {
|
|
24
33
|
const handleClickOutside = (event: MouseEvent) => {
|
|
25
|
-
if (
|
|
26
|
-
onClose
|
|
34
|
+
if (popoverElement && !popoverElement.contains(event.target as Node) && anchorEl) {
|
|
35
|
+
onClose();
|
|
27
36
|
}
|
|
28
37
|
};
|
|
38
|
+
|
|
29
39
|
if (open) {
|
|
30
40
|
document.addEventListener('mousedown', handleClickOutside);
|
|
31
41
|
}
|
|
32
42
|
return () => {
|
|
33
43
|
document.removeEventListener('mousedown', handleClickOutside);
|
|
34
44
|
};
|
|
35
|
-
}, [open, anchorEl, onClose]);
|
|
36
|
-
|
|
37
|
-
// Calculate position and handle scroll/resize
|
|
38
|
-
useLayoutEffect(() => {
|
|
39
|
-
if (anchorEl && open) {
|
|
40
|
-
const handlePositioning = () => {
|
|
41
|
-
const anchorRect = anchorEl.getBoundingClientRect();
|
|
42
|
-
const popoverRect = popoverRef.current?.getBoundingClientRect();
|
|
43
|
-
|
|
44
|
-
if (popoverRect) {
|
|
45
|
-
const spaceBelow = window.innerHeight - anchorRect.bottom;
|
|
46
|
-
const spaceAbove = anchorRect.top;
|
|
47
|
-
|
|
48
|
-
// Decide whether to place the popover above or below the anchor
|
|
49
|
-
const shouldPlaceAbove = spaceBelow < popoverRect.height + 8 && spaceAbove > popoverRect.height + 8;
|
|
50
|
-
|
|
51
|
-
// Calculate top and left positions
|
|
52
|
-
const topPosition = shouldPlaceAbove
|
|
53
|
-
? anchorRect.top + window.scrollY - popoverRect.height - 8
|
|
54
|
-
: anchorRect.bottom + window.scrollY + 8;
|
|
55
|
-
|
|
56
|
-
let leftPosition = anchorRect.left + window.scrollX + (anchorRect.width / 2) - (popoverRect.width / 2);
|
|
45
|
+
}, [open, anchorEl, popoverElement, onClose]);
|
|
57
46
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
leftPosition = window.innerWidth - popoverRect.width - 8; // Prevent overflow on the right
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
setPopoverStyle({
|
|
66
|
-
position: 'absolute',
|
|
67
|
-
top: `${topPosition}px`,
|
|
68
|
-
left: `${leftPosition}px`,
|
|
69
|
-
zIndex: 10000,
|
|
70
|
-
visibility: 'visible',
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
handlePositioning(); // Initial positioning calculation
|
|
76
|
-
window.addEventListener('resize', handlePositioning);
|
|
77
|
-
window.addEventListener('scroll', handlePositioning, true);
|
|
78
|
-
|
|
79
|
-
return () => {
|
|
80
|
-
window.removeEventListener('resize', handlePositioning);
|
|
81
|
-
window.removeEventListener('scroll', handlePositioning, true);
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
}, [anchorEl, open]);
|
|
47
|
+
// Ensure popover is only rendered after the component mounts
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
setHasMounted(true);
|
|
50
|
+
}, []);
|
|
85
51
|
|
|
86
|
-
if (!open || !anchorEl) return null;
|
|
52
|
+
if (!open || !hasMounted || !anchorEl) return null;
|
|
87
53
|
|
|
88
|
-
|
|
54
|
+
// Render popover in a portal to prevent layout shifts and positioning issues
|
|
55
|
+
return createPortal(
|
|
89
56
|
<div
|
|
90
|
-
|
|
91
|
-
|
|
57
|
+
id={id}
|
|
58
|
+
ref={setPopoverElement}
|
|
59
|
+
style={{ ...styles.popper, display: open ? 'block' : 'none' }}
|
|
60
|
+
{...attributes.popper}
|
|
92
61
|
className="bg-light-background-accent100 dark:bg-dark-background-accent100 rounded-[8px] shadow-lg p-2"
|
|
93
62
|
role="dialog"
|
|
94
63
|
>
|
|
95
64
|
{children}
|
|
96
|
-
</div
|
|
65
|
+
</div>,
|
|
66
|
+
document.body // Mounting the popover in the document body for isolation
|
|
97
67
|
);
|
|
98
68
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oneslash-design-system",
|
|
3
3
|
"description": "A design system for the Oneslash projects",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.1",
|
|
5
5
|
"private": false,
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "next dev",
|
|
@@ -12,9 +12,11 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@heroicons/react": "^2.1.5",
|
|
15
|
+
"@popperjs/core": "^2.11.8",
|
|
15
16
|
"next": "14.2.13",
|
|
16
17
|
"react": "^18",
|
|
17
|
-
"react-dom": "^18"
|
|
18
|
+
"react-dom": "^18",
|
|
19
|
+
"react-popper": "^2.3.0"
|
|
18
20
|
},
|
|
19
21
|
"devDependencies": {
|
|
20
22
|
"@types/node": "20.16.10",
|