Widgets: the three sizes and how each one gets its data

Widgets

A widget is the small, glanceable face of your app on someone’s home screen. There are three sizes and they are fixed, because every app’s widgets share one grid and a widget that sets its own height breaks the alignment of everything beside it.

The three sizes

SizePixelsGridWhat belongs in it
Small170 × 1701 × 1One number or one status. The thing you check most.
Medium360 × 1702 × 1A short list, a few days of a forecast, or three stats side by side.
Large360 × 3602 × 2A chart, a longer list, or several rows of detail.

The column pitch is 170 with a 20px gap, which is where the other numbers come from: 170 + 20 + 170 = 360. Large is square at 360, not 376, so that two stacked mediums line up with one large exactly.

Build for the exact pixel size. Responsive classes that stretch a widget to its container are the most common reason one looks cut off: the row track is a fixed 170px and does not grow to meet you.

Use the toolkit

It handles the sizes, the spacing and the tap targets, and it is what the gates check against.

shell
npm install @clarittyai/widget-toolkit

Layout

  • WidgetContainer, locks the widget to its size and clips overflow.
  • WidgetHeader, the title row.
  • WidgetList, WidgetMetric, WidgetStat, the three things a widget usually is.

Controls and marks

  • WidgetButton, meets the 44px minimum tap target on its own.
  • WidgetToggle, WidgetBadge, WidgetAvatar, WidgetAvatarGroup.
  • widgetText, text styles that never fall below the 12px minimum.
Widget.tsx
import { WidgetContainer, WidgetHeader, WidgetMetric } from '@clarittyai/widget-toolkit';

export default function Widget({ data }) {
  return (
    <WidgetContainer size="small">
      <WidgetHeader title="Overdue" />
      <WidgetMetric value={data.count} label="invoices" />
    </WidgetContainer>
  );
}

Where the data comes from

The dashboard polls GET /api/widget about every 30 seconds and hands the result to your component. Keep the endpoint’s shape and the component in step. A widget that renders empty on the dashboard is nearly always this contract drifting.

The rules the gates enforce

RuleWhy
One of the three sizes, exactlyEverything on the grid has to line up.
Tap targets at least 44 × 44Smaller than that is not reliably hittable with a thumb.
Text at least 12pxBelow that it is decoration, not information.
One glance, one actionA widget is not a small dashboard. If it needs a second look, it belongs on the dashboard.
Corner radius is 24px, and the button shape comes from the published toolkit. Take both from the toolkit rather than restyling them, so widgets from different apps sit together without looking like a collage.