Each project is now a single sidebar row with its own icon and color that opens the project's coordinator conversation. The whole row drags to reorder. The row menu gains Customize for name, icon and color. Inside the coordinator conversation, an overview lists the project's agent threads that need the user, are running, or recently finished. Claude-Session: https://claude.ai/code/session_01Tgvrj34NMnaqvtgvruYQZZ Co-authored-by: Claude <noreply@anthropic.com>
107 lines
5.6 KiB
TypeScript
107 lines
5.6 KiB
TypeScript
import { OO_PALETTE } from "./oo-palette.js";
|
|
|
|
/**
|
|
* The icons and colors a project can wear in the sidebar. Ids are stored on the space; each
|
|
* platform maps an id to its own symbol (web: lucide, iOS: SF Symbols, Android: Ionicons).
|
|
*/
|
|
export const PROJECT_ICONS = [
|
|
{ id: "folder", ios: "folder", android: "folder-outline" },
|
|
{ id: "briefcase", ios: "briefcase", android: "briefcase-outline" },
|
|
{ id: "house", ios: "house", android: "home-outline" },
|
|
{ id: "heart", ios: "heart", android: "heart-outline" },
|
|
{ id: "star", ios: "star", android: "star-outline" },
|
|
{ id: "book", ios: "book", android: "book-outline" },
|
|
{ id: "code", ios: "chevron.left.forwardslash.chevron.right", android: "code-slash-outline" },
|
|
{ id: "terminal", ios: "terminal", android: "terminal-outline" },
|
|
{ id: "globe", ios: "globe", android: "globe-outline" },
|
|
{ id: "camera", ios: "camera", android: "camera-outline" },
|
|
{ id: "film", ios: "film", android: "film-outline" },
|
|
{ id: "music", ios: "music.note", android: "musical-notes-outline" },
|
|
{ id: "mic", ios: "mic", android: "mic-outline" },
|
|
{ id: "image", ios: "photo", android: "image-outline" },
|
|
{ id: "paintbrush", ios: "paintbrush", android: "brush-outline" },
|
|
{ id: "pencil", ios: "pencil", android: "pencil-outline" },
|
|
{ id: "cart", ios: "cart", android: "cart-outline" },
|
|
{ id: "bag", ios: "bag", android: "bag-outline" },
|
|
{ id: "money", ios: "banknote", android: "cash-outline" },
|
|
{ id: "chart", ios: "chart.bar", android: "bar-chart-outline" },
|
|
{ id: "trending", ios: "chart.line.uptrend.xyaxis", android: "trending-up-outline" },
|
|
{ id: "calendar", ios: "calendar", android: "calendar-outline" },
|
|
{ id: "clock", ios: "clock", android: "time-outline" },
|
|
{ id: "mail", ios: "envelope", android: "mail-outline" },
|
|
{ id: "chat", ios: "bubble.left", android: "chatbubble-outline" },
|
|
{ id: "people", ios: "person.2", android: "people-outline" },
|
|
{ id: "person", ios: "person", android: "person-outline" },
|
|
{ id: "school", ios: "graduationcap", android: "school-outline" },
|
|
{ id: "flask", ios: "flask", android: "flask-outline" },
|
|
{ id: "bulb", ios: "lightbulb", android: "bulb-outline" },
|
|
{ id: "bolt", ios: "bolt", android: "flash-outline" },
|
|
{ id: "flame", ios: "flame", android: "flame-outline" },
|
|
{ id: "leaf", ios: "leaf", android: "leaf-outline" },
|
|
{ id: "paw", ios: "pawprint", android: "paw-outline" },
|
|
{ id: "airplane", ios: "airplane", android: "airplane-outline" },
|
|
{ id: "car", ios: "car", android: "car-outline" },
|
|
{ id: "bicycle", ios: "bicycle", android: "bicycle-outline" },
|
|
{ id: "map", ios: "map", android: "map-outline" },
|
|
{ id: "pin", ios: "mappin", android: "location-outline" },
|
|
{ id: "fitness", ios: "dumbbell", android: "barbell-outline" },
|
|
{ id: "medical", ios: "cross.case", android: "medkit-outline" },
|
|
{ id: "food", ios: "fork.knife", android: "restaurant-outline" },
|
|
{ id: "coffee", ios: "cup.and.saucer", android: "cafe-outline" },
|
|
{ id: "game", ios: "gamecontroller", android: "game-controller-outline" },
|
|
{ id: "gift", ios: "gift", android: "gift-outline" },
|
|
{ id: "trophy", ios: "trophy", android: "trophy-outline" },
|
|
{ id: "flag", ios: "flag", android: "flag-outline" },
|
|
{ id: "key", ios: "key", android: "key-outline" },
|
|
{ id: "lock", ios: "lock", android: "lock-closed-outline" },
|
|
{ id: "shield", ios: "shield", android: "shield-outline" },
|
|
{ id: "gear", ios: "gearshape", android: "settings-outline" },
|
|
{ id: "hammer", ios: "hammer", android: "hammer-outline" },
|
|
{ id: "tools", ios: "wrench.and.screwdriver", android: "construct-outline" },
|
|
{ id: "cloud", ios: "cloud", android: "cloud-outline" },
|
|
{ id: "sun", ios: "sun.max", android: "sunny-outline" },
|
|
{ id: "moon", ios: "moon", android: "moon-outline" },
|
|
{ id: "box", ios: "cube", android: "cube-outline" },
|
|
{ id: "layers", ios: "square.stack.3d.up", android: "layers-outline" },
|
|
{ id: "server", ios: "server.rack", android: "server-outline" },
|
|
{ id: "phone", ios: "iphone", android: "phone-portrait-outline" },
|
|
{ id: "desktop", ios: "desktopcomputer", android: "desktop-outline" },
|
|
{ id: "news", ios: "newspaper", android: "newspaper-outline" },
|
|
{ id: "document", ios: "doc.text", android: "document-text-outline" },
|
|
{ id: "library", ios: "books.vertical", android: "library-outline" },
|
|
{ id: "sparkles", ios: "sparkles", android: "sparkles-outline" },
|
|
{ id: "target", ios: "target", android: "locate-outline" },
|
|
{ id: "infinity", ios: "infinity", android: "infinite-outline" },
|
|
] as const;
|
|
|
|
export type ProjectIconId = (typeof PROJECT_ICONS)[number]["id"];
|
|
export const DEFAULT_PROJECT_ICON: ProjectIconId = "folder";
|
|
|
|
/** Project colors are the Oo identity palette, so projects and bots read as one family. */
|
|
export const PROJECT_COLORS = OO_PALETTE.map((color) => ({
|
|
id: color.id,
|
|
hex: color.hex,
|
|
/** The icon drawn on this color, light or dark so it stays legible. */
|
|
ink: color.eyeColor,
|
|
}));
|
|
export const DEFAULT_PROJECT_COLOR = "violet";
|
|
|
|
export function isProjectIcon(value: string): value is ProjectIconId {
|
|
return PROJECT_ICONS.some((icon) => icon.id === value);
|
|
}
|
|
|
|
export function isProjectColor(value: string): boolean {
|
|
return PROJECT_COLORS.some((color) => color.id === value);
|
|
}
|
|
|
|
/** The look to draw, with defaults for projects that never chose one. */
|
|
export function projectLook(space: { icon?: string | null; color?: string | null }) {
|
|
const icon =
|
|
PROJECT_ICONS.find((item) => item.id === space.icon) ??
|
|
PROJECT_ICONS.find((item) => item.id === DEFAULT_PROJECT_ICON)!;
|
|
const color =
|
|
PROJECT_COLORS.find((item) => item.id === space.color) ??
|
|
PROJECT_COLORS.find((item) => item.id === DEFAULT_PROJECT_COLOR)!;
|
|
return { icon, color };
|
|
}
|