mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-21 23:34:31 +00:00
[feat] Replace view mode toggle with settings dropdown menu (#8950)
This commit is contained in:
@@ -751,7 +751,8 @@
|
||||
"filterVideo": "Video",
|
||||
"filterAudio": "Audio",
|
||||
"filter3D": "3D",
|
||||
"filterText": "Text"
|
||||
"filterText": "Text",
|
||||
"viewSettings": "View settings"
|
||||
},
|
||||
"backToAssets": "Back to all assets",
|
||||
"folderView": {
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
<MediaAssetFilterButton
|
||||
v-if="isCloud"
|
||||
v-tooltip.top="{ value: $t('assetBrowser.filterBy') }"
|
||||
size="md"
|
||||
>
|
||||
<template #default="{ close }">
|
||||
<MediaAssetFilterMenu
|
||||
@@ -24,7 +23,6 @@
|
||||
<AssetSortButton
|
||||
v-if="isCloud"
|
||||
v-tooltip.top="{ value: $t('assetBrowser.sortBy') }"
|
||||
size="md"
|
||||
>
|
||||
<template #default="{ close }">
|
||||
<MediaAssetSortMenu
|
||||
@@ -34,7 +32,13 @@
|
||||
/>
|
||||
</template>
|
||||
</AssetSortButton>
|
||||
<MediaAssetViewModeToggle v-model:view-mode="viewMode" />
|
||||
<MediaAssetSettingsButton
|
||||
v-tooltip.top="{ value: $t('sideToolbar.mediaAssets.viewSettings') }"
|
||||
>
|
||||
<template #default="{ close }">
|
||||
<MediaAssetSettingsMenu v-model:view-mode="viewMode" :close />
|
||||
</template>
|
||||
</MediaAssetSettingsButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -48,7 +52,8 @@ import MediaAssetFilterMenu from './MediaAssetFilterMenu.vue'
|
||||
import AssetSortButton from './MediaAssetSortButton.vue'
|
||||
import MediaAssetSortMenu from './MediaAssetSortMenu.vue'
|
||||
import type { SortBy } from './MediaAssetSortMenu.vue'
|
||||
import MediaAssetViewModeToggle from './MediaAssetViewModeToggle.vue'
|
||||
import MediaAssetSettingsButton from './MediaAssetSettingsButton.vue'
|
||||
import MediaAssetSettingsMenu from './MediaAssetSettingsMenu.vue'
|
||||
|
||||
const { showGenerationTimeSort = false } = defineProps<{
|
||||
searchQuery: string
|
||||
|
||||
@@ -1,58 +1,19 @@
|
||||
<template>
|
||||
<div class="relative inline-flex items-center">
|
||||
<Button variant="secondary" size="icon" @click="toggle">
|
||||
<i class="icon-[lucide--list-filter]" />
|
||||
</Button>
|
||||
|
||||
<Popover
|
||||
ref="popover"
|
||||
append-to="#vue-app"
|
||||
auto-z-index
|
||||
:base-z-index="1000"
|
||||
dismissable
|
||||
close-on-escape
|
||||
unstyled
|
||||
:pt="pt"
|
||||
@show="$emit('menuOpened')"
|
||||
@hide="$emit('menuClosed')"
|
||||
>
|
||||
<div class="flex min-w-40 flex-col gap-2 p-2">
|
||||
<slot :close="hide" />
|
||||
</div>
|
||||
<div class="inline-flex items-center">
|
||||
<Popover>
|
||||
<template #button>
|
||||
<Button variant="secondary" size="icon">
|
||||
<i class="icon-[lucide--list-filter]" />
|
||||
</Button>
|
||||
</template>
|
||||
<template #default="{ close }">
|
||||
<slot :close />
|
||||
</template>
|
||||
</Popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Popover from 'primevue/popover'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { cn } from '@/utils/tailwindUtil'
|
||||
|
||||
const popover = ref<InstanceType<typeof Popover>>()
|
||||
|
||||
defineEmits<{
|
||||
menuOpened: []
|
||||
menuClosed: []
|
||||
}>()
|
||||
|
||||
const toggle = (event: Event) => {
|
||||
popover.value?.toggle(event)
|
||||
}
|
||||
|
||||
const hide = () => {
|
||||
popover.value?.hide()
|
||||
}
|
||||
|
||||
const pt = computed(() => ({
|
||||
root: {
|
||||
class: cn('absolute z-50')
|
||||
},
|
||||
content: {
|
||||
class: cn(
|
||||
'mt-1 rounded-lg bg-base-background text-base-foreground border border-border-default shadow-lg'
|
||||
)
|
||||
}
|
||||
}))
|
||||
import Popover from '@/components/ui/Popover.vue'
|
||||
</script>
|
||||
|
||||
@@ -15,7 +15,7 @@ TODO: Extract checkbox pattern into reusable Checkbox component
|
||||
<div
|
||||
v-for="filter in filters"
|
||||
:key="filter.type"
|
||||
class="flex h-10 cursor-pointer items-center gap-2 rounded-lg px-2 hover:bg-secondary-background-hover"
|
||||
class="flex h-10 min-w-32 cursor-pointer items-center gap-2 rounded-lg px-2 hover:bg-secondary-background-hover"
|
||||
tabindex="0"
|
||||
role="checkbox"
|
||||
:aria-checked="mediaTypeFilters.includes(filter.type)"
|
||||
|
||||
23
src/platform/assets/components/MediaAssetSettingsButton.vue
Normal file
23
src/platform/assets/components/MediaAssetSettingsButton.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div class="inline-flex items-center">
|
||||
<Popover>
|
||||
<template #button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="icon"
|
||||
:aria-label="$t('sideToolbar.mediaAssets.viewSettings')"
|
||||
>
|
||||
<i class="icon-[lucide--settings-2]" />
|
||||
</Button>
|
||||
</template>
|
||||
<template #default="{ close }">
|
||||
<slot :close />
|
||||
</template>
|
||||
</Popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import Popover from '@/components/ui/Popover.vue'
|
||||
</script>
|
||||
48
src/platform/assets/components/MediaAssetSettingsMenu.vue
Normal file
48
src/platform/assets/components/MediaAssetSettingsMenu.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<Button
|
||||
variant="textonly"
|
||||
class="w-full"
|
||||
@click="handleViewModeChange('list')"
|
||||
>
|
||||
<span class="flex items-center gap-2">
|
||||
<i class="icon-[lucide--table-of-contents] size-4" />
|
||||
<span>{{ $t('sideToolbar.queueProgressOverlay.viewList') }}</span>
|
||||
</span>
|
||||
<i
|
||||
class="icon-[lucide--check] ml-auto size-4"
|
||||
:class="viewMode !== 'list' && 'opacity-0'"
|
||||
/>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="textonly"
|
||||
class="w-full"
|
||||
@click="handleViewModeChange('grid')"
|
||||
>
|
||||
<span class="flex items-center gap-2">
|
||||
<i class="icon-[lucide--layout-grid] size-4" />
|
||||
<span>{{ $t('sideToolbar.queueProgressOverlay.viewGrid') }}</span>
|
||||
</span>
|
||||
<i
|
||||
class="icon-[lucide--check] ml-auto size-4"
|
||||
:class="viewMode !== 'grid' && 'opacity-0'"
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
|
||||
const { close } = defineProps<{
|
||||
close: () => void
|
||||
}>()
|
||||
|
||||
const viewMode = defineModel<'list' | 'grid'>('viewMode', { required: true })
|
||||
|
||||
function handleViewModeChange(value: 'list' | 'grid') {
|
||||
viewMode.value = value
|
||||
close()
|
||||
}
|
||||
</script>
|
||||
@@ -1,60 +1,19 @@
|
||||
<template>
|
||||
<div class="relative inline-flex items-center">
|
||||
<Button variant="secondary" size="icon" @click="toggle">
|
||||
<i class="icon-[lucide--arrow-up-down]" />
|
||||
</Button>
|
||||
|
||||
<Popover
|
||||
ref="popover"
|
||||
append-to="body"
|
||||
:auto-z-index="true"
|
||||
:base-z-index="1000"
|
||||
:dismissable="true"
|
||||
:close-on-escape="true"
|
||||
unstyled
|
||||
:pt="pt"
|
||||
@show="$emit('menuOpened')"
|
||||
@hide="$emit('menuClosed')"
|
||||
>
|
||||
<div class="flex min-w-40 flex-col gap-2 p-2">
|
||||
<slot :close="hide" />
|
||||
</div>
|
||||
<div class="inline-flex items-center">
|
||||
<Popover>
|
||||
<template #button>
|
||||
<Button variant="secondary" size="icon">
|
||||
<i class="icon-[lucide--arrow-up-down]" />
|
||||
</Button>
|
||||
</template>
|
||||
<template #default="{ close }">
|
||||
<slot :close />
|
||||
</template>
|
||||
</Popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Popover from 'primevue/popover'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { cn } from '@/utils/tailwindUtil'
|
||||
|
||||
const popover = ref<InstanceType<typeof Popover>>()
|
||||
|
||||
defineEmits<{
|
||||
menuOpened: []
|
||||
menuClosed: []
|
||||
}>()
|
||||
|
||||
const toggle = (event: Event) => {
|
||||
popover.value?.toggle(event)
|
||||
}
|
||||
|
||||
const hide = () => {
|
||||
popover.value?.hide()
|
||||
}
|
||||
|
||||
const pt = computed(() => ({
|
||||
root: {
|
||||
class: cn('absolute z-50')
|
||||
},
|
||||
content: {
|
||||
class: cn(
|
||||
'mt-1 rounded-lg',
|
||||
'bg-base-background text-base-foreground border border-border-default',
|
||||
'shadow-lg'
|
||||
)
|
||||
}
|
||||
}))
|
||||
import Popover from '@/components/ui/Popover.vue'
|
||||
</script>
|
||||
|
||||
@@ -2,39 +2,51 @@
|
||||
<div class="flex flex-col">
|
||||
<Button
|
||||
variant="textonly"
|
||||
class="justify-start"
|
||||
class="w-full"
|
||||
@click="handleSortChange('newest')"
|
||||
>
|
||||
<span>{{ $t('sideToolbar.mediaAssets.sortNewestFirst') }}</span>
|
||||
<i v-if="sortBy === 'newest'" class="icon-[lucide--check] size-4" />
|
||||
<i
|
||||
class="icon-[lucide--check] ml-auto size-4"
|
||||
:class="sortBy !== 'newest' && 'opacity-0'"
|
||||
/>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="textonly"
|
||||
class="justify-start"
|
||||
class="w-full"
|
||||
@click="handleSortChange('oldest')"
|
||||
>
|
||||
<span>{{ $t('sideToolbar.mediaAssets.sortOldestFirst') }}</span>
|
||||
<i v-if="sortBy === 'oldest'" class="icon-[lucide--check] size-4" />
|
||||
<i
|
||||
class="icon-[lucide--check] ml-auto size-4"
|
||||
:class="sortBy !== 'oldest' && 'opacity-0'"
|
||||
/>
|
||||
</Button>
|
||||
|
||||
<template v-if="showGenerationTimeSort">
|
||||
<Button
|
||||
variant="textonly"
|
||||
class="justify-start"
|
||||
class="w-full"
|
||||
@click="handleSortChange('longest')"
|
||||
>
|
||||
<span>{{ $t('sideToolbar.mediaAssets.sortLongestFirst') }}</span>
|
||||
<i v-if="sortBy === 'longest'" class="icon-[lucide--check] size-4" />
|
||||
<i
|
||||
class="icon-[lucide--check] ml-auto size-4"
|
||||
:class="sortBy !== 'longest' && 'opacity-0'"
|
||||
/>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="textonly"
|
||||
class="justify-start"
|
||||
class="w-full"
|
||||
@click="handleSortChange('fastest')"
|
||||
>
|
||||
<span>{{ $t('sideToolbar.mediaAssets.sortFastestFirst') }}</span>
|
||||
<i v-if="sortBy === 'fastest'" class="icon-[lucide--check] size-4" />
|
||||
<i
|
||||
class="icon-[lucide--check] ml-auto size-4"
|
||||
:class="sortBy !== 'fastest' && 'opacity-0'"
|
||||
/>
|
||||
</Button>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
<template>
|
||||
<div
|
||||
class="inline-flex items-center gap-1 rounded-lg bg-secondary-background p-1"
|
||||
role="group"
|
||||
>
|
||||
<Button
|
||||
type="button"
|
||||
variant="muted-textonly"
|
||||
size="icon"
|
||||
:aria-label="t('sideToolbar.queueProgressOverlay.viewList')"
|
||||
:aria-pressed="viewMode === 'list'"
|
||||
:class="
|
||||
cn(
|
||||
'rounded-lg',
|
||||
viewMode === 'list'
|
||||
? 'bg-secondary-background-selected text-text-primary hover:bg-secondary-background-selected'
|
||||
: 'text-text-secondary hover:bg-secondary-background-hover'
|
||||
)
|
||||
"
|
||||
@click="viewMode = 'list'"
|
||||
>
|
||||
<i class="icon-[lucide--table-of-contents] size-4" />
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="muted-textonly"
|
||||
size="icon"
|
||||
:aria-label="t('sideToolbar.queueProgressOverlay.viewGrid')"
|
||||
:aria-pressed="viewMode === 'grid'"
|
||||
:class="
|
||||
cn(
|
||||
'rounded-lg',
|
||||
viewMode === 'grid'
|
||||
? 'bg-secondary-background-selected text-text-primary hover:bg-secondary-background-selected'
|
||||
: 'text-text-secondary hover:bg-secondary-background-hover'
|
||||
)
|
||||
"
|
||||
@click="viewMode = 'grid'"
|
||||
>
|
||||
<i class="icon-[lucide--layout-grid] size-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { cn } from '@/utils/tailwindUtil'
|
||||
|
||||
const viewMode = defineModel<'list' | 'grid'>('viewMode', { required: true })
|
||||
|
||||
const { t } = useI18n()
|
||||
</script>
|
||||
Reference in New Issue
Block a user