mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
lib/layers.ts marked only each layer's name; its line, body, operations, link labels and POSITIONING are now phrase() too, and LayerPage, Stack and the product kits already draw them through t. lib/data/solutions.ts marks every hint, title, lede, point and product line, and lib/creative-models.ts every tagline, capability, use case and note, which CreativeLanding draws through t. ClosingCta's defaults are English inside @hanzo/ui, so Closing says them itself: "Build what’s next.", "Try Hanzo", "Read the docs". Claude-Session: https://claude.ai/code/session_015XYKLjZtDTJEnMo4eK3AFH
59 lines
2.4 KiB
TypeScript
59 lines
2.4 KiB
TypeScript
'use client'
|
||
|
||
import { useSyncExternalStore } from 'react'
|
||
import { usePathname } from 'next/navigation'
|
||
import { ClosingCta } from '@hanzo/ui/marketing'
|
||
import { track } from '@hanzo/app/lib/tags'
|
||
import { bare, betaRunning, subscribeBeta } from '@/components/shell/mode'
|
||
import { useI18n } from '@hanzo/i18n/react'
|
||
import { useSay } from '@/components/marketing/say'
|
||
|
||
/**
|
||
* Where a page ends without this call: the places a person already pays or
|
||
* reads, and the pages that state their own. Every focused page (the way in,
|
||
* the way to pay, the first run: components/shell/mode `bare`) is quiet too, so
|
||
* /forget and /join end at their mark as /login does.
|
||
*/
|
||
const QUIET = [
|
||
'/login', '/signup', '/onboarding', '/pricing', '/enterprise', '/contact', '/contact-sales', '/sms-opt-in', '/status', '/console',
|
||
'/account', '/settings', '/billing', '/auth', '/investors',
|
||
// The platform page closes on the stack's own call.
|
||
'/platform',
|
||
'/legal', '/terms', '/privacy', '/cookies', '/pay', '/checkout', '/docs', '/blog', '/newsletter/confirm',
|
||
// The application is the page. '/beta' does not match '/betaa'.
|
||
'/beta',
|
||
]
|
||
|
||
export const quiet = (path: string): boolean =>
|
||
QUIET.some((route) => path === route || path.startsWith(`${route}/`))
|
||
|
||
/**
|
||
* The one closing call, mounted once between a marketing page and its footer.
|
||
* A page outside the (marketing) layout mounts it itself, and may name its own
|
||
* headline and second door.
|
||
*/
|
||
export default function Closing({
|
||
title,
|
||
primary,
|
||
secondary,
|
||
}: {
|
||
title?: string
|
||
primary?: { label: string; href: string }
|
||
secondary?: { label: string; href: string } | null
|
||
}) {
|
||
const path = usePathname() ?? '/'
|
||
const applying = useSyncExternalStore(subscribeBeta, betaRunning, () => false)
|
||
const say = useSay()
|
||
const { t } = useI18n()
|
||
if (quiet(path) || bare(path) || applying) return null
|
||
// ClosingCta's own defaults are English, so the defaults are said here, the same words.
|
||
return (
|
||
<ClosingCta
|
||
title={title ? say(title) : t('Build what’s next.')}
|
||
primary={primary ? { ...primary, label: say(primary.label) } : { label: t('Try Hanzo'), href: '/login' }}
|
||
secondary={secondary === null ? null : secondary ? { ...secondary, label: say(secondary.label) } : { label: t('Read the docs'), href: 'https://docs.hanzo.ai' }}
|
||
onCta={(cta) => cta === 'try_hanzo' && track('cta_clicked', { page: path, cta })}
|
||
/>
|
||
)
|
||
}
|