Skip to content

Commit 73511f1

Browse files
committedJan 14, 2023
create portal
1 parent d49b042 commit 73511f1

File tree

6 files changed

+60
-22
lines changed

6 files changed

+60
-22
lines changed
 

‎index.html

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
</head>
1212
<body>
1313
<div id="root"></div>
14+
<div id="portal-root"></div>
1415
<script type="module" src="/src/main.tsx"></script>
1516
</body>
1617
</html>
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React from "react";
2+
import { useEffect, ReactNode } from "react";
3+
import { createPortal } from "react-dom";
4+
5+
type portalT = {
6+
children: ReactNode
7+
}
8+
9+
const Portal:React.FC<portalT> = ({children}) => {
10+
const mount = document.getElementById('portal-root');
11+
const el = document.createElement('div');
12+
13+
useEffect(() => {
14+
mount?.appendChild(el);
15+
16+
return () => mount?.removeChild(el) as void;
17+
}, [el, mount]);
18+
19+
return createPortal(children, el);
20+
}
21+
22+
export default Portal;

‎src/components/Molecules/Modal/modal.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111

1212
import { modalProps } from "./type";
1313
import Button from "../../Atoms/Button";
14+
import Portal from "../../Atoms/Portal/portal";
1415

1516
const Modal:React.FC<modalProps> = (props) => {
1617

@@ -26,6 +27,7 @@ const Modal:React.FC<modalProps> = (props) => {
2627
return (
2728
<>
2829
{ open &&
30+
<Portal>
2931
<StyledModal>
3032
<ModalContent width={width}>
3133
<ModalHeader>
@@ -41,6 +43,7 @@ const Modal:React.FC<modalProps> = (props) => {
4143
</ModalFooter>
4244
</ModalContent>
4345
</StyledModal>
46+
</Portal>
4447
}
4548
</>
4649
)

‎src/components/Molecules/Modal/style.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ export const StyledModal = styled.div`
1616
width: 100%;
1717
height: 100%;
1818
background-color:rgba(0,0,0,.45);
19-
z-index: 1000;
2019
overflow: auto;
2120
`;
2221

‎src/components/Molecules/Select/select.tsx

+28-17
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
OptionBody,
88
Li
99
} from "./style";
10+
import Portal from "../../Atoms/Portal/portal";
1011

1112
const Select:React.FC<selectProps> = (props) => {
1213

@@ -20,7 +21,7 @@ const Select:React.FC<selectProps> = (props) => {
2021
} = props;
2122

2223
const [show, setShow] = useState(false);
23-
24+
const [bodyCoordinates, setBodyCoordinates] = useState({x : 0, y : 0, height: 0});
2425
const selectRef = useRef<HTMLDivElement>(null);
2526
const buttonRef = useRef<HTMLButtonElement>(null);
2627

@@ -41,14 +42,21 @@ const Select:React.FC<selectProps> = (props) => {
4142
return () => document.addEventListener('click', onClickoutside);
4243
}, [selectRef]);
4344

45+
const handleButtonClick = () => {
46+
setShow(!show);
47+
if (buttonRef.current) {
48+
const coords = buttonRef.current.getBoundingClientRect();
49+
setBodyCoordinates({x: coords.x, y: coords.y, height: coords.height })
50+
}
51+
}
4452

4553
return (
4654
<>
4755
<StyledSelect width={width} ref={selectRef}>
4856
<Button
4957
width={width}
5058
variant="default"
51-
onClick={() => setShow(!show)}
59+
onClick={handleButtonClick}
5260
noborder
5361
leftIcon={leftIcon}
5462
rightIcon={rightIcon}
@@ -57,21 +65,24 @@ const Select:React.FC<selectProps> = (props) => {
5765
<Text>{selectedValue}</Text>
5866
</Button>
5967
{ show &&
60-
<OptionBody
61-
width={width}
62-
justifyTop={buttonRef.current && buttonRef.current.offsetHeight}
63-
>
64-
<ul>
65-
{options.map(({label, value}) =>
66-
<Li
67-
isSelected={selectedValue === value}
68-
onClick={() => handleClick(value)}
69-
>
70-
{label}
71-
</Li>
72-
)}
73-
</ul>
74-
</OptionBody>
68+
<Portal>
69+
<OptionBody
70+
width={width}
71+
justifyTop={buttonRef.current && buttonRef.current.offsetHeight}
72+
coords={bodyCoordinates}
73+
>
74+
<ul>
75+
{options.map(({label, value}) =>
76+
<Li
77+
isSelected={selectedValue === value}
78+
onClick={() => handleClick(value)}
79+
>
80+
{label}
81+
</Li>
82+
)}
83+
</ul>
84+
</OptionBody>
85+
</Portal>
7586
}
7687
</StyledSelect>
7788
</>

‎src/components/Molecules/Select/style.tsx

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import styled from "styled-components";
22
import { colors } from "../../../styles/styleGuide";
33

4-
type widthT = {
4+
type OptionBodyT = {
55
width: string,
66
justifyTop?: number | null
7+
coords: { x: number, y: number, height: number }
78
}
89

9-
export const StyledSelect = styled.div<widthT>`
10+
export const StyledSelect = styled.div<{width:string}>`
1011
position: relative;
1112
width: ${props => props.width};
1213
@@ -15,9 +16,10 @@ export const StyledSelect = styled.div<widthT>`
1516
}
1617
`;
1718

18-
export const OptionBody = styled.div<widthT>`
19+
export const OptionBody = styled.div<OptionBodyT>`
1920
position: absolute;
20-
top: ${props => props.justifyTop ? props.justifyTop + 3 : 0 }px;
21+
top: ${props => props?.coords?.y + props?.coords?.height + 3}px;
22+
left: ${props => props?.coords?.x}px;
2123
width: ${props => props.width};
2224
background-color: ${colors.white};
2325
border: 1px solid rgb(0, 0, 0, 0.15);

0 commit comments

Comments
 (0)