返回 CodeWhale
page.tsx
根目录 / web / app / [locale] / docs / modes / page.tsx
1 import { Fragment } from "react";
2 import { getDocsModes, splitTokens } from "@/lib/i18n/dictionaries";
3 import { buildPageMetadata } from "@/lib/page-meta";
4
5 function renderModeToken(token: string) {
6 if (token === "tab") {
7 return <kbd className="font-mono text-xs px-1.5 py-0.5 hairline">Tab</kbd>;
8 }
9 if (token === "shiftTab") {
10 return <kbd className="font-mono text-xs px-1.5 py-0.5 hairline">Shift+Tab</kbd>;
11 }
12 if (token === "configCommand") {
13 return <code className="inline">/config</code>;
14 }
15 return `{${token}}`;
16 }
17
18 function renderRichText(text: string) {
19 return splitTokens(text).map((part, i) =>
20 "token" in part ? (
21 <Fragment key={`${i}-${part.token}`}>{renderModeToken(part.token)}</Fragment>
22 ) : (
23 <Fragment key={`${i}-text`}>{part.text}</Fragment>
24 ),
25 );
26 }
27
28 export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
29 const { locale } = await params;
30 const t = getDocsModes(locale);
31 return buildPageMetadata({
32 path: "/docs/modes",
33 locale,
34 title: t.metaTitle,
35 description: t.metaDescription,
36 });
37 }
38
39 export default async function ModesPage({ params }: { params: Promise<{ locale: string }> }) {
40 const { locale } = await params;
41 const t = getDocsModes(locale);
42
43 return (
44 <section className="space-y-10">
45 <section id="overview" className="scroll-mt-32">
46 <h1 className="font-display text-3xl mb-1">{t.overviewTitle}</h1>
47 <p className={`${t.bodyClassName} mt-3`}>{t.overviewLead}</p>
48 <div className="hairline-t mt-6">
49 {t.modes.map(([name, description]) => (
50 <section key={name} className="py-4 hairline-b">
51 <h3 className="font-display text-xl">{name}</h3>
52 <p className={`${t.bodyClassName} mt-1 text-sm`}>{description}</p>
53 </section>
54 ))}
55 </div>
56 </section>
57
58 <section id="switching" className="scroll-mt-32">
59 <h2 className="font-display text-2xl mb-1">{t.switchingTitle}</h2>
60 <p className={`${t.bodyClassName} mt-3`}>{renderRichText(t.switchingLead)}</p>
61 <p className={`${t.bodyClassName} mt-3`}>{t.switchingCommandLead}</p>
62 <pre className="code-block mt-4">{`/mode plan
63 /mode act
64 /mode operate`}</pre>
65 </section>
66
67 <section id="permissions" className="scroll-mt-32">
68 <h2 className="font-display text-2xl mb-1">{t.permissionsTitle}</h2>
69 <p className={`${t.bodyClassName} mt-3`}>{renderRichText(t.permissionsLead)}</p>
70 <div className="hairline-t mt-6">
71 {t.postures.map(([name, description]) => (
72 <section key={name} className="py-4 hairline-b">
73 <h3 className="font-display text-lg">{name}</h3>
74 <p className={`${t.bodyClassName} mt-1 text-sm`}>{description}</p>
75 </section>
76 ))}
77 </div>
78 </section>
79
80 <section id="source" className="hairline-t pt-8">
81 <p className="text-sm text-ink-mute">{t.sourceNote}</p>
82 </section>
83 </section>
84 );
85 }
86
86 lines Plain Text