Feat: Add workspace context actions
This commit is contained in:
@@ -82,6 +82,12 @@ export type SidebarItem = {
|
||||
meta?: string;
|
||||
};
|
||||
|
||||
export type WorkspaceStaticKind = "workspace" | "home" | "settings";
|
||||
|
||||
export type WorkspaceStaticItem = SidebarItem & {
|
||||
contextKind: WorkspaceStaticKind;
|
||||
};
|
||||
|
||||
export type WorkspaceTreeNode = {
|
||||
id: string;
|
||||
label: string;
|
||||
@@ -111,6 +117,69 @@ export type MobileBottomNavItem = {
|
||||
active?: boolean;
|
||||
};
|
||||
|
||||
export type WorkspaceContextMenuTarget = {
|
||||
id: string;
|
||||
label: string;
|
||||
kind: WorkspaceStaticKind | WorkspaceTreeNode["kind"];
|
||||
};
|
||||
|
||||
export type WorkspaceContextMenuAction = {
|
||||
id: string;
|
||||
label: string;
|
||||
tone?: "default" | "danger";
|
||||
shortcut?: WorkspaceContextMenuShortcut;
|
||||
children?: readonly WorkspaceContextMenuAction[];
|
||||
};
|
||||
|
||||
export type WorkspaceContextMenuShortcutModifier = "meta" | "alt" | "shift";
|
||||
|
||||
export type WorkspaceContextMenuShortcutKey = "b" | "c" | "d" | "delete" | "enter" | "f" | "m" | "r";
|
||||
|
||||
export type WorkspaceContextMenuShortcut = {
|
||||
modifiers?: readonly WorkspaceContextMenuShortcutModifier[];
|
||||
key: WorkspaceContextMenuShortcutKey;
|
||||
};
|
||||
|
||||
export type WorkspaceContextMenuSection = {
|
||||
id: string;
|
||||
label?: string;
|
||||
items: readonly WorkspaceContextMenuAction[];
|
||||
};
|
||||
|
||||
export const getWorkspaceContextMenuEyebrow = (target: WorkspaceContextMenuTarget): string => {
|
||||
switch (target.kind) {
|
||||
case "workspace":
|
||||
case "home":
|
||||
return "Workspace";
|
||||
case "settings":
|
||||
return "Configuration";
|
||||
case "folder":
|
||||
return "Folder";
|
||||
case "board":
|
||||
return "Board";
|
||||
case "doc":
|
||||
return "Doc";
|
||||
}
|
||||
};
|
||||
|
||||
export const createWorkspaceSurfaceTarget = (workspace: ActiveProject): WorkspaceContextMenuTarget => ({
|
||||
id: `workspace-${workspace.id}`,
|
||||
label: workspace.name,
|
||||
kind: "workspace",
|
||||
});
|
||||
|
||||
export const createWorkspaceStaticTarget = (item: WorkspaceStaticItem): WorkspaceContextMenuTarget => ({
|
||||
id: item.id,
|
||||
label: item.label,
|
||||
kind: item.contextKind,
|
||||
});
|
||||
|
||||
export const createWorkspaceTreeTarget = (node: WorkspaceTreeNode): WorkspaceContextMenuTarget => ({
|
||||
id: node.id,
|
||||
label: node.label,
|
||||
kind: node.kind,
|
||||
});
|
||||
|
||||
export type NotificationItem = {
|
||||
id: string;
|
||||
title: string;
|
||||
@@ -190,9 +259,9 @@ export const departmentItems: readonly DepartmentItem[] = [
|
||||
|
||||
// Sidebar and topbar scaffold data
|
||||
// These static entries stay pinned in both desktop and mobile workspace navigation.
|
||||
export const workspaceStaticItems: readonly SidebarItem[] = [
|
||||
{ id: "home", label: "Home", icon: Home, active: true },
|
||||
{ id: "workspace-settings", label: "Settings", icon: Settings },
|
||||
export const workspaceStaticItems: readonly WorkspaceStaticItem[] = [
|
||||
{ id: "home", label: "Home", icon: Home, active: true, contextKind: "home" },
|
||||
{ id: "workspace-settings", label: "Settings", icon: Settings, contextKind: "settings" },
|
||||
] as const;
|
||||
|
||||
// Freeform workspace tree scaffold: folders, boards, and docs are first-class siblings.
|
||||
@@ -240,6 +309,129 @@ export const mobileBottomNavItems: readonly MobileBottomNavItem[] = [
|
||||
{ id: "browse", label: "Browse", icon: Folder },
|
||||
] as const;
|
||||
|
||||
// Initial context-menu IA scaffold. Behavior wiring can evolve later, but the
|
||||
// target kinds and action grouping should stay shared across workspace surfaces.
|
||||
export const getWorkspaceContextMenuSections = (
|
||||
target: WorkspaceContextMenuTarget,
|
||||
): readonly WorkspaceContextMenuSection[] => {
|
||||
const createActions = [
|
||||
{ id: "new-folder", label: "New folder", shortcut: { modifiers: ["alt"], key: "f" } },
|
||||
{ id: "new-board", label: "New board", shortcut: { modifiers: ["alt"], key: "b" } },
|
||||
{ id: "new-doc", label: "New doc", shortcut: { modifiers: ["alt"], key: "d" } },
|
||||
] as const;
|
||||
|
||||
const createSubmenuAction = {
|
||||
id: "create",
|
||||
label: "Create",
|
||||
children: createActions,
|
||||
} as const;
|
||||
|
||||
switch (target.kind) {
|
||||
case "workspace":
|
||||
return [
|
||||
{
|
||||
id: "create",
|
||||
label: undefined,
|
||||
items: [createSubmenuAction],
|
||||
},
|
||||
{
|
||||
id: "workspace",
|
||||
label: undefined,
|
||||
items: [
|
||||
{ id: "rename-workspace", label: "Rename workspace", shortcut: { key: "enter" } },
|
||||
{ id: "copy-workspace-link", label: "Copy link", shortcut: { modifiers: ["meta"], key: "c" } },
|
||||
],
|
||||
},
|
||||
] as const;
|
||||
case "home":
|
||||
return [
|
||||
{
|
||||
id: "create",
|
||||
label: undefined,
|
||||
items: [createSubmenuAction],
|
||||
},
|
||||
{
|
||||
id: "workspace",
|
||||
label: undefined,
|
||||
items: [{ id: "open-home", label: "Open home", shortcut: { key: "enter" } }],
|
||||
},
|
||||
] as const;
|
||||
case "settings":
|
||||
return [
|
||||
{
|
||||
id: "settings",
|
||||
label: undefined,
|
||||
items: [
|
||||
{ id: "open-settings", label: "Open settings", shortcut: { key: "enter" } },
|
||||
{ id: "copy-settings-link", label: "Copy link", shortcut: { modifiers: ["meta"], key: "c" } },
|
||||
],
|
||||
},
|
||||
] as const;
|
||||
case "folder":
|
||||
return [
|
||||
{
|
||||
id: "open",
|
||||
items: [
|
||||
{ id: "open-folder", label: "Open folder", shortcut: { key: "enter" } },
|
||||
{ id: "rename-folder", label: "Rename", shortcut: { modifiers: ["meta"], key: "r" } },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "create",
|
||||
label: undefined,
|
||||
items: [createSubmenuAction],
|
||||
},
|
||||
{
|
||||
id: "organize",
|
||||
label: undefined,
|
||||
items: [
|
||||
{ id: "duplicate-folder", label: "Duplicate", shortcut: { modifiers: ["meta"], key: "d" } },
|
||||
{ id: "move-folder", label: "Move", shortcut: { modifiers: ["meta"], key: "m" } },
|
||||
{ id: "delete-folder", label: "Delete", shortcut: { modifiers: ["meta"], key: "delete" }, tone: "danger" },
|
||||
],
|
||||
},
|
||||
] as const;
|
||||
case "board":
|
||||
return [
|
||||
{
|
||||
id: "board",
|
||||
items: [
|
||||
{ id: "open-board", label: "Open board", shortcut: { key: "enter" } },
|
||||
{ id: "rename-board", label: "Rename", shortcut: { modifiers: ["meta"], key: "r" } },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "organize",
|
||||
label: undefined,
|
||||
items: [
|
||||
{ id: "duplicate-board", label: "Duplicate", shortcut: { modifiers: ["meta"], key: "d" } },
|
||||
{ id: "move-board", label: "Move", shortcut: { modifiers: ["meta"], key: "m" } },
|
||||
{ id: "delete-board", label: "Delete", shortcut: { modifiers: ["meta"], key: "delete" }, tone: "danger" },
|
||||
],
|
||||
},
|
||||
] as const;
|
||||
case "doc":
|
||||
return [
|
||||
{
|
||||
id: "doc",
|
||||
items: [
|
||||
{ id: "open-doc", label: "Open doc", shortcut: { key: "enter" } },
|
||||
{ id: "rename-doc", label: "Rename", shortcut: { modifiers: ["meta"], key: "r" } },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "organize",
|
||||
label: undefined,
|
||||
items: [
|
||||
{ id: "duplicate-doc", label: "Duplicate", shortcut: { modifiers: ["meta"], key: "d" } },
|
||||
{ id: "move-doc", label: "Move", shortcut: { modifiers: ["meta"], key: "m" } },
|
||||
{ id: "delete-doc", label: "Delete", shortcut: { modifiers: ["meta"], key: "delete" }, tone: "danger" },
|
||||
],
|
||||
},
|
||||
] as const;
|
||||
}
|
||||
};
|
||||
|
||||
export const topBarActions: readonly TopBarAction[] = [
|
||||
{ id: "search", label: "Search", icon: Search },
|
||||
] as const;
|
||||
|
||||
Reference in New Issue
Block a user