aboutsummaryrefslogtreecommitdiffhomepage
path: root/frontend
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-03-21 00:44:20 +0900
committernsfisis <nsfisis@gmail.com>2025-03-21 00:44:20 +0900
commit0ab9bdf4ad937913dd3a29dbddf93f09b57deedd (patch)
treea8b5041633caac13f8e2978fed9f71be6b9861b3 /frontend
parent1afd2781818ef5cba0f018811f12cd8653da10b6 (diff)
downloadphperkaigi-2025-albatross-0ab9bdf4ad937913dd3a29dbddf93f09b57deedd.tar.gz
phperkaigi-2025-albatross-0ab9bdf4ad937913dd3a29dbddf93f09b57deedd.tar.zst
phperkaigi-2025-albatross-0ab9bdf4ad937913dd3a29dbddf93f09b57deedd.zip
feat(frontend): make container foldable
Diffstat (limited to 'frontend')
-rw-r--r--frontend/app/components/FoldableBorderedContainerWithCaption.tsx45
-rw-r--r--frontend/app/components/Gaming/ProblemColumn.tsx14
-rw-r--r--frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx20
3 files changed, 61 insertions, 18 deletions
diff --git a/frontend/app/components/FoldableBorderedContainerWithCaption.tsx b/frontend/app/components/FoldableBorderedContainerWithCaption.tsx
new file mode 100644
index 0000000..2d21b61
--- /dev/null
+++ b/frontend/app/components/FoldableBorderedContainerWithCaption.tsx
@@ -0,0 +1,45 @@
+import { faChevronDown, faChevronUp } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import React, { useState } from "react";
+import BorderedContainer from "./BorderedContainer";
+
+type Props = {
+ caption: string;
+ children: React.ReactNode;
+};
+
+export default function FoldableBorderedContainerWithCaption({
+ caption,
+ children,
+}: Props) {
+ const [isOpen, setIsOpen] = useState(true);
+
+ const handleToggle = () => {
+ setIsOpen((prev) => !prev);
+ };
+
+ return (
+ <BorderedContainer>
+ <div className="flex flex-col gap-4">
+ <div className="flex items-center">
+ <div className="flex-1 text-center">
+ <h2 className="text-lg font-semibold">{caption}</h2>
+ </div>
+ <div className="flex-shrink-0">
+ <button
+ onClick={handleToggle}
+ className="p-1 bg-gray-50 border-1 border-gray-300 rounded-sm"
+ >
+ <FontAwesomeIcon
+ icon={isOpen ? faChevronUp : faChevronDown}
+ fixedWidth
+ className="text-gray-500"
+ />
+ </button>
+ </div>
+ </div>
+ <div className={isOpen ? "" : "hidden"}>{children}</div>
+ </div>
+ </BorderedContainer>
+ );
+}
diff --git a/frontend/app/components/Gaming/ProblemColumn.tsx b/frontend/app/components/Gaming/ProblemColumn.tsx
index 2a57afd..922cbe7 100644
--- a/frontend/app/components/Gaming/ProblemColumn.tsx
+++ b/frontend/app/components/Gaming/ProblemColumn.tsx
@@ -1,4 +1,4 @@
-import BorderedContainerWithCaption from "../BorderedContainerWithCaption";
+import FoldableBorderedContainerWithCaption from "../FoldableBorderedContainerWithCaption";
import TitledColumn from "../TitledColumn";
import CodeBlock from "./CodeBlock";
import InlineCode from "./InlineCode";
@@ -16,15 +16,15 @@ export default function ProblemColumn({
}: Props) {
return (
<TitledColumn title={title}>
- <BorderedContainerWithCaption caption="問題">
+ <FoldableBorderedContainerWithCaption caption="問題">
<pre className="text-gray-700 whitespace-pre-wrap break-words">
{description}
</pre>
- </BorderedContainerWithCaption>
- <BorderedContainerWithCaption caption="サンプルコード">
+ </FoldableBorderedContainerWithCaption>
+ <FoldableBorderedContainerWithCaption caption="サンプルコード">
<CodeBlock code={sampleCode} language="php" />
- </BorderedContainerWithCaption>
- <BorderedContainerWithCaption caption="スコア計算・PHP 環境">
+ </FoldableBorderedContainerWithCaption>
+ <FoldableBorderedContainerWithCaption caption="スコア計算・PHP 環境">
<div className="text-gray-700 flex flex-col gap-2">
<p>
スコアはコード中の全 ASCII
@@ -54,7 +54,7 @@ export default function ProblemColumn({
に設定されています。
</p>
</div>
- </BorderedContainerWithCaption>
+ </FoldableBorderedContainerWithCaption>
</TitledColumn>
);
}
diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx
index 5b975e7..a647214 100644
--- a/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx
+++ b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx
@@ -5,7 +5,7 @@ import {
latestGameStatesAtom,
} from "../../states/watch";
import type { PlayerProfile } from "../../types/PlayerProfile";
-import BorderedContainer from "../BorderedContainer";
+import FoldableBorderedContainerWithCaption from "../FoldableBorderedContainerWithCaption";
import CodeBlock from "../Gaming/CodeBlock";
import LeftTime from "../Gaming/LeftTime";
import ProblemColumn from "../Gaming/ProblemColumn";
@@ -109,12 +109,11 @@ export default function GolfWatchAppGaming1v1({
/>
<ThreeColumnLayout>
<TitledColumn title={<SubmitStatusLabel status={statusA} />}>
- <BorderedContainer className="grow flex flex-col gap-4">
- <div className="text-center font-semibold text-lg">
- コードサイズ: {codeSizeA}
- </div>
+ <FoldableBorderedContainerWithCaption
+ caption={`コードサイズ: ${codeSizeA}`}
+ >
<CodeBlock code={codeA} language="php" />
- </BorderedContainer>
+ </FoldableBorderedContainerWithCaption>
</TitledColumn>
<ProblemColumn
title={problemTitle}
@@ -122,12 +121,11 @@ export default function GolfWatchAppGaming1v1({
sampleCode={sampleCode}
/>
<TitledColumn title={<SubmitStatusLabel status={statusB} />}>
- <BorderedContainer className="grow flex flex-col gap-4">
- <div className="text-center font-semibold text-lg">
- コードサイズ: {codeSizeB}
- </div>
+ <FoldableBorderedContainerWithCaption
+ caption={`コードサイズ: ${codeSizeB}`}
+ >
<CodeBlock code={codeB} language="php" />
- </BorderedContainer>
+ </FoldableBorderedContainerWithCaption>
</TitledColumn>
</ThreeColumnLayout>
</div>