Making it feel native

Design guidelines

What makes a widget feel native to DeskDash: components first, tokens always, quiet motion, and restraint in density and decoration.

A widget feels native when a user cannot tell where DeskDash ends and your work begins: it follows their theme, it behaves like the widgets around it, and it stays quiet until looked at. Most of that comes from the platform for free, if you take what it offers. These are the habits that keep you on that path; each links to the guide that shows the how.

Components first

Build chrome from the dd-* components: the panel, the text roles, the buttons, chips, and meters. They carry the house look, react to themes, and auto-wire shared settings. Custom markup is for what is genuinely yours (the visualization, the art, the layout); the frame around it should be stock. And inside your own code, the second time you build the same shape, unify it rather than copying it.

Tokens, always

Every color, size, font, radius and duration comes from a --dd-* token. One literal hex value is all it takes to break theming; a user who switches to a light theme, or lets the automatic theme follow their wallpaper, will find your widget the one thing on the desktop that did not come along. The single carve-out is symbol art whose color is its identity (a cherry is red in every theme); keep that palette private to the art and tokenize everything around it.

Structure in HTML

Someone opening your index.html should see what the widget is: its regions, its parts, its shape. Keep the skeleton in markup, update values in place, and build DOM in JavaScript only where structure genuinely varies. It is a code-quality rule, but also a design one: widgets built this way tend to have a clear, calm hierarchy, because the hierarchy had to be written down.

Motion that stays out of the way

The desktop is a background, and nothing on it should move uninvited. DeskDash's own motion is opt-in and one-shot: entrance animations play once, controls transition their hover and press states subtly, and all of it respects the OS reduced-motion preference without you doing anything. Follow the same rules in your own motion: animate opacity and transform only, time it with the motion tokens, and reserve continuous animation for things that genuinely represent live data (a spectrum, a sweep second hand), never for decoration.

Respect the click-through desktop

At rest, the desktop is the user's. Capture input only where your widget is genuinely interactive, mark exactly what should feel solid, and let everything else pass through. A glanceable widget often needs no capture at all: ghost hover gives you presence (a highlight as the cursor passes) at zero cost to the desktop underneath. Widgets that grab more than they use are the fastest way to make a desktop feel broken.

Icons

Use the built-in glyphs for UI verbs (play, close, settings, refresh); they tint with the text color and follow the theme. Ship your own SVG for identity art, one file per icon, tinted when it should behave like text and full-color when the color is the point. Stateful, animated, or multi-part art is widget code, built with dd.ui.create and bound to your data, not a pile of swapped image files.

Density and restraint

A widget is furniture, not an app. It should answer its one question at a glance and otherwise stay quiet:

  • Prefer one clear readout over four small ones. If everything is emphasized, nothing is.
  • Use the house empty state (.dd-empty) and status line (.dd-status) instead of inventing chrome for "nothing here" and "last updated".
  • An idle state should look calm, not busy. Blank space on a desktop is a feature.
  • Test the widget over a bright wallpaper, a dark one, and a photo. The surface tokens handle this; hardcoded backgrounds do not.

Settings that respect the theme

Every setting is a question the user has to answer, so add them deliberately. Use the shared presets (panel style and accent color) rather than inventing your own variants of the same ideas, and do not add settings for things the theme already decides; a widget with its own font picker or corner-radius slider is fighting the system it lives in. The best settings change what the widget shows, not how DeskDash looks.