Bento Grid
betaA grid of soft gray cards that show off features, each with a live preview, an icon, or a link.
Preview
Set the team up
Leads plan events and check who is coming. Everyone answers for themselves.
Everyone answers
- Tom H.
- Sam D.
- Ravi P.
Every meeting and event has an answer-by date. People change their answer until then.
Watch the count
- Fri, company all-hands24
- Tue, whole-team sync31
- Thu, design workshop14
The number going sits on the event, with the people who haven't answered beside it.
previews with icons and links, size lg
6 haven't answered by Thursday
Reminder emails
Pick the event, and the email takes people straight back to it.
A calendar that updates itself
When an event changes, calendar apps pick up the new time.
- 1Website redesign
- 2Mobile app
- 3Billing
Goals
Track goals by team and quarter. Everyone finds their own progress.
feature grid: icons only
Saved agendas
Attach a saved agenda to another event, or copy it for the next one.
Answer for someone
The person who texts their lead still gets counted. The lead sets the answer.
Download your data
Any member can download what we hold about them, without asking first.
Delete an account
Members can ask for their account to be deleted, across every record.
Always in sync
When an event changes, every phone shows the new time on its next refresh.
narrow container
Watch the count
- Fri, company all-hands24
- Tue, whole-team sync31
- Thu, design workshop14
The number going sits on the event.
Install
1. Add the registry to
components.json, once per app. Without it, the shadcn CLI looks up@txbrendanin a public list that txbrendan/ui does not control.npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.
npx shadcn@latest add @txbrendan/theme3. Add the website component. It also adds every component it uses. Its own files go in your
componentsfolder, and they are yours to edit.npx shadcn@latest add @txbrendan/bento-grid
Use it for
- The feature sections of a landing page, under a Headline.
- A showcase: three cards, each with a `label`, a `preview` built from real parts, and a `description` at the bottom.
- Feature cards: an `icon`, a `title`, and a `description`, with a `preview` above them if you have one. Use size lg for three big ones.
- A feature list: up to nine cards with only an icon, title, and description.
- Give a card an `href` when a page tells more. The whole card becomes the link, and an arrow shows.
- Make one card wider with className="@3xl:col-span-2".
Avoid it for
- Numbers people check, like a dashboard's key stats. Use Stats Cards.
- Screenshots as previews. Build them from parts, so they stay sharp and follow the theme.
- More than nine cards in one grid. Split them under two Headlines.
Props
- label
BentoCard. A small label at the top.
string
- preview
BentoCard. A live mock of the feature. With a title under it, its bottom fades out.
ReactNode
- icon
BentoCard. An icon over the title, in the brand color, drawn at 28px.
ReactNode
- title
BentoCard. What the feature is. It is an h3, and it names the link.
ReactNode
- description
BentoCard. What it does. Without a title, it sits at the bottom of the card.
ReactNode
- href
BentoCard. Where the card leads. Needs a title, which becomes the link text.
string
- renderLink
BentoCard. Draws the link. Spread the props onto your router's link: (props) => <Link {...props} />.
(props: BentoLinkProps) => ReactNode · default a plain <a>
- pattern
BentoCard. A field of dots fading down from the top edge, in the card's tone.
boolean · default false
- tone
BentoCard. The color of the dots.
"neutral" | "brand" | "danger" | "success" | "warning" · default "neutral"
- size
BentoCard. Text size: 13px for a grid of many cards, 16px for a few big ones.
"md" | "lg" · default "md"
- className
Extra classes on the root. On BentoGrid it holds the container query.
string
- BentoGrid
Part. The grid: one column when narrow, three from 48rem of its own width. Put BentoCards inside.
ComponentProps<"div">
| Prop | Type | Default | What it does |
|---|---|---|---|
| label | string | - | BentoCard. A small label at the top. |
| preview | ReactNode | - | BentoCard. A live mock of the feature. With a title under it, its bottom fades out. |
| icon | ReactNode | - | BentoCard. An icon over the title, in the brand color, drawn at 28px. |
| title | ReactNode | - | BentoCard. What the feature is. It is an h3, and it names the link. |
| description | ReactNode | - | BentoCard. What it does. Without a title, it sits at the bottom of the card. |
| href | string | - | BentoCard. Where the card leads. Needs a title, which becomes the link text. |
| renderLink | (props: BentoLinkProps) => ReactNode | a plain <a> | BentoCard. Draws the link. Spread the props onto your router's link: (props) => <Link {...props} />. |
| pattern | boolean | false | BentoCard. A field of dots fading down from the top edge, in the card's tone. |
| tone | "neutral" | "brand" | "danger" | "success" | "warning" | "neutral" | BentoCard. The color of the dots. |
| size | "md" | "lg" | "md" | BentoCard. Text size: 13px for a grid of many cards, 16px for a few big ones. |
| className | string | - | Extra classes on the root. On BentoGrid it holds the container query. |
| BentoGrid | ComponentProps<"div"> | - | Part. The grid: one column when narrow, three from 48rem of its own width. Put BentoCards inside. |
Accessibility
- Each title is an h3, so put the grid under an h2, like a Headline.
- With an href, the link is the title, stretched over the card. Screen readers hear one link with the title as its name.
- A focused link outlines the whole card.
- Icons, arrows, and the dot pattern are aria-hidden.
- A preview is a picture of the product. Keep it free of real buttons, so nothing inside it takes focus.
- In forced colors the preview's fade is turned off, so nothing is hidden.
- In forced colors each card gets a border, so its edge still shows when its fill is painted away.
Examples
Three showcase cards
<BentoGrid>
<BentoCard label="Everyone answers" preview={<AnswersMock />} pattern tone="success" description="Every event has an answer-by date." />
<BentoCard label="Watch the count" preview={<CountsMock />} pattern tone="danger" description="The number going sits on the event." />
<BentoCard label="Set the team up" preview={<RolesMock />} pattern tone="brand" description="Leads plan, everyone answers." />
</BentoGrid>A feature list with links
<BentoGrid>
<BentoCard icon={<Calendar />} title="Calendar feed" description="Add it once and it stays up to date." href="/features/calendar" />
<BentoCard icon={<Mail />} title="Reminder emails" description="Chase the people who haven't answered." href="/features/reminders" />
<BentoCard icon={<Download />} title="Download your data" description="Anyone can take their data with them." />
</BentoGrid>