rework activators

This commit is contained in:
Gauthier Roebroeck 2026-01-15 16:33:33 +08:00
parent be735135cf
commit b5185283b6
2 changed files with 36 additions and 7 deletions

View file

@ -88,6 +88,7 @@
<!-- Bottom left quick action icon -->
<v-icon-btn
v-if="isHovering && quickActionIcon && !hideQuickAction"
v-bind="quickActionPropsOverlay"
:icon="quickActionIcon"
variant="plain"
color="white"
@ -102,10 +103,20 @@
variant="plain"
color="white"
class="bottom-0 right-0 position-absolute"
v-bind="menuProps"
@click.stop="emit('clickMenu')"
@mouseenter="(event: Event) => menuMouseEnter(event)"
/>
</v-overlay>
<!-- Underlay: Bottom left quick action icon -->
<!-- Underlay is necessary to use as activator for dialogs, as the overlay disappears when it loses focus -->
<v-icon-btn
v-bind="quickActionPropsUnderlay"
variant="text"
color="red"
class="bottom-0 left-0 position-absolute"
style="z-index: -50"
/>
</div>
</v-hover>
@ -138,6 +149,7 @@
import type { ItemCardEmits, ItemCardLine, ItemCardProps, ItemCardTitle } from '@/types/ItemCard'
import { vOnLongPress } from '@vueuse/components'
import { usePrimaryInput } from '@/composables/device'
import { reactiveOmit, reactivePick } from '@vueuse/core'
const { isTouchPrimary } = usePrimaryInput()
@ -153,8 +165,8 @@ const {
preSelect = false,
fabIcon,
quickActionIcon,
quickActionProps = {},
menuIcon,
menuMouseEnter = () => {},
} = defineProps<
ItemCardProps & {
/**
@ -185,15 +197,18 @@ const {
* Icon displayed in the bottom-left corner.
*/
quickActionIcon?: string
/**
* Props to pass to the menu icon element.
*/
quickActionProps?: Record<string, unknown>
/**
* Icon displayed in the bottom-right corner.
*/
menuIcon?: string
/**
* Callback function called when the mouse enters the menu button.
* @param event
* Props to pass to the menu icon element.
*/
menuMouseEnter?: (event: Event) => void
menuProps?: object
}
>()
@ -222,6 +237,12 @@ const hideSelection = computed(
const hideFab = computed(() => selected || isPreSelect.value || isTouchPrimary.value)
const hideQuickAction = computed(() => selected || isPreSelect.value || isTouchPrimary.value)
const hideMenu = computed(() => selected || isPreSelect.value || isTouchPrimary.value)
// for the quick action button to work as a dialog activator
// when the dialog is shown, the overlay disappears, along with the activator
// we use an underlay with the same positioning, but a negative z-index, and we map the `id` to the underlay
const quickActionPropsOverlay = reactiveOmit(quickActionProps, 'id')
const quickActionPropsUnderlay = reactivePick(quickActionProps, 'id')
</script>
<style lang="scss">

View file

@ -8,10 +8,10 @@
:top-right-icon="isRead ? 'i-mdi:check' : undefined"
fab-icon="i-mdi:play"
:quick-action-icon="quickActionIcon"
:quick-action-props="quickActionProps"
:menu-icon="menuIcon"
:menu-mouse-enter="(event: Event) => (menuActivator = event.currentTarget as Element)"
:menu-props="menuProps"
v-bind="props"
@mouseenter="editMetadataActivator = `#${id}`"
@selection="(val) => emit('selection', val)"
@click-quick-action="showEditMetadataDialog()"
@card-long-press="bottomSheet = true"
@ -95,7 +95,13 @@ const lines = computed<ItemCardLine[]>(() => {
const { isAdmin } = useCurrentUser()
const quickActionIcon = computed(() => (isAdmin.value ? 'i-mdi:pencil' : undefined))
const quickActionProps = computed(() => ({
id: `${id}_quick`,
}))
const menuIcon = computed(() => (isAdmin.value ? 'i-mdi:dots-vertical' : undefined))
const menuProps = computed(() => ({
onmouseenter: (event: Event) => (menuActivator.value = event.currentTarget as Element),
}))
const {
prepareDialog: prepareEditSeriesMetadataDialog,
@ -103,6 +109,8 @@ const {
activator: editMetadataActivator,
} = useEditSeriesMetadataDialog()
editMetadataActivator.value = `#${id}_quick`
function showEditMetadataDialog() {
prepareEditSeriesMetadataDialog(series)
showEditSeriesMetadataDialog()