Folder Shelf

@sushindustries/ui

A desktop of folders that open into draggable windows, several at once, remembered between visits.

11 min read
View as MarkdownEdit on GitHub

Examples are the tab where the component is shown doing a job, not demonstrating a prop. The API tab already lists the props.

Viewport width
Phone22remthe floor, the narrowest this promises to work at
tanstacktanstack add https://adamjurek.com/r/tanstack/folder-shelf.jsonshadcnpnpm dlx shadcn@latest add https://adamjurek.com/r/shadcn/folder-shelf.json

Press Compare. The frames are real viewports, so a layout that breaks at 320 breaks here too rather than in somebody's hands.

In a page

import { DEVICES, FolderShelf, useDeviceKind, type ShelfEntry } from "@sushindustries/ui";

const entries: ShelfEntry[] = [
	{
		id: "packages",
		label: "Packages",
		children: [
			{ id: "ui", label: "ui", href: "/packages/ui" },
			{ id: "atoms", label: "atoms", href: "/packages/atoms" },
			{ id: "db", label: "db", href: "/packages/db" },
		],
	},
];

// The narrowest machine, so the server render and the first client frame
// agree - `useDeviceKind` is null until mounted.
function columnsFor(kind: ReturnType<typeof useDeviceKind>): number {
	return DEVICES.find((device) => device.kind === kind)?.columns ?? DEVICES[0].columns;
}

export function PackagesDesk() {
	const columns = columnsFor(useDeviceKind());

	return (
		<main className="container section">
			<FolderShelf
				entries={entries}
				label="Packages"
				columns={columns}
				rememberAs="sushindustries.packages-desk"
			/>
		</main>
	);
}
tsx

What this example is not

The columnsFor helper is the same lookup the site's own desktop does against DEVICES - the table the stylesheet's breakpoints are compiled from

  • so the icon grid agrees with the CSS about how many columns are on screen. A hardcoded number would still render, just not in step with it. rememberAs is given its own key because this shelf is not the site's main desktop - sharing the default key would mix its window state into the one on the home page.
UsesIconIconThe glyph set, generated from a Markdown table where every drawing carries its reason. One component, typed names, no icon font.@sushindustries/ui · contentContext MenuContext MenuOne menu, reachable by right-click, by long press, and by a button. Escape and arrow keys included.@sushindustries/ui · layoutDesk WindowDesk WindowA window you can drag, close and stack. Position is written to the element during a drag and to state only on release.@sushindustries/ui · layoutuseDeskStateuseDeskStateWhich windows are open, where they sit and what has been put away, remembered without breaking a server render.@sushindustries/ui · layout