返回 CodeWhale
hero-install.tsx
根目录 / web / components / hero-install.tsx
1 "use client";
2
3 import { useState } from "react";
4 import { INSTALL_COMMANDS } from "@/lib/content/install";
5 import { InstallCodeBlock } from "./install-code-block";
6
7 /**
8 * The hero's copyable install plate: one segmented choice between the
9 * checked shell installer (macOS and Linux), winget on Windows, and npm (any
10 * platform with Node 18+), above the same copy block the install page uses. The option
11 * labels are code-owned proper nouns; only the group's accessible name is
12 * translated.
13 */
14 const OPTIONS = [
15 { id: "shell", label: "macOS · Linux", cmd: INSTALL_COMMANDS.shell },
16 { id: "windows", label: "Windows", cmd: INSTALL_COMMANDS.windows },
17 { id: "npm", label: "npm", cmd: INSTALL_COMMANDS.npm },
18 ] as const;
19
20 export function HeroInstall({
21 ariaLabel,
22 copyLabel,
23 copiedLabel,
24 }: {
25 ariaLabel: string;
26 copyLabel: string;
27 copiedLabel: string;
28 }) {
29 const [selected, setSelected] = useState<(typeof OPTIONS)[number]["id"]>("shell");
30 const option = OPTIONS.find((o) => o.id === selected) ?? OPTIONS[0];
31
32 return (
33 <div className="hero-install plate">
34 <div className="segmented" role="group" aria-label={ariaLabel}>
35 {OPTIONS.map((o) => (
36 <button
37 key={o.id}
38 type="button"
39 onClick={() => setSelected(o.id)}
40 aria-pressed={o.id === selected}
41 >
42 {o.label}
43 </button>
44 ))}
45 </div>
46 <InstallCodeBlock cmd={option.cmd} copyLabel={copyLabel} copiedLabel={copiedLabel} />
47 </div>
48 );
49 }
50
50 lines Plain Text