From 84662cb94c79e40a2c0802c113fe420b11f58a22 Mon Sep 17 00:00:00 2001 From: Benjamin Lu Date: Tue, 13 Jan 2026 16:21:06 -0800 Subject: [PATCH] [QPOv2] Add ... context menu to list view (#7745) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add ... context menu to list view This is the same ... context menu used in the grid view, now moved up to the tab scope so it can be shared between views. Part of the QPO v2 iteration, figma design can be found [here](https://www.figma.com/design/LVilZgHGk5RwWOkVN6yCEK/Queue-Progress-Modal?node-id=3330-37286&m=dev). This will be implemented in a series of stacked PRs that can be reviewed and merged individually. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7745-QPOv2-Add-context-menu-to-list-view-2d26d73d365081329a11ce97472bbf87) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action --- .../sidebar/tabs/AssetsSidebarListView.vue | 28 +++++++- .../sidebar/tabs/AssetsSidebarTab.vue | 68 ++++++++++++++----- .../assets/components/MediaAssetCard.vue | 61 +++-------------- .../components/MediaAssetContextMenu.vue | 2 + 4 files changed, 89 insertions(+), 70 deletions(-) diff --git a/src/components/sidebar/tabs/AssetsSidebarListView.vue b/src/components/sidebar/tabs/AssetsSidebarListView.vue index f750661ba..dd7982fc9 100644 --- a/src/components/sidebar/tabs/AssetsSidebarListView.vue +++ b/src/components/sidebar/tabs/AssetsSidebarListView.vue @@ -74,8 +74,22 @@ " :primary-text="getAssetPrimaryText(item.asset)" :secondary-text="getAssetSecondaryText(item.asset)" + @mouseenter="onAssetEnter(item.asset.id)" + @mouseleave="onAssetLeave(item.asset.id)" + @contextmenu.prevent.stop="emit('context-menu', $event, item.asset)" @click.stop="emit('select-asset', item.asset)" - /> + > + + @@ -111,12 +125,14 @@ const { assets, isSelected } = defineProps<{ const emit = defineEmits<{ (e: 'select-asset', asset: AssetItem): void + (e: 'context-menu', event: MouseEvent, asset: AssetItem): void (e: 'approach-end'): void }>() const { t } = useI18n() const { jobItems } = useJobList() const hoveredJobId = ref(null) +const hoveredAssetId = ref(null) type AssetListItem = { key: string; asset: AssetItem } @@ -192,6 +208,16 @@ function onJobLeave(jobId: string) { } } +function onAssetEnter(assetId: string) { + hoveredAssetId.value = assetId +} + +function onAssetLeave(assetId: string) { + if (hoveredAssetId.value === assetId) { + hoveredAssetId.value = null + } +} + function getJobIconClass(job: JobListItem): string | undefined { const classes = [] const iconName = job.iconName ?? iconForJobState(job.state) diff --git a/src/components/sidebar/tabs/AssetsSidebarTab.vue b/src/components/sidebar/tabs/AssetsSidebarTab.vue index 7da25bb8e..61f6a205e 100644 --- a/src/components/sidebar/tabs/AssetsSidebarTab.vue +++ b/src/components/sidebar/tabs/AssetsSidebarTab.vue @@ -101,6 +101,7 @@ :assets="displayAssets" :is-selected="isSelected" @select-asset="handleAssetSelect" + @context-menu="handleAssetContextMenu" @approach-end="handleApproachEnd" /> @@ -196,6 +190,21 @@ v-model:active-index="galleryActiveIndex" :all-gallery-items="galleryItems" /> + diff --git a/src/platform/assets/components/MediaAssetContextMenu.vue b/src/platform/assets/components/MediaAssetContextMenu.vue index 9325f7a17..fe49c2ca1 100644 --- a/src/platform/assets/components/MediaAssetContextMenu.vue +++ b/src/platform/assets/components/MediaAssetContextMenu.vue @@ -11,6 +11,7 @@ ) } }" + @hide="emit('hide')" >