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} -

- -
- ))} +
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}

+ +
+ ))} + + ); +}; 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, +};