<div id="root"></div>
const { useState, useCallback } = React;
const Button = styled.button`
background-color: ${({ colors }) => (colors && colors.bg) || "lightgray"};
border: none;
border-radius: 0.6vmin;
cursor: ${({ isDisabled }) => (isDisabled ? "cursor" : "pointer")};
color: ${({ colors }) => (colors && colors.text) || "#333333"};
font-size: ${({ sizes }) => (sizes && sizes.font) || "1em"};
height: ${({ sizes }) => (sizes && sizes.height) || "auto"};
outline: none;
opacity: ${({ isDisabled }) => (isDisabled ? 0.5 : 1)};
padding: ${({ sizes }) => (sizes && sizes.padding) || "1em 2em"};
pointer-events: ${({ isDisabled }) => (isDisabled ? "none" : "auto")};
user-select: none;
width: ${({ sizes }) => (sizes && sizes.width) || "auto"};
`;
const StyledModalWindow = styled.div`
z-index: 1000;
`;
const Overlay = styled.div`
background-color: rgba(0, 0, 0, 0.6);
position: fixed;
top: -100vh;
left: -100vw;
bottom: -100vh;
right: -100vw;
z-index: 1;
`;
const ContentWrapper = styled.div`
background-color: white;
box-sizing: border-box;
border-radius: 2vmin;
color: #333;
display: flex;
align-items: center;
justify-content: center;
min-height: 60vmin;
text-align: center;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
min-width: 80vmin;
z-index: 2;
> button {
position: absolute;
top: 4vmin;
right: 4vmin;
}
`;
const Content = styled.div`
max-height: 80vmin;
padding: 4vmin;
`;
const Title = styled.h1`
font-size: 4vmin;
margin: 0 auto 2vmin;
`;
const Text = styled.p`
color: #777;
font-size: 2vmin;
margin: 0 0 4vmin;
`;
const Buttons = styled.div`
display: flex;
justify-content: center;
& .btn {
margin: 0 0.6vmin;
}
`;
const ModalWindow = ({
className,
title,
text,
isShow,
isShowCloseButton,
buttons
}) => {
const [isClose, setIsClose] = useState(false);
const closeButtonSizes = {
padding: "0"
};
return (
<>
{isShow ? (
<StyledModalWindow className={className}>
<Overlay />
<ContentWrapper>
{isShowCloseButton && (
<Button
colors={{
bg: "transparent"
}}
sizes={closeButtonSizes}
onClick={() => setIsClose(true)}
>
✖
</Button>
)}
<Content>
<Title>{title}</Title>
<Text>{text}</Text>
<Buttons>
{buttons.map((b, i) => (
<Button
className="btn"
onClick={b.callback}
colors={b.colors}
sizes={b.sizes}
>
{b.name}
</Button>
))}
</Buttons>
</Content>
</ContentWrapper>
</StyledModalWindow>
) : (
<></>
)}
</>
);
};
const App = () => {
const [isShow, setIsShow] = useState(true);
const handleClick = useCallback(() => setIsShow(false), []);
const buttonColors = {
bg: "orange",
text: "#ffffff"
};
const buttonSizes = {
font: "1vmin",
padding: "2vmin 4vmin"
};
const buttonNo = {
name: "いいえ",
sizes: buttonSizes,
callback: handleClick
};
const buttonYes = {
name: "はい",
colors: buttonColors,
sizes: buttonSizes,
callback: handleClick
};
return (
<div>
<ModalWindow
title="年齢認証"
text="あなたは18歳以上ですか?"
isShow={isShow}
isShowCloseButton={false}
buttons={[buttonNo, buttonYes]}
></ModalWindow>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
View Compiled
This Pen doesn't use any external CSS resources.