Files
zeekay 11265a21fd Highlight every code sample with shiki in the code theme
Code on hanzo.ai was plain monospace: 285 blocks across 200 pages, one of
them hand-inked in four greys. components/code now renders each sample
at build with shiki and @hanzo/ui's codeTheme (Dracula dark, GitHub
Light light), every colour written as light-dark() so the page's
color-scheme picks it, on the theme's own ground. The page ships the
coloured spans and no highlighter; e2e/gates/code.spec.ts holds both.

A client page that shows code is split into a server page.tsx that owns
the sample and a client view.tsx that takes the highlighted node:
ProductLanding's code.source, the blockchain pages' codeExamples, the
models kit Sample, the guest-key card, realtime, analytics, payments,
sdks and the rest. Transcripts, agent prompts and ASCII diagrams are not
code and keep their markup.

Takes @hanzo/ui 8.27.83 for codeTheme and @hanzo/design 0.5.35 with it,
regenerates app/gui.css for the new theme keys, and lowers the raw-colour
allowance to 58: the samples' literal inks are gone.
2026-10-05 01:31:58 -07:00

135 lines
4.3 KiB
TypeScript

'use client'
/**
* A quick-start, told as one sample per language.
*
* Everything here already existed somewhere else on this site and was written
* out again by hand:
*
* the strip @hanzo/ui's `Tabs`, as the package draws it.
* the frame a labelled bar with @hanzo/ui's `CopyButton`, over the sample
* the server page highlighted (components/code).
* the head the eyebrow/heading/lede ladder `SDKSection` beside it sets.
*
* WHY THE COPY BUTTON MOVED. It floated over the code at `top-3 right-3`, which
* covers the first line — the import or the prompt, the part most read. The
* bar above the sample holds it instead. It also ends a duplicate
* `id="code-example"` that this file was stamping on one element per tab.
*
* `Eyebrow` is deliberately NOT used for the label. That role is 0.2em of
* tracking in `--neutral-400`; this label is 0.05em in the foreground, which is
* what `SDKSection` sets, and these two sections read as a pair.
*/
import { motion } from '@/components/motion'
import { Terminal } from 'lucide-react'
import type { ReactNode } from 'react'
import { Tabs, TabsContent, TabsList, TabsTrigger, XStack, YStack } from '@hanzo/ui'
import { CopyButton } from '@hanzo/ui/product'
import { Line } from '@/components/type'
/** One language's sample: its text for the clipboard, and that text highlighted
* by the server page (components/code). */
export interface Example {
language: string;
label: string;
code: string;
sample: ReactNode;
description?: string;
}
interface CodeExamplesSectionProps {
title?: string;
subtitle?: string;
examples: Example[];
}
export function CodeExamplesSection({
title = "Quick Start",
subtitle = "Pick a language.",
examples
}: CodeExamplesSectionProps) {
const languageIcons: Record<string, string> = {
python: "🐍",
javascript: "📜",
typescript: "📘",
go: "🐹",
rust: "🦀",
curl: "🔗",
cli: "💻",
bash: "💻",
docker: "🐳",
};
return (
<motion.section
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
>
<YStack py={64} px={16} $md={{ px: 32 }}>
<YStack width="100%" maxW={896} mx="auto">
<XStack items="center" gap={8} mb={8}>
<Terminal width={20} height={20} color="var(--foreground)" />
<Line
size="sm"
weight="500"
caps
>
Code Examples
</Line>
</XStack>
<Line
render="h2"
size="x2"
weight="700"
marginBottom={8}
$md={{ fontSize: 'var(--text-3xl)', lineHeight: '1.2' }}
>
{title}
</Line>
<Line render="p" tone="muted" marginBottom={32}>
{subtitle}
</Line>
<Tabs defaultValue={examples[0]?.language}>
<TabsList mb="$6">
{examples.map((example) => (
<TabsTrigger key={example.language} value={example.language}>
<span>{languageIcons[example.language.toLowerCase()] || "📄"}</span>
{example.label}
</TabsTrigger>
))}
</TabsList>
{examples.map((example) => (
<TabsContent key={example.language} value={example.language}>
{example.description && (
<Line render="p" size="sm" tone="muted" marginBottom={16}>
{example.description}
</Line>
)}
<YStack rounded="$4" borderWidth={1} borderColor="$borderColor" overflow="hidden">
<XStack items="center" gap="$1" px="$3" py="$1.5" borderBottomWidth={1} borderColor="$borderColor">
<Line size="xs" tone="muted" fontFamily="$mono">
{example.label}
</Line>
<XStack flex={1} />
<CopyButton value={example.code} />
</XStack>
{example.sample}
</YStack>
</TabsContent>
))}
</Tabs>
</YStack>
</YStack>
</motion.section>
);
}
export default CodeExamplesSection;