Files
ComfyUI_frontend/src/platform/assets/components/UploadModelFooter.vue
Jin Yi 96fd25de5c feat: add Logo C fill and Comfy wave loading indicator components (#9433)
## Summary

Add SVG-based brand loading indicators (LogoCFillLoader,
LogoComfyWaveLoader) and use the wave loader as the app loading screen.

## Changes

- **What**: New `LogoCFillLoader` (bottom-to-top fill, plays once) and
`LogoComfyWaveLoader` (wave water-fill animation) components with
`size`, `color`, `bordered`, and `disableAnimation` props. Move all
loaders from `components/common/` to `components/loader/`. Use
`LogoComfyWaveLoader` in `App.vue` and `WorkspaceAuthGate.vue`. Render
loader above BlockUI overlay (z-1200) to prevent dim wash-out.
- **Dependencies**: None

## Review Focus

- SVG mask-based animation approach using `currentColor` for flexible
theming
- z-index layering: loader at z-1200 renders above PrimeVue BlockUI's
z-1100 modal overlay
- `disableAnimation` prop used in WorkspaceAuthGate to show static logo
outline during auth loading

## Screenshots (if applicable)

[loading_record.webm](https://github.com/user-attachments/assets/b34f7296-9904-4a42-9273-a7d5fda49d15)

Storybook stories added for both components under `Components/Loader/`.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9433-feat-add-Logo-C-fill-and-Comfy-wave-loading-indicator-components-31a6d73d3650811cacfdcf867b1f835f)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-03-06 00:32:20 -08:00

133 lines
3.6 KiB
Vue

<template>
<div class="flex w-full justify-end gap-2">
<div v-if="currentStep === 1" class="mr-auto flex items-center gap-2">
<i class="icon-[lucide--circle-question-mark] text-muted-foreground" />
<Button
variant="muted-textonly"
size="sm"
data-attr="upload-model-step1-help-civitai"
@click="showCivitaiHelp = true"
>
{{ $t('assetBrowser.providerCivitai') }}
</Button>
<Button
variant="muted-textonly"
size="sm"
data-attr="upload-model-step1-help-huggingface"
@click="showHuggingFaceHelp = true"
>
{{ $t('assetBrowser.providerHuggingFace') }}
</Button>
</div>
<Button
v-if="currentStep === 1"
variant="muted-textonly"
size="lg"
data-attr="upload-model-step1-cancel-button"
:disabled="isFetchingMetadata || isUploading"
@click="emit('close')"
>
{{ $t('g.cancel') }}
</Button>
<Button
v-if="currentStep !== 1 && currentStep !== 3"
variant="muted-textonly"
size="lg"
:data-attr="`upload-model-step${currentStep}-back-button`"
:disabled="isFetchingMetadata || isUploading"
@click="emit('back')"
>
{{ $t('g.back') }}
</Button>
<span v-else />
<Button
v-if="currentStep === 1"
variant="secondary"
size="lg"
data-attr="upload-model-step1-continue-button"
:disabled="!canFetchMetadata || isFetchingMetadata"
@click="emit('fetchMetadata')"
>
<Loader v-if="isFetchingMetadata" />
<span>{{ $t('g.continue') }}</span>
</Button>
<Button
v-else-if="currentStep === 2"
variant="secondary"
size="lg"
data-attr="upload-model-step2-confirm-button"
:disabled="!canUploadModel || isUploading"
@click="emit('upload')"
>
<Loader v-if="isUploading" />
<span>{{ $t('assetBrowser.upload') }}</span>
</Button>
<template
v-else-if="
currentStep === 3 &&
(uploadStatus === 'success' || uploadStatus === 'processing')
"
>
<Button
variant="muted-textonly"
size="lg"
data-attr="upload-model-step3-import-another-button"
@click="emit('importAnother')"
>
{{ $t('assetBrowser.importAnother') }}
</Button>
<Button
variant="secondary"
size="lg"
data-attr="upload-model-step3-finish-button"
@click="emit('close')"
>
{{
uploadStatus === 'processing'
? $t('g.close')
: $t('assetBrowser.finish')
}}
</Button>
</template>
<VideoHelpDialog
v-model="showCivitaiHelp"
video-url="https://media.comfy.org/compressed_768/civitai_howto.webm"
:aria-label="$t('assetBrowser.uploadModelHelpVideo')"
/>
<VideoHelpDialog
v-model="showHuggingFaceHelp"
video-url="https://media.comfy.org/byom/huggingfacehowto.mp4"
:aria-label="$t('assetBrowser.uploadModelHelpVideo')"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Loader from '@/components/loader/Loader.vue'
import Button from '@/components/ui/button/Button.vue'
import VideoHelpDialog from '@/platform/assets/components/VideoHelpDialog.vue'
const showCivitaiHelp = ref(false)
const showHuggingFaceHelp = ref(false)
defineProps<{
currentStep: number
isFetchingMetadata: boolean
isUploading: boolean
canFetchMetadata: boolean
canUploadModel: boolean
uploadStatus?: 'processing' | 'success' | 'error'
}>()
const emit = defineEmits<{
(e: 'back'): void
(e: 'fetchMetadata'): void
(e: 'upload'): void
(e: 'close'): void
(e: 'importAnother'): void
}>()
</script>