From eb3034d048beb210746999c13a8f065f48c67fdc Mon Sep 17 00:00:00 2001 From: Matt Toohey Date: Tue, 2 Jun 2026 14:34:03 +1000 Subject: [PATCH 01/28] refactor(staged): migrate UI to shadcn-svelte + Tailwind v4 Land the shadcn-svelte spike: adopt Tailwind v4, bridge design tokens to the Staged theme, and migrate bespoke chrome to shadcn-svelte primitives. - Add shadcn-svelte UI components (Button, Input, Select, Checkbox, Label, Badge, Dialog, AlertDialog, DropdownMenu, Popover, Alert, Tooltip, Context Menu, etc.) - Replace native inputs, bespoke menus, modals, banners, and theme selector with shadcn equivalents; delete the bespoke chrome they replace - Migrate toasts/alerts to svelte-sonner - Sweep Button and Tooltip usage across settings, branches, projects, sidebar, timeline, sessions, diff, notes, and actions - Consolidate icon imports onto @lucide/svelte and drop lucide-svelte Signed-off-by: Matt Toohey --- apps/staged/components.json | 20 + apps/staged/package.json | 14 +- apps/staged/src/App.svelte | 178 ++-- apps/staged/src/app.css | 157 ++++ .../alert-dialog/alert-dialog-action.svelte | 27 + .../alert-dialog/alert-dialog-cancel.svelte | 27 + .../alert-dialog/alert-dialog-content.svelte | 32 + .../alert-dialog-description.svelte | 20 + .../alert-dialog/alert-dialog-footer.svelte | 23 + .../alert-dialog/alert-dialog-header.svelte | 23 + .../ui/alert-dialog/alert-dialog-media.svelte | 23 + .../alert-dialog/alert-dialog-overlay.svelte | 20 + .../alert-dialog/alert-dialog-portal.svelte | 7 + .../ui/alert-dialog/alert-dialog-title.svelte | 20 + .../alert-dialog/alert-dialog-trigger.svelte | 7 + .../ui/alert-dialog/alert-dialog.svelte | 7 + .../lib/components/ui/alert-dialog/index.ts | 40 + .../components/ui/alert/alert-action.svelte | 20 + .../ui/alert/alert-description.svelte | 23 + .../components/ui/alert/alert-title.svelte | 23 + .../src/lib/components/ui/alert/alert.svelte | 44 + .../src/lib/components/ui/alert/index.ts | 17 + .../src/lib/components/ui/badge/badge.svelte | 50 + .../src/lib/components/ui/badge/index.ts | 2 + .../lib/components/ui/button/button.svelte | 89 ++ .../src/lib/components/ui/button/index.ts | 17 + .../components/ui/checkbox/checkbox.svelte | 39 + .../src/lib/components/ui/checkbox/index.ts | 6 + .../context-menu-checkbox-item.svelte | 41 + .../context-menu/context-menu-content.svelte | 28 + .../context-menu-group-heading.svelte | 21 + .../ui/context-menu/context-menu-group.svelte | 7 + .../ui/context-menu/context-menu-item.svelte | 27 + .../ui/context-menu/context-menu-label.svelte | 27 + .../context-menu/context-menu-portal.svelte | 7 + .../context-menu-radio-group.svelte | 16 + .../context-menu-radio-item.svelte | 35 + .../context-menu-separator.svelte | 17 + .../context-menu/context-menu-shortcut.svelte | 23 + .../context-menu-sub-content.svelte | 20 + .../context-menu-sub-trigger.svelte | 29 + .../ui/context-menu/context-menu-sub.svelte | 7 + .../context-menu/context-menu-trigger.svelte | 17 + .../ui/context-menu/context-menu.svelte | 7 + .../lib/components/ui/context-menu/index.ts | 52 ++ .../components/ui/dialog/dialog-close.svelte | 11 + .../ui/dialog/dialog-content.svelte | 48 + .../ui/dialog/dialog-description.svelte | 20 + .../components/ui/dialog/dialog-footer.svelte | 32 + .../components/ui/dialog/dialog-header.svelte | 20 + .../ui/dialog/dialog-overlay.svelte | 20 + .../components/ui/dialog/dialog-portal.svelte | 7 + .../components/ui/dialog/dialog-title.svelte | 17 + .../ui/dialog/dialog-trigger.svelte | 11 + .../lib/components/ui/dialog/dialog.svelte | 7 + .../src/lib/components/ui/dialog/index.ts | 34 + .../dropdown-menu-checkbox-group.svelte | 16 + .../dropdown-menu-checkbox-item.svelte | 44 + .../dropdown-menu-content.svelte | 31 + .../dropdown-menu-group-heading.svelte | 22 + .../dropdown-menu/dropdown-menu-group.svelte | 7 + .../dropdown-menu/dropdown-menu-item.svelte | 27 + .../dropdown-menu/dropdown-menu-label.svelte | 27 + .../dropdown-menu/dropdown-menu-portal.svelte | 7 + .../dropdown-menu-radio-group.svelte | 16 + .../dropdown-menu-radio-item.svelte | 34 + .../dropdown-menu-separator.svelte | 17 + .../dropdown-menu-shortcut.svelte | 23 + .../dropdown-menu-sub-content.svelte | 20 + .../dropdown-menu-sub-trigger.svelte | 29 + .../ui/dropdown-menu/dropdown-menu-sub.svelte | 7 + .../dropdown-menu-trigger.svelte | 7 + .../ui/dropdown-menu/dropdown-menu.svelte | 7 + .../lib/components/ui/dropdown-menu/index.ts | 54 ++ .../src/lib/components/ui/input/index.ts | 7 + .../src/lib/components/ui/input/input.svelte | 48 + .../src/lib/components/ui/label/index.ts | 7 + .../src/lib/components/ui/label/label.svelte | 20 + .../src/lib/components/ui/popover/index.ts | 28 + .../ui/popover/popover-close.svelte | 7 + .../ui/popover/popover-content.svelte | 31 + .../ui/popover/popover-description.svelte | 20 + .../ui/popover/popover-header.svelte | 20 + .../ui/popover/popover-portal.svelte | 7 + .../ui/popover/popover-title.svelte | 15 + .../ui/popover/popover-trigger.svelte | 17 + .../lib/components/ui/popover/popover.svelte | 7 + .../src/lib/components/ui/select/index.ts | 37 + .../ui/select/select-content.svelte | 45 + .../ui/select/select-group-heading.svelte | 21 + .../components/ui/select/select-group.svelte | 17 + .../components/ui/select/select-item.svelte | 38 + .../components/ui/select/select-label.svelte | 20 + .../components/ui/select/select-portal.svelte | 7 + .../select/select-scroll-down-button.svelte | 23 + .../ui/select/select-scroll-up-button.svelte | 23 + .../ui/select/select-separator.svelte | 18 + .../ui/select/select-trigger.svelte | 29 + .../lib/components/ui/select/select.svelte | 11 + .../src/lib/components/ui/separator/index.ts | 7 + .../components/ui/separator/separator.svelte | 23 + .../src/lib/components/ui/sonner/index.ts | 1 + .../lib/components/ui/sonner/sonner.svelte | 32 + .../lib/components/ui/toggle-group/index.ts | 10 + .../ui/toggle-group/toggle-group-item.svelte | 35 + .../ui/toggle-group/toggle-group.svelte | 75 ++ .../src/lib/components/ui/toggle/index.ts | 13 + .../lib/components/ui/toggle/toggle.svelte | 52 ++ .../src/lib/components/ui/tooltip/index.ts | 19 + .../ui/tooltip/tooltip-content.svelte | 52 ++ .../ui/tooltip/tooltip-portal.svelte | 7 + .../ui/tooltip/tooltip-provider.svelte | 7 + .../ui/tooltip/tooltip-trigger.svelte | 7 + .../lib/components/ui/tooltip/tooltip.svelte | 7 + apps/staged/src/lib/components/utils.ts | 13 + .../features/actions/ActionOutputModal.svelte | 395 +++----- .../lib/features/agents/AgentSelector.svelte | 183 +--- .../lib/features/branches/BranchCard.svelte | 425 ++++----- .../branches/BranchCardActionsBar.svelte | 882 ++++++++---------- .../branches/BranchCardHeaderInfo.svelte | 136 +-- .../branches/BranchCardPrButton.svelte | 303 +++--- .../BranchCardSessionManager.svelte.ts | 18 +- .../branches/ParentBranchCommitsHover.svelte | 19 +- .../RemoteWorkspaceStatusBadge.svelte | 5 +- .../branches/RemoteWorkspaceStatusView.svelte | 3 +- .../features/diff/DiffCommentsSection.svelte | 268 ++---- .../diff/DiffCommitSessionLauncher.svelte | 53 +- .../features/diff/DiffFileTreeSection.svelte | 155 +-- .../src/lib/features/diff/DiffModal.svelte | 242 ++--- .../features/diff/DiffReferenceSection.svelte | 95 +- .../lib/features/doctor/DoctorCheckRow.svelte | 101 +- .../src/lib/features/layout/TopBar.svelte | 138 +-- .../src/lib/features/notes/NoteModal.svelte | 387 +++----- .../lib/features/projects/AddRepoModal.svelte | 242 +---- .../lib/features/projects/BranchPicker.svelte | 39 +- .../features/projects/NewProjectForm.svelte | 84 +- .../features/projects/NewProjectModal.svelte | 144 +-- .../projects/ProjectContextMenu.svelte | 61 -- .../lib/features/projects/ProjectHome.svelte | 138 ++- .../features/projects/ProjectSection.svelte | 656 ++++++------- .../lib/features/projects/ProjectsList.svelte | 402 ++++---- .../features/projects/ProjectsSidebar.svelte | 378 ++++---- .../src/lib/features/projects/RepoCard.svelte | 185 ++-- .../features/projects/RepoConfigForm.svelte | 114 +-- .../features/projects/RepoSearchInput.svelte | 32 +- .../features/projects/ReposListView.svelte | 245 ++--- .../projects/SidebarPinnedRepo.svelte | 302 +++--- .../lib/features/projects/SplashScreen.svelte | 72 +- .../lib/features/projects/SubpathInput.svelte | 38 +- .../features/projects/SuggestedRepos.svelte | 45 +- .../projects/workspaceLifecycle.svelte.ts | 18 +- .../lib/features/sessions/HashtagInput.svelte | 5 +- .../features/sessions/ImageAttachment.svelte | 127 +-- .../features/sessions/NewSessionModal.svelte | 213 +---- .../features/sessions/PipelineSteps.svelte | 95 +- .../features/sessions/SessionLauncher.svelte | 226 ++--- .../lib/features/sessions/SessionModal.svelte | 876 ++++++----------- .../src/lib/features/sessions/hashtagItems.ts | 4 +- .../settings/ActionsPreferencesModal.svelte | 127 --- .../settings/ActionsSettingsPanel.svelte | 281 +++--- .../settings/DoctorSettingsPanel.svelte | 43 +- .../settings/GeneralSettingsPanel.svelte | 161 ++-- .../settings/KeyboardSettingsPanel.svelte | 134 +-- .../lib/features/settings/SettingsPage.svelte | 47 +- .../settings/ThemeSelectorModal.svelte | 249 ----- .../features/timeline/BranchTimeline.svelte | 342 +++---- .../features/timeline/ImageViewerModal.svelte | 210 ++--- .../timeline/TimelineContextMenu.svelte | 68 -- .../lib/features/timeline/TimelineRow.svelte | 750 ++++++++------- apps/staged/src/lib/shared/AlertCard.svelte | 122 --- .../src/lib/shared/ConfirmDialog.svelte | 292 ------ .../staged/src/lib/shared/DropdownMenu.svelte | 166 ---- apps/staged/src/lib/shared/FormButton.svelte | 97 -- apps/staged/src/lib/shared/FormInput.svelte | 45 - apps/staged/src/lib/shared/FormToggle.svelte | 109 --- .../src/lib/shared/InContentSearch.svelte | 137 ++- apps/staged/src/lib/shared/RepoBadge.svelte | 14 +- apps/staged/src/lib/shared/RepoLabel.svelte | 19 +- apps/staged/src/lib/shared/ToastHost.svelte | 39 - apps/staged/src/lib/shared/alerts.svelte.ts | 80 -- .../src/lib/shared/backdropDismiss.test.ts | 59 -- apps/staged/src/lib/shared/backdropDismiss.ts | 35 - .../src/lib/shared/menu/ContextMenu.svelte | 139 --- .../src/lib/shared/menu/MenuSurface.svelte | 487 ---------- .../src/lib/shared/menu/MoreMenu.svelte | 222 ----- .../src/lib/shared/menu/actions.test.ts | 47 - apps/staged/src/lib/shared/menu/actions.ts | 16 - .../src/lib/shared/menu/coordination.ts | 19 - apps/staged/src/lib/shared/menu/types.ts | 26 - apps/staged/tsconfig.app.json | 7 +- apps/staged/tsconfig.json | 9 +- apps/staged/vite.config.ts | 8 +- pnpm-lock.yaml | 407 +++++++- 193 files changed, 7442 insertions(+), 8981 deletions(-) create mode 100644 apps/staged/components.json create mode 100644 apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte create mode 100644 apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte create mode 100644 apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte create mode 100644 apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte create mode 100644 apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte create mode 100644 apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte create mode 100644 apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-media.svelte create mode 100644 apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte create mode 100644 apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-portal.svelte create mode 100644 apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte create mode 100644 apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte create mode 100644 apps/staged/src/lib/components/ui/alert-dialog/alert-dialog.svelte create mode 100644 apps/staged/src/lib/components/ui/alert-dialog/index.ts create mode 100644 apps/staged/src/lib/components/ui/alert/alert-action.svelte create mode 100644 apps/staged/src/lib/components/ui/alert/alert-description.svelte create mode 100644 apps/staged/src/lib/components/ui/alert/alert-title.svelte create mode 100644 apps/staged/src/lib/components/ui/alert/alert.svelte create mode 100644 apps/staged/src/lib/components/ui/alert/index.ts create mode 100644 apps/staged/src/lib/components/ui/badge/badge.svelte create mode 100644 apps/staged/src/lib/components/ui/badge/index.ts create mode 100644 apps/staged/src/lib/components/ui/button/button.svelte create mode 100644 apps/staged/src/lib/components/ui/button/index.ts create mode 100644 apps/staged/src/lib/components/ui/checkbox/checkbox.svelte create mode 100644 apps/staged/src/lib/components/ui/checkbox/index.ts create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu-content.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu-group-heading.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu-group.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu-item.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu-label.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu-portal.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu-radio-group.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu-radio-item.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu-separator.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu-shortcut.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu-sub-content.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu-sub.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu-trigger.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/context-menu.svelte create mode 100644 apps/staged/src/lib/components/ui/context-menu/index.ts create mode 100644 apps/staged/src/lib/components/ui/dialog/dialog-close.svelte create mode 100644 apps/staged/src/lib/components/ui/dialog/dialog-content.svelte create mode 100644 apps/staged/src/lib/components/ui/dialog/dialog-description.svelte create mode 100644 apps/staged/src/lib/components/ui/dialog/dialog-footer.svelte create mode 100644 apps/staged/src/lib/components/ui/dialog/dialog-header.svelte create mode 100644 apps/staged/src/lib/components/ui/dialog/dialog-overlay.svelte create mode 100644 apps/staged/src/lib/components/ui/dialog/dialog-portal.svelte create mode 100644 apps/staged/src/lib/components/ui/dialog/dialog-title.svelte create mode 100644 apps/staged/src/lib/components/ui/dialog/dialog-trigger.svelte create mode 100644 apps/staged/src/lib/components/ui/dialog/dialog.svelte create mode 100644 apps/staged/src/lib/components/ui/dialog/index.ts create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte create mode 100644 apps/staged/src/lib/components/ui/dropdown-menu/index.ts create mode 100644 apps/staged/src/lib/components/ui/input/index.ts create mode 100644 apps/staged/src/lib/components/ui/input/input.svelte create mode 100644 apps/staged/src/lib/components/ui/label/index.ts create mode 100644 apps/staged/src/lib/components/ui/label/label.svelte create mode 100644 apps/staged/src/lib/components/ui/popover/index.ts create mode 100644 apps/staged/src/lib/components/ui/popover/popover-close.svelte create mode 100644 apps/staged/src/lib/components/ui/popover/popover-content.svelte create mode 100644 apps/staged/src/lib/components/ui/popover/popover-description.svelte create mode 100644 apps/staged/src/lib/components/ui/popover/popover-header.svelte create mode 100644 apps/staged/src/lib/components/ui/popover/popover-portal.svelte create mode 100644 apps/staged/src/lib/components/ui/popover/popover-title.svelte create mode 100644 apps/staged/src/lib/components/ui/popover/popover-trigger.svelte create mode 100644 apps/staged/src/lib/components/ui/popover/popover.svelte create mode 100644 apps/staged/src/lib/components/ui/select/index.ts create mode 100644 apps/staged/src/lib/components/ui/select/select-content.svelte create mode 100644 apps/staged/src/lib/components/ui/select/select-group-heading.svelte create mode 100644 apps/staged/src/lib/components/ui/select/select-group.svelte create mode 100644 apps/staged/src/lib/components/ui/select/select-item.svelte create mode 100644 apps/staged/src/lib/components/ui/select/select-label.svelte create mode 100644 apps/staged/src/lib/components/ui/select/select-portal.svelte create mode 100644 apps/staged/src/lib/components/ui/select/select-scroll-down-button.svelte create mode 100644 apps/staged/src/lib/components/ui/select/select-scroll-up-button.svelte create mode 100644 apps/staged/src/lib/components/ui/select/select-separator.svelte create mode 100644 apps/staged/src/lib/components/ui/select/select-trigger.svelte create mode 100644 apps/staged/src/lib/components/ui/select/select.svelte create mode 100644 apps/staged/src/lib/components/ui/separator/index.ts create mode 100644 apps/staged/src/lib/components/ui/separator/separator.svelte create mode 100644 apps/staged/src/lib/components/ui/sonner/index.ts create mode 100644 apps/staged/src/lib/components/ui/sonner/sonner.svelte create mode 100644 apps/staged/src/lib/components/ui/toggle-group/index.ts create mode 100644 apps/staged/src/lib/components/ui/toggle-group/toggle-group-item.svelte create mode 100644 apps/staged/src/lib/components/ui/toggle-group/toggle-group.svelte create mode 100644 apps/staged/src/lib/components/ui/toggle/index.ts create mode 100644 apps/staged/src/lib/components/ui/toggle/toggle.svelte create mode 100644 apps/staged/src/lib/components/ui/tooltip/index.ts create mode 100644 apps/staged/src/lib/components/ui/tooltip/tooltip-content.svelte create mode 100644 apps/staged/src/lib/components/ui/tooltip/tooltip-portal.svelte create mode 100644 apps/staged/src/lib/components/ui/tooltip/tooltip-provider.svelte create mode 100644 apps/staged/src/lib/components/ui/tooltip/tooltip-trigger.svelte create mode 100644 apps/staged/src/lib/components/ui/tooltip/tooltip.svelte create mode 100644 apps/staged/src/lib/components/utils.ts delete mode 100644 apps/staged/src/lib/features/projects/ProjectContextMenu.svelte delete mode 100644 apps/staged/src/lib/features/settings/ActionsPreferencesModal.svelte delete mode 100644 apps/staged/src/lib/features/settings/ThemeSelectorModal.svelte delete mode 100644 apps/staged/src/lib/features/timeline/TimelineContextMenu.svelte delete mode 100644 apps/staged/src/lib/shared/AlertCard.svelte delete mode 100644 apps/staged/src/lib/shared/ConfirmDialog.svelte delete mode 100644 apps/staged/src/lib/shared/DropdownMenu.svelte delete mode 100644 apps/staged/src/lib/shared/FormButton.svelte delete mode 100644 apps/staged/src/lib/shared/FormInput.svelte delete mode 100644 apps/staged/src/lib/shared/FormToggle.svelte delete mode 100644 apps/staged/src/lib/shared/ToastHost.svelte delete mode 100644 apps/staged/src/lib/shared/alerts.svelte.ts delete mode 100644 apps/staged/src/lib/shared/backdropDismiss.test.ts delete mode 100644 apps/staged/src/lib/shared/backdropDismiss.ts delete mode 100644 apps/staged/src/lib/shared/menu/ContextMenu.svelte delete mode 100644 apps/staged/src/lib/shared/menu/MenuSurface.svelte delete mode 100644 apps/staged/src/lib/shared/menu/MoreMenu.svelte delete mode 100644 apps/staged/src/lib/shared/menu/actions.test.ts delete mode 100644 apps/staged/src/lib/shared/menu/actions.ts delete mode 100644 apps/staged/src/lib/shared/menu/coordination.ts delete mode 100644 apps/staged/src/lib/shared/menu/types.ts diff --git a/apps/staged/components.json b/apps/staged/components.json new file mode 100644 index 000000000..cff913d0f --- /dev/null +++ b/apps/staged/components.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://shadcn-svelte.com/schema.json", + "tailwind": { + "css": "src/app.css", + "baseColor": "neutral" + }, + "aliases": { + "components": "$lib/components", + "utils": "$lib/components/utils", + "ui": "$lib/components/ui", + "hooks": "$lib/components/hooks", + "lib": "$lib" + }, + "typescript": true, + "registry": "https://shadcn-svelte.com/registry", + "style": "vega", + "iconLibrary": "lucide", + "menuColor": "default", + "menuAccent": "subtle" +} diff --git a/apps/staged/package.json b/apps/staged/package.json index 50588dec0..5c53b9e00 100644 --- a/apps/staged/package.json +++ b/apps/staged/package.json @@ -5,7 +5,6 @@ "type": "module", "scripts": { "dev": "vite", - "build": "vite build", "preview": "vite preview", "check": "svelte-check --tsconfig ./tsconfig.app.json --fail-on-warnings && tsc -p tsconfig.node.json", @@ -19,14 +18,26 @@ "test:watch": "vitest" }, "devDependencies": { + "@fontsource-variable/inter": "^5.2.8", + "@internationalized/date": "^3.12.2", + "@lucide/svelte": "^1.17.0", "@sveltejs/vite-plugin-svelte": "^6.2.1", + "@tailwindcss/vite": "^4.0.0", "@tauri-apps/cli": "^2.10.0", "@tsconfig/svelte": "^5.0.6", "@types/node": "^24.10.1", + "bits-ui": "^2.18.1", + "clsx": "^2.1.1", "prettier": "^3.7.4", "prettier-plugin-svelte": "^3.4.1", + "shadcn-svelte": "^1.2.7", "svelte": "^5.46.4", "svelte-check": "^4.3.4", + "svelte-sonner": "^1.1.1", + "tailwind-merge": "^3.6.0", + "tailwind-variants": "^3.2.2", + "tailwindcss": "^4.0.0", + "tw-animate-css": "^1.4.0", "typescript": "~5.9.3", "vite": "^7.2.4", "vitest": "^4.0.18" @@ -41,7 +52,6 @@ "@tauri-apps/plugin-store": "^2.4.2", "@tauri-apps/plugin-updater": "^2.10.0", "ansi-to-html": "^0.7.2", - "lucide-svelte": "^0.577.0", "marked": "^17.0.1", "sanitize-html": "^2.17.0", "shiki": "^3.20.0" diff --git a/apps/staged/src/App.svelte b/apps/staged/src/App.svelte index b9d61ba49..d5c237946 100644 --- a/apps/staged/src/App.svelte +++ b/apps/staged/src/App.svelte @@ -14,7 +14,9 @@ import ReposListView from './lib/features/projects/ReposListView.svelte'; import SessionLauncher from './lib/features/sessions/SessionLauncher.svelte'; import SettingsPage from './lib/features/settings/SettingsPage.svelte'; - import ToastHost from './lib/shared/ToastHost.svelte'; + import { Toaster } from '$lib/components/ui/sonner'; + import { Button } from '$lib/components/ui/button'; + import { TooltipProvider } from '$lib/components/ui/tooltip'; import { preferences, initPreferences, @@ -442,80 +444,82 @@ {#if preferences.loaded} - {#if storeIncompat && storeIncompat.kind === 'needs_reset'} -
-
-
-
-

Update Required

- v{storeIncompat.appVersion} -
-

- Staged beta updates can require backwards-incompatible changes. The info stored by - Staged (session history, notes) will be cleared, but your - git repos and branches are not affected. -

- -
- {:else} -
- -
- {#if storeError} -
-

{storeError}

-
- {:else if navigation.activeView === 'settings'} - - {:else if reposUiEnabled && navigation.showReposList} - - {:else if navigation.selectedProjectId} - - {:else} - - {/if} -
-
- {/if} - - {#if showSessionLab} - (showSessionLab = false)} /> - {/if} - - + + {:else} +
+ +
+ {#if storeError} +
+

{storeError}

+
+ {:else if navigation.activeView === 'settings'} + + {:else if reposUiEnabled && navigation.showReposList} + + {:else if navigation.selectedProjectId} + + {:else} + + {/if} +
+
+ {/if} + + {#if showSessionLab} + (showSessionLab = false)} /> + {/if} + + + {/if} diff --git a/apps/staged/src/app.css b/apps/staged/src/app.css index 7738112fd..b2c40ded6 100644 --- a/apps/staged/src/app.css +++ b/apps/staged/src/app.css @@ -1,3 +1,11 @@ +@import 'tailwindcss'; +@import 'tw-animate-css'; +@import 'shadcn-svelte/tailwind.css'; +@import '@fontsource-variable/inter'; +/*---break--- + */ +@custom-variant dark (&:is(.dark *)); + /** * Global styles for Staged * @@ -111,6 +119,57 @@ -moz-osx-font-smoothing: grayscale; } +/* ── Token bridge: shadcn-svelte semantic tokens → Staged adaptive tokens. + * Step 3 of the shadcn-svelte spike. The right-hand sides resolve through + * Staged's :root (above), which createAdaptiveTheme() rewrites per Shiki + * theme, so the cascade carries theme switches into shadcn primitives + * without any JS bridge. The @theme inline block below preserves the + * existing `--color-X → var(--X)` mapping shadcn-svelte's init wrote, so + * Tailwind utilities (`bg-background`, `text-primary-foreground`, …) + * inherit through this :root indirection unchanged. ── */ +:root { + --background: var(--bg-primary); + --foreground: var(--text-primary); + --card: var(--bg-elevated); + --card-foreground: var(--text-primary); + --popover: var(--bg-elevated); + --popover-foreground: var(--text-primary); + --primary: var(--ui-accent); + --primary-foreground: var( + --bg-deepest + ); /* contrast on light Shiki themes is the spike's open question */ + --secondary: var(--bg-elevated); + --secondary-foreground: var(--text-primary); + --muted: var(--bg-hover); + --muted-foreground: var(--text-muted); + --accent: var(--bg-hover); + --accent-foreground: var(--text-primary); + --destructive: var(--ui-danger); + --destructive-foreground: var(--text-primary); + --border: var(--border-muted); + --input: var(--border-muted); + --ring: var(--border-emphasis); + --radius: 4px; /* invented — Staged has no radius token */ + + /* ── Gaps: shadcn tokens with no Staged analogue. Button (Step 4) does not + * consume these; later shadcn primitives (sidebar, chart) will force a + * decision — extend theme.ts or alias statically. Left as the oklch + * defaults shadcn-svelte init wrote so the file still type-checks. ── */ + --chart-1: oklch(0.87 0 0); + --chart-2: oklch(0.556 0 0); + --chart-3: oklch(0.439 0 0); + --chart-4: oklch(0.371 0 0); + --chart-5: oklch(0.269 0 0); + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); +} + html, body { overflow: hidden; @@ -171,3 +230,101 @@ mark.search-match-current { margin-right: 2px; flex-shrink: 0; } + +/*---break--- + */ + +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.205 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.205 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.922 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.556 0 0); + --chart-1: oklch(0.87 0 0); + --chart-2: oklch(0.556 0 0); + --chart-3: oklch(0.439 0 0); + --chart-4: oklch(0.371 0 0); + --chart-5: oklch(0.269 0 0); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.556 0 0); +} + +/*---break--- + */ + +@theme inline { + --font-sans: 'Inter Variable', sans-serif; + --color-sidebar-ring: var(--sidebar-ring); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar: var(--sidebar); + --color-chart-5: var(--chart-5); + --color-chart-4: var(--chart-4); + --color-chart-3: var(--chart-3); + --color-chart-2: var(--chart-2); + --color-chart-1: var(--chart-1); + --color-ring: var(--ring); + --color-input: var(--input); + --color-border: var(--border); + --color-destructive-foreground: var(--destructive-foreground); + --color-destructive: var(--destructive); + --color-accent-foreground: var(--accent-foreground); + --color-accent: var(--accent); + --color-muted-foreground: var(--muted-foreground); + --color-muted: var(--muted); + --color-secondary-foreground: var(--secondary-foreground); + --color-secondary: var(--secondary); + --color-primary-foreground: var(--primary-foreground); + --color-primary: var(--primary); + --color-popover-foreground: var(--popover-foreground); + --color-popover: var(--popover); + --color-card-foreground: var(--card-foreground); + --color-card: var(--card); + --color-foreground: var(--foreground); + --color-background: var(--background); + --radius-sm: calc(var(--radius) * 0.6); + --radius-md: calc(var(--radius) * 0.8); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) * 1.4); + --radius-2xl: calc(var(--radius) * 1.8); + --radius-3xl: calc(var(--radius) * 2.2); + --radius-4xl: calc(var(--radius) * 2.6); +} + +/*---break--- + */ + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } + html { + @apply font-sans; + } +} diff --git a/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte new file mode 100644 index 000000000..fbb3f768a --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte @@ -0,0 +1,27 @@ + + + diff --git a/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte new file mode 100644 index 000000000..322b143a3 --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte @@ -0,0 +1,27 @@ + + + diff --git a/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte new file mode 100644 index 000000000..1e582a049 --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte @@ -0,0 +1,32 @@ + + + + + + diff --git a/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte new file mode 100644 index 000000000..2ac5cb436 --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte @@ -0,0 +1,20 @@ + + + diff --git a/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte new file mode 100644 index 000000000..c64bc3fac --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte @@ -0,0 +1,23 @@ + + +
+ {@render children?.()} +
diff --git a/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte new file mode 100644 index 000000000..a462f3ed0 --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte @@ -0,0 +1,23 @@ + + +
+ {@render children?.()} +
diff --git a/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-media.svelte b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-media.svelte new file mode 100644 index 000000000..f7c0f9823 --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-media.svelte @@ -0,0 +1,23 @@ + + +
+ {@render children?.()} +
diff --git a/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte new file mode 100644 index 000000000..c20edb260 --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte @@ -0,0 +1,20 @@ + + + diff --git a/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-portal.svelte b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-portal.svelte new file mode 100644 index 000000000..fad8f9ef9 --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte new file mode 100644 index 000000000..d69f7abf5 --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte @@ -0,0 +1,20 @@ + + + diff --git a/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte new file mode 100644 index 000000000..5566a6977 --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog.svelte b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog.svelte new file mode 100644 index 000000000..94f27e4f4 --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert-dialog/alert-dialog.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/alert-dialog/index.ts b/apps/staged/src/lib/components/ui/alert-dialog/index.ts new file mode 100644 index 000000000..5adb4d0d1 --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert-dialog/index.ts @@ -0,0 +1,40 @@ +import Root from './alert-dialog.svelte'; +import Portal from './alert-dialog-portal.svelte'; +import Trigger from './alert-dialog-trigger.svelte'; +import Title from './alert-dialog-title.svelte'; +import Action from './alert-dialog-action.svelte'; +import Cancel from './alert-dialog-cancel.svelte'; +import Footer from './alert-dialog-footer.svelte'; +import Header from './alert-dialog-header.svelte'; +import Overlay from './alert-dialog-overlay.svelte'; +import Content from './alert-dialog-content.svelte'; +import Description from './alert-dialog-description.svelte'; +import Media from './alert-dialog-media.svelte'; + +export { + Root, + Title, + Action, + Cancel, + Portal, + Footer, + Header, + Trigger, + Overlay, + Content, + Description, + Media, + // + Root as AlertDialog, + Title as AlertDialogTitle, + Action as AlertDialogAction, + Cancel as AlertDialogCancel, + Portal as AlertDialogPortal, + Footer as AlertDialogFooter, + Header as AlertDialogHeader, + Trigger as AlertDialogTrigger, + Overlay as AlertDialogOverlay, + Content as AlertDialogContent, + Description as AlertDialogDescription, + Media as AlertDialogMedia, +}; diff --git a/apps/staged/src/lib/components/ui/alert/alert-action.svelte b/apps/staged/src/lib/components/ui/alert/alert-action.svelte new file mode 100644 index 000000000..fb92bdc0f --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert/alert-action.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/apps/staged/src/lib/components/ui/alert/alert-description.svelte b/apps/staged/src/lib/components/ui/alert/alert-description.svelte new file mode 100644 index 000000000..9b08f6ccc --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert/alert-description.svelte @@ -0,0 +1,23 @@ + + +
+ {@render children?.()} +
diff --git a/apps/staged/src/lib/components/ui/alert/alert-title.svelte b/apps/staged/src/lib/components/ui/alert/alert-title.svelte new file mode 100644 index 000000000..06f602dbd --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert/alert-title.svelte @@ -0,0 +1,23 @@ + + +
svg]/alert:col-start-2 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3', + className + )} + {...restProps} +> + {@render children?.()} +
diff --git a/apps/staged/src/lib/components/ui/alert/alert.svelte b/apps/staged/src/lib/components/ui/alert/alert.svelte new file mode 100644 index 000000000..4479d74bf --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert/alert.svelte @@ -0,0 +1,44 @@ + + + + + diff --git a/apps/staged/src/lib/components/ui/alert/index.ts b/apps/staged/src/lib/components/ui/alert/index.ts new file mode 100644 index 000000000..9bd4a42fc --- /dev/null +++ b/apps/staged/src/lib/components/ui/alert/index.ts @@ -0,0 +1,17 @@ +import Root from './alert.svelte'; +import Description from './alert-description.svelte'; +import Title from './alert-title.svelte'; +import Action from './alert-action.svelte'; +export { alertVariants, type AlertVariant } from './alert.svelte'; + +export { + Root, + Description, + Title, + Action, + // + Root as Alert, + Description as AlertDescription, + Title as AlertTitle, + Action as AlertAction, +}; diff --git a/apps/staged/src/lib/components/ui/badge/badge.svelte b/apps/staged/src/lib/components/ui/badge/badge.svelte new file mode 100644 index 000000000..556647793 --- /dev/null +++ b/apps/staged/src/lib/components/ui/badge/badge.svelte @@ -0,0 +1,50 @@ + + + + + + {@render children?.()} + diff --git a/apps/staged/src/lib/components/ui/badge/index.ts b/apps/staged/src/lib/components/ui/badge/index.ts new file mode 100644 index 000000000..f05fb87fa --- /dev/null +++ b/apps/staged/src/lib/components/ui/badge/index.ts @@ -0,0 +1,2 @@ +export { default as Badge } from './badge.svelte'; +export { badgeVariants, type BadgeVariant } from './badge.svelte'; diff --git a/apps/staged/src/lib/components/ui/button/button.svelte b/apps/staged/src/lib/components/ui/button/button.svelte new file mode 100644 index 000000000..4122fdeac --- /dev/null +++ b/apps/staged/src/lib/components/ui/button/button.svelte @@ -0,0 +1,89 @@ + + + + +{#if href} + + {@render children?.()} + +{:else} + +{/if} diff --git a/apps/staged/src/lib/components/ui/button/index.ts b/apps/staged/src/lib/components/ui/button/index.ts new file mode 100644 index 000000000..66c1087b8 --- /dev/null +++ b/apps/staged/src/lib/components/ui/button/index.ts @@ -0,0 +1,17 @@ +import Root, { + type ButtonProps, + type ButtonSize, + type ButtonVariant, + buttonVariants, +} from './button.svelte'; + +export { + Root, + type ButtonProps as Props, + // + Root as Button, + buttonVariants, + type ButtonProps, + type ButtonSize, + type ButtonVariant, +}; diff --git a/apps/staged/src/lib/components/ui/checkbox/checkbox.svelte b/apps/staged/src/lib/components/ui/checkbox/checkbox.svelte new file mode 100644 index 000000000..17a64de45 --- /dev/null +++ b/apps/staged/src/lib/components/ui/checkbox/checkbox.svelte @@ -0,0 +1,39 @@ + + + + {#snippet children({ checked, indeterminate })} +
+ {#if checked} + + {:else if indeterminate} + + {/if} +
+ {/snippet} +
diff --git a/apps/staged/src/lib/components/ui/checkbox/index.ts b/apps/staged/src/lib/components/ui/checkbox/index.ts new file mode 100644 index 000000000..ba3b7d76a --- /dev/null +++ b/apps/staged/src/lib/components/ui/checkbox/index.ts @@ -0,0 +1,6 @@ +import Root from './checkbox.svelte'; +export { + Root, + // + Root as Checkbox, +}; diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte new file mode 100644 index 000000000..d9ee07bdf --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte @@ -0,0 +1,41 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.()} + {/snippet} + diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu-content.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu-content.svelte new file mode 100644 index 000000000..c80271eb4 --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu-content.svelte @@ -0,0 +1,28 @@ + + + + + diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu-group-heading.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu-group-heading.svelte new file mode 100644 index 000000000..98f5cb558 --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu-group-heading.svelte @@ -0,0 +1,21 @@ + + + diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu-group.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu-group.svelte new file mode 100644 index 000000000..19f694bb5 --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu-group.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu-item.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu-item.svelte new file mode 100644 index 000000000..931f92a3c --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu-item.svelte @@ -0,0 +1,27 @@ + + + diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu-label.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu-label.svelte new file mode 100644 index 000000000..1cb2c8287 --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu-label.svelte @@ -0,0 +1,27 @@ + + +
+ {@render children?.()} +
diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu-portal.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu-portal.svelte new file mode 100644 index 000000000..2897cc0b4 --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu-radio-group.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu-radio-group.svelte new file mode 100644 index 000000000..b1abdf318 --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu-radio-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu-radio-item.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu-radio-item.svelte new file mode 100644 index 000000000..87ccff39a --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu-radio-item.svelte @@ -0,0 +1,35 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.({ checked })} + {/snippet} + diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu-separator.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu-separator.svelte new file mode 100644 index 000000000..b0a519810 --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu-separator.svelte @@ -0,0 +1,17 @@ + + + diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu-shortcut.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu-shortcut.svelte new file mode 100644 index 000000000..63da87336 --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu-shortcut.svelte @@ -0,0 +1,23 @@ + + + + {@render children?.()} + diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu-sub-content.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu-sub-content.svelte new file mode 100644 index 000000000..67b87b216 --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu-sub-content.svelte @@ -0,0 +1,20 @@ + + + diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte new file mode 100644 index 000000000..0c73857bb --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte @@ -0,0 +1,29 @@ + + + + {@render children?.()} + + diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu-sub.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu-sub.svelte new file mode 100644 index 000000000..0ba70c9b6 --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu-sub.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu-trigger.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu-trigger.svelte new file mode 100644 index 000000000..2948d838c --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu-trigger.svelte @@ -0,0 +1,17 @@ + + + diff --git a/apps/staged/src/lib/components/ui/context-menu/context-menu.svelte b/apps/staged/src/lib/components/ui/context-menu/context-menu.svelte new file mode 100644 index 000000000..4b6908e23 --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/context-menu.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/context-menu/index.ts b/apps/staged/src/lib/components/ui/context-menu/index.ts new file mode 100644 index 000000000..77acbbc4e --- /dev/null +++ b/apps/staged/src/lib/components/ui/context-menu/index.ts @@ -0,0 +1,52 @@ +import Root from './context-menu.svelte'; +import Sub from './context-menu-sub.svelte'; +import Portal from './context-menu-portal.svelte'; +import Trigger from './context-menu-trigger.svelte'; +import Group from './context-menu-group.svelte'; +import RadioGroup from './context-menu-radio-group.svelte'; +import Item from './context-menu-item.svelte'; +import GroupHeading from './context-menu-group-heading.svelte'; +import Content from './context-menu-content.svelte'; +import Shortcut from './context-menu-shortcut.svelte'; +import RadioItem from './context-menu-radio-item.svelte'; +import Separator from './context-menu-separator.svelte'; +import SubContent from './context-menu-sub-content.svelte'; +import SubTrigger from './context-menu-sub-trigger.svelte'; +import CheckboxItem from './context-menu-checkbox-item.svelte'; +import Label from './context-menu-label.svelte'; + +export { + Root, + Sub, + Portal, + Item, + GroupHeading, + Label, + Group, + Trigger, + Content, + Shortcut, + Separator, + RadioItem, + SubContent, + SubTrigger, + RadioGroup, + CheckboxItem, + // + Root as ContextMenu, + Sub as ContextMenuSub, + Portal as ContextMenuPortal, + Item as ContextMenuItem, + GroupHeading as ContextMenuGroupHeading, + Group as ContextMenuGroup, + Content as ContextMenuContent, + Trigger as ContextMenuTrigger, + Shortcut as ContextMenuShortcut, + RadioItem as ContextMenuRadioItem, + Separator as ContextMenuSeparator, + RadioGroup as ContextMenuRadioGroup, + SubContent as ContextMenuSubContent, + SubTrigger as ContextMenuSubTrigger, + CheckboxItem as ContextMenuCheckboxItem, + Label as ContextMenuLabel, +}; diff --git a/apps/staged/src/lib/components/ui/dialog/dialog-close.svelte b/apps/staged/src/lib/components/ui/dialog/dialog-close.svelte new file mode 100644 index 000000000..2f313f6f6 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dialog/dialog-close.svelte @@ -0,0 +1,11 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dialog/dialog-content.svelte b/apps/staged/src/lib/components/ui/dialog/dialog-content.svelte new file mode 100644 index 000000000..ae078876b --- /dev/null +++ b/apps/staged/src/lib/components/ui/dialog/dialog-content.svelte @@ -0,0 +1,48 @@ + + + + + + {@render children?.()} + {#if showCloseButton} + + {#snippet child({ props })} + + {/snippet} + + {/if} + + diff --git a/apps/staged/src/lib/components/ui/dialog/dialog-description.svelte b/apps/staged/src/lib/components/ui/dialog/dialog-description.svelte new file mode 100644 index 000000000..12f271206 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dialog/dialog-description.svelte @@ -0,0 +1,20 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dialog/dialog-footer.svelte b/apps/staged/src/lib/components/ui/dialog/dialog-footer.svelte new file mode 100644 index 000000000..ae94220ad --- /dev/null +++ b/apps/staged/src/lib/components/ui/dialog/dialog-footer.svelte @@ -0,0 +1,32 @@ + + +
+ {@render children?.()} + {#if showCloseButton} + + {#snippet child({ props })} + + {/snippet} + + {/if} +
diff --git a/apps/staged/src/lib/components/ui/dialog/dialog-header.svelte b/apps/staged/src/lib/components/ui/dialog/dialog-header.svelte new file mode 100644 index 000000000..29983f64b --- /dev/null +++ b/apps/staged/src/lib/components/ui/dialog/dialog-header.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/apps/staged/src/lib/components/ui/dialog/dialog-overlay.svelte b/apps/staged/src/lib/components/ui/dialog/dialog-overlay.svelte new file mode 100644 index 000000000..f17b74dcf --- /dev/null +++ b/apps/staged/src/lib/components/ui/dialog/dialog-overlay.svelte @@ -0,0 +1,20 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dialog/dialog-portal.svelte b/apps/staged/src/lib/components/ui/dialog/dialog-portal.svelte new file mode 100644 index 000000000..4a9048a8d --- /dev/null +++ b/apps/staged/src/lib/components/ui/dialog/dialog-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dialog/dialog-title.svelte b/apps/staged/src/lib/components/ui/dialog/dialog-title.svelte new file mode 100644 index 000000000..5889f5cc0 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dialog/dialog-title.svelte @@ -0,0 +1,17 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dialog/dialog-trigger.svelte b/apps/staged/src/lib/components/ui/dialog/dialog-trigger.svelte new file mode 100644 index 000000000..434c574e1 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dialog/dialog-trigger.svelte @@ -0,0 +1,11 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dialog/dialog.svelte b/apps/staged/src/lib/components/ui/dialog/dialog.svelte new file mode 100644 index 000000000..88b4799ad --- /dev/null +++ b/apps/staged/src/lib/components/ui/dialog/dialog.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dialog/index.ts b/apps/staged/src/lib/components/ui/dialog/index.ts new file mode 100644 index 000000000..d2dd4a373 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dialog/index.ts @@ -0,0 +1,34 @@ +import Root from './dialog.svelte'; +import Portal from './dialog-portal.svelte'; +import Title from './dialog-title.svelte'; +import Footer from './dialog-footer.svelte'; +import Header from './dialog-header.svelte'; +import Overlay from './dialog-overlay.svelte'; +import Content from './dialog-content.svelte'; +import Description from './dialog-description.svelte'; +import Trigger from './dialog-trigger.svelte'; +import Close from './dialog-close.svelte'; + +export { + Root, + Title, + Portal, + Footer, + Header, + Trigger, + Overlay, + Content, + Description, + Close, + // + Root as Dialog, + Title as DialogTitle, + Portal as DialogPortal, + Footer as DialogFooter, + Header as DialogHeader, + Trigger as DialogTrigger, + Overlay as DialogOverlay, + Content as DialogContent, + Description as DialogDescription, + Close as DialogClose, +}; diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte new file mode 100644 index 000000000..6b4d728f0 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte new file mode 100644 index 000000000..022670832 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte @@ -0,0 +1,44 @@ + + + + {#snippet children({ checked, indeterminate })} + + {#if indeterminate} + + {:else if checked} + + {/if} + + {@render childrenProp?.()} + {/snippet} + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte new file mode 100644 index 000000000..f1df8a5b9 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte @@ -0,0 +1,31 @@ + + + + + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte new file mode 100644 index 000000000..cf8bca9ec --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte @@ -0,0 +1,22 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte new file mode 100644 index 000000000..bf972af46 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte new file mode 100644 index 000000000..ff70760e4 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte @@ -0,0 +1,27 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte new file mode 100644 index 000000000..7ad9f8728 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte @@ -0,0 +1,27 @@ + + +
+ {@render children?.()} +
diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte new file mode 100644 index 000000000..130c20f79 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte new file mode 100644 index 000000000..74523661b --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte new file mode 100644 index 000000000..daf69402d --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte @@ -0,0 +1,34 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.({ checked })} + {/snippet} + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte new file mode 100644 index 000000000..974163fed --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte @@ -0,0 +1,17 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte new file mode 100644 index 000000000..c4b2b7f82 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte @@ -0,0 +1,23 @@ + + + + {@render children?.()} + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte new file mode 100644 index 000000000..89179751c --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte @@ -0,0 +1,20 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte new file mode 100644 index 000000000..31cded2dc --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte @@ -0,0 +1,29 @@ + + + + {@render children?.()} + + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte new file mode 100644 index 000000000..02f5f63a5 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte new file mode 100644 index 000000000..7409c7773 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte new file mode 100644 index 000000000..5c2776c5b --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/dropdown-menu/index.ts b/apps/staged/src/lib/components/ui/dropdown-menu/index.ts new file mode 100644 index 000000000..b6bce25d8 --- /dev/null +++ b/apps/staged/src/lib/components/ui/dropdown-menu/index.ts @@ -0,0 +1,54 @@ +import Root from './dropdown-menu.svelte'; +import Sub from './dropdown-menu-sub.svelte'; +import CheckboxGroup from './dropdown-menu-checkbox-group.svelte'; +import CheckboxItem from './dropdown-menu-checkbox-item.svelte'; +import Content from './dropdown-menu-content.svelte'; +import Group from './dropdown-menu-group.svelte'; +import Item from './dropdown-menu-item.svelte'; +import Label from './dropdown-menu-label.svelte'; +import RadioGroup from './dropdown-menu-radio-group.svelte'; +import RadioItem from './dropdown-menu-radio-item.svelte'; +import Separator from './dropdown-menu-separator.svelte'; +import Shortcut from './dropdown-menu-shortcut.svelte'; +import Trigger from './dropdown-menu-trigger.svelte'; +import SubContent from './dropdown-menu-sub-content.svelte'; +import SubTrigger from './dropdown-menu-sub-trigger.svelte'; +import GroupHeading from './dropdown-menu-group-heading.svelte'; +import Portal from './dropdown-menu-portal.svelte'; + +export { + CheckboxGroup, + CheckboxItem, + Content, + Portal, + Root as DropdownMenu, + CheckboxGroup as DropdownMenuCheckboxGroup, + CheckboxItem as DropdownMenuCheckboxItem, + Content as DropdownMenuContent, + Portal as DropdownMenuPortal, + Group as DropdownMenuGroup, + Item as DropdownMenuItem, + Label as DropdownMenuLabel, + RadioGroup as DropdownMenuRadioGroup, + RadioItem as DropdownMenuRadioItem, + Separator as DropdownMenuSeparator, + Shortcut as DropdownMenuShortcut, + Sub as DropdownMenuSub, + SubContent as DropdownMenuSubContent, + SubTrigger as DropdownMenuSubTrigger, + Trigger as DropdownMenuTrigger, + GroupHeading as DropdownMenuGroupHeading, + Group, + GroupHeading, + Item, + Label, + RadioGroup, + RadioItem, + Root, + Separator, + Shortcut, + Sub, + SubContent, + SubTrigger, + Trigger, +}; diff --git a/apps/staged/src/lib/components/ui/input/index.ts b/apps/staged/src/lib/components/ui/input/index.ts new file mode 100644 index 000000000..0888f0e06 --- /dev/null +++ b/apps/staged/src/lib/components/ui/input/index.ts @@ -0,0 +1,7 @@ +import Root from './input.svelte'; + +export { + Root, + // + Root as Input, +}; diff --git a/apps/staged/src/lib/components/ui/input/input.svelte b/apps/staged/src/lib/components/ui/input/input.svelte new file mode 100644 index 000000000..79eec3b84 --- /dev/null +++ b/apps/staged/src/lib/components/ui/input/input.svelte @@ -0,0 +1,48 @@ + + +{#if type === 'file'} + +{:else} + +{/if} diff --git a/apps/staged/src/lib/components/ui/label/index.ts b/apps/staged/src/lib/components/ui/label/index.ts new file mode 100644 index 000000000..36fb393d4 --- /dev/null +++ b/apps/staged/src/lib/components/ui/label/index.ts @@ -0,0 +1,7 @@ +import Root from './label.svelte'; + +export { + Root, + // + Root as Label, +}; diff --git a/apps/staged/src/lib/components/ui/label/label.svelte b/apps/staged/src/lib/components/ui/label/label.svelte new file mode 100644 index 000000000..d6528f8b3 --- /dev/null +++ b/apps/staged/src/lib/components/ui/label/label.svelte @@ -0,0 +1,20 @@ + + + diff --git a/apps/staged/src/lib/components/ui/popover/index.ts b/apps/staged/src/lib/components/ui/popover/index.ts new file mode 100644 index 000000000..5427570fc --- /dev/null +++ b/apps/staged/src/lib/components/ui/popover/index.ts @@ -0,0 +1,28 @@ +import Root from './popover.svelte'; +import Close from './popover-close.svelte'; +import Content from './popover-content.svelte'; +import Description from './popover-description.svelte'; +import Header from './popover-header.svelte'; +import Title from './popover-title.svelte'; +import Trigger from './popover-trigger.svelte'; +import Portal from './popover-portal.svelte'; + +export { + Root, + Content, + Description, + Header, + Title, + Trigger, + Close, + Portal, + // + Root as Popover, + Content as PopoverContent, + Description as PopoverDescription, + Header as PopoverHeader, + Title as PopoverTitle, + Trigger as PopoverTrigger, + Close as PopoverClose, + Portal as PopoverPortal, +}; diff --git a/apps/staged/src/lib/components/ui/popover/popover-close.svelte b/apps/staged/src/lib/components/ui/popover/popover-close.svelte new file mode 100644 index 000000000..c9518f46e --- /dev/null +++ b/apps/staged/src/lib/components/ui/popover/popover-close.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/popover/popover-content.svelte b/apps/staged/src/lib/components/ui/popover/popover-content.svelte new file mode 100644 index 000000000..274b5f5b0 --- /dev/null +++ b/apps/staged/src/lib/components/ui/popover/popover-content.svelte @@ -0,0 +1,31 @@ + + + + + diff --git a/apps/staged/src/lib/components/ui/popover/popover-description.svelte b/apps/staged/src/lib/components/ui/popover/popover-description.svelte new file mode 100644 index 000000000..415892c93 --- /dev/null +++ b/apps/staged/src/lib/components/ui/popover/popover-description.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/apps/staged/src/lib/components/ui/popover/popover-header.svelte b/apps/staged/src/lib/components/ui/popover/popover-header.svelte new file mode 100644 index 000000000..71b234a12 --- /dev/null +++ b/apps/staged/src/lib/components/ui/popover/popover-header.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/apps/staged/src/lib/components/ui/popover/popover-portal.svelte b/apps/staged/src/lib/components/ui/popover/popover-portal.svelte new file mode 100644 index 000000000..234766e85 --- /dev/null +++ b/apps/staged/src/lib/components/ui/popover/popover-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/popover/popover-title.svelte b/apps/staged/src/lib/components/ui/popover/popover-title.svelte new file mode 100644 index 000000000..957f21905 --- /dev/null +++ b/apps/staged/src/lib/components/ui/popover/popover-title.svelte @@ -0,0 +1,15 @@ + + +
+ {@render children?.()} +
diff --git a/apps/staged/src/lib/components/ui/popover/popover-trigger.svelte b/apps/staged/src/lib/components/ui/popover/popover-trigger.svelte new file mode 100644 index 000000000..ef43541fc --- /dev/null +++ b/apps/staged/src/lib/components/ui/popover/popover-trigger.svelte @@ -0,0 +1,17 @@ + + + diff --git a/apps/staged/src/lib/components/ui/popover/popover.svelte b/apps/staged/src/lib/components/ui/popover/popover.svelte new file mode 100644 index 000000000..4551a94f3 --- /dev/null +++ b/apps/staged/src/lib/components/ui/popover/popover.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/select/index.ts b/apps/staged/src/lib/components/ui/select/index.ts new file mode 100644 index 000000000..39971402d --- /dev/null +++ b/apps/staged/src/lib/components/ui/select/index.ts @@ -0,0 +1,37 @@ +import Root from './select.svelte'; +import Group from './select-group.svelte'; +import Label from './select-label.svelte'; +import Item from './select-item.svelte'; +import Content from './select-content.svelte'; +import Trigger from './select-trigger.svelte'; +import Separator from './select-separator.svelte'; +import ScrollDownButton from './select-scroll-down-button.svelte'; +import ScrollUpButton from './select-scroll-up-button.svelte'; +import GroupHeading from './select-group-heading.svelte'; +import Portal from './select-portal.svelte'; + +export { + Root, + Group, + Label, + Item, + Content, + Trigger, + Separator, + ScrollDownButton, + ScrollUpButton, + GroupHeading, + Portal, + // + Root as Select, + Group as SelectGroup, + Label as SelectLabel, + Item as SelectItem, + Content as SelectContent, + Trigger as SelectTrigger, + Separator as SelectSeparator, + ScrollDownButton as SelectScrollDownButton, + ScrollUpButton as SelectScrollUpButton, + GroupHeading as SelectGroupHeading, + Portal as SelectPortal, +}; diff --git a/apps/staged/src/lib/components/ui/select/select-content.svelte b/apps/staged/src/lib/components/ui/select/select-content.svelte new file mode 100644 index 000000000..dd4a133d4 --- /dev/null +++ b/apps/staged/src/lib/components/ui/select/select-content.svelte @@ -0,0 +1,45 @@ + + + + + + + {@render children?.()} + + + + diff --git a/apps/staged/src/lib/components/ui/select/select-group-heading.svelte b/apps/staged/src/lib/components/ui/select/select-group-heading.svelte new file mode 100644 index 000000000..39caedb8e --- /dev/null +++ b/apps/staged/src/lib/components/ui/select/select-group-heading.svelte @@ -0,0 +1,21 @@ + + + + {@render children?.()} + diff --git a/apps/staged/src/lib/components/ui/select/select-group.svelte b/apps/staged/src/lib/components/ui/select/select-group.svelte new file mode 100644 index 000000000..d6d7cfeb4 --- /dev/null +++ b/apps/staged/src/lib/components/ui/select/select-group.svelte @@ -0,0 +1,17 @@ + + + diff --git a/apps/staged/src/lib/components/ui/select/select-item.svelte b/apps/staged/src/lib/components/ui/select/select-item.svelte new file mode 100644 index 000000000..900ee9774 --- /dev/null +++ b/apps/staged/src/lib/components/ui/select/select-item.svelte @@ -0,0 +1,38 @@ + + + + {#snippet children({ selected, highlighted })} + + {#if selected} + + {/if} + + {#if childrenProp} + {@render childrenProp({ selected, highlighted })} + {:else} + {label || value} + {/if} + {/snippet} + diff --git a/apps/staged/src/lib/components/ui/select/select-label.svelte b/apps/staged/src/lib/components/ui/select/select-label.svelte new file mode 100644 index 000000000..4303702aa --- /dev/null +++ b/apps/staged/src/lib/components/ui/select/select-label.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/apps/staged/src/lib/components/ui/select/select-portal.svelte b/apps/staged/src/lib/components/ui/select/select-portal.svelte new file mode 100644 index 000000000..fa48d6a20 --- /dev/null +++ b/apps/staged/src/lib/components/ui/select/select-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/select/select-scroll-down-button.svelte b/apps/staged/src/lib/components/ui/select/select-scroll-down-button.svelte new file mode 100644 index 000000000..b518d1f4e --- /dev/null +++ b/apps/staged/src/lib/components/ui/select/select-scroll-down-button.svelte @@ -0,0 +1,23 @@ + + + + + diff --git a/apps/staged/src/lib/components/ui/select/select-scroll-up-button.svelte b/apps/staged/src/lib/components/ui/select/select-scroll-up-button.svelte new file mode 100644 index 000000000..445ed848e --- /dev/null +++ b/apps/staged/src/lib/components/ui/select/select-scroll-up-button.svelte @@ -0,0 +1,23 @@ + + + + + diff --git a/apps/staged/src/lib/components/ui/select/select-separator.svelte b/apps/staged/src/lib/components/ui/select/select-separator.svelte new file mode 100644 index 000000000..5f186f186 --- /dev/null +++ b/apps/staged/src/lib/components/ui/select/select-separator.svelte @@ -0,0 +1,18 @@ + + + diff --git a/apps/staged/src/lib/components/ui/select/select-trigger.svelte b/apps/staged/src/lib/components/ui/select/select-trigger.svelte new file mode 100644 index 000000000..cbccb18a1 --- /dev/null +++ b/apps/staged/src/lib/components/ui/select/select-trigger.svelte @@ -0,0 +1,29 @@ + + + + {@render children?.()} + + diff --git a/apps/staged/src/lib/components/ui/select/select.svelte b/apps/staged/src/lib/components/ui/select/select.svelte new file mode 100644 index 000000000..ec122f3e1 --- /dev/null +++ b/apps/staged/src/lib/components/ui/select/select.svelte @@ -0,0 +1,11 @@ + + + diff --git a/apps/staged/src/lib/components/ui/separator/index.ts b/apps/staged/src/lib/components/ui/separator/index.ts new file mode 100644 index 000000000..56b27672e --- /dev/null +++ b/apps/staged/src/lib/components/ui/separator/index.ts @@ -0,0 +1,7 @@ +import Root from './separator.svelte'; + +export { + Root, + // + Root as Separator, +}; diff --git a/apps/staged/src/lib/components/ui/separator/separator.svelte b/apps/staged/src/lib/components/ui/separator/separator.svelte new file mode 100644 index 000000000..5bcb3d63e --- /dev/null +++ b/apps/staged/src/lib/components/ui/separator/separator.svelte @@ -0,0 +1,23 @@ + + + diff --git a/apps/staged/src/lib/components/ui/sonner/index.ts b/apps/staged/src/lib/components/ui/sonner/index.ts new file mode 100644 index 000000000..fcaf06bfb --- /dev/null +++ b/apps/staged/src/lib/components/ui/sonner/index.ts @@ -0,0 +1 @@ +export { default as Toaster } from './sonner.svelte'; diff --git a/apps/staged/src/lib/components/ui/sonner/sonner.svelte b/apps/staged/src/lib/components/ui/sonner/sonner.svelte new file mode 100644 index 000000000..0eca70d87 --- /dev/null +++ b/apps/staged/src/lib/components/ui/sonner/sonner.svelte @@ -0,0 +1,32 @@ + + + + {#snippet loadingIcon()} + + {/snippet} + {#snippet successIcon()} + + {/snippet} + {#snippet errorIcon()} + + {/snippet} + {#snippet infoIcon()} + + {/snippet} + {#snippet warningIcon()} + + {/snippet} + diff --git a/apps/staged/src/lib/components/ui/toggle-group/index.ts b/apps/staged/src/lib/components/ui/toggle-group/index.ts new file mode 100644 index 000000000..eade42e62 --- /dev/null +++ b/apps/staged/src/lib/components/ui/toggle-group/index.ts @@ -0,0 +1,10 @@ +import Root from './toggle-group.svelte'; +import Item from './toggle-group-item.svelte'; + +export { + Root, + Item, + // + Root as ToggleGroup, + Item as ToggleGroupItem, +}; diff --git a/apps/staged/src/lib/components/ui/toggle-group/toggle-group-item.svelte b/apps/staged/src/lib/components/ui/toggle-group/toggle-group-item.svelte new file mode 100644 index 000000000..42e0b1791 --- /dev/null +++ b/apps/staged/src/lib/components/ui/toggle-group/toggle-group-item.svelte @@ -0,0 +1,35 @@ + + + diff --git a/apps/staged/src/lib/components/ui/toggle-group/toggle-group.svelte b/apps/staged/src/lib/components/ui/toggle-group/toggle-group.svelte new file mode 100644 index 000000000..e920426cc --- /dev/null +++ b/apps/staged/src/lib/components/ui/toggle-group/toggle-group.svelte @@ -0,0 +1,75 @@ + + + + + + diff --git a/apps/staged/src/lib/components/ui/toggle/index.ts b/apps/staged/src/lib/components/ui/toggle/index.ts new file mode 100644 index 000000000..dca3690cf --- /dev/null +++ b/apps/staged/src/lib/components/ui/toggle/index.ts @@ -0,0 +1,13 @@ +import Root from './toggle.svelte'; +export { + toggleVariants, + type ToggleSize, + type ToggleVariant, + type ToggleVariants, +} from './toggle.svelte'; + +export { + Root, + // + Root as Toggle, +}; diff --git a/apps/staged/src/lib/components/ui/toggle/toggle.svelte b/apps/staged/src/lib/components/ui/toggle/toggle.svelte new file mode 100644 index 000000000..302f0d8dc --- /dev/null +++ b/apps/staged/src/lib/components/ui/toggle/toggle.svelte @@ -0,0 +1,52 @@ + + + + + diff --git a/apps/staged/src/lib/components/ui/tooltip/index.ts b/apps/staged/src/lib/components/ui/tooltip/index.ts new file mode 100644 index 000000000..2e8df8230 --- /dev/null +++ b/apps/staged/src/lib/components/ui/tooltip/index.ts @@ -0,0 +1,19 @@ +import Root from './tooltip.svelte'; +import Trigger from './tooltip-trigger.svelte'; +import Content from './tooltip-content.svelte'; +import Provider from './tooltip-provider.svelte'; +import Portal from './tooltip-portal.svelte'; + +export { + Root, + Trigger, + Content, + Provider, + Portal, + // + Root as Tooltip, + Content as TooltipContent, + Trigger as TooltipTrigger, + Provider as TooltipProvider, + Portal as TooltipPortal, +}; diff --git a/apps/staged/src/lib/components/ui/tooltip/tooltip-content.svelte b/apps/staged/src/lib/components/ui/tooltip/tooltip-content.svelte new file mode 100644 index 000000000..0796dd902 --- /dev/null +++ b/apps/staged/src/lib/components/ui/tooltip/tooltip-content.svelte @@ -0,0 +1,52 @@ + + + + + {@render children?.()} + + {#snippet child({ props })} +
+ {/snippet} +
+
+
diff --git a/apps/staged/src/lib/components/ui/tooltip/tooltip-portal.svelte b/apps/staged/src/lib/components/ui/tooltip/tooltip-portal.svelte new file mode 100644 index 000000000..7b9e8f9f1 --- /dev/null +++ b/apps/staged/src/lib/components/ui/tooltip/tooltip-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/tooltip/tooltip-provider.svelte b/apps/staged/src/lib/components/ui/tooltip/tooltip-provider.svelte new file mode 100644 index 000000000..49f8379ba --- /dev/null +++ b/apps/staged/src/lib/components/ui/tooltip/tooltip-provider.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/tooltip/tooltip-trigger.svelte b/apps/staged/src/lib/components/ui/tooltip/tooltip-trigger.svelte new file mode 100644 index 000000000..b7640e4ed --- /dev/null +++ b/apps/staged/src/lib/components/ui/tooltip/tooltip-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/ui/tooltip/tooltip.svelte b/apps/staged/src/lib/components/ui/tooltip/tooltip.svelte new file mode 100644 index 000000000..42a939b4c --- /dev/null +++ b/apps/staged/src/lib/components/ui/tooltip/tooltip.svelte @@ -0,0 +1,7 @@ + + + diff --git a/apps/staged/src/lib/components/utils.ts b/apps/staged/src/lib/components/utils.ts new file mode 100644 index 000000000..ee339984d --- /dev/null +++ b/apps/staged/src/lib/components/utils.ts @@ -0,0 +1,13 @@ +import { clsx, type ClassValue } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type WithoutChild = T extends { child?: any } ? Omit : T; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type WithoutChildren = T extends { children?: any } ? Omit : T; +export type WithoutChildrenOrChild = WithoutChildren>; +export type WithElementRef = T & { ref?: U | null }; diff --git a/apps/staged/src/lib/features/actions/ActionOutputModal.svelte b/apps/staged/src/lib/features/actions/ActionOutputModal.svelte index 1462c16da..618cb01db 100644 --- a/apps/staged/src/lib/features/actions/ActionOutputModal.svelte +++ b/apps/staged/src/lib/features/actions/ActionOutputModal.svelte @@ -20,20 +20,20 @@ --> - - - - + + diff --git a/apps/staged/src/lib/features/branches/BranchCard.svelte b/apps/staged/src/lib/features/branches/BranchCard.svelte index 71b6214c7..b24ecccc6 100644 --- a/apps/staged/src/lib/features/branches/BranchCard.svelte +++ b/apps/staged/src/lib/features/branches/BranchCard.svelte @@ -12,16 +12,14 @@ --> @@ -697,49 +633,62 @@ class:fading={execution.fading} transition:slideAndFade={{ duration: 300, axis: 'x' }} > - + + + {#snippet child({ props })} + + {/snippet} + + + {isStopping + ? 'Stopping…' + : showStopIcon + ? `Stop ${execution.actionName}` + : isRunning + ? `View output for ${execution.actionName}` + : execution.status === 'completed' + ? `${execution.actionName} completed` + : execution.status === 'failed' + ? `${execution.actionName} failed` + : execution.actionName} + + {/each} @@ -762,175 +711,315 @@ {#if isRunning && hasEndpoint && phase?.type === 'running' && phase.endpoint}
- - + + + {#snippet child({ props })} + + {/snippet} + + + {isStopping + ? 'Stopping…' + : showStopIcon + ? `Stop ${primaryRunAction.name}` + : `View output for ${primaryRunAction.name}`} + + + + + {#snippet child({ props })} + + {/snippet} + + Copy endpoint: {copyUrl} +
{:else} - + + + {#snippet child({ props })} + + {/snippet} + + + {isStopping + ? 'Stopping…' + : showStopIcon + ? `Stop ${primaryRunAction.name}` + : isRunning + ? `View output for ${primaryRunAction.name}` + : execution?.status === 'completed' + ? `${primaryRunAction.name} completed` + : execution?.status === 'failed' + ? `${primaryRunAction.name} failed` + : primaryRunAction.name} + + {/if} {/if} {/if} - - -{#if actionOutputModal} - (actionOutputModal = null)} - onRunAgain={async () => { - const action = actions.find((a) => a.id === actionOutputModal?.actionId); - if (!action) return; - - // Clean up stale executions of this action - const staleExecutions = runningActions.filter( - (a) => a.actionId === action.id && a.status !== 'running' - ); - for (const stale of staleExecutions) { - clearActionExecution(stale.executionId).catch(() => {}); - } - runningActions = runningActions.filter( - (a) => !(a.actionId === action.id && a.status !== 'running') - ); - - // If already running, just switch the modal to that execution - const existingExecution = runningActions.find( - (a) => a.actionId === action.id && a.status === 'running' - ); - if (existingExecution) { - actionOutputModal = { - executionId: existingExecution.executionId, - actionId: action.id, - actionName: action.name, - isStopping: stoppingExecutions.has(existingExecution.executionId), - }; - return; - } +{#snippet renderSubItems(items: MenuItem[])} + {#each items as item, i (i)} + {#if item.type === 'separator'} + + {:else if item.type === 'action'} + + {#if item.icon} + {@const Icon = item.icon} + + {:else if item.iconSrc} + + {/if} + {item.label} + + {/if} + {/each} +{/snippet} + + + + + + + {#if !isSettingUp} + {#if isRemote && branch.workspaceName} + { + navigator.clipboard.writeText(branch.workspaceName!); + }} + > + Copy Workspace Name + + {/if} + {#if hasActionsForSubmenu} + + + Actions + + + {#each actionMenuItems as item, i (i)} + {#if item.type === 'separator'} + + {:else if item.type === 'submenu'} + + + {#if item.icon} + {@const Icon = item.icon} + + {/if} + {item.label} + + + {@render renderSubItems(item.children)} + + + {:else} + + {#if item.icon} + {@const Icon = item.icon} + + {/if} + {item.label} + + {/if} + {/each} + + + {/if} + {#if isLocal && branch.worktreePath && openerApps.length > 0} + + + + Open In + + + {@render renderSubItems(openInMenuItems)} + + + {:else if isLocal && branch.worktreePath} + + + Copy Worktree Path + + {/if} + + + Rename Branch + + onRebaseBranch?.()}> + Rebase Branch + + {#if commitCount >= 2} + onSquashCommits?.()}> + Squash Commits + + {/if} + + {/if} + + Delete Repo + + + + + (actionOutputModal = null)} + onRunAgain={async () => { + const action = actions.find((a) => a.id === actionOutputModal?.actionId); + if (!action) return; + + // Clean up stale executions of this action + const staleExecutions = runningActions.filter( + (a) => a.actionId === action.id && a.status !== 'running' + ); + for (const stale of staleExecutions) { + clearActionExecution(stale.executionId).catch(() => {}); + } + runningActions = runningActions.filter( + (a) => !(a.actionId === action.id && a.status !== 'running') + ); - try { - const provider = getPreferredAgent(agentState.providers) ?? undefined; - const newExecutionId = await runBranchAction(branch.id, action.id, provider); - // Keep the modal open and switch to the new execution - actionOutputModal = { - executionId: newExecutionId, - actionId: action.id, - actionName: action.name, - isStopping: false, - }; - } catch (e) { - console.error('Failed to run action:', e); - notifyError(`Failed to run action "${action.name}"`, e); - } - }} - {onNoteCreated} - /> -{/if} + // If already running, just switch the modal to that execution + const existingExecution = runningActions.find( + (a) => a.actionId === action.id && a.status === 'running' + ); + if (existingExecution) { + actionOutputModal = { + executionId: existingExecution.executionId, + actionId: action.id, + actionName: action.name, + isStopping: stoppingExecutions.has(existingExecution.executionId), + }; + return; + } + + try { + const provider = getPreferredAgent(agentState.providers) ?? undefined; + const newExecutionId = await runBranchAction(branch.id, action.id, provider); + // Keep the modal open and switch to the new execution + actionOutputModal = { + executionId: newExecutionId, + actionId: action.id, + actionName: action.name, + isStopping: false, + }; + } catch (e) { + console.error('Failed to run action:', e); + notifyError(`Failed to run action "${action.name}"`, e); + } + }} + {onNoteCreated} +/> diff --git a/apps/staged/src/lib/features/branches/BranchCardHeaderInfo.svelte b/apps/staged/src/lib/features/branches/BranchCardHeaderInfo.svelte index defd2c20a..7f06809ca 100644 --- a/apps/staged/src/lib/features/branches/BranchCardHeaderInfo.svelte +++ b/apps/staged/src/lib/features/branches/BranchCardHeaderInfo.svelte @@ -1,9 +1,12 @@ {#snippet capsule()} - - {baseBranch}{#if parentAheadCount > 0} - +{parentAheadCount}{/if} - + + + {#snippet child({ props })} + + {baseBranch}{#if parentAheadCount > 0} + +{parentAheadCount}{/if} + + {/snippet} + + {baseBranch} + {/snippet} {#snippet parentPill()} @@ -54,13 +64,24 @@ {@render capsule()} {/if} {#if parentAheadCount > 0 && onRebase} - + + + {#snippet child({ props })} + + + + {/snippet} + + + {rebaseDisabled ? 'Rebase unavailable' : 'Rebase onto parent'} + + {/if} {/if} {/snippet} @@ -69,9 +90,16 @@ {#if refreshingGitState} {:else if fetchError} - - - + + + {#snippet child({ props })} + + + + {/snippet} + + {fetchError} + {/if} {/snippet} @@ -84,16 +112,30 @@ />
- {branchName} + + + {#snippet child({ props })} + {branchName} + {/snippet} + + {branchName} + {#if baseBranch} {/if} {@render parentPill()} {#if warning} - - - {warning} - + + + {#snippet child({ props })} + + + {warning} + + {/snippet} + + {warning} + {/if} {@render refreshStatus()}
@@ -103,10 +145,17 @@
{@render parentPill()} {#if warning} - - - {warning} - + + + {#snippet child({ props })} + + + {warning} + + {/snippet} + + {warning} + {/if} {@render refreshStatus()}
@@ -167,37 +216,6 @@ color: var(--ui-accent); } - .rebase-btn { - display: flex; - align-items: center; - justify-content: center; - height: 22px; - padding: 0 8px; - font-size: var(--size-xs); - font-weight: 500; - color: var(--text-muted); - background: none; - border: 1px solid var(--border-subtle); - border-radius: 6px; - cursor: pointer; - white-space: nowrap; - transition: - color 0.15s, - border-color 0.15s, - background-color 0.15s; - } - - .rebase-btn:hover:not(:disabled) { - border-color: var(--border-muted); - color: var(--text-primary); - background: var(--bg-hover); - } - - .rebase-btn:disabled { - opacity: 0.3; - cursor: not-allowed; - } - .branch-warning { display: inline-flex; align-items: center; diff --git a/apps/staged/src/lib/features/branches/BranchCardPrButton.svelte b/apps/staged/src/lib/features/branches/BranchCardPrButton.svelte index ef3428286..7354e8490 100644 --- a/apps/staged/src/lib/features/branches/BranchCardPrButton.svelte +++ b/apps/staged/src/lib/features/branches/BranchCardPrButton.svelte @@ -6,15 +6,15 @@ --> {#if hasCodeChanges || branch.prNumber} - + + + {#snippet child({ props })} + + + + {/snippet} + + {prButtonTitle} + {/if} -{#if showPrErrorDialog} - -{/if} - -{#if showPushErrorDialog} - -{/if} - -{#if showForcePushDialog} - -{/if} + + + + PR Creation Failed + + {prError ?? 'An unknown error occurred while creating the PR.'} + + + + Cancel + Retry + + + + + + + + Push Failed + + {pushError ?? 'An unknown error occurred while pushing.'} + + + + Cancel + + Retry + + + + + + + + + Push Rejected + + The remote branch has commits that would be lost. Do you want to force push? This will + overwrite the remote branch with your local version. + + + + Cancel + + Force Push + + + + diff --git a/apps/staged/src/lib/features/diff/DiffCommitSessionLauncher.svelte b/apps/staged/src/lib/features/diff/DiffCommitSessionLauncher.svelte index fbf8b20e4..00b7d87e2 100644 --- a/apps/staged/src/lib/features/diff/DiffCommitSessionLauncher.svelte +++ b/apps/staged/src/lib/features/diff/DiffCommitSessionLauncher.svelte @@ -1,9 +1,10 @@ - - - - -{#if showNewProjectModal && hasContent} - (showNewProjectModal = false)} /> -{/if} + (showNewProjectModal = false)} +/> -{#if projectToDelete} - (projectToDelete = null)} - /> -{/if} + !v && (projectToDelete = null)} +> + + {#if projectToDelete} + + Remove Project + + {`Remove "${projectDisplayName(projectToDelete)}" from Staged? There are unmerged changes in this project's branches. Deleting this project will lose any changes not pushed to GitHub.`} + + + + Cancel + + Remove + + + {/if} + + -{#if branchToDelete} - (branchToDelete = null)} - /> -{/if} + !v && (branchToDelete = null)} +> + + {#if branchToDelete} + + Delete Repo + + {`Delete repo for branch "${branchToDelete.branch.branchName}"? This removes its tracked branch and local worktree/remote workspace.`} + + + + Cancel + + Delete + + + {/if} + + diff --git a/apps/staged/src/lib/features/projects/ProjectsList.svelte b/apps/staged/src/lib/features/projects/ProjectsList.svelte index b6b86f969..edb201458 100644 --- a/apps/staged/src/lib/features/projects/ProjectsList.svelte +++ b/apps/staged/src/lib/features/projects/ProjectsList.svelte @@ -7,14 +7,14 @@ import { onMount, tick } from 'svelte'; import { fade } from 'svelte/transition'; import { listenToEvent } from '../../transport'; - import { - Cloud, - GitPullRequest, - GitPullRequestClosed, - GitPullRequestDraft, - Plus, - Sprout, - } from 'lucide-svelte'; + import Cloud from '@lucide/svelte/icons/cloud'; + import GitPullRequest from '@lucide/svelte/icons/git-pull-request'; + import GitPullRequestClosed from '@lucide/svelte/icons/git-pull-request-closed'; + import GitPullRequestDraft from '@lucide/svelte/icons/git-pull-request-draft'; + import Mail from '@lucide/svelte/icons/mail'; + import Plus from '@lucide/svelte/icons/plus'; + import Sprout from '@lucide/svelte/icons/sprout'; + import Trash2 from '@lucide/svelte/icons/trash-2'; import type { Project, ProjectRepo, @@ -37,14 +37,15 @@ import { selectProject, showAllRepos } from '../layout/navigation.svelte'; import NewProjectModal from './NewProjectModal.svelte'; import ProjectsSidebar from './ProjectsSidebar.svelte'; - import ProjectContextMenu from './ProjectContextMenu.svelte'; import { getProjectStatus } from './projectStatus'; + import * as ContextMenu from '$lib/components/ui/context-menu'; import SplashScreen from './SplashScreen.svelte'; import Spinner from '../../shared/Spinner.svelte'; import SineWave from '../../shared/SineWave.svelte'; import RepoLabel from '../../shared/RepoLabel.svelte'; - import ConfirmDialog from '../../shared/ConfirmDialog.svelte'; - import { alerts } from '../../shared/alerts.svelte'; + import { toast } from 'svelte-sonner'; + import * as AlertDialog from '$lib/components/ui/alert-dialog'; + import { Button } from '$lib/components/ui/button'; import { setProjects } from './projectsSidebarState.svelte'; import { @@ -69,7 +70,6 @@ let isCommandKeyHeld = $state(false); let deletingProjectNames = $state>(new Map()); let projectToDelete = $state(null); - let projectMenu = $state<{ project: Project; x: number; y: number } | null>(null); let reposByProject = $state>(new Map()); let reposHydrating = $state(false); let mainPanelEl = $state(null); @@ -404,11 +404,7 @@ } catch (e) { console.error('[ProjectsList] Failed to clone repo:', e); const message = e instanceof Error ? e.message : String(e); - alerts.show({ - tone: 'error', - title: 'Failed to clone repo', - message, - }); + toast.error('Failed to clone repo', { description: message }); } } @@ -456,7 +452,6 @@ } function openProject(projectId: string) { - closeProjectMenu(); if (isProjectDeleting(projectId)) return; if (mainPanelEl) { setProjectsListScrollTop(mainPanelEl.scrollTop); @@ -464,17 +459,6 @@ selectProject(projectId); } - function closeProjectMenu() { - projectMenu = null; - } - - function openProjectMenu(event: MouseEvent, project: Project, deleting: boolean) { - if (deleting) return; - event.preventDefault(); - event.stopPropagation(); - projectMenu = { project, x: event.clientX, y: event.clientY }; - } - function handleMarkProjectUnread(project: Project) { if (isProjectDeleting(project.id)) return; projectStateStore.markAsUnread(project.id); @@ -519,11 +503,7 @@ } catch (e) { console.error('Failed to delete project:', e); const message = e instanceof Error ? e.message : String(e); - alerts.show({ - tone: 'error', - title: 'Unable to delete project', - message, - }); + toast.error('Unable to delete project', { description: message }); } finally { const next = new Map(deletingProjectNames); next.delete(id); @@ -650,7 +630,12 @@

Repos

- +
{#each homeRepos as repo (repo.githubRepo + ':' + repo.subpath)} @@ -666,10 +651,15 @@

Projects

- +
{#if projects.length > 0}
@@ -723,122 +713,145 @@ {@const workspaceStatus = project.location === 'remote' ? getProjectWorkspaceStatus(project.id) : null}
-
- {:else if status.kind === 'runAction' || status.kind === 'running'} -
- -
- {:else if status.kind === 'unread'} -
- {/if} -
- {#if project.location === 'remote'} - - {:else if prStatus === 'merged'} - - {:else if prStatus === 'checks_failing'} - - {:else if prStatus === 'open'} - - {:else if prStatus === 'closed'} - - {:else if prStatus === 'conflict'} - - {:else if projectHasCodeChanges(projectBranches.get(project.id) || [])} - - {:else} - - {/if} - {projectDisplayName(project)} -
- {#if status.kind === 'deleting'} -
Deleting…
- {/if} -
- {#if repos.length > 0} - {#each [...repos].sort((a, b) => { - const aKey = a.subpath ? `${a.githubRepo}/${a.subpath}` : a.githubRepo; - const bKey = b.subpath ? `${b.githubRepo}/${b.subpath}` : b.githubRepo; - return aKey.localeCompare(bKey); - }) as r} - {@const badge = repoBadgeStore.lookup(r.githubRepo, r.subpath)} - {#if badge} - - - + {#if viewport.showShortcutHints && isCommandKeyHeld && index < 9} +
+ + {index + 1} +
+ {/if} + {#if status.runActionPhase === 'running' && status.kind === 'running'} +
+ + +
+ {:else if status.runActionPhase === 'running'} +
+ +
+ {:else if status.kind === 'runAction' || status.kind === 'running'} +
+ +
+ {:else if status.kind === 'unread'} +
+ {/if} +
+ {#if project.location === 'remote'} + + {:else if prStatus === 'merged'} + + {:else if prStatus === 'checks_failing'} + + {:else if prStatus === 'open'} + + {:else if prStatus === 'closed'} + + {:else if prStatus === 'conflict'} + + {:else if projectHasCodeChanges(projectBranches.get(project.id) || [])} + {:else} - - - + {/if} - {/each} - {:else if project.githubRepo} - {@const badge = repoBadgeStore.lookup(project.githubRepo, project.subpath)} - {#if badge} - - - - {:else} - - - + {projectDisplayName(project)} +
+ {#if status.kind === 'deleting'} +
Deleting…
{/if} - {:else} - No repo attached - {/if} -
- +
+ {#if repos.length > 0} + {#each [...repos].sort((a, b) => { + const aKey = a.subpath ? `${a.githubRepo}/${a.subpath}` : a.githubRepo; + const bKey = b.subpath ? `${b.githubRepo}/${b.subpath}` : b.githubRepo; + return aKey.localeCompare(bKey); + }) as r} + {@const badge = repoBadgeStore.lookup(r.githubRepo, r.subpath)} + {#if badge} + + + + {:else} + + + + {/if} + {/each} + {:else if project.githubRepo} + {@const badge = repoBadgeStore.lookup(project.githubRepo, project.subpath)} + {#if badge} + + + + {:else} + + + + {/if} + {:else} + No repo attached + {/if} +
+ + + + handleMarkProjectUnread(project)} + > + Mark as Unread + + handleRemoveProject(project)} + > + Remove Project + + +
{projectSubtitle(repoCount, sessionTypes, status.runActionPhase)}
@@ -850,31 +863,33 @@
-{#if showNewProjectModal && projects.length > 0} - (showNewProjectModal = false)} /> -{/if} - -{#if projectMenu} - {@const menuProject = projectMenu.project} - handleMarkProjectUnread(menuProject)} - onRemoveProject={() => handleRemoveProject(menuProject)} - onClose={closeProjectMenu} - /> -{/if} - -{#if projectToDelete} - (projectToDelete = null)} - /> -{/if} + 0} + onCreated={handleProjectCreated} + onClose={() => (showNewProjectModal = false)} +/> + + !v && (projectToDelete = null)} +> + + {#if projectToDelete} + + Remove Project + + {`Remove "${projectDisplayName(projectToDelete)}" from Staged? There are unmerged changes in this project's branches. Deleting this project will lose any changes not pushed to GitHub.`} + + + + Cancel + + Remove + + + {/if} + + diff --git a/apps/staged/src/lib/features/projects/RepoConfigForm.svelte b/apps/staged/src/lib/features/projects/RepoConfigForm.svelte index 5210ea52a..5323806d0 100644 --- a/apps/staged/src/lib/features/projects/RepoConfigForm.svelte +++ b/apps/staged/src/lib/features/projects/RepoConfigForm.svelte @@ -12,7 +12,10 @@ - - - -