Files

244 lines
8.8 KiB
TypeScript

'use client'
import type { ReactNode } from 'react'
import { ArrowRight, Code2, ExternalLink, Terminal, Layers, BookOpen, Key, Cpu, Zap } from 'lucide-react'
import { Box, Text, XStack, YStack } from '@hanzo/ui'
import { Grid } from '@hanzo/ui/grid'
import { Action, Chip, Eyebrow, Lede, Line, More, Title } from '@hanzo/ui/marketing'
import { Band, Card, Head } from '@/components/marketing/band'
import { Sample } from '@/components/models/kit'
export interface ModelSpecItem {
label: string
value: string
mono?: boolean
note?: string
}
export interface SdkLinkItem {
language: string
href: string
tag?: string
}
export interface ModelCardSectionProps {
id?: string
badge: string
title: string
description: ReactNode
modelId: string
endpoint: string
specs: ModelSpecItem[]
sdkLinks: SdkLinkItem[]
recipesLink?: { label: string; href: string }
githubRepo: string
huggingFaceUrl?: string
hfBadgeText?: string
docsUrl: string
sampleCode?: {
lang: string
code: string
}
}
export function ModelCardSection({
id = 'model-card',
badge,
title,
description,
modelId,
endpoint,
specs,
sdkLinks,
recipesLink,
githubRepo,
huggingFaceUrl,
hfBadgeText,
docsUrl,
sampleCode,
}: ModelCardSectionProps) {
return (
<Band id={id} measure={1180}>
<Head
eyebrow={badge}
title={title}
lede={description}
loud
/>
<Grid columns={{ min: 320, max: 2 }} gap={20} mt="$6">
{/* Left Card: Core Model Specifications */}
<Card display="flex" flexDirection="column" gap="$4" p="$6" borderColor="var(--border)" bg="$panel">
<XStack justify="space-between" items="center" borderBottomWidth={1} borderColor="var(--border)" pb="$3">
<XStack items="center" gap="$2">
<Cpu size={18} color="var(--primary)" />
<Text fontSize="$4" lineHeight="$4" fontWeight="600" color="$ink">
Model Card Specifications
</Text>
</XStack>
<Chip px={10} py={3} fontSize="$1" lineHeight="$1">
{modelId}
</Chip>
</XStack>
<YStack gap="$2" py="$1">
<XStack justify="space-between" items="baseline" gap="$3" py="$2" borderBottomWidth={1} borderColor="var(--border)">
<Text shrink={0} fontSize="$2" lineHeight="$2" color="var(--muted-foreground)">
Wire Endpoint
</Text>
{/* A URL is one word: it breaks anywhere rather than run off a phone. */}
<Text minW={0} fontFamily="$mono" fontSize="$2" lineHeight="$2" color="$ink" text="right" $platform-web={{ overflowWrap: 'anywhere' }}>
{endpoint}
</Text>
</XStack>
{specs.map((item) => (
<XStack key={item.label} justify="space-between" items="baseline" py="$2" borderBottomWidth={1} borderColor="var(--border)">
<YStack gap="$1">
<Text fontSize="$2" lineHeight="$2" color="var(--muted-foreground)">
{item.label}
</Text>
{item.note && (
<Text fontSize="$1" lineHeight="$1" color="var(--text-tertiary)">
{item.note}
</Text>
)}
</YStack>
<Text
fontFamily={item.mono ? '$mono' : undefined}
fontSize="$2"
lineHeight="$2"
fontWeight="600"
color="$ink"
$platform-web={{ fontVariantNumeric: 'tabular-nums', textAlign: 'right' }}
>
{item.value}
</Text>
</XStack>
))}
</YStack>
<XStack mt="auto" pt="$3" flexWrap="wrap" gap="$3">
<Action href="https://platform.hanzo.ai/keys" fill>
<Key size={14} /> Get API key <ArrowRight size={14} />
</Action>
{huggingFaceUrl && (
<Action href={huggingFaceUrl} target="_blank" rel="noreferrer">
🤗 {hfBadgeText ?? 'Hugging Face'}
</Action>
)}
<Action href={docsUrl}>
<BookOpen size={14} /> Documentation
</Action>
</XStack>
</Card>
{/* Right Card: Multi-Language SDKs & Runnable Recipes */}
<Card display="flex" flexDirection="column" gap="$4" p="$6" borderColor="var(--border)" bg="$panel">
<XStack justify="space-between" items="center" borderBottomWidth={1} borderColor="var(--border)" pb="$3" flexWrap="wrap" gap="$2">
<XStack items="center" gap="$2">
<Code2 size={18} color="var(--primary)" />
<Text fontSize="$4" lineHeight="$4" fontWeight="600" color="$ink">
Multi-Language SDKs & OSS Examples
</Text>
</XStack>
<XStack items="center" gap="$3">
{huggingFaceUrl && (
<More href={huggingFaceUrl} target="_blank" rel="noreferrer" fontSize="$2">
🤗 Hugging Face
</More>
)}
<More href={githubRepo} fontSize="$2">
GitHub Repo <ExternalLink size={12} />
</More>
</XStack>
</XStack>
<Text fontSize="$2" lineHeight="$3" color="var(--text-secondary)">
Runnable examples across all tier-one runtimes. Zero-install authentication with <Text fontFamily="$mono">hanzo auth login</Text> or environment variable <Text fontFamily="$mono">HANZO_API_KEY</Text>.
</Text>
{/* SDK Language Links Grid */}
<Grid columns={{ min: 140, max: 3 }} gap={10} my="$2">
{sdkLinks.map((sdk) => (
<YStack
key={sdk.language}
render={<a href={sdk.href} target="_blank" rel="noreferrer" />}
gap={4}
p={12}
rounded={10}
borderWidth={1}
borderColor="var(--border)"
bg="var(--background)"
$platform-web={{ textDecoration: 'none' }}
>
<XStack justify="space-between" items="center">
<Text fontSize="$2" lineHeight="$2" fontWeight="600" color="$ink">
{sdk.language}
</Text>
<ExternalLink size={12} color="var(--muted-foreground)" />
</XStack>
{sdk.tag && (
<Text fontFamily="$mono" fontSize="$1" lineHeight="$1" color="var(--muted-foreground)">
{sdk.tag}
</Text>
)}
</YStack>
))}
</Grid>
{recipesLink && (
<Box
render={<a href={recipesLink.href} target="_blank" rel="noreferrer" />}
p={12}
rounded={10}
borderWidth={1}
borderColor="var(--border)"
bg="var(--background)"
$platform-web={{ textDecoration: 'none' }}
>
<XStack justify="space-between" items="center">
<XStack items="center" gap="$2">
<Zap size={14} color="var(--primary)" />
<Text fontSize="$2" lineHeight="$2" fontWeight="600" color="$ink">
{recipesLink.label}
</Text>
</XStack>
<ExternalLink size={12} color="var(--muted-foreground)" />
</XStack>
<Text display="block" fontSize="$1" lineHeight="$2" color="var(--text-secondary)" mt="$1">
Modular production blueprints, enterprise crates, and automated verification suites.
</Text>
</Box>
)}
{sampleCode && (
<YStack gap="$1" mt="auto">
<Sample lang={sampleCode.lang}>
{/* Plain text in the code frame's face. components/code's `Code` is an
async server component; rendered inside this client component it is
an async client component, which React refuses (#482) and which put
/kai behind its error boundary on about half of its loads. */}
<Line
render="pre"
display="block"
m={0}
p={16}
overflowX="auto"
whiteSpace="pre"
fontFamily="$mono"
fontSize="$2"
lineHeight="var(--leading-relaxed)"
$platform-web={{ backgroundColor: 'light-dark(var(--pure-white), var(--card))' }}
>
<code>{sampleCode.code}</code>
</Line>
</Sample>
</YStack>
)}
</Card>
</Grid>
</Band>
)
}