feat/fix: App mode QA fixes (#9530)

## Summary

Additional updates for app mode

## Changes

- **What**:
- Reposition toolbar button in app mode so it doesnt jump between modes
- Move node name to under title on input/output selection
- Change delete asset button text
- Change exit builder button icon

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9530-feat-fix-App-mode-QA-fixes-31c6d73d365081738b5cc5beaf2cbd41)
by [Unito](https://www.unito.io)
This commit is contained in:
pythongosssss
2026-03-07 18:54:13 +00:00
committed by GitHub
parent ca2d61f393
commit 5bb742ac3a
6 changed files with 89 additions and 65 deletions

View File

@@ -46,71 +46,74 @@ function showApps() {
</script> </script>
<template> <template>
<div class="pointer-events-auto flex flex-col gap-2"> <div class="pointer-events-auto flex flex-row items-start gap-2">
<WorkflowActionsDropdown source="app_mode_toolbar" /> <div class="pointer-events-auto flex flex-col gap-2">
<Button
v-if="enableAppBuilder"
v-tooltip.right="{
value: t('linearMode.appModeToolbar.appBuilder'),
...tooltipOptions
}"
variant="secondary"
size="unset"
:disabled="!hasNodes"
:aria-label="t('linearMode.appModeToolbar.appBuilder')"
class="size-10 rounded-lg"
@click="enterBuilder"
>
<i class="icon-[lucide--hammer] size-4" />
</Button>
<Button
v-if="isCloud && flags.workflowSharingEnabled"
v-tooltip.right="{
value: t('actionbar.shareTooltip'),
...tooltipOptions
}"
variant="secondary"
size="unset"
:aria-label="t('actionbar.shareTooltip')"
class="size-10 rounded-lg"
@click="() => openShareDialog().catch(toastErrorHandler)"
@pointerenter="prefetchShareDialog"
>
<i class="icon-[lucide--send] size-4" />
</Button>
<div
class="flex w-10 flex-col overflow-hidden rounded-lg bg-secondary-background"
>
<Button <Button
v-if="enableAppBuilder"
v-tooltip.right="{ v-tooltip.right="{
value: t('sideToolbar.mediaAssets.title'), value: t('linearMode.appModeToolbar.appBuilder'),
...tooltipOptions ...tooltipOptions
}" }"
variant="textonly" variant="secondary"
size="unset" size="unset"
:aria-label="t('sideToolbar.mediaAssets.title')" :disabled="!hasNodes"
:class=" :aria-label="t('linearMode.appModeToolbar.appBuilder')"
cn('size-10', isAssetsActive && 'bg-secondary-background-hover') class="size-10 rounded-lg"
" @click="enterBuilder"
@click="openAssets"
> >
<i class="icon-[comfy--image-ai-edit] size-4" /> <i class="icon-[lucide--hammer] size-4" />
</Button> </Button>
<Button <Button
v-if="isCloud && flags.workflowSharingEnabled"
v-tooltip.right="{ v-tooltip.right="{
value: t('linearMode.appModeToolbar.apps'), value: t('actionbar.shareTooltip'),
...tooltipOptions ...tooltipOptions
}" }"
variant="textonly" variant="secondary"
size="unset" size="unset"
:aria-label="t('linearMode.appModeToolbar.apps')" :aria-label="t('actionbar.shareTooltip')"
:class="cn('size-10', isAppsActive && 'bg-secondary-background-hover')" class="size-10 rounded-lg"
@click="showApps" @click="() => openShareDialog().catch(toastErrorHandler)"
@pointerenter="prefetchShareDialog"
> >
<i class="icon-[lucide--panels-top-left] size-4" /> <i class="icon-[lucide--send] size-4" />
</Button> </Button>
<div
class="flex w-10 flex-col overflow-hidden rounded-lg bg-secondary-background"
>
<Button
v-tooltip.right="{
value: t('sideToolbar.mediaAssets.title'),
...tooltipOptions
}"
variant="textonly"
size="unset"
:aria-label="t('sideToolbar.mediaAssets.title')"
:class="
cn('size-10', isAssetsActive && 'bg-secondary-background-hover')
"
@click="openAssets"
>
<i class="icon-[comfy--image-ai-edit] size-4" />
</Button>
<Button
v-tooltip.right="{
value: t('linearMode.appModeToolbar.apps'),
...tooltipOptions
}"
variant="textonly"
size="unset"
:aria-label="t('linearMode.appModeToolbar.apps')"
:class="
cn('size-10', isAppsActive && 'bg-secondary-background-hover')
"
@click="showApps"
>
<i class="icon-[lucide--panels-top-left] size-4" />
</Button>
</div>
</div> </div>
<WorkflowActionsDropdown source="app_mode_toolbar" />
</div> </div>
</template> </template>

View File

@@ -72,7 +72,7 @@ const menuItems = computed(() => [
}, },
{ {
label: t('builderMenu.exitAppBuilder'), label: t('builderMenu.exitAppBuilder'),
icon: 'icon-[lucide--square-pen]', icon: 'icon-[lucide--x]',
action: onExitBuilder action: onExitBuilder
} }
]) ])

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Popover from '@/components/ui/Popover.vue' import Popover from '@/components/ui/Popover.vue'
@@ -7,6 +7,13 @@ import Button from '@/components/ui/button/Button.vue'
const { t } = useI18n() const { t } = useI18n()
const titleTooltip = ref<string | null>(null)
const subTitleTooltip = ref<string | null>(null)
function isTruncated(e: MouseEvent): boolean {
const el = e.currentTarget as HTMLElement
return el.scrollWidth > el.clientWidth
}
const { rename, remove } = defineProps<{ const { rename, remove } = defineProps<{
title: string title: string
subTitle?: string subTitle?: string
@@ -32,15 +39,28 @@ const entries = computed(() => {
}) })
</script> </script>
<template> <template>
<div class="my-2 flex items-center-safe gap-2 rounded-lg p-2"> <div
<div class="my-2 flex items-center-safe gap-2 rounded-lg p-2"
class="drag-handle mr-auto inline max-w-max min-w-0 flex-[4_1_0%] truncate" data-testid="builder-io-item"
v-text="title" >
/> <div class="drag-handle mr-auto flex min-w-0 flex-col gap-1">
<div <div
class="drag-handle inline max-w-max min-w-0 flex-[2_1_0%] truncate text-end text-muted-foreground" v-tooltip.left="{ value: titleTooltip, showDelay: 300 }"
v-text="subTitle" class="drag-handle truncate text-sm"
/> data-testid="builder-io-item-title"
@mouseenter="titleTooltip = isTruncated($event) ? title : null"
v-text="title"
/>
<div
v-tooltip.left="{ value: subTitleTooltip, showDelay: 300 }"
class="drag-handle truncate text-xs text-muted-foreground"
data-testid="builder-io-item-subtitle"
@mouseenter="
subTitleTooltip = isTruncated($event) ? (subTitle ?? null) : null
"
v-text="subTitle"
/>
</div>
<Popover :entries> <Popover :entries>
<template #button> <template #button>
<Button variant="muted-textonly"> <Button variant="muted-textonly">

View File

@@ -3178,6 +3178,7 @@
"backToWorkflow": "Back to workflow", "backToWorkflow": "Back to workflow",
"loadTemplate": "Load a template", "loadTemplate": "Load a template",
"cancelThisRun": "Cancel this run", "cancelThisRun": "Cancel this run",
"deleteAllAssets": "Delete all assets from this run",
"welcome": { "welcome": {
"title": "App Mode", "title": "App Mode",
"message": "A simplified view that hides the node graph so you can focus on creating.", "message": "A simplified view that hides the node graph so you can focus on creating.",

View File

@@ -126,7 +126,7 @@ async function rerun(e: Event) {
: []), : []),
{ {
icon: 'icon-[lucide--trash-2]', icon: 'icon-[lucide--trash-2]',
label: t('queue.jobMenu.deleteAsset'), label: t('linearMode.deleteAllAssets'),
command: () => mediaActions.deleteAssets(selectedItem!) command: () => mediaActions.deleteAssets(selectedItem!)
} }
]" ]"

View File

@@ -145,13 +145,13 @@ const linearWorkflowRef = useTemplateRef('linearWorkflowRef')
class="relative flex min-w-[20vw] flex-col gap-4 text-muted-foreground outline-none" class="relative flex min-w-[20vw] flex-col gap-4 text-muted-foreground outline-none"
> >
<LinearProgressBar <LinearProgressBar
class="absolute top-0 left-0 z-21 w-[calc(100%+16px)]" class="absolute top-0 left-0 z-21 h-1 w-[calc(100%+16px)]"
/> />
<LinearPreview <LinearPreview
:run-button-click="linearWorkflowRef?.runButtonClick" :run-button-click="linearWorkflowRef?.runButtonClick"
:typeform-widget-id="TYPEFORM_WIDGET_ID" :typeform-widget-id="TYPEFORM_WIDGET_ID"
/> />
<div class="absolute top-4 left-4 z-21"> <div class="absolute top-2 left-4.5 z-21">
<AppModeToolbar v-if="!isBuilderMode" /> <AppModeToolbar v-if="!isBuilderMode" />
</div> </div>
<div ref="bottomLeftRef" class="absolute bottom-7 left-4 z-20" /> <div ref="bottomLeftRef" class="absolute bottom-7 left-4 z-20" />