Files
zeekayandGitHub 082402c87f i18n: the layers, the solutions, the creative models and the closing call say their words (#110)
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
2026-10-30 01:20:05 -07:00

59 lines
2.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'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 })}
/>
)
}