<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
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/styled-components/4.3.1/styled-components.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js