mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-02 04:02:20 +00:00
feat(ui): Add templates sidebar, tooltips styling, and canvas menu improvements
- Add Templates tab to both v1 sidebar and v2 bottom bar - Add template categories (Official, SDXL, ControlNet, Video, Community) - Style tooltips with JetBrains Mono, smaller size, uppercase - Convert native title attributes to v-tooltip directive - Add workspace/account sections to canvas logo dropdown menu - Move Settings to icon in sidebar footer near Sign out - Add sort/filter features across workspace pages 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import Tooltip from 'primevue/tooltip'
|
||||
|
||||
const vTooltip = Tooltip
|
||||
|
||||
interface MenuItem {
|
||||
label: string
|
||||
@@ -23,28 +26,6 @@ const router = useRouter()
|
||||
|
||||
const isTeam = computed(() => props.workspaceId === 'team')
|
||||
|
||||
// Workspace dropdown
|
||||
const showWorkspaceMenu = ref(false)
|
||||
|
||||
// Mock workspaces for switching
|
||||
const workspaces = [
|
||||
{ id: 'personal', name: 'Personal', type: 'personal' as const },
|
||||
{ id: 'team', name: 'Team Workspace', type: 'team' as const }
|
||||
]
|
||||
|
||||
function toggleWorkspaceMenu(): void {
|
||||
showWorkspaceMenu.value = !showWorkspaceMenu.value
|
||||
}
|
||||
|
||||
function closeWorkspaceMenu(): void {
|
||||
showWorkspaceMenu.value = false
|
||||
}
|
||||
|
||||
function switchWorkspace(workspaceId: string): void {
|
||||
router.push(`/${workspaceId}`)
|
||||
closeWorkspaceMenu()
|
||||
}
|
||||
|
||||
const userMenuGroups = computed<MenuGroup[]>(() => [
|
||||
{
|
||||
label: 'Overview',
|
||||
@@ -109,132 +90,24 @@ function signOut(): void {
|
||||
<aside
|
||||
class="flex h-full w-60 flex-col border-r border-zinc-200 bg-zinc-50/50 dark:border-zinc-800 dark:bg-zinc-950"
|
||||
>
|
||||
<!-- Header with Dropdown -->
|
||||
<div class="relative border-b border-zinc-200 dark:border-zinc-800">
|
||||
<button
|
||||
class="flex h-14 w-full items-center gap-3 px-4 transition-colors hover:bg-zinc-100 dark:hover:bg-zinc-800/50"
|
||||
@click="toggleWorkspaceMenu"
|
||||
>
|
||||
<div
|
||||
:class="[
|
||||
'flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-md text-sm font-semibold',
|
||||
isTeam ? 'bg-blue-600 text-white' : 'bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900'
|
||||
]"
|
||||
>
|
||||
{{ workspaceId.charAt(0).toUpperCase() }}
|
||||
</div>
|
||||
<div class="flex-1 overflow-hidden text-left">
|
||||
<p class="truncate text-sm font-medium text-zinc-900 dark:text-zinc-100">
|
||||
{{ workspaceId }}
|
||||
</p>
|
||||
<p class="text-xs text-zinc-500 dark:text-zinc-400">
|
||||
{{ isTeam ? 'Team' : 'Personal' }}
|
||||
</p>
|
||||
</div>
|
||||
<i
|
||||
:class="[
|
||||
'pi text-xs text-zinc-400 transition-transform',
|
||||
showWorkspaceMenu ? 'pi-chevron-up' : 'pi-chevron-down'
|
||||
]"
|
||||
/>
|
||||
</button>
|
||||
|
||||
<!-- Dropdown Menu -->
|
||||
<!-- Header -->
|
||||
<div class="flex h-14 items-center gap-3 border-b border-zinc-200 px-4 dark:border-zinc-800">
|
||||
<div
|
||||
v-if="showWorkspaceMenu"
|
||||
class="absolute left-2 right-2 top-full z-50 mt-1 rounded-lg border border-zinc-200 bg-white shadow-lg dark:border-zinc-700 dark:bg-zinc-900"
|
||||
:class="[
|
||||
'flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-md text-sm font-semibold',
|
||||
isTeam ? 'bg-blue-600 text-white' : 'bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900'
|
||||
]"
|
||||
>
|
||||
<!-- Account Section -->
|
||||
<div class="border-b border-zinc-100 p-2 dark:border-zinc-800">
|
||||
<p class="px-2 py-1 text-xs font-medium text-zinc-500 dark:text-zinc-400">Account</p>
|
||||
<RouterLink
|
||||
to="/account/profile"
|
||||
class="flex items-center gap-3 rounded-md px-2 py-2 text-sm text-zinc-700 transition-colors hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-800"
|
||||
@click="closeWorkspaceMenu"
|
||||
>
|
||||
<i class="pi pi-user text-zinc-400" />
|
||||
<span>Profile</span>
|
||||
</RouterLink>
|
||||
<RouterLink
|
||||
to="/account/billing"
|
||||
class="flex items-center gap-3 rounded-md px-2 py-2 text-sm text-zinc-700 transition-colors hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-800"
|
||||
@click="closeWorkspaceMenu"
|
||||
>
|
||||
<i class="pi pi-credit-card text-zinc-400" />
|
||||
<span>Billing</span>
|
||||
</RouterLink>
|
||||
</div>
|
||||
|
||||
<!-- Workspaces Section -->
|
||||
<div class="border-b border-zinc-100 p-2 dark:border-zinc-800">
|
||||
<p class="px-2 py-1 text-xs font-medium text-zinc-500 dark:text-zinc-400">Workspaces</p>
|
||||
<button
|
||||
v-for="ws in workspaces"
|
||||
:key="ws.id"
|
||||
class="flex w-full items-center gap-3 rounded-md px-2 py-2 text-left text-sm text-zinc-700 transition-colors hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-800"
|
||||
@click="switchWorkspace(ws.id)"
|
||||
>
|
||||
<div
|
||||
:class="[
|
||||
'flex h-6 w-6 items-center justify-center rounded text-xs font-semibold',
|
||||
ws.type === 'team' ? 'bg-blue-600 text-white' : 'bg-zinc-200 text-zinc-700 dark:bg-zinc-700 dark:text-zinc-300'
|
||||
]"
|
||||
>
|
||||
{{ ws.name.charAt(0) }}
|
||||
</div>
|
||||
<span class="flex-1">{{ ws.name }}</span>
|
||||
<i v-if="ws.id === workspaceId" class="pi pi-check text-xs text-blue-600 dark:text-blue-400" />
|
||||
</button>
|
||||
<button
|
||||
class="flex w-full items-center gap-3 rounded-md px-2 py-2 text-left text-sm text-zinc-500 transition-colors hover:bg-zinc-100 hover:text-zinc-700 dark:text-zinc-400 dark:hover:bg-zinc-800 dark:hover:text-zinc-300"
|
||||
@click="closeWorkspaceMenu"
|
||||
>
|
||||
<div class="flex h-6 w-6 items-center justify-center rounded border border-dashed border-zinc-300 dark:border-zinc-600">
|
||||
<i class="pi pi-plus text-xs" />
|
||||
</div>
|
||||
<span>Create workspace</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- About Section -->
|
||||
<div class="p-2">
|
||||
<RouterLink
|
||||
to="/about"
|
||||
class="flex items-center gap-3 rounded-md px-2 py-2 text-sm text-zinc-700 transition-colors hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-800"
|
||||
@click="closeWorkspaceMenu"
|
||||
>
|
||||
<i class="pi pi-info-circle text-zinc-400" />
|
||||
<span>About</span>
|
||||
</RouterLink>
|
||||
<a
|
||||
href="https://docs.comfy.org"
|
||||
target="_blank"
|
||||
class="flex items-center gap-3 rounded-md px-2 py-2 text-sm text-zinc-700 transition-colors hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-800"
|
||||
@click="closeWorkspaceMenu"
|
||||
>
|
||||
<i class="pi pi-book text-zinc-400" />
|
||||
<span>Documentation</span>
|
||||
<i class="pi pi-external-link ml-auto text-xs text-zinc-400" />
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/comfyanonymous/ComfyUI"
|
||||
target="_blank"
|
||||
class="flex items-center gap-3 rounded-md px-2 py-2 text-sm text-zinc-700 transition-colors hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-800"
|
||||
@click="closeWorkspaceMenu"
|
||||
>
|
||||
<i class="pi pi-github text-zinc-400" />
|
||||
<span>GitHub</span>
|
||||
<i class="pi pi-external-link ml-auto text-xs text-zinc-400" />
|
||||
</a>
|
||||
</div>
|
||||
{{ workspaceId.charAt(0).toUpperCase() }}
|
||||
</div>
|
||||
<div class="flex-1 overflow-hidden">
|
||||
<p class="truncate text-sm font-medium text-zinc-900 dark:text-zinc-100">
|
||||
{{ workspaceId }}
|
||||
</p>
|
||||
<p class="text-xs text-zinc-500 dark:text-zinc-400">
|
||||
{{ isTeam ? 'Team' : 'Personal' }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Backdrop to close menu -->
|
||||
<div
|
||||
v-if="showWorkspaceMenu"
|
||||
class="fixed inset-0 z-40"
|
||||
@click="closeWorkspaceMenu"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Menu Groups -->
|
||||
@@ -279,6 +152,7 @@ function signOut(): void {
|
||||
<!-- Footer -->
|
||||
<div class="flex items-center justify-end gap-1 border-t border-zinc-200 px-3 py-2 dark:border-zinc-800">
|
||||
<RouterLink
|
||||
v-tooltip.top="'Settings'"
|
||||
:to="`/${workspaceId}/settings`"
|
||||
:class="[
|
||||
'flex h-8 w-8 items-center justify-center rounded-md transition-colors',
|
||||
@@ -286,13 +160,12 @@ function signOut(): void {
|
||||
? 'bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900'
|
||||
: 'text-zinc-500 hover:bg-zinc-100 hover:text-zinc-700 dark:text-zinc-400 dark:hover:bg-zinc-800 dark:hover:text-zinc-200'
|
||||
]"
|
||||
title="Settings"
|
||||
>
|
||||
<i class="pi pi-cog text-base" />
|
||||
</RouterLink>
|
||||
<button
|
||||
v-tooltip.top="'Sign out'"
|
||||
class="flex h-8 w-8 items-center justify-center rounded-md text-zinc-500 transition-colors hover:bg-zinc-100 hover:text-zinc-700 dark:text-zinc-400 dark:hover:bg-zinc-800 dark:hover:text-zinc-200"
|
||||
title="Sign out"
|
||||
@click="signOut"
|
||||
>
|
||||
<i class="pi pi-sign-out text-base" />
|
||||
|
||||
Reference in New Issue
Block a user