Skip to content

Components / Sections

Widget Bento

An app beyond its own screen, in a bento: its home-screen widgets in three sizes, its lock screen (a phone's top half, cut by the tile) and its watch face, each drawn from rows (AppScreen without its chrome) on a tile of a colour block, with a title and a line under it. Small widgets take one column, medium two, large two by two, the lock screen two rows. The tiles arrive in turn and each drawing fills as its tile arrives: the ring, the bars, the checks. Zero JavaScript.

Live demo

Widgets

On every screen you have

The home screen, the lock screen and the wrist each show today at a glance.

  • Today at a glance

    The ring, on your home screen.

  • A nudge at your usual time

    One notification a day, never more.

  • The week

    Each day as a bar.

  • On your wrist

    Tick a habit off from the watch.

  • The streak

    Days in a row, kept.

  • Next up

    The one habit left today.

Live, from the library itself, at full size: scroll, hover, navigate away and back. The demo is never gated.

Variants · each row writes the attribute the prop writes; the section's own CSS answers

tone
density

Measured

JavaScript of its own

0 B

Uses Reveal and the shared runtime (1.9 kB raw, once per site). With those included: 3.0 kB raw.

CSS 26.8 kB raw including the base tokens. Measured from a production build, and again in CI for every change that can move it.

Browser support

Baseline · widely available

Chrome 105 · Firefox 110 · Safari 16; needs container-units. Elsewhere: without container units the drawings keep the page's text size.

Install Pro

The demo above is never gated; the source is. With a key in components.json (see account), the registry serves it like any other item:

terminal
npx shadcn@latest add @moonarc-pro/widget-bento
src/pages/index.astro
---
import WidgetBento from '@/components/moonarc/pro/WidgetBento.astro';
---
<WidgetBento
  headline="On every screen you have"
  tiles={[
    { kind: 'widget', size: 'small', title: 'Today at a glance', screen: { rows: [{ kind: 'ring', value: 0.75, text: '3/4', label: 'done' }] } },
    { kind: 'widget', size: 'medium', title: 'The week', screen: { rows: [{ kind: 'bars', values: [3, 4, 2, 4, 4, 3, 1] }] } },
    { kind: 'lock', title: 'A nudge at the right time', screen: { rows: [{ kind: 'clock', time: '7:42', date: 'Friday 9 October' }, { kind: 'notice', app: 'Sitename', title: 'Walk 20 minutes', text: 'Your usual time' }] } },
    { kind: 'watch', title: 'On your wrist', screen: { rows: [{ kind: 'ring', value: 0.5, text: '2/4', label: 'today' }] } },
  ]}
/>

Without a key the registry answers 401 with an upgrade message. Everything this section composes is free: app-screen, reveal.

Props

PropTypeDefaultDescription
tiles{ kind; size?; title; text?; block?; screen }[]noneThe tiles, in order (the grid fills gaps densely). kind is widget, lock or watch; size (widgets) is small, medium or large; block is the tile's colour block (unset, the tiles take blocks 1 to 5 in turn); screen is AppScreen's props, and its drawing keeps the app's accent (the primary) unless the screen names a block.
headlinestringnoneThe section's heading. Slot "headline" wins and may hold an <em>.
eyebrowstringnoneA short line above the heading.
copystringnoneA line under the heading.
level2 | 32Heading level of the heading; each tile's title is one below.
tone'surface' | 'muted' | 'ink' | 'brand'unset (paints nothing)The section's ground.
density'compact' | 'cozy' | 'roomy''cozy'Block padding ×0.8 / ×1 / ×1.25 through --ma-density.

Theming and overrides

The section reads the theme contract (shadcn's variable names with the base tokens as fallback), so a pasted theme or one --ma-brand recolours it. Its class names are the override surface and stay stable; a named slot replaces the matching prop with your own markup.

Classes

.ma-wbento.ma-wbento__art.ma-wbento__caption.ma-wbento__copy.ma-wbento__eyebrow.ma-wbento__grid.ma-wbento__head.ma-wbento__headline.ma-wbento__inner.ma-wbento__lock.ma-wbento__text.ma-wbento__tile.ma-wbento__title.ma-wbento__watch.ma-wbento__widget

Slots

slot="headline"

Reduced motion

The tiles are there at once and the drawings are drawn as they end.

With ClientRouter

CSS and Reveal.

Why it is built this way

Replaces: Widget showcase sections on app landing pages. See the migration table.

A phone app's screen drawn from rows instead of a screenshot: a status bar, a title, then rows of fourteen kinds (a big figure, a ring of progress, a checklist, a bar chart, a card, chips, a map with a route, a player, a chat, a list, a week of days, a button, a lock screen's clock, a notification) and a tab bar.

every browserload

A hero for a mobile app: the headline, the rating line (stars, the average, how many rated and where) and the store buttons beside a phone on a disc of the app's colour.

every browserload

What is on offer, as colour blocks: each card paints one of the palette's blocks and carries a drawing in its corner (Motif), an index, a name, a line, chips for what it includes and a foot with a price and a round arrow.

newly · Chrome 105 · Firefox 121 · Safari 15.4hover

The first screen of one person's work, as a bento.

newly · Chrome 105 · Firefox 128 · Safari 17pointerscrollalways

Also: view transitions · how costs are measured · browser support · accessibility policy · five-minute setup · MCP for agents · this page as Markdown