Design
Size
The board is a 12 × 6 grid. Your widget can be any size from
widget.minSize up to the whole board, and users resize it freely. Lay
out from ctx.size and the resize event, not from the window:
const layout = ({ cols, rows }: FrameSize) => {
document.body.dataset.compact = String(cols < 4 || rows < 3);
};
layout(ctx.size);
notch.on("resize", layout);
Design for 2×2 first, then add detail as it grows.
Theme tokens
The app has 9 themes. Use these CSS variables instead of hard-coded colors.
The SDK sets them on :root and keeps them current.
| Token | Use |
|---|---|
--notch-text, --notch-text-2, --notch-text-3 |
primary, secondary, tertiary text |
--notch-accent, --notch-on-accent |
accent fill and text on it: your widget’s own color when the user gives it one in their theme (“A color per widget”), else the theme accent |
--notch-surface-1, -2, -3 |
layered fills (rows, inputs, hover) |
--notch-hairline |
dividers |
--notch-success, --notch-danger |
status |
--notch-font, --notch-text-scale |
font family and the user’s text size |
--notch-radius-sm, --notch-radius-md |
corner radii |
import "@notch-monster/plugin-sdk/ui.css" gives you a matching base: a
transparent body, the theme font, and styled button, button.primary,
inputs and .muted.
Do
- Keep the page transparent. The host draws the tile.
- Scale font sizes with
calc(… * var(--notch-text-scale)). - Animate only
transformandopacity, keep it brief, and respectprefers-reduced-motion. - Show something useful right away, and fill it in as data arrives.
- Handle an empty state, an offline state and a denied permission.
Don’t
- Run timers or animation loops while
visibilityisfalse. - Repeat your plugin’s name inside the tile. The header already shows it.
- Use the pill for anything that isn’t glanceable right now.