mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-06 13:40:25 +00:00
Component: Button Migration 3: IconTextButton (#7603)
## Summary Replace all the `IconTextButton`s with `Button` ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7603-WIP-Component-Button-Migraion-3-IconTextButton-2cd6d73d365081b7b742fa2172dc2ba8) by [Unito](https://www.unito.io)
This commit is contained in:
@@ -29,19 +29,18 @@
|
||||
:placeholder="$t('g.searchPlaceholder')"
|
||||
class="max-w-96"
|
||||
/>
|
||||
<IconTextButton
|
||||
<Button
|
||||
v-if="isUploadButtonEnabled"
|
||||
type="accent"
|
||||
size="md"
|
||||
class="!h-10 [&>span]:hidden md:[&>span]:inline"
|
||||
variant="primary"
|
||||
:size="breakpoints.md ? 'md' : 'icon'"
|
||||
data-attr="upload-model-button"
|
||||
:label="$t('assetBrowser.uploadModel')"
|
||||
:on-click="showUploadDialog"
|
||||
@click="showUploadDialog"
|
||||
>
|
||||
<template #icon>
|
||||
<i class="icon-[lucide--folder-input]" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<i class="icon-[lucide--folder-input]" />
|
||||
<span class="hidden md:inline">{{
|
||||
$t('assetBrowser.uploadModel')
|
||||
}}</span>
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -64,12 +63,16 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useAsyncState } from '@vueuse/core'
|
||||
import {
|
||||
breakpointsTailwind,
|
||||
useAsyncState,
|
||||
useBreakpoints
|
||||
} from '@vueuse/core'
|
||||
import { computed, provide, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||
import SearchBox from '@/components/common/SearchBox.vue'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import BaseModalLayout from '@/components/widget/layout/BaseModalLayout.vue'
|
||||
import LeftSidePanel from '@/components/widget/panel/LeftSidePanel.vue'
|
||||
import AssetFilterBar from '@/platform/assets/components/AssetFilterBar.vue'
|
||||
@@ -99,6 +102,8 @@ const emit = defineEmits<{
|
||||
close: []
|
||||
}>()
|
||||
|
||||
const breakpoints = useBreakpoints(breakpointsTailwind)
|
||||
|
||||
provide(OnCloseKey, props.onClose ?? (() => {}))
|
||||
|
||||
const fetchAssets = async () => {
|
||||
|
||||
@@ -43,26 +43,24 @@
|
||||
>
|
||||
<MoreButton ref="dropdown-menu-button" size="sm">
|
||||
<template #default>
|
||||
<IconTextButton
|
||||
:label="$t('g.rename')"
|
||||
type="secondary"
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="md"
|
||||
class="justify-start"
|
||||
@click="startAssetRename"
|
||||
>
|
||||
<template #icon>
|
||||
<i class="icon-[lucide--pencil]" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<IconTextButton
|
||||
:label="$t('g.delete')"
|
||||
type="secondary"
|
||||
<i class="icon-[lucide--pencil]" />
|
||||
<span>{{ $t('g.rename') }}</span>
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="md"
|
||||
class="justify-start"
|
||||
@click="confirmDeletion"
|
||||
>
|
||||
<template #icon>
|
||||
<i class="icon-[lucide--trash-2]" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<i class="icon-[lucide--trash-2]" />
|
||||
<span>{{ $t('g.delete') }}</span>
|
||||
</Button>
|
||||
</template>
|
||||
</MoreButton>
|
||||
</IconGroup>
|
||||
@@ -121,10 +119,10 @@ import { computed, ref, toValue, useId, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import IconGroup from '@/components/button/IconGroup.vue'
|
||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||
import MoreButton from '@/components/button/MoreButton.vue'
|
||||
import EditableText from '@/components/common/EditableText.vue'
|
||||
import { showConfirmDialog } from '@/components/dialog/confirm/confirmDialog'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { useFeatureFlags } from '@/composables/useFeatureFlags'
|
||||
import AssetBadgeGroup from '@/platform/assets/components/AssetBadgeGroup.vue'
|
||||
import type { AssetDisplayItem } from '@/platform/assets/composables/useAssetBrowser'
|
||||
|
||||
@@ -70,19 +70,17 @@
|
||||
|
||||
<!-- Output count (top-right) -->
|
||||
<template v-if="showOutputCount" #top-right>
|
||||
<IconTextButton
|
||||
<Button
|
||||
v-tooltip.top.pt:pointer-events-none="
|
||||
$t('mediaAsset.actions.seeMoreOutputs')
|
||||
"
|
||||
type="secondary"
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
:label="String(outputCount)"
|
||||
@click.stop="handleOutputCountClick"
|
||||
>
|
||||
<template #icon>
|
||||
<i class="icon-[lucide--layers] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<i class="icon-[lucide--layers] size-4" />
|
||||
<span>{{ outputCount }}</span>
|
||||
</Button>
|
||||
</template>
|
||||
</CardTop>
|
||||
</template>
|
||||
@@ -130,7 +128,6 @@ import { useElementHover, whenever } from '@vueuse/core'
|
||||
import { computed, defineAsyncComponent, provide, ref, toRef } from 'vue'
|
||||
|
||||
import IconGroup from '@/components/button/IconGroup.vue'
|
||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||
import CardBottom from '@/components/card/CardBottom.vue'
|
||||
import CardContainer from '@/components/card/CardContainer.vue'
|
||||
import CardTop from '@/components/card/CardTop.vue'
|
||||
|
||||
@@ -13,18 +13,17 @@
|
||||
}"
|
||||
>
|
||||
<template #item="{ item, props }">
|
||||
<IconTextButton
|
||||
type="secondary"
|
||||
size="full-width"
|
||||
:label="
|
||||
typeof item.label === 'function' ? item.label() : (item.label ?? '')
|
||||
"
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
class="w-full justify-start"
|
||||
v-bind="props.action"
|
||||
>
|
||||
<template #icon>
|
||||
<i :class="item.icon" class="size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<i :class="item.icon" class="size-4" />
|
||||
<span>{{
|
||||
typeof item.label === 'function' ? item.label() : (item.label ?? '')
|
||||
}}</span>
|
||||
</Button>
|
||||
</template>
|
||||
</ContextMenu>
|
||||
</template>
|
||||
@@ -34,9 +33,9 @@ import { onClickOutside } from '@vueuse/core'
|
||||
import ContextMenu from 'primevue/contextmenu'
|
||||
import type { MenuItem } from 'primevue/menuitem'
|
||||
import { computed, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||
import { t } from '@/i18n'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import { supportsWorkflowMetadata } from '@/platform/workflow/utils/workflowExtractionUtil'
|
||||
import { detectNodeTypeFromFilename } from '@/utils/loaderNodeUtil'
|
||||
@@ -60,6 +59,7 @@ const emit = defineEmits<{
|
||||
|
||||
const contextMenu = ref<InstanceType<typeof ContextMenu>>()
|
||||
const actions = useMediaAssetActions()
|
||||
const { t } = useI18n()
|
||||
|
||||
// Close context menu when clicking outside
|
||||
onClickOutside(
|
||||
|
||||
@@ -25,10 +25,9 @@
|
||||
>
|
||||
<template #default="{ close }">
|
||||
<MediaAssetSortMenu
|
||||
:sort-by="sortBy"
|
||||
v-model:sort-by="sortBy"
|
||||
:show-generation-time-sort
|
||||
:close="close"
|
||||
@update:sort-by="handleSortChange"
|
||||
/>
|
||||
</template>
|
||||
</AssetSortButton>
|
||||
@@ -43,30 +42,25 @@ import MediaAssetFilterButton from './MediaAssetFilterButton.vue'
|
||||
import MediaAssetFilterMenu from './MediaAssetFilterMenu.vue'
|
||||
import AssetSortButton from './MediaAssetSortButton.vue'
|
||||
import MediaAssetSortMenu from './MediaAssetSortMenu.vue'
|
||||
import type { SortBy } from './MediaAssetSortMenu.vue'
|
||||
|
||||
const { showGenerationTimeSort = false } = defineProps<{
|
||||
searchQuery: string
|
||||
sortBy: 'newest' | 'oldest' | 'longest' | 'fastest'
|
||||
showGenerationTimeSort?: boolean
|
||||
mediaTypeFilters: string[]
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:searchQuery': [value: string]
|
||||
'update:sortBy': [value: 'newest' | 'oldest' | 'longest' | 'fastest']
|
||||
'update:mediaTypeFilters': [value: string[]]
|
||||
}>()
|
||||
|
||||
const sortBy = defineModel<SortBy>('sortBy', { required: true })
|
||||
|
||||
const handleSearchChange = (value: string | undefined) => {
|
||||
emit('update:searchQuery', value ?? '')
|
||||
}
|
||||
|
||||
const handleSortChange = (
|
||||
value: 'newest' | 'oldest' | 'longest' | 'fastest'
|
||||
) => {
|
||||
emit('update:sortBy', value)
|
||||
}
|
||||
|
||||
const handleMediaTypeFiltersChange = (value: string[]) => {
|
||||
emit('update:mediaTypeFilters', value)
|
||||
}
|
||||
|
||||
@@ -1,74 +1,59 @@
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<IconTextButton
|
||||
type="transparent"
|
||||
icon-position="right"
|
||||
:label="$t('sideToolbar.mediaAssets.sortNewestFirst')"
|
||||
<Button
|
||||
variant="textonly"
|
||||
class="justify-start"
|
||||
@click="handleSortChange('newest')"
|
||||
>
|
||||
<template #icon>
|
||||
<i v-if="sortBy === 'newest'" class="icon-[lucide--check] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<span>{{ $t('sideToolbar.mediaAssets.sortNewestFirst') }}</span>
|
||||
<i v-if="sortBy === 'newest'" class="icon-[lucide--check] size-4" />
|
||||
</Button>
|
||||
|
||||
<IconTextButton
|
||||
type="transparent"
|
||||
icon-position="right"
|
||||
:label="$t('sideToolbar.mediaAssets.sortOldestFirst')"
|
||||
<Button
|
||||
variant="textonly"
|
||||
class="justify-start"
|
||||
@click="handleSortChange('oldest')"
|
||||
>
|
||||
<template #icon>
|
||||
<i v-if="sortBy === 'oldest'" class="icon-[lucide--check] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<span>{{ $t('sideToolbar.mediaAssets.sortOldestFirst') }}</span>
|
||||
<i v-if="sortBy === 'oldest'" class="icon-[lucide--check] size-4" />
|
||||
</Button>
|
||||
|
||||
<template v-if="showGenerationTimeSort">
|
||||
<IconTextButton
|
||||
type="transparent"
|
||||
icon-position="right"
|
||||
:label="$t('sideToolbar.mediaAssets.sortLongestFirst')"
|
||||
<Button
|
||||
variant="textonly"
|
||||
class="justify-start"
|
||||
@click="handleSortChange('longest')"
|
||||
>
|
||||
<template #icon>
|
||||
<i v-if="sortBy === 'longest'" class="icon-[lucide--check] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<span>{{ $t('sideToolbar.mediaAssets.sortLongestFirst') }}</span>
|
||||
<i v-if="sortBy === 'longest'" class="icon-[lucide--check] size-4" />
|
||||
</Button>
|
||||
|
||||
<IconTextButton
|
||||
type="transparent"
|
||||
icon-position="right"
|
||||
:label="$t('sideToolbar.mediaAssets.sortFastestFirst')"
|
||||
<Button
|
||||
variant="textonly"
|
||||
class="justify-start"
|
||||
@click="handleSortChange('fastest')"
|
||||
>
|
||||
<template #icon>
|
||||
<i v-if="sortBy === 'fastest'" class="icon-[lucide--check] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<span>{{ $t('sideToolbar.mediaAssets.sortFastestFirst') }}</span>
|
||||
<i v-if="sortBy === 'fastest'" class="icon-[lucide--check] size-4" />
|
||||
</Button>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
|
||||
const {
|
||||
sortBy,
|
||||
close,
|
||||
showGenerationTimeSort = false
|
||||
} = defineProps<{
|
||||
sortBy: 'newest' | 'oldest' | 'longest' | 'fastest'
|
||||
export type SortBy = 'newest' | 'oldest' | 'longest' | 'fastest'
|
||||
|
||||
const { close, showGenerationTimeSort = false } = defineProps<{
|
||||
close: () => void
|
||||
showGenerationTimeSort?: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:sortBy': [value: 'newest' | 'oldest' | 'longest' | 'fastest']
|
||||
}>()
|
||||
const sortBy = defineModel<SortBy>('sortBy', { required: true })
|
||||
|
||||
const handleSortChange = (
|
||||
value: 'newest' | 'oldest' | 'longest' | 'fastest'
|
||||
) => {
|
||||
emit('update:sortBy', value)
|
||||
const handleSortChange = (value: SortBy) => {
|
||||
sortBy.value = value
|
||||
close()
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
<template>
|
||||
<div class="flex justify-end gap-2 w-full">
|
||||
<IconTextButton
|
||||
<Button
|
||||
v-if="currentStep === 1"
|
||||
:label="$t('assetBrowser.uploadModelHowDoIFindThis')"
|
||||
type="transparent"
|
||||
size="md"
|
||||
class="mr-auto underline text-muted-foreground"
|
||||
variant="muted-textonly"
|
||||
size="lg"
|
||||
class="mr-auto underline"
|
||||
data-attr="upload-model-step1-help-link"
|
||||
@click="showVideoHelp = true"
|
||||
>
|
||||
<template #icon>
|
||||
<i class="icon-[lucide--circle-question-mark]" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<i class="icon-[lucide--circle-question-mark]" />
|
||||
<span>{{ $t('assetBrowser.uploadModelHowDoIFindThis') }}</span>
|
||||
</Button>
|
||||
<Button
|
||||
v-if="currentStep === 1"
|
||||
variant="muted-textonly"
|
||||
@@ -35,38 +33,31 @@
|
||||
</Button>
|
||||
<span v-else />
|
||||
|
||||
<IconTextButton
|
||||
<Button
|
||||
v-if="currentStep === 1"
|
||||
:label="$t('g.continue')"
|
||||
type="secondary"
|
||||
size="md"
|
||||
variant="secondary"
|
||||
size="lg"
|
||||
data-attr="upload-model-step1-continue-button"
|
||||
:disabled="!canFetchMetadata || isFetchingMetadata"
|
||||
@click="emit('fetchMetadata')"
|
||||
>
|
||||
<template #icon>
|
||||
<i
|
||||
v-if="isFetchingMetadata"
|
||||
class="icon-[lucide--loader-circle] animate-spin"
|
||||
/>
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<IconTextButton
|
||||
<i
|
||||
v-if="isFetchingMetadata"
|
||||
class="icon-[lucide--loader-circle] animate-spin"
|
||||
/>
|
||||
<span>{{ $t('g.continue') }}</span>
|
||||
</Button>
|
||||
<Button
|
||||
v-else-if="currentStep === 2"
|
||||
:label="$t('assetBrowser.upload')"
|
||||
type="secondary"
|
||||
size="md"
|
||||
variant="secondary"
|
||||
size="lg"
|
||||
data-attr="upload-model-step2-confirm-button"
|
||||
:disabled="!canUploadModel || isUploading"
|
||||
@click="emit('upload')"
|
||||
>
|
||||
<template #icon>
|
||||
<i
|
||||
v-if="isUploading"
|
||||
class="icon-[lucide--loader-circle] animate-spin"
|
||||
/>
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<i v-if="isUploading" class="icon-[lucide--loader-circle] animate-spin" />
|
||||
<span>{{ $t('assetBrowser.upload') }}</span>
|
||||
</Button>
|
||||
<Button
|
||||
v-else-if="currentStep === 3 && uploadStatus === 'success'"
|
||||
variant="secondary"
|
||||
@@ -86,7 +77,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import VideoHelpDialog from '@/platform/assets/components/VideoHelpDialog.vue'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user