Skip to content

Commit efc0431

Browse files
pythongosssssgithub-actions
andauthored
Update side toolbar menu (#4946)
Side toolbar menu UI updates ## Summary - Currently the template modal is very hidden. Many users do not find it - The current icons are quite aleatory ## Changes **What**: - Add templates shortcut button - Add item label in normal size - Use custom icon Critical design decisions or edge cases that need attention: - Sidebar tabs registered using custom icons will have their associated command registed with an undefined icon (currently only string icons are accepted, not components). I couldn't see anywhere directly using this icon, but we should consider autogenerating an icon font so we can use classes for our custom icons (or locating and updating locations to support both icon types) ## Screenshots (if applicable) Normal mode: <img width="621" height="1034" alt="image" src="https://github.com/user-attachments/assets/c1d1cee2-004e-4ff8-b3fa-197329b0d2ae" /> Small mode: <img width="176" height="325" alt="image" src="https://github.com/user-attachments/assets/3824b8f6-bc96-4e62-aece-f0265113d2e3" /> ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-4946-Update-side-toolbar-menu-24d6d73d365081c5b2bdc0ee8b61dc50) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <[email protected]>
1 parent 1784e2b commit efc0431

File tree

23 files changed

+218
-19
lines changed

23 files changed

+218
-19
lines changed
Lines changed: 6 additions & 0 deletions
Loading

src/assets/icons/custom/node.svg

Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 5 additions & 0 deletions
Loading

src/components/sidebar/SideToolbar.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@
88
:icon-badge="tab.iconBadge"
99
:tooltip="tab.tooltip"
1010
:tooltip-suffix="getTabTooltipSuffix(tab)"
11+
:label="tab.label || tab.title"
12+
:is-small="isSmall"
1113
:selected="tab.id === selectedTab?.id"
1214
:class="tab.id + '-tab-button'"
1315
@click="onTabClick(tab)"
1416
/>
17+
<SidebarTemplatesButton />
1518
<div class="side-tool-bar-end">
1619
<SidebarLogoutIcon v-if="userStore.isMultiUserServer" />
1720
<SidebarHelpCenterIcon />
@@ -43,6 +46,7 @@ import type { SidebarTabExtension } from '@/types/extensionTypes'
4346
import SidebarHelpCenterIcon from './SidebarHelpCenterIcon.vue'
4447
import SidebarIcon from './SidebarIcon.vue'
4548
import SidebarLogoutIcon from './SidebarLogoutIcon.vue'
49+
import SidebarTemplatesButton from './SidebarTemplatesButton.vue'
4650
4751
const workspaceStore = useWorkspaceStore()
4852
const settingStore = useSettingStore()
@@ -86,7 +90,7 @@ const getTabTooltipSuffix = (tab: SidebarTabExtension) => {
8690
box-shadow: var(--bar-shadow);
8791
8892
--sidebar-width: 4rem;
89-
--sidebar-icon-size: 1.5rem;
93+
--sidebar-icon-size: 1rem;
9094
}
9195
9296
.side-tool-bar-container.small-sidebar {

src/components/sidebar/SidebarIcon.vue

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,29 @@
1919
@click="emit('click', $event)"
2020
>
2121
<template #icon>
22-
<slot name="icon">
23-
<OverlayBadge v-if="shouldShowBadge" :value="overlayValue">
24-
<i :class="icon + ' side-bar-button-icon'" />
25-
</OverlayBadge>
26-
<i v-else :class="icon + ' side-bar-button-icon'" />
27-
</slot>
22+
<div class="side-bar-button-content">
23+
<slot name="icon">
24+
<OverlayBadge v-if="shouldShowBadge" :value="overlayValue">
25+
<i
26+
v-if="typeof icon === 'string'"
27+
:class="icon + ' side-bar-button-icon'"
28+
/>
29+
<component :is="icon" v-else class="side-bar-button-icon" />
30+
</OverlayBadge>
31+
<i
32+
v-else-if="typeof icon === 'string'"
33+
:class="icon + ' side-bar-button-icon'"
34+
/>
35+
<component
36+
:is="icon"
37+
v-else-if="typeof icon === 'object'"
38+
class="side-bar-button-icon"
39+
/>
40+
</slot>
41+
<span v-if="label && !isSmall" class="side-bar-button-label">{{
42+
t(label)
43+
}}</span>
44+
</div>
2845
</template>
2946
</Button>
3047
</template>
@@ -33,6 +50,7 @@
3350
import Button from 'primevue/button'
3451
import OverlayBadge from 'primevue/overlaybadge'
3552
import { computed } from 'vue'
53+
import type { Component } from 'vue'
3654
import { useI18n } from 'vue-i18n'
3755
3856
const { t } = useI18n()
@@ -41,13 +59,17 @@ const {
4159
selected = false,
4260
tooltip = '',
4361
tooltipSuffix = '',
44-
iconBadge = ''
62+
iconBadge = '',
63+
label = '',
64+
isSmall = false
4565
} = defineProps<{
46-
icon?: string
66+
icon?: string | Component
4767
selected?: boolean
4868
tooltip?: string
4969
tooltipSuffix?: string
5070
iconBadge?: string | (() => string | null)
71+
label?: string
72+
isSmall?: boolean
5173
}>()
5274
5375
const emit = defineEmits<{
@@ -74,10 +96,23 @@ const computedTooltip = computed(() => t(tooltip) + tooltipSuffix)
7496
<style scoped>
7597
.side-bar-button {
7698
width: var(--sidebar-width);
77-
height: var(--sidebar-width);
99+
height: calc(var(--sidebar-width) + 0.5rem);
78100
border-radius: 0;
79101
}
80102
103+
.side-tool-bar-end .side-bar-button {
104+
height: var(--sidebar-width);
105+
}
106+
107+
.side-bar-button-content {
108+
@apply flex flex-col items-center gap-2;
109+
}
110+
111+
.side-bar-button-label {
112+
@apply text-[10px] text-center whitespace-nowrap;
113+
line-height: 1;
114+
}
115+
81116
.comfyui-body-left .side-bar-button.side-bar-button-selected,
82117
.comfyui-body-left .side-bar-button.side-bar-button-selected:hover {
83118
border-left: 4px solid var(--p-button-text-primary-color);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<template>
2+
<SidebarIcon
3+
:icon="TemplateIcon"
4+
:tooltip="$t('sideToolbar.templates')"
5+
:label="$t('sideToolbar.labels.templates')"
6+
:is-small="isSmall"
7+
class="templates-tab-button"
8+
@click="openTemplates"
9+
/>
10+
</template>
11+
12+
<script setup lang="ts">
13+
import { computed, defineAsyncComponent, markRaw } from 'vue'
14+
15+
import { useCommandStore } from '@/stores/commandStore'
16+
import { useSettingStore } from '@/stores/settingStore'
17+
18+
import SidebarIcon from './SidebarIcon.vue'
19+
20+
// Import the custom template icon
21+
const TemplateIcon = markRaw(
22+
defineAsyncComponent(() => import('virtual:icons/comfy/template'))
23+
)
24+
25+
const settingStore = useSettingStore()
26+
const commandStore = useCommandStore()
27+
28+
const isSmall = computed(
29+
() => settingStore.get('Comfy.Sidebar.Size') === 'small'
30+
)
31+
32+
const openTemplates = () => {
33+
void commandStore.execute('Comfy.BrowseTemplates')
34+
}
35+
</script>

src/composables/sidebarTabs/useModelLibrarySidebarTab.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
1-
import { markRaw } from 'vue'
1+
import { defineAsyncComponent, markRaw } from 'vue'
22

33
import ModelLibrarySidebarTab from '@/components/sidebar/tabs/ModelLibrarySidebarTab.vue'
44
import { useElectronDownloadStore } from '@/stores/electronDownloadStore'
55
import type { SidebarTabExtension } from '@/types/extensionTypes'
66
import { isElectron } from '@/utils/envUtil'
77

8+
const AiModelIcon = markRaw(
9+
defineAsyncComponent(() => import('virtual:icons/comfy/ai-model'))
10+
)
11+
812
export const useModelLibrarySidebarTab = (): SidebarTabExtension => {
913
return {
1014
id: 'model-library',
11-
icon: 'pi pi-box',
15+
icon: AiModelIcon,
1216
title: 'sideToolbar.modelLibrary',
1317
tooltip: 'sideToolbar.modelLibrary',
18+
label: 'sideToolbar.labels.models',
1419
component: markRaw(ModelLibrarySidebarTab),
1520
type: 'vue',
1621
iconBadge: () => {

src/composables/sidebarTabs/useNodeLibrarySidebarTab.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1-
import { markRaw } from 'vue'
1+
import { defineAsyncComponent, markRaw } from 'vue'
22

33
import NodeLibrarySidebarTab from '@/components/sidebar/tabs/NodeLibrarySidebarTab.vue'
44
import type { SidebarTabExtension } from '@/types/extensionTypes'
55

6+
const NodeIcon = markRaw(
7+
defineAsyncComponent(() => import('virtual:icons/comfy/node'))
8+
)
9+
610
export const useNodeLibrarySidebarTab = (): SidebarTabExtension => {
711
return {
812
id: 'node-library',
9-
icon: 'pi pi-book',
13+
icon: NodeIcon,
1014
title: 'sideToolbar.nodeLibrary',
1115
tooltip: 'sideToolbar.nodeLibrary',
16+
label: 'sideToolbar.labels.nodes',
1217
component: markRaw(NodeLibrarySidebarTab),
1318
type: 'vue'
1419
}

src/composables/sidebarTabs/useQueueSidebarTab.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const useQueueSidebarTab = (): SidebarTabExtension => {
1515
},
1616
title: 'sideToolbar.queue',
1717
tooltip: 'sideToolbar.queue',
18+
label: 'sideToolbar.labels.queue',
1819
component: markRaw(QueueSidebarTab),
1920
type: 'vue'
2021
}

src/composables/sidebarTabs/useWorkflowsSidebarTab.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1-
import { markRaw } from 'vue'
1+
import { defineAsyncComponent, markRaw } from 'vue'
22

33
import WorkflowsSidebarTab from '@/components/sidebar/tabs/WorkflowsSidebarTab.vue'
44
import { useSettingStore } from '@/stores/settingStore'
55
import { useWorkflowStore } from '@/stores/workflowStore'
66
import type { SidebarTabExtension } from '@/types/extensionTypes'
77

8+
const WorkflowIcon = markRaw(
9+
defineAsyncComponent(() => import('virtual:icons/comfy/workflow'))
10+
)
11+
812
export const useWorkflowsSidebarTab = (): SidebarTabExtension => {
913
const settingStore = useSettingStore()
1014
const workflowStore = useWorkflowStore()
1115
return {
1216
id: 'workflows',
13-
icon: 'pi pi-folder-open',
17+
icon: WorkflowIcon,
1418
iconBadge: () => {
1519
if (
1620
settingStore.get('Comfy.Workflow.WorkflowTabsPosition') !== 'Sidebar'
@@ -22,6 +26,7 @@ export const useWorkflowsSidebarTab = (): SidebarTabExtension => {
2226
},
2327
title: 'sideToolbar.workflows',
2428
tooltip: 'sideToolbar.workflows',
29+
label: 'sideToolbar.labels.workflows',
2530
component: markRaw(WorkflowsSidebarTab),
2631
type: 'vue'
2732
}

0 commit comments

Comments
 (0)