diff --git a/apps/client/src/scenes/lobby/LobbyScene.tsx b/apps/client/src/scenes/lobby/LobbyScene.tsx
index 1bdbb14..866d055 100644
--- a/apps/client/src/scenes/lobby/LobbyScene.tsx
+++ b/apps/client/src/scenes/lobby/LobbyScene.tsx
@@ -1,6 +1,7 @@
import { useEffect, useMemo, useState } from "react";
import { domain } from "@repo/shared";
import { OVERLAY_BUTTON_STYLE } from "@client/scenes/shared/styles/overlayStyles";
+import { LobbyRuleModal } from "./components/LobbyRuleModal";
type Props = {
room: domain.room.Room | null;
@@ -45,6 +46,7 @@
const [selectedStartPlayerCount, setSelectedStartPlayerCount] = useState(
minimumStartPlayerCount,
);
+ const [isRuleModalOpen, setIsRuleModalOpen] = useState(false);
useEffect(() => {
setSelectedStartPlayerCount((prev) => {
@@ -222,22 +224,54 @@
>
ゲームスタート
+
+
) : (
- ホストの開始を待っています...
+
+ ホストの開始を待っています...
+
+
+
)}
@@ -309,6 +343,14 @@
+
+ {isRuleModalOpen && (
+ {
+ setIsRuleModalOpen(false);
+ }}
+ />
+ )}
>
);
};
diff --git a/apps/client/src/scenes/lobby/components/LobbyRuleModal.styles.ts b/apps/client/src/scenes/lobby/components/LobbyRuleModal.styles.ts
new file mode 100644
index 0000000..b3992de
--- /dev/null
+++ b/apps/client/src/scenes/lobby/components/LobbyRuleModal.styles.ts
@@ -0,0 +1,66 @@
+import type { CSSProperties } from "react";
+
+export const LOBBY_RULE_MODAL_OVERLAY_STYLE: CSSProperties = {
+ position: "fixed",
+ inset: 0,
+ background: "rgba(0, 0, 0, 0.72)",
+ zIndex: 120,
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ padding: "16px",
+};
+
+export const LOBBY_RULE_MODAL_PANEL_STYLE: CSSProperties = {
+ width: "min(760px, 100%)",
+ maxHeight: "min(78dvh, 820px)",
+ borderRadius: "12px",
+ background: "rgba(20, 20, 20, 0.95)",
+ border: "1px solid rgba(255, 255, 255, 0.15)",
+ boxShadow: "0 12px 28px rgba(0, 0, 0, 0.45)",
+ color: "white",
+ display: "flex",
+ flexDirection: "column",
+};
+
+export const LOBBY_RULE_MODAL_HEADER_STYLE: CSSProperties = {
+ padding: "16px 18px",
+ borderBottom: "1px solid rgba(255, 255, 255, 0.16)",
+ fontSize: "1.1rem",
+ fontWeight: 800,
+};
+
+export const LOBBY_RULE_MODAL_BODY_STYLE: CSSProperties = {
+ padding: "14px 18px",
+ overflowY: "auto",
+ display: "flex",
+ flexDirection: "column",
+ gap: "16px",
+};
+
+export const LOBBY_RULE_MODAL_SECTION_STYLE: CSSProperties = {
+ display: "flex",
+ flexDirection: "column",
+ gap: "8px",
+};
+
+export const LOBBY_RULE_MODAL_SECTION_TITLE_STYLE: CSSProperties = {
+ margin: 0,
+ fontSize: "1rem",
+ fontWeight: 800,
+};
+
+export const LOBBY_RULE_MODAL_LIST_STYLE: CSSProperties = {
+ margin: 0,
+ paddingLeft: "20px",
+ display: "flex",
+ flexDirection: "column",
+ gap: "6px",
+};
+
+export const LOBBY_RULE_MODAL_FOOTER_STYLE: CSSProperties = {
+ padding: "14px 18px",
+ borderTop: "1px solid rgba(255, 255, 255, 0.16)",
+ display: "flex",
+ justifyContent: "flex-end",
+};
diff --git a/apps/client/src/scenes/lobby/components/LobbyRuleModal.tsx b/apps/client/src/scenes/lobby/components/LobbyRuleModal.tsx
new file mode 100644
index 0000000..8f41610
--- /dev/null
+++ b/apps/client/src/scenes/lobby/components/LobbyRuleModal.tsx
@@ -0,0 +1,47 @@
+import { OVERLAY_BUTTON_STYLE } from "@client/scenes/shared/styles/overlayStyles";
+import {
+ LOBBY_RULE_MODAL_BODY_STYLE,
+ LOBBY_RULE_MODAL_FOOTER_STYLE,
+ LOBBY_RULE_MODAL_HEADER_STYLE,
+ LOBBY_RULE_MODAL_LIST_STYLE,
+ LOBBY_RULE_MODAL_OVERLAY_STYLE,
+ LOBBY_RULE_MODAL_PANEL_STYLE,
+ LOBBY_RULE_MODAL_SECTION_STYLE,
+ LOBBY_RULE_MODAL_SECTION_TITLE_STYLE,
+} from "./LobbyRuleModal.styles";
+import { LOBBY_RULE_SECTIONS } from "../presentation/lobbyRuleContent";
+
+type LobbyRuleModalProps = {
+ onClose: () => void;
+};
+
+export const LobbyRuleModal = ({ onClose }: LobbyRuleModalProps) => {
+ return (
+
+
+
ルール
+
+
+ {LOBBY_RULE_SECTIONS.map((section) => (
+
+
+ {section.title}
+
+
+ {section.lines.map((line) => (
+ - {line}
+ ))}
+
+
+ ))}
+
+
+
+
+
+
+
+ );
+};
diff --git a/apps/client/src/scenes/lobby/presentation/lobbyRuleContent.ts b/apps/client/src/scenes/lobby/presentation/lobbyRuleContent.ts
new file mode 100644
index 0000000..5a0977c
--- /dev/null
+++ b/apps/client/src/scenes/lobby/presentation/lobbyRuleContent.ts
@@ -0,0 +1,26 @@
+/**
+ * lobbyRuleContent
+ * ロビーのルール表示で使う短文テキストを定義する
+ */
+
+/** ルール画面の短文セクション */
+export type LobbyRuleSection = {
+ title: string;
+ lines: string[];
+};
+
+/** ロビーに表示するルール内容 */
+export const LOBBY_RULE_SECTIONS: LobbyRuleSection[] = [
+ {
+ title: "操作",
+ lines: ["左で移動", "右下で爆弾設置"],
+ },
+ {
+ title: "被弾",
+ lines: ["被弾でその場ステイ", "一定回数で初期位置へ戻る"],
+ },
+ {
+ title: "勝利",
+ lines: ["制限時間終了時に塗り面積が最も高いチームが勝利"],
+ },
+];