Files
zeekay 7464cc7013 Lede is a fold caller: /commerce, /sign, /dataroom, /captable, /iam, /s3
The six pages that opened on components/products/Lede drew a centred
heading over a glow, short of the window and narrower than the bar. Lede now
hands its title, paragraph, badge, actions and facts to the shared fold, and
each page walks its product beside the words: an order from variant to
return, a document from upload to certificate, a shared link from folder to
revoked access, a round from share classes to the waterfall. /iam's and
/s3's fact lists are the walk itself, with the API reference, the discovery
document and the source beside the title (each answers 200).
2026-10-30 01:51:10 -07:00

64 lines
2.0 KiB
TypeScript

import type { ReactNode } from 'react'
import type { LucideIcon } from 'lucide-react'
import { ArrowRight } from 'lucide-react'
import { Action } from '@hanzo/ui/marketing'
import { T } from '@hanzo/i18n/react'
import type { CTA } from '@/components/product/ProductLanding'
import { Fold } from '@/components/marketing/fold'
/**
* A product stated in one heading and one paragraph: the first screen six pages
* open on (/commerce, /sign, /dataroom, /captable, /iam, /s3). It is a caller
* of `components/marketing/fold`, so it fills the window, keeps the bar's
* measure and stands the product's `preview` beside the words from 1024px.
*
* The title is a node rather than a string because a caller may count
* something in its own heading. `badge`, a string `title`, each action's label
* and each fact are drawn through the catalog: a caller marks the literal
* `phrase('…')` where it writes it. The paragraph is the caller's markup.
*/
export function Lede({
title,
badge,
badgeIcon: Badge,
actions,
facts,
preview,
children,
}: {
title: ReactNode
badge?: string
badgeIcon?: LucideIcon
actions?: CTA[]
/** What the product does, one fact a line, under the paragraph. */
facts?: readonly string[]
/** The product at work, beside the words. */
preview?: ReactNode
children: ReactNode
}) {
return (
<Fold
label={badge}
mark={Badge ? <Badge width={14} height={14} color="currentColor" aria-hidden /> : undefined}
title={title}
lede={children}
points={facts ? [...facts] : undefined}
preview={preview}
actions={
actions && actions.length > 0
? actions.map((a, i) => {
const Icon = a.icon ?? (i === 0 ? ArrowRight : undefined)
return (
<Action key={a.label} href={a.href} fill={i === 0}>
<T>{a.label}</T> {Icon && <Icon width={16} height={16} data-i18n-mirror={a.icon ? undefined : ''} />}
</Action>
)
})
: undefined
}
/>
)
}
export default Lede