/** * Use-case gallery as switchable tabs — the RAG docs expert and the penguin sled * game, each shown as its FINISHED PRODUCT (mockup shots matched to the visitor's * locale and theme) under its condensed one-sentence prompt. Tab order follows * S.cases.tabs; CASE_SHOTS is index-aligned with it. A tab may carry a `cost` * line (the RAG one does) — an emphasized token-cost hook under the caption. */ import { useState } from "react"; import { S } from "../lib/strings"; import { useLocale } from "../state/locale"; import type { Locale } from "../state/locale"; import { Section } from "../components/section"; import { BrowserFrame } from "../components/browser-frame"; import { demoVideoUrl } from "../lib/links"; import ragAppZhLight from "../assets/rag-app-zh-light.webp"; import ragAppZhDark from "../assets/rag-app-zh-dark.webp"; import ragAppEnLight from "../assets/rag-app-en-light.webp"; import ragAppEnDark from "../assets/rag-app-en-dark.webp"; import gameZhLight from "../assets/game-zh-light.webp"; import gameZhDark from "../assets/game-zh-dark.webp"; import gameEnLight from "../assets/game-en-light.webp"; import gameEnDark from "../assets/game-en-dark.webp"; type ShotSet = Record; /** * Demo recording for a case, index-aligned with S.cases.tabs; null where the finished * product is still shown as a still. The community-hosted file only downloads on play * (preload="none"), and the matching screenshot doubles as the poster — so a video tab * costs a visitor exactly what an image tab already did until they press play. */ const CASE_VIDEOS: Array | null> = [ { zh: demoVideoUrl("rag_zh"), en: demoVideoUrl("rag_en") }, null, ]; /** Finished-product shots, index-aligned with S.cases.tabs. */ const CASE_SHOTS: ShotSet[] = [ { zh: { light: ragAppZhLight, dark: ragAppZhDark }, en: { light: ragAppEnLight, dark: ragAppEnDark }, }, { zh: { light: gameZhLight, dark: gameZhDark }, en: { light: gameEnLight, dark: gameEnDark }, }, ]; export function Cases() { const { locale } = useLocale(); const tabs = S.cases.tabs; const [active, setActive] = useState(0); const tab = tabs[active] ?? tabs[0]!; const shots = (CASE_SHOTS[active] ?? CASE_SHOTS[0]!)[locale]; const video = (CASE_VIDEOS[active] ?? null)?.[locale]; return (
{tabs.map((t, i) => ( ))}
> {tab.prompt}
{/* Light/dark are two elements rather than one with a swapped source: a
{tab.caption}
{tab.cost && (

{tab.cost}

)}
); }