Card
A surface with media, a title, content and actions, pressable and dismissible.
Invite your team
Everyone you invite can edit every page.
New
Three seats left on the Starter plan.
forSlots(CardSlots)(Recipes.Card({}))
Usage
The function that drew the preview, over the theme module Create a theme writes. The preview passes it the style picked above instead of its default.
export const CardStyle = forSlots(CardSlots)(Recipes.Card({}))
/** A sparkle in the text's color, for the card's media tile. */
const sparkle = <Message>(h: HtmlBuilder<Message>): Html =>
h.svg(
[h.ViewBox('0 0 16 16'), h.Attribute('fill', 'currentColor'), h.AriaHidden(true)],
[h.path([h.Attribute('d', 'M8 0l2 6 6 2-6 2-2 6-2-6-6-2 6-2z')], [])],
)
/** Whether the card was dismissed, and the Messages that dismiss it and bring it back. */
export interface Dismissal<Message> {
readonly dismissed: boolean
readonly onDismiss: Message
readonly onRestore: Message
}
export const card = <Message>(
style: NamedStyle<typeof CardSlots>,
dismissal: Dismissal<Message>,
h: HtmlBuilder<Message>,
): Html =>
dismissal.dismissed
? Button.view(
{ label: 'Bring the card back', onClick: dismissal.onRestore, style: ButtonStyle },
h,
)
: Card.view(
{
media: sparkle(h),
title: 'Invite your team',
description: 'Everyone you invite can edit every page.',
action: Badge.view({ text: 'New', tone: 'live', style: BadgeStyle }, h),
content: h.p([], ['Three seats left on the Starter plan.']),
footer: Button.view({ label: 'Send invites', style: ButtonStyle }, h),
dismiss: { onDismiss: dismissal.onDismiss },
style,
},
h,
)