mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
The owner's spec for a landing page is the models bento's: monochrome, the words left and the art right, no extra prose. The folds carried two to four sentences under each heading, and some a claim, a lede and a list besides. Each now says one line: ProductLanding the tagline where a page states one (the lede still describes it to search), a claim alone where the claim is the line (/payments, /treasury, /zap, the extension), and elsewhere the sentence that says what the thing is. /philosophy's two points, /dns' claim that repeated its title, /calculator's capabilities line and the Spare clauses on /research and /learn go.
126 lines
6.2 KiB
TypeScript
126 lines
6.2 KiB
TypeScript
"use client"
|
|
|
|
import type { ReactNode } from 'react'
|
|
|
|
/**
|
|
* /treasury — the double-entry ledger, what it is made of, and how a
|
|
* transaction is written.
|
|
*
|
|
* NO TAILWIND. The three sections under the hero are
|
|
* `components/marketing/band`'s `Band` and `Head`; the type is @hanzo/ui's
|
|
* marketing components (`Display`, `Claim`, `Lede`, `Title`, `Chip`, `Action`,
|
|
* `Leaf`, `Line`); the grids are `@hanzo/ui/grid`'s `Grid`; every frame is gui
|
|
* props. A `color-mix()` ink is not a value gui's colour props type, so a
|
|
* frame's tint rides `$platform-web`, which gui still writes as a class.
|
|
*
|
|
* One thing to know before editing the hero: the wash behind it is animated by
|
|
* framer, which owns `transform` for the length of the animation. Its centring
|
|
* is therefore the `translate` PROPERTY — which is also what Tailwind v4's
|
|
* `-translate-x-1/2` set, so nothing moved — and writing it as a
|
|
* `transform: translate(...)` would be overwritten by the `scale` keyframe on
|
|
* the first frame.
|
|
*/
|
|
|
|
import { motion } from "@/components/motion"
|
|
import { ProductFooter } from "@/components/products/ProductFooter"
|
|
import {
|
|
ArrowRight,
|
|
Banknote,
|
|
GitMerge,
|
|
Landmark,
|
|
RefreshCw,
|
|
Shield,
|
|
Wallet,
|
|
} from "lucide-react"
|
|
import { Box, XStack } from '@hanzo/ui'
|
|
import { Grid } from '@hanzo/ui/grid'
|
|
import { Band, Head } from '@/components/marketing/band'
|
|
import { Action, Title, Leaf, Line } from '@hanzo/ui/marketing'
|
|
import { Fold } from '@/components/marketing/fold'
|
|
import { Win } from '@/components/home/chrome'
|
|
import { phrase } from '@hanzo/i18n'
|
|
import { T } from '@hanzo/i18n/react'
|
|
|
|
/** The inks this page draws in. */
|
|
const INK = 'var(--foreground)'
|
|
const DIM = 'var(--muted-foreground)'
|
|
|
|
const SMALL = { fontSize: '$2', lineHeight: '1.4286', color: DIM } as const
|
|
|
|
/** A feature card: the same tile as a `Leaf`, so its edge answers a pointer. */
|
|
const FEATURE = { p: 24, borderColor: "var(--border)", bg: "color-mix(in oklab, var(--secondary) 50%, transparent)", hoverStyle: { borderColor: "var(--neutral-600)" } } as const
|
|
|
|
/** The 48px disc a feature's mark sits on. */
|
|
const DISC = {
|
|
width: 48,
|
|
height: 48,
|
|
items: 'center',
|
|
justify: 'center',
|
|
rounded: 'var(--radius-lg)',
|
|
'$platform-web': { backgroundColor: 'color-mix(in oklab, var(--pure-white) 10%, transparent)' },
|
|
} as const
|
|
|
|
/** The pair that closes the page: stacked on a phone, side by side from 640.
|
|
* PROPS, so the `$sm` row is one atomic class beside the base column. */
|
|
const ROW = { display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: 12 } as const
|
|
|
|
const features = [
|
|
{ icon: Banknote, title: phrase("Double-entry ledger"), description: phrase("A transaction is a set of postings with a source and a destination, and it is rejected unless it balances. Entries are immutable — a correction is another transaction, so history stays true.") },
|
|
{ icon: GitMerge, title: phrase("Reconciliation"), description: phrase("Match what the ledger believes against what a payment provider reports, and show the rows that disagree. The breaks are the output; agreeing totals need no attention.") },
|
|
{ icon: Wallet, title: phrase("Accounts and balances"), description: phrase("Hold balances per account and per currency, and move between them as ledger transactions. What an account settles against is configured per deployment.") },
|
|
{ icon: RefreshCw, title: phrase("Wallets with holds"), description: phrase("Multi-currency virtual wallets that can hold an amount and release it later. That is how you take money at checkout and pay a seller on delivery without the balance lying in between.") },
|
|
{ icon: Shield, title: phrase("Flows and webhooks"), description: phrase("Longer sequences — capture, split, pay out, retry — run as orchestrated flows, and every change of financial state is delivered as an event you can subscribe to.") },
|
|
]
|
|
|
|
export default function TreasuryPage({ split }: { split: ReactNode }) {
|
|
return (
|
|
<>
|
|
<Fold
|
|
label="Treasury Operations"
|
|
mark={<Landmark width={14} height={14} color="currentColor" aria-hidden />}
|
|
title="Hanzo Treasury"
|
|
claim="A double-entry ledger for money moving inside your product"
|
|
actions={
|
|
<>
|
|
<Action href="https://docs.hanzo.ai/docs/cli/treasury" fill><T>Read the docs</T> <ArrowRight width={16} height={16} data-i18n-mirror /></Action>
|
|
<Action href="https://github.com/hanzoai">GitHub</Action>
|
|
</>
|
|
}
|
|
preview={
|
|
<Win title="split.num" icon={<Landmark size={12} color="currentColor" />}>
|
|
{split}
|
|
</Win>
|
|
}
|
|
/>
|
|
|
|
<Band pad="$11">
|
|
<Head title={<T>What it is made of</T>} lede={<T>A ledger, a language for writing transactions, and the machinery around them.</T>} />
|
|
<Grid columns={{ min: 300, max: 3 }} gap={24}>
|
|
{features.map((feature, index) => (
|
|
<Leaf render={<motion.div initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ duration: 0.5, delay: index * 0.05 }} />} key={feature.title} {...FEATURE} hoverStyle={{ borderColor: "var(--neutral-600)" }}>
|
|
<XStack mb={16} {...DISC}><feature.icon width={24} height={24} color={INK} /></XStack>
|
|
<Line render="h3" display="block" mb={8} fontSize="$4" lineHeight="1.5556" fontWeight="600" color={INK}><T>{feature.title}</T></Line>
|
|
<Line render="p" display="block" {...SMALL}><T>{feature.description}</T></Line>
|
|
</Leaf>
|
|
))}
|
|
</Grid>
|
|
</Band>
|
|
|
|
<Band pad="$10" measure={768}>
|
|
<Box $platform-web={{ textAlign: 'center' }}>
|
|
<Title quiet mb={16}><T>Post your first transaction</T></Title>
|
|
<Box {...ROW} $sm={{ flexDirection: 'row' }}>
|
|
<Action href="https://docs.hanzo.ai/docs/cli/treasury" target="_blank" rel="noopener noreferrer" fill justify="center">
|
|
<T>Read the docs</T> <ArrowRight width={16} height={16} data-i18n-mirror />
|
|
</Action>
|
|
<Action href="https://github.com/hanzoai" target="_blank" rel="noopener noreferrer" justify="center">
|
|
<T>View on GitHub</T>
|
|
</Action>
|
|
</Box>
|
|
<ProductFooter slug="treasury" name="Treasury" />
|
|
</Box>
|
|
</Band>
|
|
</>
|
|
)
|
|
}
|