diff --git a/apps/client/src/scenes/lobby/components/LobbyRuleModal.styles.ts b/apps/client/src/scenes/lobby/components/LobbyRuleModal.styles.ts
index b3992de..239cc2d 100644
--- a/apps/client/src/scenes/lobby/components/LobbyRuleModal.styles.ts
+++ b/apps/client/src/scenes/lobby/components/LobbyRuleModal.styles.ts
@@ -1,4 +1,9 @@
import type { CSSProperties } from "react";
+import {
+ OVERLAY_PANEL_BASE_STYLE,
+ OVERLAY_PANEL_FOOTER_BASE_STYLE,
+ OVERLAY_PANEL_HEADER_BASE_STYLE,
+} from "@client/scenes/shared/styles/overlayStyles";
export const LOBBY_RULE_MODAL_OVERLAY_STYLE: CSSProperties = {
position: "fixed",
@@ -12,20 +17,15 @@
};
export const LOBBY_RULE_MODAL_PANEL_STYLE: CSSProperties = {
+ ...OVERLAY_PANEL_BASE_STYLE,
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)",
+ ...OVERLAY_PANEL_HEADER_BASE_STYLE,
fontSize: "1.1rem",
fontWeight: 800,
};
@@ -59,8 +59,7 @@
};
export const LOBBY_RULE_MODAL_FOOTER_STYLE: CSSProperties = {
- padding: "14px 18px",
- borderTop: "1px solid rgba(255, 255, 255, 0.16)",
+ ...OVERLAY_PANEL_FOOTER_BASE_STYLE,
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
index 8f41610..9613ad5 100644
--- a/apps/client/src/scenes/lobby/components/LobbyRuleModal.tsx
+++ b/apps/client/src/scenes/lobby/components/LobbyRuleModal.tsx
@@ -3,13 +3,11 @@
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";
+import { LobbyRuleSectionList } from "./LobbyRuleSectionList";
type LobbyRuleModalProps = {
onClose: () => void;
@@ -22,18 +20,7 @@
ルール
- {LOBBY_RULE_SECTIONS.map((section) => (
-
-
- {section.title}
-
-
- {section.lines.map((line) => (
- - {line}
- ))}
-
-
- ))}
+
diff --git a/apps/client/src/scenes/lobby/components/LobbyRuleSectionList.tsx b/apps/client/src/scenes/lobby/components/LobbyRuleSectionList.tsx
new file mode 100644
index 0000000..588dcdc
--- /dev/null
+++ b/apps/client/src/scenes/lobby/components/LobbyRuleSectionList.tsx
@@ -0,0 +1,29 @@
+import {
+ LOBBY_RULE_MODAL_LIST_STYLE,
+ LOBBY_RULE_MODAL_SECTION_STYLE,
+ LOBBY_RULE_MODAL_SECTION_TITLE_STYLE,
+} from "./LobbyRuleModal.styles";
+import type { LobbyRuleSection } from "../presentation/lobbyRuleContent";
+
+type LobbyRuleSectionListProps = {
+ sections: LobbyRuleSection[];
+};
+
+export const LobbyRuleSectionList = ({
+ sections,
+}: LobbyRuleSectionListProps) => {
+ return (
+ <>
+ {sections.map((section) => (
+
+ {section.title}
+
+ {section.lines.map((line, index) => (
+ - {line}
+ ))}
+
+
+ ))}
+ >
+ );
+};
diff --git a/apps/client/src/scenes/lobby/presentation/lobbyRuleContent.ts b/apps/client/src/scenes/lobby/presentation/lobbyRuleContent.ts
index 5a0977c..b7d36c1 100644
--- a/apps/client/src/scenes/lobby/presentation/lobbyRuleContent.ts
+++ b/apps/client/src/scenes/lobby/presentation/lobbyRuleContent.ts
@@ -2,25 +2,39 @@
* lobbyRuleContent
* ロビーのルール表示で使う短文テキストを定義する
*/
+import { config } from "@client/config";
/** ルール画面の短文セクション */
export type LobbyRuleSection = {
+ id: "controls" | "hits" | "win";
title: string;
lines: string[];
};
+/** ロビーに表示するルール内容を組み立てる */
+export const buildLobbyRuleSections = (
+ respawnHitCount: number,
+): LobbyRuleSection[] => {
+ return [
+ {
+ id: "controls",
+ title: "操作",
+ lines: ["左で移動", "右下で爆弾設置"],
+ },
+ {
+ id: "hits",
+ title: "被弾",
+ lines: ["被弾でその場ステイ", `${respawnHitCount}回で初期位置へ戻る`],
+ },
+ {
+ id: "win",
+ title: "勝利",
+ lines: ["制限時間終了時に塗り面積が最も高いチームが勝利"],
+ },
+ ];
+};
+
/** ロビーに表示するルール内容 */
-export const LOBBY_RULE_SECTIONS: LobbyRuleSection[] = [
- {
- title: "操作",
- lines: ["左で移動", "右下で爆弾設置"],
- },
- {
- title: "被弾",
- lines: ["被弾でその場ステイ", "一定回数で初期位置へ戻る"],
- },
- {
- title: "勝利",
- lines: ["制限時間終了時に塗り面積が最も高いチームが勝利"],
- },
-];
+export const LOBBY_RULE_SECTIONS: LobbyRuleSection[] = buildLobbyRuleSections(
+ config.GAME_CONFIG.PLAYER_RESPAWN_HIT_COUNT,
+);
diff --git a/apps/client/src/scenes/shared/styles/overlayStyles.ts b/apps/client/src/scenes/shared/styles/overlayStyles.ts
index f965dbf..62b46c2 100644
--- a/apps/client/src/scenes/shared/styles/overlayStyles.ts
+++ b/apps/client/src/scenes/shared/styles/overlayStyles.ts
@@ -4,6 +4,17 @@
*/
import type { CSSProperties } from "react";
+/** オーバーレイ面共通トークン */
+export const OVERLAY_SURFACE_TOKENS = {
+ PANEL_BACKGROUND: "rgba(20, 20, 20, 0.95)",
+ PANEL_BORDER: "1px solid rgba(255, 255, 255, 0.15)",
+ PANEL_SHADOW: "0 12px 28px rgba(0, 0, 0, 0.45)",
+ PANEL_RADIUS: "12px",
+ DIVIDER: "1px solid rgba(255, 255, 255, 0.16)",
+ HEADER_PADDING: "16px 18px",
+ FOOTER_PADDING: "14px 18px",
+} as const;
+
/** オーバーレイボタンの共通スタイル */
export const OVERLAY_BUTTON_STYLE: CSSProperties = {
padding: "10px 14px",
@@ -25,3 +36,24 @@
gap: "10px",
marginBottom: "10px",
};
+
+/** オーバーレイパネルの共通ベーススタイル */
+export const OVERLAY_PANEL_BASE_STYLE: CSSProperties = {
+ borderRadius: OVERLAY_SURFACE_TOKENS.PANEL_RADIUS,
+ background: OVERLAY_SURFACE_TOKENS.PANEL_BACKGROUND,
+ border: OVERLAY_SURFACE_TOKENS.PANEL_BORDER,
+ boxShadow: OVERLAY_SURFACE_TOKENS.PANEL_SHADOW,
+ color: "white",
+};
+
+/** オーバーレイパネルヘッダーの共通ベーススタイル */
+export const OVERLAY_PANEL_HEADER_BASE_STYLE: CSSProperties = {
+ padding: OVERLAY_SURFACE_TOKENS.HEADER_PADDING,
+ borderBottom: OVERLAY_SURFACE_TOKENS.DIVIDER,
+};
+
+/** オーバーレイパネルフッターの共通ベーススタイル */
+export const OVERLAY_PANEL_FOOTER_BASE_STYLE: CSSProperties = {
+ padding: OVERLAY_SURFACE_TOKENS.FOOTER_PADDING,
+ borderTop: OVERLAY_SURFACE_TOKENS.DIVIDER,
+};