mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
191 lines
6.6 KiB
TypeScript
191 lines
6.6 KiB
TypeScript
/**
|
||
* /support — the Help Center, the docs, live status, and a way to reach a human.
|
||
*
|
||
* NO TAILWIND except one prose-link hover, named at its call site. This is a
|
||
* SERVER page and stays one: no `Head` here, because `Head` carries a scroll
|
||
* entrance and this page has never had motion — giving it one would be a change
|
||
* to the picture smuggled in as a conversion. The frame is `Box render="section"`
|
||
* with the paddings the page already stated; the type and the controls are the
|
||
* @hanzo/ui's `Display`, `Lede`, `Chip`, `Leaf` and `More`.
|
||
*
|
||
* Each channel card is a `Leaf`, the site's card-that-IS-a-link, and its call
|
||
* to action lifts with it: the card decides the hover, the content says who
|
||
* takes part.
|
||
*/
|
||
|
||
import type { Metadata } from 'next'
|
||
import { LifeBuoy, BookOpen, Activity, Mail, MessagesSquare, ArrowUpRight } from 'lucide-react'
|
||
import { Github } from '@/components/brand'
|
||
import { Box, Text } from '@/components/ui'
|
||
import { mix } from '@hanzo/app/lib/mix'
|
||
import { Chip, Display, Lede, More, Leaf } from '@hanzo/ui/marketing'
|
||
import { Grid } from '@hanzo/ui/grid'
|
||
|
||
export const metadata: Metadata = {
|
||
title: 'Support — Hanzo',
|
||
description: 'Get help with Hanzo — the Help Center, documentation, live system status, and a way to reach a human.',
|
||
}
|
||
|
||
const CHANNELS = [
|
||
{
|
||
icon: LifeBuoy,
|
||
title: 'Help Center',
|
||
body: 'Search answers, browse guides, and open a support ticket. The fastest path to a resolution.',
|
||
href: 'https://hanzo.help',
|
||
cta: 'Open Help Center',
|
||
},
|
||
{
|
||
icon: BookOpen,
|
||
title: 'Documentation',
|
||
body: 'Guides, API references, and quickstarts for every product across the Hanzo Cloud.',
|
||
href: 'https://docs.hanzo.ai',
|
||
cta: 'Read the docs',
|
||
},
|
||
{
|
||
icon: Activity,
|
||
title: 'System Status',
|
||
body: 'Live uptime and incident history for every Hanzo service. Check here first if something feels off.',
|
||
href: 'https://status.hanzo.ai',
|
||
cta: 'View status',
|
||
},
|
||
{
|
||
icon: MessagesSquare,
|
||
title: 'Community',
|
||
body: 'Ask questions and share what you build with other developers on the Hanzo Discord and Community.',
|
||
href: 'https://discord.gg/XthHQQj',
|
||
cta: 'Join the community',
|
||
},
|
||
{
|
||
icon: Github,
|
||
title: 'GitHub',
|
||
body: 'Report a bug, request a feature, or contribute — our SDKs and tooling are open source.',
|
||
href: 'https://github.com/hanzoai',
|
||
cta: 'Open an issue',
|
||
},
|
||
{
|
||
icon: Mail,
|
||
title: 'Email us',
|
||
body: 'Prefer email? Reach the team directly and we’ll get back to you.',
|
||
href: 'mailto:[email protected]',
|
||
cta: '[email protected]',
|
||
},
|
||
]
|
||
|
||
/** The hairline tile this page sets a card and a footnote in. */
|
||
const TILE = {
|
||
borderRadius: 'var(--radius-xl)',
|
||
borderWidth: 1,
|
||
borderColor: 'var(--neutral-800)',
|
||
backgroundColor: 'color-mix(in oklab, var(--neutral-900) 50%, transparent)',
|
||
padding: 24,
|
||
} as const
|
||
|
||
/** A card: the tile above, plus the edge lift `Leaf` owns. */
|
||
const CARD = { p: 24, borderColor: "var(--neutral-800)", display: "flex", flexDirection: "column", bg: "color-mix(in oklab, var(--neutral-900) 50%, transparent)", hoverStyle: { borderColor: "var(--neutral-600)" } } as const
|
||
|
||
/** The disc a channel's mark sits on; the mark paints in its ink. */
|
||
const MARK = {
|
||
render: 'span',
|
||
mb: 16,
|
||
display: 'inline-flex',
|
||
height: 40,
|
||
width: 40,
|
||
items: 'center',
|
||
justify: 'center',
|
||
rounded: 'var(--radius-lg)',
|
||
borderWidth: 1,
|
||
borderColor: 'var(--neutral-800)',
|
||
bg: mix('var(--pure-white)', 5),
|
||
color: 'var(--foreground)',
|
||
} as const
|
||
|
||
export default function SupportPage() {
|
||
return (
|
||
<Box render="main" position="relative" overflow="hidden">
|
||
{/* Hero */}
|
||
<Box
|
||
render="section"
|
||
position="relative"
|
||
display="flex"
|
||
flexDirection="column"
|
||
items="center"
|
||
pt={112}
|
||
pb={32}
|
||
px={16}
|
||
$sm={{ px: 24 }}
|
||
$lg={{ px: 32 }}
|
||
>
|
||
<Chip mb={24} px={16} py={6} bg="color-mix(in oklab, var(--pure-white) 5%, transparent)">
|
||
<LifeBuoy width={16} height={16} /> Support
|
||
</Chip>
|
||
<Display text="center">
|
||
How can we help?
|
||
</Display>
|
||
<Lede mt={20} width="100%" maxW={672} mx="auto" text="center">
|
||
Answers, docs, live status, and a direct line to the team.
|
||
</Lede>
|
||
</Box>
|
||
|
||
{/* Channels */}
|
||
<Box
|
||
render="section"
|
||
width="100%"
|
||
maxW={1152}
|
||
mx="auto"
|
||
pt={32}
|
||
pb={96}
|
||
px={16}
|
||
$sm={{ px: 24 }}
|
||
$lg={{ px: 32 }}
|
||
>
|
||
<Grid columns={{ min: 300, max: 3 }} gap={16}>
|
||
{CHANNELS.map((c) => {
|
||
const Icon = c.icon
|
||
const external = c.href.startsWith('http')
|
||
return (
|
||
<Leaf
|
||
render="a"
|
||
key={c.title}
|
||
href={c.href}
|
||
target={external ? '_blank' : undefined}
|
||
rel={external ? 'noopener noreferrer' : undefined}
|
||
{...CARD}
|
||
hoverStyle={{ borderColor: "var(--neutral-600)" }}
|
||
>
|
||
<Text {...MARK}>
|
||
<Icon width={20} height={20} />
|
||
</Text>
|
||
<Text render="h2" mb={6} fontSize="$4" lineHeight="1.2891rem" fontWeight="600" color="var(--foreground)">
|
||
{c.title}
|
||
</Text>
|
||
<Text render="p" mb={20} grow={1} shrink={1} flexBasis="0%" fontSize="$2" lineHeight="1.3203rem" color="var(--muted-foreground)">
|
||
{c.body}
|
||
</Text>
|
||
<More render="span" gap={6} $group-hover={{ color: 'var(--text-primary)' }}>
|
||
{c.cta} <ArrowUpRight width={16} height={16} />
|
||
</More>
|
||
</Leaf>
|
||
)
|
||
})}
|
||
</Grid>
|
||
|
||
{/* Enterprise footer note */}
|
||
<Box mt={24} {...TILE}>
|
||
<Text render="p" display="block" fontSize="$2" text="center" color="var(--muted-foreground)">
|
||
On an enterprise plan or need a dedicated channel?{' '}
|
||
{/* A link in a sentence, not a control: the underline appearing on
|
||
approach is the whole treatment, and @hanzo/design's base
|
||
already states it once for every link inside a paragraph
|
||
(`:is(p,li,…) a:hover{text-decoration:underline}`), so this one
|
||
says nothing. */}
|
||
<Text render="a" {...{ href: 'mailto:[email protected]' }} fontWeight="500" color="var(--foreground)">
|
||
Email support@hanzo.ai
|
||
</Text>{' '}
|
||
and we’ll route you to your team.
|
||
</Text>
|
||
</Box>
|
||
</Box>
|
||
</Box>
|
||
)
|
||
}
|