Skip to content

Commit 2f2affc

Browse files
committed
スクショ(画像ではない)
1 parent 8464a19 commit 2f2affc

2 files changed

Lines changed: 242 additions & 40 deletions

File tree

app/featureCard.tsx

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
"use client";
2+
3+
import clsx from "clsx";
4+
import { ReactNode } from "react";
5+
import { StyledMarkdown } from "./markdown/markdown";
6+
import { Heading } from "./markdown/heading";
7+
import {
8+
ChatAreaStateProvider,
9+
ChatAreaStateUpdater,
10+
} from "./(docs)/chatAreaState";
11+
12+
export function FeatureCard(props: {
13+
reversed?: boolean;
14+
icon: ReactNode;
15+
title: ReactNode;
16+
children: ReactNode;
17+
iconColor: string;
18+
image: ReactNode;
19+
}) {
20+
return (
21+
<div
22+
className={clsx(
23+
"flex flex-col items-center gap-4 md:gap-8",
24+
props.reversed ? "md:flex-row-reverse" : "md:flex-row"
25+
)}
26+
>
27+
<div className="flex-1 space-y-4 lg:space-y-8">
28+
<div className="flex flex-row gap-2 items-center">
29+
<span className={clsx("p-3 rounded-xl text-2xl", props.iconColor)}>
30+
{props.icon}
31+
</span>
32+
<h3 className="text-2xl/8 md:text-3xl/10 font-bold">{props.title}</h3>
33+
</div>
34+
<p className="opacity-70 leading-relaxed text-lg">{props.children}</p>
35+
</div>
36+
<div className="w-80 max-w-full md:min-w-3/7 md:max-w-1/2">
37+
<div
38+
className={clsx(
39+
"aspect-video bg-base-200 rounded-xl border border-base-300 shadow-sm",
40+
"relative overflow-hidden select-none"
41+
)}
42+
>
43+
{props.image}
44+
</div>
45+
</div>
46+
</div>
47+
);
48+
}
49+
50+
export function RuntimeImage() {
51+
// public/docs/python/1-basics/2-2-str.md より
52+
return (
53+
<div className="absolute left-2 w-200 -inset-y-100 h-max my-auto scale-70 md:scale-85 origin-left">
54+
<StyledMarkdown
55+
content={`### 文字列(str)
56+
57+
文字列はシングルクォート (\`'\`) またはダブルクォート (\`"\`) で囲んで作成します。
58+
59+
文字列の連結は \`+\` 演算子、繰り返しは \`*\` 演算子を使います。
60+
`}
61+
/>
62+
<pre
63+
className={clsx(
64+
"bg-base-300 border-2 border-accent rounded-box shadow-md m-2 h-max",
65+
"p-4 font-mono"
66+
)}
67+
>
68+
&gt;&gt;&gt; name <HOperator>=</HOperator>{" "}
69+
<HString>&quot;Guido&quot;</HString>
70+
{"\n"}
71+
&gt;&gt;&gt; greeting <HOperator>=</HOperator>{" "}
72+
<HString>&apos;Hello&apos;</HString>
73+
{"\n"}
74+
&gt;&gt;&gt; full_greeting <HOperator>=</HOperator> greeting{" "}
75+
<HOperator>+</HOperator> <HString>&quot;, &quot;</HString>{" "}
76+
<HOperator>+</HOperator> name <HOperator>+</HOperator>{" "}
77+
<HString>&quot;!&quot;</HString>
78+
{"\n"}
79+
&gt;&gt;&gt; <Cursor />
80+
</pre>
81+
</div>
82+
);
83+
}
84+
85+
export function PracticeImage() {
86+
// public/docs/python/1-basics/2-2-str.md より
87+
return (
88+
<div className="absolute left-2 w-200 top-0 scale-70 md:scale-85 origin-top-left">
89+
<StyledMarkdown
90+
content={`### 練習問題1
91+
92+
\`item_name\` という変数に商品名(文字列)、\`price\` という変数に価格(整数)、\`stock\` という変数に在庫数(整数)をそれぞれ代入してください。その後、f-stringを使って「商品: [商品名], 価格: [価格]円, 在庫: [在庫数]個」という形式の文字列にし、 \`print()\` で出力するコードを書いてみましょう。
93+
`}
94+
/>
95+
<div
96+
className={clsx(
97+
"bg-base-300 border-2 border-accent rounded-box shadow-md m-2",
98+
"h-60 overflow-hidden"
99+
)}
100+
>
101+
<div className="flex flex-row items-center bg-base-200">
102+
<span className="mt-2 mb-1 ml-3 mr-2 text-sm text-left">
103+
<span>ファイルを編集:</span>
104+
<span className="font-mono ml-2">practice2-1.py</span>
105+
</span>
106+
<div className="flex-1" />
107+
</div>
108+
<pre className="px-4 py-2">
109+
item_name = <HString>&quot;高性能マウス&quot;</HString>
110+
{"\n"}
111+
price = <HNumber>4500</HNumber>
112+
</pre>
113+
</div>
114+
</div>
115+
);
116+
}
117+
118+
export function ChatImage() {
119+
// public/docs/python/1-basics/2-1-str.md より
120+
return (
121+
<>
122+
<div className="absolute right-2/5 w-[85%] md:w-[70%] top-0 scale-70 md:scale-85 origin-top-right pointer-events-none">
123+
{/*ここでChatAreaStateProviderのインスタンス作りダミーの値をセットすることで、
124+
StyledMarkdownが呼び出すMultiHighlightに現在このチャットを開いていると認識させる
125+
*/}
126+
<ChatAreaStateProvider>
127+
<ChatAreaStateUpdater chatId="sample" />
128+
<StyledMarkdown
129+
content={`### 数値(int, float)
130+
131+
Pythonは整数 (\`int\`) と浮動小数点数 (\`float\`) を区別します。
132+
浮動小数点数 (\`float\`) は、他の言語の double 型に相当する倍精度浮動小数点数です。
133+
`}
134+
replacedRange={[{ start: 64, end: 120, id: "sample" }]}
135+
/>
136+
</ChatAreaStateProvider>
137+
<pre
138+
className={clsx(
139+
"bg-base-300 border-2 border-accent rounded-box shadow-md m-2 h-max",
140+
"p-4 font-mono"
141+
)}
142+
>
143+
&gt;&gt;&gt; <HDim># 整数 (int)</HDim>
144+
{"\n"}
145+
&gt;&gt;&gt; a <HOperator>=</HOperator> <HNumber>10</HNumber>
146+
{"\n"}
147+
&gt;&gt;&gt; <HFunc>type</HFunc>
148+
<HDim>(</HDim>a<HDim>)</HDim>
149+
{"\n"}
150+
<HOperator>
151+
&lt;class <HString>&apos;int&apos;</HString>&gt;
152+
</HOperator>
153+
{"\n"}
154+
&gt;&gt;&gt; <HDim># 浮動小数点数 (float)</HDim>
155+
{"\n"}
156+
&gt;&gt;&gt; b <HOperator>=</HOperator> <HNumber>3.14</HNumber>
157+
{"\n"}
158+
&gt;&gt;&gt; <HFunc>type</HFunc>
159+
<HDim>(</HDim>b<HDim>)</HDim>
160+
{"\n"}
161+
<HOperator>
162+
&lt;class <HString>&apos;float&apos;</HString>&gt;
163+
</HOperator>
164+
</pre>
165+
</div>
166+
<aside
167+
className={clsx(
168+
"absolute left-3/5 md:w-80 top-0 scale-70 md:scale-85 origin-top-left",
169+
"bg-base-300 shadow-md p-3 flex flex-col"
170+
)}
171+
>
172+
<span className="flex-1 text-base font-bold opacity-40">
173+
AIへの質問
174+
</span>
175+
<Heading level={2} className="mt-1! mb-1! text-nowrap">
176+
Pythonのdouble型について
177+
</Heading>
178+
<div className="divider my-0" />
179+
<div className="chat chat-end place-items-start ml-3">
180+
<div
181+
className="chat-bubble p-0! bg-secondary/30"
182+
style={{ maxWidth: "100%", wordBreak: "break-word" }}
183+
>
184+
<StyledMarkdown content="double型はありますか?" />
185+
</div>
186+
</div>
187+
<StyledMarkdown
188+
content={`Pythonには「double型」は存在しません。他の言語(C++、Java、C#など)でおなじみのdouble型に相当するのは、Pythonの**float型**です。
189+
190+
Pythonのfloat型は**倍精度浮動小数点数(double-precision floating point)** を表し、他の言語のdouble型と同じ桁数の精度(通常15〜17桁)を提供します。そのため、Pythonでは単一のfloat型だけで十分です。`}
191+
/>
192+
</aside>
193+
</>
194+
);
195+
}
196+
197+
function HString(props: { children: ReactNode }) {
198+
return <span className="text-green-700">{props.children}</span>;
199+
}
200+
function HOperator(props: { children: ReactNode }) {
201+
return <span className="text-fuchsia-500">{props.children}</span>;
202+
}
203+
function HNumber(props: { children: ReactNode }) {
204+
return <span className="text-yellow-700">{props.children}</span>;
205+
}
206+
function HFunc(props: { children: ReactNode }) {
207+
return <span className="text-cyan-600">{props.children}</span>;
208+
}
209+
function HDim(props: { children: ReactNode }) {
210+
return <span className="opacity-50">{props.children}</span>;
211+
}
212+
function Cursor() {
213+
return (
214+
<span
215+
ref={(el) => {
216+
// カーソルの点滅アニメーション
217+
el?.animate([{ opacity: "1" }, { opacity: "0" }, { opacity: "1" }], {
218+
duration: 1000,
219+
iterations: Infinity,
220+
easing: "steps(2, end)",
221+
});
222+
}}
223+
style={{
224+
display: "inline-block",
225+
boxShadow: `2px 0 0 var(--color-primary) inset`,
226+
verticalAlign: "top",
227+
}}
228+
>
229+
{" "}
230+
</span>
231+
);
232+
}

app/page.tsx

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { Metadata } from "next";
22
import Link from "next/link";
33
import { getPagesList } from "@/lib/docs";
44
import clsx from "clsx";
5-
import { ReactNode } from "react";
65
import { LanguageIcon } from "./terminal/icons";
76
import { RuntimeLang } from "@my-code/runtime/languages";
7+
import { ChatImage, FeatureCard, PracticeImage, RuntimeImage } from "./featureCard";
88

99
export const metadata: Metadata = {
1010
title: "my.code(); へようこそ",
@@ -71,9 +71,11 @@ export default async function Home() {
7171
icon="⚡"
7272
iconColor="bg-primary/10 text-primary"
7373
title="環境構築は一切不要。ブラウザで動く実行環境"
74+
image={<RuntimeImage />}
7475
>
7576
面倒な開発環境のセットアップで挫折する必要はありません。
76-
チュートリアル内のサンプルコードは、ボタン一つでそのまま実行可能。
77+
チュートリアル内のサンプルコードは、 my.code();
78+
のウェブサイト上でそのまま実行可能。
7779
もちろん自由に編集して結果を試すこともできます。
7880
{/*さらに、エラーメッセージの解説やエラー箇所のハイライト表示など、初心者に優しい機能も充実しています。*/}
7981
</FeatureCard>
@@ -82,6 +84,7 @@ export default async function Home() {
8284
iconColor="bg-secondary/10 text-secondary"
8385
title="AIアシスタントがあなたの学習をサポート"
8486
reversed
87+
image={<ChatImage />}
8588
>
8689
エラーの原因がわからない?コードの意味を知りたい?
8790
AIアシスタントにいつでも質問できます。
@@ -90,12 +93,12 @@ export default async function Home() {
9093
<FeatureCard
9194
icon="✏️"
9295
iconColor="bg-accent/10 text-accent"
93-
title="実践的な練習問題"
96+
title="練習問題で理解を深める"
97+
image={<PracticeImage />}
9498
>
95-
{/*todo: 他セクションと同じスタイルの文章で書き直す?*/}
96-
各チュートリアルには練習問題が含まれており、学んだ内容を実際に試すことができます。
97-
練習問題は段階的に難易度が上がるように設計されており、理解度を深めるのに役立ちます。
98-
書いたコードはその場ですぐにAIアシスタントがレビューし、フィードバックを提供します。
99+
各チュートリアルには、学んだ内容を実践できる練習問題が用意されています。
100+
実際に自分でコードを書いて実行することで、理解をさらに深めることができます。
101+
{/*書いたコードはAIアシスタントがレビューし、フィードバックを提供します。*/}
99102
</FeatureCard>
100103
</div>
101104

@@ -145,36 +148,3 @@ export default async function Home() {
145148
</div>
146149
);
147150
}
148-
149-
function FeatureCard(props: {
150-
reversed?: boolean;
151-
icon: ReactNode;
152-
title: ReactNode;
153-
children: ReactNode;
154-
iconColor: string;
155-
}) {
156-
return (
157-
<div
158-
className={clsx(
159-
"flex flex-col items-center gap-4 md:gap-8 lg:gap-16",
160-
props.reversed ? "md:flex-row-reverse" : "md:flex-row"
161-
)}
162-
>
163-
<div className="flex-1 space-y-4 lg:space-y-8">
164-
<div className="flex flex-row gap-2 items-center">
165-
<span className={clsx("p-3 rounded-xl text-2xl", props.iconColor)}>
166-
{props.icon}
167-
</span>
168-
<h3 className="text-2xl/8 md:text-3xl/10 font-bold">{props.title}</h3>
169-
</div>
170-
<p className="opacity-70 leading-relaxed text-lg">{props.children}</p>
171-
</div>
172-
<div className="w-80 max-w-full md:min-w-2/5 md:max-w-1/2">
173-
{/* スクリーンショットのプレースホルダー(後で実際の画像に差し替えてください) */}
174-
<div className="aspect-video bg-base-200 rounded-xl border border-base-300 shadow-lg flex items-center justify-center overflow-hidden">
175-
<span className="text-base-content/40 font-mono">Screenshot</span>
176-
</div>
177-
</div>
178-
</div>
179-
);
180-
}

0 commit comments

Comments
 (0)