mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-26 09:44:06 +00:00
Additional linear tweaks (#8375)
- Textareas have a fixed (larger) height. This was requested by design and I thought I fixed it while back. | Before | After | | ------ | ----- | | <img width="360" alt="before" src="https://github.com/user-attachments/assets/35ecfa42-4812-43b3-9844-4ef1f757ae40" /> | <img width="360" alt="after" src="https://github.com/user-attachments/assets/8d13e114-6524-4f3e-ae61-0d31d754466c" />| - Since the typeform survey popover doesn't work well on mobile, the button will instead open the survey in a new tab for mobile users. - Workaround for the first linear output on local not being automatically selected for display - Add the linear mode toggle to the bottom left of mobile layout <img width="634" height="90" alt="image" src="https://github.com/user-attachments/assets/571c672c-5913-4dc9-84f9-d16c49b4a587" /> - Adds a hamburger menu to the mobile layout providing buttons for opening workflows, templates, and an additional exit linear option. - Button takes up a full line of space, so it doesn't provide much space savings currently. May need some design iteration. <img width="635" height="225" alt="image" src="https://github.com/user-attachments/assets/a305e795-db0d-4265-b64b-04326a69216d" /> And an unrelated tweak requested by Comfy: when opening templates, the searchbar is autofocused. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8375-Additional-linear-tweaks-2f66d73d36508172a5e7e716d0cba873) by [Unito](https://www.unito.io)
This commit is contained in:
@@ -14,7 +14,12 @@
|
||||
</template>
|
||||
|
||||
<template #header>
|
||||
<SearchBox v-model="searchQuery" size="lg" class="max-w-[384px]" />
|
||||
<SearchBox
|
||||
v-model="searchQuery"
|
||||
size="lg"
|
||||
class="max-w-[384px]"
|
||||
autofocus
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #header-right-area>
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
<template>
|
||||
<div
|
||||
class="comfy-vue-side-bar-container group/sidebar-tab flex h-full flex-col"
|
||||
:class="props.class"
|
||||
:class="
|
||||
cn(
|
||||
'comfy-vue-side-bar-container group/sidebar-tab flex h-full flex-col',
|
||||
props.class
|
||||
)
|
||||
"
|
||||
>
|
||||
<div class="comfy-vue-side-bar-header flex flex-col gap-2">
|
||||
<Toolbar
|
||||
@@ -35,6 +39,8 @@
|
||||
import ScrollPanel from 'primevue/scrollpanel'
|
||||
import Toolbar from 'primevue/toolbar'
|
||||
|
||||
import { cn } from '@/utils/tailwindUtil'
|
||||
|
||||
const props = defineProps<{
|
||||
title: string
|
||||
class?: string
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { whenever } from '@vueuse/core'
|
||||
import { breakpointsTailwind, useBreakpoints, whenever } from '@vueuse/core'
|
||||
import { useTemplateRef } from 'vue'
|
||||
|
||||
import Popover from '@/components/ui/Popover.vue'
|
||||
@@ -10,6 +10,7 @@ defineProps<{
|
||||
}>()
|
||||
|
||||
const feedbackRef = useTemplateRef('feedbackRef')
|
||||
const isMobile = useBreakpoints(breakpointsTailwind).smaller('md')
|
||||
|
||||
whenever(feedbackRef, () => {
|
||||
const scriptEl = document.createElement('script')
|
||||
@@ -18,9 +19,20 @@ whenever(feedbackRef, () => {
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<Popover>
|
||||
<Button
|
||||
v-if="isMobile"
|
||||
as="a"
|
||||
:href="`https://form.typeform.com/to/${dataTfWidget}`"
|
||||
target="_blank"
|
||||
variant="inverted"
|
||||
class="rounded-full size-12"
|
||||
v-bind="$attrs"
|
||||
>
|
||||
<i class="icon-[lucide--circle-question-mark] size-6" />
|
||||
</Button>
|
||||
<Popover v-else>
|
||||
<template #button>
|
||||
<Button variant="inverted" class="rounded-full size-12">
|
||||
<Button variant="inverted" class="rounded-full size-12" v-bind="$attrs">
|
||||
<i class="icon-[lucide--circle-question-mark] size-6" />
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
@@ -205,7 +205,7 @@ defineExpose({ runButtonClick })
|
||||
<NodeWidgets
|
||||
:node-data
|
||||
:style="{ background: applyLightThemeColor(nodeData.bgcolor) }"
|
||||
class="py-3 gap-y-3 **:[.col-span-2]:grid-cols-1 not-has-[textarea]:flex-0 rounded-lg max-w-100"
|
||||
class="py-3 gap-y-3 **:[.col-span-2]:grid-cols-1 *:has-[textarea]:h-50 rounded-lg max-w-100"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
@@ -237,7 +237,7 @@ defineExpose({ runButtonClick })
|
||||
:node-data
|
||||
:class="
|
||||
cn(
|
||||
'py-3 gap-y-3 **:[.col-span-2]:grid-cols-1 not-has-[textarea]:flex-0 rounded-lg',
|
||||
'py-3 gap-y-3 **:[.col-span-2]:grid-cols-1 *:has-[textarea]:h-50 rounded-lg',
|
||||
nodeData.hasErrors &&
|
||||
'ring-2 ring-inset ring-node-stroke-error'
|
||||
)
|
||||
|
||||
58
src/renderer/extensions/linearMode/MobileMenu.vue
Normal file
58
src/renderer/extensions/linearMode/MobileMenu.vue
Normal file
@@ -0,0 +1,58 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
CollapsibleRoot,
|
||||
CollapsibleTrigger,
|
||||
CollapsibleContent
|
||||
} from 'reka-ui'
|
||||
|
||||
import WorkflowsSidebarTab from '@/components/sidebar/tabs/WorkflowsSidebarTab.vue'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import Popover from '@/components/ui/Popover.vue'
|
||||
import { useWorkflowTemplateSelectorDialog } from '@/composables/useWorkflowTemplateSelectorDialog'
|
||||
import { t } from '@/i18n'
|
||||
import { useCommandStore } from '@/stores/commandStore'
|
||||
</script>
|
||||
<template>
|
||||
<CollapsibleRoot class="flex flex-col">
|
||||
<CollapsibleTrigger as-child>
|
||||
<Button variant="secondary" class="size-10 self-end m-4 mb-2">
|
||||
<i class="icon-[lucide--menu] size-8" />
|
||||
</Button>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent class="flex gap-2 flex-col">
|
||||
<div class="w-full border-b-2 border-border-subtle" />
|
||||
<Popover>
|
||||
<template #button>
|
||||
<Button variant="secondary" size="lg" class="w-full">
|
||||
<i class="icon-[comfy--workflow]" />
|
||||
{{ t('Workflows') }}
|
||||
</Button>
|
||||
</template>
|
||||
<WorkflowsSidebarTab class="h-300 w-[80vw]" />
|
||||
</Popover>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="lg"
|
||||
class="w-full"
|
||||
@click="useWorkflowTemplateSelectorDialog().show('menu')"
|
||||
>
|
||||
<i class="icon-[comfy--template]" />
|
||||
{{ t('sideToolbar.templates') }}
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="lg"
|
||||
class="w-full"
|
||||
@click="
|
||||
useCommandStore().execute('Comfy.ToggleLinear', {
|
||||
metadata: { source: 'button' }
|
||||
})
|
||||
"
|
||||
>
|
||||
<i class="icon-[lucide--log-out]" />
|
||||
{{ t('linearMode.graphMode') }}
|
||||
</Button>
|
||||
<div class="w-full border-b-2 border-border-subtle" />
|
||||
</CollapsibleContent>
|
||||
</CollapsibleRoot>
|
||||
</template>
|
||||
@@ -156,7 +156,11 @@ watch([selectedIndex, selectedOutput], doEmit)
|
||||
watch(
|
||||
() => outputs.media.value,
|
||||
(newAssets, oldAssets) => {
|
||||
if (newAssets.length === oldAssets.length || oldAssets.length === 0) return
|
||||
if (
|
||||
newAssets.length === oldAssets.length ||
|
||||
(oldAssets.length === 0 && newAssets.length !== 1)
|
||||
)
|
||||
return
|
||||
if (selectedIndex.value[0] <= 0) {
|
||||
selectedIndex.value = [0, 0]
|
||||
return
|
||||
|
||||
@@ -9,6 +9,7 @@ import Splitter from 'primevue/splitter'
|
||||
import SplitterPanel from 'primevue/splitterpanel'
|
||||
import { ref, useTemplateRef } from 'vue'
|
||||
|
||||
import ModeToggle from '@/components/sidebar/ModeToggle.vue'
|
||||
import TopbarBadges from '@/components/topbar/TopbarBadges.vue'
|
||||
import WorkflowTabs from '@/components/topbar/WorkflowTabs.vue'
|
||||
import TypeformPopoverButton from '@/components/ui/TypeformPopoverButton.vue'
|
||||
@@ -17,6 +18,7 @@ import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
import LinearControls from '@/renderer/extensions/linearMode/LinearControls.vue'
|
||||
import LinearPreview from '@/renderer/extensions/linearMode/LinearPreview.vue'
|
||||
import MobileMenu from '@/renderer/extensions/linearMode/MobileMenu.vue'
|
||||
import OutputHistory from '@/renderer/extensions/linearMode/OutputHistory.vue'
|
||||
import { useNodeOutputStore } from '@/stores/imagePreviewStore'
|
||||
import type { ResultItemImpl } from '@/stores/queueStore'
|
||||
@@ -58,6 +60,7 @@ const linearWorkflowRef = useTemplateRef('linearWorkflowRef')
|
||||
v-if="mobileDisplay"
|
||||
class="justify-center border-border-subtle border-t overflow-y-scroll h-[calc(100%-38px)] bg-comfy-menu-bg"
|
||||
>
|
||||
<MobileMenu />
|
||||
<div class="flex flex-col text-muted-foreground">
|
||||
<LinearPreview
|
||||
:latent-preview="
|
||||
@@ -84,12 +87,12 @@ const linearWorkflowRef = useTemplateRef('linearWorkflowRef')
|
||||
"
|
||||
/>
|
||||
<LinearControls ref="linearWorkflowRef" mobile />
|
||||
<div class="text-base-foreground flex items-center gap-4 justify-end m-4">
|
||||
<a
|
||||
href="https://form.typeform.com/to/gmVqFi8l"
|
||||
v-text="t('linearMode.beta')"
|
||||
/>
|
||||
<TypeformPopoverButton data-tf-widget="gmVqFi8l" />
|
||||
<div class="text-base-foreground flex items-center gap-4">
|
||||
<div class="border-r border-border-subtle mr-auto">
|
||||
<ModeToggle class="m-2" />
|
||||
</div>
|
||||
<div v-text="t('linearMode.beta')" />
|
||||
<TypeformPopoverButton data-tf-widget="gmVqFi8l" class="mx-2" />
|
||||
</div>
|
||||
</div>
|
||||
<Splitter
|
||||
|
||||
Reference in New Issue
Block a user