From eacbe4ab8761c26a29514b22f4a8209c7c2edb81 Mon Sep 17 00:00:00 2001 From: Benjamin Toby Date: Thu, 22 Oct 2026 10:18:35 +0100 Subject: [PATCH] Lead the files browser's folders with a tinted type icon Each folder row in /admin/files now opens with its type as an icon in a box tinted with its own hue (Bots ember, Workspaces teal, Computers cobalt, Media violet, MCP servers moss, Database amber), so the picker reads at a glance and the row's width goes to the name. The box carries the type as its title, so hovering still names it. --- .../files/(data)/storage-volume-icons.ts | 39 +++++++++++++++++++ .../files/(partials)/files-volume-row.tsx | 29 +++++++++++--- 2 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 src/pages/admin/files/(data)/storage-volume-icons.ts diff --git a/src/pages/admin/files/(data)/storage-volume-icons.ts b/src/pages/admin/files/(data)/storage-volume-icons.ts new file mode 100644 index 0000000..95f8373 --- /dev/null +++ b/src/pages/admin/files/(data)/storage-volume-icons.ts @@ -0,0 +1,39 @@ +import { + Bot, + Database, + Images, + Layers, + Monitor, + Plug, + type LucideIcon, +} from "lucide-react"; +import type { StorageVolume } from "@/src/utils/storage-volumes"; + +/** + * The icon each volume's folder rows lead with in the files browser's + * picker, imported one by one (never by name: a string icon ships every + * icon). Route-local so the shared, server-safe storage utils stay free + * of lucide. + */ +export const StorageVolumeIcons: Record = { + bots: Bot, + workspaces: Layers, + computers: Monitor, + media: Images, + mcp: Plug, + db: Database, +}; + +/** + * The tinted box each volume icon sits in: a soft wash and icon color from + * the hue palette, one hue per volume so the picker reads at a glance. + * Static class names only, so Tailwind keeps them. + */ +export const StorageVolumeIconClasses: Record = { + bots: "bg-hue-ember/15 text-hue-ember dark:bg-hue-ember/25", + workspaces: "bg-hue-teal/15 text-hue-teal dark:bg-hue-teal/25", + computers: "bg-hue-cobalt/15 text-hue-cobalt dark:bg-hue-cobalt/25", + media: "bg-hue-violet/15 text-hue-violet dark:bg-hue-violet/25", + mcp: "bg-hue-moss/15 text-hue-moss dark:bg-hue-moss/25", + db: "bg-hue-amber/15 text-hue-amber dark:bg-hue-amber/25", +}; diff --git a/src/pages/admin/files/(partials)/files-volume-row.tsx b/src/pages/admin/files/(partials)/files-volume-row.tsx index b5a3737..3d006dd 100644 --- a/src/pages/admin/files/(partials)/files-volume-row.tsx +++ b/src/pages/admin/files/(partials)/files-volume-row.tsx @@ -3,6 +3,10 @@ import Span from "@moduletrace/twui/layout/Span"; import { twMerge } from "tailwind-merge"; import type { StorageSpecOption } from "@/src/types"; import { storageSpecHref, storageVolumeLabel } from "@/src/utils/storage-volumes"; +import { + StorageVolumeIconClasses, + StorageVolumeIcons, +} from "../(data)/storage-volume-icons"; type Props = { option: StorageSpecOption; @@ -12,14 +16,19 @@ type Props = { /** * One folder in the files browser's picker: the bot, workspace, computer, - * media library, MCP server or database it is, named the way the crew - * names it. + * media library, MCP server or database it is, its type an icon in a tinted + * box and its name beside it. The box carries the type as its title, so + * hovering names it without spending the row's width on a label. */ export default function FilesVolumeRow({ option, selected, onOpen }: Props) { + const volume = option.spec.volume; + const Icon = StorageVolumeIcons[volume]; + const type_label = storageVolumeLabel({ volume }); + return ( { event.preventDefault(); @@ -31,9 +40,17 @@ export default function FilesVolumeRow({ option, selected, onOpen }: Props) { selected && "bg-ink/5 hover:bg-ink/5", )} > - {option.label} - - {storageVolumeLabel({ volume: option.spec.volume })} + + + + + {option.label} );