diff --git a/src/components/guides/commands/command-card-details.astro b/src/components/guides/commands/command-card-details.astro new file mode 100644 index 0000000..4fa9e74 --- /dev/null +++ b/src/components/guides/commands/command-card-details.astro @@ -0,0 +1,193 @@ +--- +// Renders chip rows (subcommands/args/flags/betaFlags) followed by a +// "Details" trigger that opens a native modal listing each +// chip with its 1-line explanation. Card height stays constant so the +// CSS grid does not jump. Accepts both legacy string chips (MK) and +// structured ChipItem chips (EK migrated in Phase 1); only chips +// carrying a descKey appear in the modal definition list. +import { chipDescKey, chipName, type Chip, type CommandItem, type TranslationFn } from "@/data/guides/commands-types"; + +interface Props { + cmd: CommandItem; + t: TranslationFn; +} + +const { cmd, t } = Astro.props; + +type Section = { + kind: "subcommand" | "arg" | "flag" | "betaFlag"; + headerKey: string; + chips: Chip[]; +}; + +const sections: Section[] = [ + { kind: "subcommand", headerKey: "commands.details.section.subcommands", chips: cmd.subcommands ?? [] }, + { kind: "arg", headerKey: "commands.details.section.args", chips: cmd.args ?? [] }, + { kind: "flag", headerKey: "commands.details.section.flags", chips: cmd.flags ?? [] }, + { kind: "betaFlag", headerKey: "commands.details.section.beta_flags", chips: cmd.betaFlags ?? [] }, +]; + +// Sections with at least one chip carrying a descKey contribute rows +// to the modal definition list. Empty descKey sections are skipped. +const detailSections = sections + .map((s) => ({ ...s, rows: s.chips.filter((c) => chipDescKey(c) !== null) })) + .filter((s) => s.rows.length > 0); + +const hasDetails = detailSections.length > 0; + +// Counter on the trigger button, e.g. "3 subcommands · 8 flags" +const counterParts = sections + .map((s) => { + if (s.chips.length === 0) return null; + const label = t(`commands.details.count.${s.kind === "betaFlag" ? "beta_flag" : s.kind}`); + return `${s.chips.length} ${label}`; + }) + .filter((x): x is string => x !== null); + +// Stable DOM id for the dialog. cmd.command shape: "/ck:plan", "/mkt:ask". +const dialogId = `cmd-dialog-${cmd.command.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase()}`; +--- + +{/* Subcommands chips (purple) */} +{cmd.subcommands && cmd.subcommands.length > 0 && ( +
+ {cmd.subcommands.map((sub: Chip) => ( + + {chipName(sub)} + + ))} +
+)} + +{/* Args chips (slate) */} +{cmd.args && cmd.args.length > 0 && ( +
+ {cmd.args.map((arg: Chip) => ( + + {chipName(arg)} + + ))} +
+)} + +{/* Flags + betaFlags chips */} +{((cmd.flags && cmd.flags.length > 0) || (cmd.betaFlags && cmd.betaFlags.length > 0)) && ( +
+ {cmd.flags && cmd.flags.map((flag: Chip) => ( + + {chipName(flag)} + + ))} + {cmd.betaFlags && cmd.betaFlags.map((flag: Chip) => ( + + {chipName(flag)} beta + + ))} +
+)} + +{/* Details trigger + modal */} +{hasDetails && ( + <> + + + +
+
+ {cmd.command} + {counterParts.length > 0 && ( + · {counterParts.join(" · ")} + )} +
+ +
+
+ {detailSections.map((section) => ( +
+
+ {t(section.headerKey)} +
+
+ {section.rows.map((chip) => { + const key = chipDescKey(chip); + const desc = key ? t(key) : ""; + const chipClass = + section.kind === "subcommand" + ? "bg-purple-100 dark:bg-purple-900/30 text-purple-600 dark:text-purple-400" + : section.kind === "arg" + ? "bg-slate-200 dark:bg-slate-700 text-slate-600 dark:text-slate-400" + : section.kind === "betaFlag" + ? "bg-amber-100 dark:bg-amber-900/30 text-amber-600 dark:text-amber-400" + : "bg-teal-100 dark:bg-teal-900/30 text-teal-600 dark:text-teal-400"; + return ( + <> +
+ {chipName(chip)} +
+
+ {desc || } +
+ + ); + })} +
+
+ ))} +
+
+ +)} + + + + diff --git a/src/components/guides/commands/commands-categories-grid.astro b/src/components/guides/commands/commands-categories-grid.astro index 1bddf2c..aed936d 100644 --- a/src/components/guides/commands/commands-categories-grid.astro +++ b/src/components/guides/commands/commands-categories-grid.astro @@ -5,6 +5,7 @@ import { getLangFromUrl, type Language } from "@/i18n"; import { getEngineerKitCategories } from "@/data/guides/commands-engineer-kit"; import { getMarketingKitCategories } from "@/data/guides/commands-marketing-kit"; import { styles } from "@/data/guides/commands-styles"; +import CommandCardDetails from "./command-card-details.astro"; interface Props { lang?: Language; @@ -152,41 +153,7 @@ const marketingCategories = getMarketingKitCategories(t as any); {cmd.betaNote} )} - {/* Subcommands (space-separated) */} - {cmd.subcommands && cmd.subcommands.length > 0 && ( -
- {cmd.subcommands.map((sub: string) => ( - - {sub} - - ))} -
- )} - {/* Arguments (space-separated) */} - {cmd.args && cmd.args.length > 0 && ( -
- {cmd.args.map((arg: string) => ( - - {arg} - - ))} -
- )} - {/* Flags (dash-prefixed) */} - {cmd.flags && cmd.flags.length > 0 && ( -
- {cmd.flags.map((flag: string) => ( - - {flag} - - ))} - {cmd.betaFlags && cmd.betaFlags.map((flag: string) => ( - - {flag} beta - - ))} -
- )} + {cmd.replacedCommand && (

@@ -297,41 +264,7 @@ const marketingCategories = getMarketingKitCategories(t as any); {cmd.betaNote} )} - {/* Subcommands (space-separated) */} - {cmd.subcommands && cmd.subcommands.length > 0 && ( -

- {cmd.subcommands.map((sub: string) => ( - - {sub} - - ))} -
- )} - {/* Arguments (space-separated) */} - {cmd.args && cmd.args.length > 0 && ( -
- {cmd.args.map((arg: string) => ( - - {arg} - - ))} -
- )} - {/* Flags (dash-prefixed) */} - {cmd.flags && cmd.flags.length > 0 && ( -
- {cmd.flags.map((flag: string) => ( - - {flag} - - ))} - {cmd.betaFlags && cmd.betaFlags.map((flag: string) => ( - - {flag} beta - - ))} -
- )} + {/* Beta syntax footer note */} {cmd.betaSyntax && (
diff --git a/src/data/guides/commands-engineer-kit.ts b/src/data/guides/commands-engineer-kit.ts index e6ea91e..3992876 100644 --- a/src/data/guides/commands-engineer-kit.ts +++ b/src/data/guides/commands-engineer-kit.ts @@ -38,7 +38,7 @@ export function getEngineerKitCategories(t: TranslationFn): CommandCategory[] { desc: t("commands.stable.ask.desc"), detail: t("commands.stable.ask.detail"), isSkill: true, - args: ["[question]"], + args: [{ name: "[question]", descKey: "commands.stable.ask.arg.question" }], step: 2, }, // Step 3: Brainstorm ideas @@ -59,8 +59,21 @@ export function getEngineerKitCategories(t: TranslationFn): CommandCategory[] { desc: t("commands.stable.plan.desc"), detail: t("commands.stable.plan.detail"), isSkill: true, - subcommands: ["archive", "red-team", "validate"], - flags: ["--auto", "--fast", "--hard", "--parallel", "--two", "--no-tasks", "--deep", "--tdd"], + subcommands: [ + { name: "archive", descKey: "commands.stable.plan.subcommand.archive" }, + { name: "red-team", descKey: "commands.stable.plan.subcommand.red_team" }, + { name: "validate", descKey: "commands.stable.plan.subcommand.validate" }, + ], + flags: [ + { name: "--auto", descKey: "commands.stable.plan.flag.auto" }, + { name: "--fast", descKey: "commands.stable.plan.flag.fast" }, + { name: "--hard", descKey: "commands.stable.plan.flag.hard" }, + { name: "--parallel", descKey: "commands.stable.plan.flag.parallel" }, + { name: "--two", descKey: "commands.stable.plan.flag.two" }, + { name: "--no-tasks", descKey: "commands.stable.plan.flag.no_tasks" }, + { name: "--deep", descKey: "commands.stable.plan.flag.deep" }, + { name: "--tdd", descKey: "commands.stable.plan.flag.tdd" }, + ], step: 4, }, // Step 5: Execute plan @@ -71,7 +84,14 @@ export function getEngineerKitCategories(t: TranslationFn): CommandCategory[] { desc: t("commands.stable.cook.desc"), detail: t("commands.stable.cook.detail"), isSkill: true, - flags: ["--interactive", "--fast", "--parallel", "--auto", "--no-test", "--tdd"], + flags: [ + { name: "--interactive", descKey: "commands.stable.cook.flag.interactive" }, + { name: "--fast", descKey: "commands.stable.cook.flag.fast" }, + { name: "--parallel", descKey: "commands.stable.cook.flag.parallel" }, + { name: "--auto", descKey: "commands.stable.cook.flag.auto" }, + { name: "--no-test", descKey: "commands.stable.cook.flag.no_test" }, + { name: "--tdd", descKey: "commands.stable.cook.flag.tdd" }, + ], step: 5, }, ], @@ -97,7 +117,7 @@ export function getEngineerKitCategories(t: TranslationFn): CommandCategory[] { desc: t("commands.stable.research.desc"), detail: t("commands.stable.research.detail"), isSkill: true, - args: ["[topic]"], + args: [{ name: "[topic]", descKey: "commands.stable.research.arg.topic" }], }, { command: "/ck:scout", @@ -106,7 +126,10 @@ export function getEngineerKitCategories(t: TranslationFn): CommandCategory[] { desc: t("commands.stable.scout.desc"), detail: t("commands.stable.scout.detail"), isSkill: true, - args: ["[search-target]", "[ext]"], + args: [ + { name: "[search-target]", descKey: "commands.stable.scout.arg.search_target" }, + { name: "[ext]", descKey: "commands.stable.scout.arg.ext" }, + ], }, { command: "/ck:plan", @@ -115,8 +138,21 @@ export function getEngineerKitCategories(t: TranslationFn): CommandCategory[] { desc: t("commands.stable.plan.desc"), detail: t("commands.stable.plan.detail"), isSkill: true, - subcommands: ["archive", "red-team", "validate"], - flags: ["--auto", "--fast", "--hard", "--parallel", "--two", "--no-tasks", "--deep", "--tdd"], + subcommands: [ + { name: "archive", descKey: "commands.stable.plan.subcommand.archive" }, + { name: "red-team", descKey: "commands.stable.plan.subcommand.red_team" }, + { name: "validate", descKey: "commands.stable.plan.subcommand.validate" }, + ], + flags: [ + { name: "--auto", descKey: "commands.stable.plan.flag.auto" }, + { name: "--fast", descKey: "commands.stable.plan.flag.fast" }, + { name: "--hard", descKey: "commands.stable.plan.flag.hard" }, + { name: "--parallel", descKey: "commands.stable.plan.flag.parallel" }, + { name: "--two", descKey: "commands.stable.plan.flag.two" }, + { name: "--no-tasks", descKey: "commands.stable.plan.flag.no_tasks" }, + { name: "--deep", descKey: "commands.stable.plan.flag.deep" }, + { name: "--tdd", descKey: "commands.stable.plan.flag.tdd" }, + ], }, { command: "/ck:sequential-thinking", @@ -158,7 +194,10 @@ export function getEngineerKitCategories(t: TranslationFn): CommandCategory[] { desc: t("commands.stable.predict.desc"), detail: t("commands.stable.predict.detail"), isSkill: true, - flags: ["--chain reason", "--chain probe"], + flags: [ + { name: "--chain reason", descKey: "commands.stable.predict.flag.chain_reason" }, + { name: "--chain probe", descKey: "commands.stable.predict.flag.chain_probe" }, + ], }, { command: "/ck:xia", @@ -167,8 +206,18 @@ export function getEngineerKitCategories(t: TranslationFn): CommandCategory[] { desc: t("commands.stable.xia.desc"), detail: t("commands.stable.xia.detail"), isSkill: true, - args: ["", "[feature]"], - flags: ["--compare", "--copy", "--improve", "--port", "--auto", "--fast"], + args: [ + { name: "", descKey: "commands.stable.xia.arg.target" }, + { name: "[feature]", descKey: "commands.stable.xia.arg.feature" }, + ], + flags: [ + { name: "--compare", descKey: "commands.stable.xia.flag.compare" }, + { name: "--copy", descKey: "commands.stable.xia.flag.copy" }, + { name: "--improve", descKey: "commands.stable.xia.flag.improve" }, + { name: "--port", descKey: "commands.stable.xia.flag.port" }, + { name: "--auto", descKey: "commands.stable.xia.flag.auto" }, + { name: "--fast", descKey: "commands.stable.xia.flag.fast" }, + ], }, ], }, @@ -217,8 +266,15 @@ export function getEngineerKitCategories(t: TranslationFn): CommandCategory[] { desc: t("commands.stable.stitch.desc"), detail: t("commands.stable.stitch.detail"), isSkill: true, - subcommands: ["generate", "export"], - flags: ["--format all", "--format html", "--device mobile"], + subcommands: [ + { name: "generate", descKey: "commands.stable.stitch.subcommand.generate" }, + { name: "export", descKey: "commands.stable.stitch.subcommand.export" }, + ], + flags: [ + { name: "--format all", descKey: "commands.stable.stitch.flag.format_all" }, + { name: "--format html", descKey: "commands.stable.stitch.flag.format_html" }, + { name: "--device mobile", descKey: "commands.stable.stitch.flag.device_mobile" }, + ], }, { command: "/ck:ui-ux-pro-max", @@ -291,7 +347,13 @@ export function getEngineerKitCategories(t: TranslationFn): CommandCategory[] { desc: t("commands.stable.ai_artist.desc"), detail: t("commands.stable.ai_artist.detail"), isSkill: true, - flags: ["--mode search", "--mode creative", "--mode wild", "--mode all", "--skip"], + flags: [ + { name: "--mode search", descKey: "commands.stable.ai_artist.flag.mode_search" }, + { name: "--mode creative", descKey: "commands.stable.ai_artist.flag.mode_creative" }, + { name: "--mode wild", descKey: "commands.stable.ai_artist.flag.mode_wild" }, + { name: "--mode all", descKey: "commands.stable.ai_artist.flag.mode_all" }, + { name: "--skip", descKey: "commands.stable.ai_artist.flag.skip" }, + ], }, { command: "/ck:media-processing", @@ -324,7 +386,12 @@ export function getEngineerKitCategories(t: TranslationFn): CommandCategory[] { desc: t("commands.stable.bootstrap.desc"), detail: t("commands.stable.bootstrap.detail"), isSkill: true, - flags: ["--full", "--auto", "--fast", "--parallel"], + flags: [ + { name: "--full", descKey: "commands.stable.bootstrap.flag.full" }, + { name: "--auto", descKey: "commands.stable.bootstrap.flag.auto" }, + { name: "--fast", descKey: "commands.stable.bootstrap.flag.fast" }, + { name: "--parallel", descKey: "commands.stable.bootstrap.flag.parallel" }, + ], }, { command: "/ck:backend-development", @@ -381,7 +448,12 @@ export function getEngineerKitCategories(t: TranslationFn): CommandCategory[] { desc: t("commands.stable.ship.desc"), detail: t("commands.stable.ship.detail"), isSkill: true, - flags: ["--official", "--beta", "--skip-tests", "--skip-review"], + flags: [ + { name: "--official", descKey: "commands.stable.ship.flag.official" }, + { name: "--beta", descKey: "commands.stable.ship.flag.beta" }, + { name: "--skip-tests", descKey: "commands.stable.ship.flag.skip_tests" }, + { name: "--skip-review", descKey: "commands.stable.ship.flag.skip_review" }, + ], }, { command: "/ck:mobile-development", @@ -398,7 +470,13 @@ export function getEngineerKitCategories(t: TranslationFn): CommandCategory[] { desc: t("commands.stable.team.desc"), detail: t("commands.stable.team.detail"), isSkill: true, - flags: ["