DesktopIcons
DesktopIcons renders a column of file-style shortcuts on the right edge of the desktop. Each shortcut maps to a system window whose appearsAsDesktopIcon predicate currently returns true. The library subscribes to storage change events so the column updates without polling.
Import
Section titled “Import”import { DesktopIcons, registerSystemWindow, type SystemWindowDef,} from "@react-ui-os/desktop";None. The component reads from the registered system window list and the active storage adapter.
Registering a system window
Section titled “Registering a system window”registerSystemWindow("downloads", { name: "Downloads", accent: "#7c66f5", defaultBounds: { w: 560, h: 420 }, content: DownloadsFolder, appearsAsDesktopIcon: (storage) => hasDownloads(storage),});The fields that control desktop-icon behavior:
| Field | Type | Description |
|---|---|---|
appearsAsDesktopIcon | boolean | ((storage: StorageAdapter) => boolean) | false (default) hides the icon. true always shows it. A function is the state-earned pattern: evaluated on each storage change. |
desktopIcon | ComponentType<{ size?: number }> | The icon painted on the shortcut. Defaults to a generic folder SVG. |
State-earned folders
Section titled “State-earned folders”The library follows the rule: a folder icon should not exist until the user has put something in it. Same shape a maker tool uses for Downloads and Presets:
registerSystemWindow("downloads", { name: "Downloads", defaultBounds: { w: 560, h: 420 }, content: DownloadsFolder, appearsAsDesktopIcon: (storage) => listDownloads(storage).length > 0,});- The first time
recordDownload(...)writes to storage, the icon fades in. - When the last entry is deleted, it fades out.
- The desktop never shows an empty-state pane for it, because the surface whose empty state you would design isn’t there yet.
Interaction
Section titled “Interaction”The column mirrors the macOS desktop selection model (the same one FileExplorer uses) and is an ARIA multi-select listbox (role="listbox" with aria-multiselectable, role="option" with aria-selected), so the whole column is one tab stop and assistive tech announces the active icon.
| Gesture / key | Effect |
|---|---|
| Single click | Selects the icon (accent highlight) |
| Cmd / Ctrl click | Toggles the icon in the selection |
| Shift click | Extends the selection from the active icon |
| Double click / Enter | Opens the matching system window via openWindow({ kind: "system", systemId }) |
| Right click | Selects the icon and opens its context menu (Open) |
| ArrowUp / ArrowDown | Moves the selection within the column |
| Home / End | Selects the first / last icon |
| Cmd / Ctrl + A | Selects every icon |
| Escape / click off | Clears the selection |
Marquee
Section titled “Marquee”A left drag that starts on the bare desktop (off any window, the dock, the menu bar, or an icon) sweeps a rubber-band rectangle and selects the icons it covers, the way macOS, Windows, and GNOME all do. Hold Shift, Cmd, or Ctrl as the drag starts to add the sweep to the current selection rather than replace it. Press Escape, or the right mouse button, mid-sweep to cancel it and restore the previous selection. After a sweep that selected something, keyboard focus lands on the column so the arrow keys work right away.
Position
Section titled “Position”DesktopIcons reserves the upper-right edge, below the menu bar when present. Stacked vertically with 18 px gaps between tiles.
See also
Section titled “See also”- FileExplorer is the typical body for a folder-style system window.
StorageAdapteris how the predicate reads state.