mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-07 00:36:41 +08:00
fix: 修复卡片 hover 上浮抖动
This commit is contained in:
@@ -46,17 +46,18 @@ const getImgUrl = computed(() => {
|
|||||||
<template>
|
<template>
|
||||||
<VHover>
|
<VHover>
|
||||||
<template #default="hover">
|
<template #default="hover">
|
||||||
<VCard
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
v-bind="hover.props"
|
<div v-bind="hover.props" class="backdrop-card-hover-area">
|
||||||
:height="props.height"
|
<VCard
|
||||||
:width="props.width"
|
:height="props.height"
|
||||||
class="ring-gray-500"
|
:width="props.width"
|
||||||
:class="{
|
class="app-hover-lift-card ring-gray-500"
|
||||||
'transition transform-cpu duration-300 -translate-y-1': hover.isHovering,
|
:class="{
|
||||||
'ring-1': imageLoaded,
|
'app-hover-lift-card--hovering': hover.isHovering,
|
||||||
}"
|
'ring-1': imageLoaded,
|
||||||
@click="goPlay"
|
}"
|
||||||
>
|
@click="goPlay"
|
||||||
|
>
|
||||||
<template #image>
|
<template #image>
|
||||||
<VImg :src="getImgUrl" aspect-ratio="2/3" cover @load="imageLoadHandler" @error="imageErrorHandler">
|
<VImg :src="getImgUrl" aspect-ratio="2/3" cover @load="imageLoadHandler" @error="imageErrorHandler">
|
||||||
<template #placeholder>
|
<template #placeholder>
|
||||||
@@ -86,7 +87,14 @@ const getImgUrl = computed(() => {
|
|||||||
color="success"
|
color="success"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</VHover>
|
</VHover>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.backdrop-card-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -73,16 +73,16 @@ async function deleteDownload() {
|
|||||||
<template>
|
<template>
|
||||||
<VHover>
|
<VHover>
|
||||||
<template #default="hover">
|
<template #default="hover">
|
||||||
<VCard
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
v-if="cardState"
|
<div v-if="cardState" v-bind="hover.props" class="downloading-card-hover-area h-full">
|
||||||
v-bind="hover.props"
|
<VCard
|
||||||
:key="props.info?.hash"
|
:key="props.info?.hash"
|
||||||
class="downloading-card app-surface flex flex-col h-full overflow-hidden"
|
class="downloading-card app-hover-lift-card app-surface flex flex-col h-full overflow-hidden"
|
||||||
:class="{
|
:class="{
|
||||||
'transition transform-cpu duration-300 -translate-y-1': hover.isHovering,
|
'app-hover-lift-card--hovering': hover.isHovering,
|
||||||
}"
|
}"
|
||||||
min-height="150"
|
min-height="150"
|
||||||
>
|
>
|
||||||
<template #image>
|
<template #image>
|
||||||
<VImg
|
<VImg
|
||||||
:src="props.info?.media.image"
|
:src="props.info?.media.image"
|
||||||
@@ -130,7 +130,8 @@ async function deleteDownload() {
|
|||||||
<VBtn color="error" icon="mdi-trash-can-outline" @click="deleteDownload" />
|
<VBtn color="error" icon="mdi-trash-can-outline" @click="deleteDownload" />
|
||||||
</VCardActions>
|
</VCardActions>
|
||||||
</div>
|
</div>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</VHover>
|
</VHover>
|
||||||
</template>
|
</template>
|
||||||
@@ -138,6 +139,10 @@ async function deleteDownload() {
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
/* stylelint-disable selector-pseudo-class-no-unknown */
|
/* stylelint-disable selector-pseudo-class-no-unknown */
|
||||||
|
|
||||||
|
.downloading-card-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.downloading-card-image {
|
.downloading-card-image {
|
||||||
block-size: 100%;
|
block-size: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,15 +156,17 @@ onMounted(async () => {
|
|||||||
<template>
|
<template>
|
||||||
<VHover>
|
<VHover>
|
||||||
<template #default="hover">
|
<template #default="hover">
|
||||||
<VCard
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
v-bind="hover.props"
|
<div v-bind="hover.props" class="library-card-hover-area">
|
||||||
:height="props.height"
|
<VCard
|
||||||
:width="props.width"
|
:height="props.height"
|
||||||
:class="{
|
:width="props.width"
|
||||||
'transition transform-cpu duration-300 -translate-y-1': hover.isHovering,
|
class="app-hover-lift-card"
|
||||||
}"
|
:class="{
|
||||||
@click="goPlay"
|
'app-hover-lift-card--hovering': hover.isHovering,
|
||||||
>
|
}"
|
||||||
|
@click="goPlay"
|
||||||
|
>
|
||||||
<template #image>
|
<template #image>
|
||||||
<canvas ref="canvasRef" width="640" height="360" class="w-full h-full hidden" />
|
<canvas ref="canvasRef" width="640" height="360" class="w-full h-full hidden" />
|
||||||
<VImg :src="imgUrl" aspect-ratio="2/3" cover @load="imageLoadHandler" @error="imageErrorHandler">
|
<VImg :src="imgUrl" aspect-ratio="2/3" cover @load="imageLoadHandler" @error="imageErrorHandler">
|
||||||
@@ -184,7 +186,14 @@ onMounted(async () => {
|
|||||||
</template>
|
</template>
|
||||||
</VImg>
|
</VImg>
|
||||||
</template>
|
</template>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</VHover>
|
</VHover>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.library-card-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -498,9 +498,9 @@ onBeforeUnmount(() => {
|
|||||||
<VCard
|
<VCard
|
||||||
:height="props.height"
|
:height="props.height"
|
||||||
:width="props.width"
|
:width="props.width"
|
||||||
class="outline-none ring-gray-500 media-card"
|
class="app-hover-lift-card outline-none ring-gray-500 media-card"
|
||||||
:class="{
|
:class="{
|
||||||
'transition transform-cpu duration-300 -translate-y-1': hover.isHovering,
|
'app-hover-lift-card--hovering': hover.isHovering,
|
||||||
'ring-1': isImageLoaded,
|
'ring-1': isImageLoaded,
|
||||||
}"
|
}"
|
||||||
@click.stop="goMediaDetail(hover.isHovering ?? false)"
|
@click.stop="goMediaDetail(hover.isHovering ?? false)"
|
||||||
|
|||||||
@@ -75,15 +75,17 @@ function goPersonDetail() {
|
|||||||
<template>
|
<template>
|
||||||
<VHover>
|
<VHover>
|
||||||
<template #default="hover">
|
<template #default="hover">
|
||||||
<VCard
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
v-bind="hover.props"
|
<div v-bind="hover.props" class="person-card-hover-area">
|
||||||
:height="personProps.height"
|
<VCard
|
||||||
:width="personProps.width"
|
:height="personProps.height"
|
||||||
:class="{
|
:width="personProps.width"
|
||||||
'transition transform-cpu duration-300 -translate-y-1': hover.isHovering,
|
class="app-hover-lift-card"
|
||||||
}"
|
:class="{
|
||||||
@click.stop="goPersonDetail"
|
'app-hover-lift-card--hovering': hover.isHovering,
|
||||||
>
|
}"
|
||||||
|
@click.stop="goPersonDetail"
|
||||||
|
>
|
||||||
<div class="person-card relative cursor-pointer ring-gray-700">
|
<div class="person-card relative cursor-pointer ring-gray-700">
|
||||||
<div style="padding-block-end: 150%">
|
<div style="padding-block-end: 150%">
|
||||||
<div class="absolute inset-0 flex h-full w-full flex-col items-center p-2">
|
<div class="absolute inset-0 flex h-full w-full flex-col items-center p-2">
|
||||||
@@ -107,12 +109,17 @@ function goPersonDetail() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</VHover>
|
</VHover>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.person-card-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.person-card {
|
.person-card {
|
||||||
background-image: linear-gradient(
|
background-image: linear-gradient(
|
||||||
45deg,
|
45deg,
|
||||||
|
|||||||
@@ -230,16 +230,17 @@ onUnmounted(() => {
|
|||||||
<div>
|
<div>
|
||||||
<VHover>
|
<VHover>
|
||||||
<template #default="hover">
|
<template #default="hover">
|
||||||
<VCard
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
v-bind="hover.props"
|
<div v-bind="hover.props" class="plugin-app-card-hover-area h-full">
|
||||||
:width="props.width"
|
<VCard
|
||||||
:height="props.height"
|
:width="props.width"
|
||||||
@click="showPluginDetail"
|
:height="props.height"
|
||||||
class="flex flex-col h-full"
|
@click="showPluginDetail"
|
||||||
:class="{
|
class="app-hover-lift-card flex flex-col h-full"
|
||||||
'transition transform-cpu duration-300 -translate-y-1': hover.isHovering,
|
:class="{
|
||||||
}"
|
'app-hover-lift-card--hovering': hover.isHovering,
|
||||||
>
|
}"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="flex-grow"
|
class="flex-grow"
|
||||||
:style="`background: linear-gradient(rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.5) 100%), linear-gradient(${backgroundColor} 0%, ${backgroundColor} 100%)`"
|
:style="`background: linear-gradient(rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.5) 100%), linear-gradient(${backgroundColor} 0%, ${backgroundColor} 100%)`"
|
||||||
@@ -325,13 +326,18 @@ onUnmounted(() => {
|
|||||||
</IconBtn>
|
</IconBtn>
|
||||||
</div>
|
</div>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</VHover>
|
</VHover>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.plugin-app-card-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.plugin-app-card__tags-section {
|
.plugin-app-card__tags-section {
|
||||||
display: flex;
|
display: flex;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -567,19 +567,19 @@ watch(
|
|||||||
<!-- 插件卡片 -->
|
<!-- 插件卡片 -->
|
||||||
<VHover>
|
<VHover>
|
||||||
<template #default="hover">
|
<template #default="hover">
|
||||||
<VCard
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
v-if="isVisible"
|
<div v-if="isVisible" v-bind="hover.props" class="plugin-card-hover-area h-full">
|
||||||
v-bind="hover.props"
|
<VCard
|
||||||
:width="props.width"
|
:width="props.width"
|
||||||
:height="props.height"
|
:height="props.height"
|
||||||
@click="handleCardClick"
|
@click="handleCardClick"
|
||||||
class="flex flex-col h-full"
|
class="app-hover-lift-card flex flex-col h-full"
|
||||||
:class="{
|
:class="{
|
||||||
'transition transform-cpu duration-300 -translate-y-1': hover.isHovering && !props.sortable,
|
'app-hover-lift-card--hovering': hover.isHovering && !props.sortable,
|
||||||
'cursor-move': props.sortable,
|
'cursor-move': props.sortable,
|
||||||
}"
|
}"
|
||||||
:ripple="!props.sortable"
|
:ripple="!props.sortable"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="flex-grow"
|
class="flex-grow"
|
||||||
:style="`background: linear-gradient(rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.5) 100%), linear-gradient(${backgroundColor} 0%, ${backgroundColor} 100%)`"
|
:style="`background: linear-gradient(rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.5) 100%), linear-gradient(${backgroundColor} 0%, ${backgroundColor} 100%)`"
|
||||||
@@ -669,7 +669,8 @@ watch(
|
|||||||
<div v-if="props.plugin?.has_update" class="me-n3 absolute top-0 right-5">
|
<div v-if="props.plugin?.has_update" class="me-n3 absolute top-0 right-5">
|
||||||
<VIcon icon="mdi-new-box" class="text-white" />
|
<VIcon icon="mdi-new-box" class="text-white" />
|
||||||
</div>
|
</div>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</VHover>
|
</VHover>
|
||||||
|
|
||||||
@@ -677,6 +678,10 @@ watch(
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.plugin-card-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.card-cover-blurred::before {
|
.card-cover-blurred::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
/* stylelint-disable-next-line property-no-vendor-prefix */
|
/* stylelint-disable-next-line property-no-vendor-prefix */
|
||||||
|
|||||||
@@ -211,20 +211,21 @@ const dropdownItems = ref([
|
|||||||
<!-- 文件夹卡片 -->
|
<!-- 文件夹卡片 -->
|
||||||
<VHover>
|
<VHover>
|
||||||
<template #default="hover">
|
<template #default="hover">
|
||||||
<VCard
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
v-bind="hover.props"
|
<div v-bind="hover.props" class="plugin-folder-card-hover-area h-full">
|
||||||
:ripple="false"
|
<VCard
|
||||||
:width="props.width"
|
:ripple="false"
|
||||||
:height="props.height"
|
:width="props.width"
|
||||||
min-height="8.5rem"
|
:height="props.height"
|
||||||
@click="handleCardClick"
|
min-height="8.5rem"
|
||||||
class="plugin-folder-card h-full"
|
@click="handleCardClick"
|
||||||
:class="{
|
class="plugin-folder-card app-hover-lift-card h-full"
|
||||||
'plugin-folder-card--mobile': display.mobile,
|
:class="{
|
||||||
'plugin-folder-card--hover': hover.isHovering && !props.sortable,
|
'plugin-folder-card--mobile': display.mobile,
|
||||||
'plugin-folder-card--sortable': props.sortable,
|
'plugin-folder-card--hover': hover.isHovering && !props.sortable,
|
||||||
}"
|
'plugin-folder-card--sortable': props.sortable,
|
||||||
>
|
}"
|
||||||
|
>
|
||||||
<template v-if="backgroundImage" #image>
|
<template v-if="backgroundImage" #image>
|
||||||
<VImg :src="backgroundImage" cover position="top"> </VImg>
|
<VImg :src="backgroundImage" cover position="top"> </VImg>
|
||||||
</template>
|
</template>
|
||||||
@@ -288,25 +289,29 @@ const dropdownItems = ref([
|
|||||||
</VMenu>
|
</VMenu>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</VHover>
|
</VHover>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.plugin-folder-card-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.plugin-folder-card {
|
.plugin-folder-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
||||||
|
|
||||||
&--sortable {
|
&--sortable {
|
||||||
cursor: move;
|
cursor: move;
|
||||||
}
|
}
|
||||||
|
|
||||||
&--hover {
|
&--hover {
|
||||||
transform: translateY(-4px);
|
transform: translate3d(0, -0.25rem, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
&__bg {
|
&__bg {
|
||||||
|
|||||||
@@ -47,16 +47,17 @@ async function goPlay(isHovering: boolean | null = false) {
|
|||||||
<template>
|
<template>
|
||||||
<VHover>
|
<VHover>
|
||||||
<template #default="hover">
|
<template #default="hover">
|
||||||
<VCard
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
v-bind="hover.props"
|
<div v-bind="hover.props" class="poster-card-hover-area">
|
||||||
:height="props.height"
|
<VCard
|
||||||
:width="props.width"
|
:height="props.height"
|
||||||
class="outline-none ring-gray-500"
|
:width="props.width"
|
||||||
:class="{
|
class="app-hover-lift-card outline-none ring-gray-500"
|
||||||
'transition transform-cpu duration-300 -translate-y-1': hover.isHovering,
|
:class="{
|
||||||
'ring-1': isImageLoaded,
|
'app-hover-lift-card--hovering': hover.isHovering,
|
||||||
}"
|
'ring-1': isImageLoaded,
|
||||||
>
|
}"
|
||||||
|
>
|
||||||
<VImg
|
<VImg
|
||||||
aspect-ratio="2/3"
|
aspect-ratio="2/3"
|
||||||
:src="getImgUrl"
|
:src="getImgUrl"
|
||||||
@@ -93,7 +94,14 @@ async function goPlay(isHovering: boolean | null = false) {
|
|||||||
{{ props.media?.title }}
|
{{ props.media?.title }}
|
||||||
</h1>
|
</h1>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</VHover>
|
</VHover>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.poster-card-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -239,25 +239,27 @@ onMounted(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<VCard
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
class="site-card relative h-full flex flex-col overflow-hidden group transition-all duration-300"
|
<div class="site-card-hover-area h-full">
|
||||||
:class="[
|
<VCard
|
||||||
cardProps.site?.is_active ? '' : 'opacity-70',
|
class="site-card app-hover-lift-card relative h-full flex flex-col overflow-hidden group"
|
||||||
{
|
:class="[
|
||||||
'border-error': statColor === 'error',
|
cardProps.site?.is_active ? '' : 'opacity-70',
|
||||||
'border-warning': statColor === 'warning',
|
{
|
||||||
'border-success': statColor === 'success',
|
'border-error': statColor === 'error',
|
||||||
'cursor-pointer hover:-translate-y-1': !cardProps.sortable,
|
'border-warning': statColor === 'warning',
|
||||||
'cursor-move': cardProps.sortable,
|
'border-success': statColor === 'success',
|
||||||
'site-card--sortable': cardProps.sortable,
|
'cursor-pointer site-card--hoverable': !cardProps.sortable,
|
||||||
},
|
'cursor-move': cardProps.sortable,
|
||||||
]"
|
'site-card--sortable': cardProps.sortable,
|
||||||
:ripple="false"
|
},
|
||||||
variant="flat"
|
]"
|
||||||
elevation="0"
|
:ripple="false"
|
||||||
:hover="!cardProps.sortable"
|
variant="flat"
|
||||||
@click="handleCardClick"
|
elevation="0"
|
||||||
>
|
:hover="!cardProps.sortable"
|
||||||
|
@click="handleCardClick"
|
||||||
|
>
|
||||||
<!-- 装饰性状态指示器 -->
|
<!-- 装饰性状态指示器 -->
|
||||||
<div v-if="cardProps.site?.is_active" class="site-status-indicator" :class="statColor"></div>
|
<div v-if="cardProps.site?.is_active" class="site-status-indicator" :class="statColor"></div>
|
||||||
|
|
||||||
@@ -419,11 +421,20 @@ onMounted(() => {
|
|||||||
</VMenu>
|
</VMenu>
|
||||||
</VBtn>
|
</VBtn>
|
||||||
</VSheet>
|
</VSheet>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.site-card-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-card-hover-area:hover .site-card--hoverable {
|
||||||
|
transform: translate3d(0, -0.25rem, 0);
|
||||||
|
}
|
||||||
|
|
||||||
.site-status-indicator {
|
.site-status-indicator {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
@@ -455,7 +466,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 站点卡片悬停时状态指示器变化 */
|
/* 站点卡片悬停时状态指示器变化 */
|
||||||
.site-card:not(.site-card--sortable):hover .site-status-indicator {
|
.site-card-hover-area:hover .site-card:not(.site-card--sortable) .site-status-indicator {
|
||||||
block-size: 2px;
|
block-size: 2px;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
@@ -644,7 +655,7 @@ onMounted(() => {
|
|||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.site-card:hover .site-card-actions {
|
.site-card-hover-area:hover .site-card-actions {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateX(0);
|
transform: translateX(0);
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
|
|||||||
@@ -404,26 +404,27 @@ function handleCardClick() {
|
|||||||
<div>
|
<div>
|
||||||
<VHover>
|
<VHover>
|
||||||
<template #default="hover">
|
<template #default="hover">
|
||||||
<div
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
class="subscribe-card-shell w-full h-full relative"
|
<div v-bind="hover.props" class="subscribe-card-hover-area w-full h-full">
|
||||||
:class="{
|
<div
|
||||||
'transition transform-cpu duration-300 -translate-y-1': hover.isHovering && !props.sortable,
|
class="subscribe-card-shell app-hover-lift-card w-full h-full relative"
|
||||||
'outline-dotted outline-pink-500 outline-2': props.batchMode && props.selected,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<VCard
|
|
||||||
v-bind="hover.props"
|
|
||||||
:key="props.media?.id"
|
|
||||||
class="flex flex-col h-full overflow-hidden"
|
|
||||||
:class="{
|
:class="{
|
||||||
'subscribe-card-paused': subscribeState === 'S',
|
'app-hover-lift-card--hovering': hover.isHovering && !props.sortable,
|
||||||
'subscribe-card-pending-tint': subscribeState === 'P',
|
'outline-dotted outline-pink-500 outline-2': props.batchMode && props.selected,
|
||||||
'cursor-move': props.sortable,
|
|
||||||
}"
|
}"
|
||||||
min-height="150"
|
|
||||||
@click="handleCardClick"
|
|
||||||
:ripple="!props.batchMode && !props.sortable"
|
|
||||||
>
|
>
|
||||||
|
<VCard
|
||||||
|
:key="props.media?.id"
|
||||||
|
class="flex flex-col h-full overflow-hidden"
|
||||||
|
:class="{
|
||||||
|
'subscribe-card-paused': subscribeState === 'S',
|
||||||
|
'subscribe-card-pending-tint': subscribeState === 'P',
|
||||||
|
'cursor-move': props.sortable,
|
||||||
|
}"
|
||||||
|
min-height="150"
|
||||||
|
@click="handleCardClick"
|
||||||
|
:ripple="!props.batchMode && !props.sortable"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-if="bestVersionBadge && imageLoaded"
|
v-if="bestVersionBadge && imageLoaded"
|
||||||
class="best-version-badge"
|
class="best-version-badge"
|
||||||
@@ -568,13 +569,18 @@ function handleCardClick() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</VHover>
|
</VHover>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.subscribe-card-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.subscribe-card-background {
|
.subscribe-card-background {
|
||||||
background-image: linear-gradient(180deg, rgba(31, 41, 55, 47%) 0%, rgb(31, 41, 55) 100%);
|
background-image: linear-gradient(180deg, rgba(31, 41, 55, 47%) 0%, rgb(31, 41, 55) 100%);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,16 +93,17 @@ function doDelete() {
|
|||||||
<div class="h-full">
|
<div class="h-full">
|
||||||
<VHover>
|
<VHover>
|
||||||
<template #default="hover">
|
<template #default="hover">
|
||||||
<div
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
class="w-full h-full overflow-hidden"
|
<div v-bind="hover.props" class="subscribe-share-card-hover-area w-full h-full">
|
||||||
:class="{
|
<div
|
||||||
'transition transform-cpu duration-300 -translate-y-1': hover.isHovering,
|
class="app-hover-lift-card w-full h-full overflow-hidden"
|
||||||
}"
|
:class="{
|
||||||
>
|
'app-hover-lift-card--hovering': hover.isHovering,
|
||||||
|
}"
|
||||||
|
>
|
||||||
<VCard
|
<VCard
|
||||||
v-bind="hover.props"
|
|
||||||
:key="props.media?.id"
|
:key="props.media?.id"
|
||||||
class="flex flex-col h-full"
|
class="app-hover-lift-card flex flex-col h-full"
|
||||||
min-height="150"
|
min-height="150"
|
||||||
@click="showForkSubscribe"
|
@click="showForkSubscribe"
|
||||||
>
|
>
|
||||||
@@ -155,13 +156,18 @@ function doDelete() {
|
|||||||
{{ dateText }}
|
{{ dateText }}
|
||||||
</VCardText>
|
</VCardText>
|
||||||
</div>
|
</div>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</VHover>
|
</VHover>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.subscribe-share-card-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.subscribe-card-background {
|
.subscribe-card-background {
|
||||||
background-image: linear-gradient(180deg, rgba(31, 41, 55, 47%) 0%, rgb(31, 41, 55) 100%);
|
background-image: linear-gradient(180deg, rgba(31, 41, 55, 47%) 0%, rgb(31, 41, 55) 100%);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,12 +100,13 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="h-full">
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
|
<div class="subtitle-card-hover-area h-full">
|
||||||
<VCard
|
<VCard
|
||||||
:width="props.width || '100%'"
|
:width="props.width || '100%'"
|
||||||
:variant="isDownloaded ? 'outlined' : 'flat'"
|
:variant="isDownloaded ? 'outlined' : 'flat'"
|
||||||
@click="handleAddDownload"
|
@click="handleAddDownload"
|
||||||
class="h-full cursor-pointer transition-transform hover:-translate-y-1 duration-300 d-flex flex-column overflow-hidden subtitle-card"
|
class="app-hover-lift-card h-full cursor-pointer d-flex flex-column overflow-hidden subtitle-card"
|
||||||
:class="{ 'border-success border-2 opacity-85': isDownloaded }"
|
:class="{ 'border-success border-2 opacity-85': isDownloaded }"
|
||||||
hover
|
hover
|
||||||
>
|
>
|
||||||
@@ -203,11 +204,19 @@ watch(
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.subtitle-card-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle-card-hover-area:hover .subtitle-card {
|
||||||
|
transform: translate3d(0, -0.25rem, 0);
|
||||||
|
}
|
||||||
|
|
||||||
.subtitle-card {
|
.subtitle-card {
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtitle-card:hover {
|
.subtitle-card-hover-area:hover .subtitle-card {
|
||||||
border-color: rgba(var(--v-theme-primary), 0.3);
|
border-color: rgba(var(--v-theme-primary), 0.3);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -99,10 +99,11 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="w-100">
|
<!-- Hover 命中区域保持静止,避免列表项上浮后底边反复触发 mouseleave。 -->
|
||||||
|
<div class="subtitle-item-hover-area w-100">
|
||||||
<VListItem
|
<VListItem
|
||||||
:value="subtitle?.enclosure"
|
:value="subtitle?.enclosure"
|
||||||
class="pa-3 mb-2 rounded subtitle-item transition-all duration-300 hover:-translate-y-1 overflow-hidden"
|
class="app-hover-lift-card pa-3 mb-2 rounded subtitle-item overflow-hidden"
|
||||||
:class="{ 'border-start border-success border-3 opacity-85': isDownloaded }"
|
:class="{ 'border-start border-success border-3 opacity-85': isDownloaded }"
|
||||||
@click="handleAddDownload"
|
@click="handleAddDownload"
|
||||||
>
|
>
|
||||||
@@ -206,11 +207,19 @@ watch(
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.subtitle-item-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle-item-hover-area:hover .subtitle-item {
|
||||||
|
transform: translate3d(0, -0.25rem, 0);
|
||||||
|
}
|
||||||
|
|
||||||
.subtitle-item {
|
.subtitle-item {
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtitle-item:hover {
|
.subtitle-item-hover-area:hover .subtitle-item {
|
||||||
border-color: rgba(var(--v-theme-primary), 0.3);
|
border-color: rgba(var(--v-theme-primary), 0.3);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -146,12 +146,13 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="h-full">
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
|
<div class="torrent-card-hover-area h-full">
|
||||||
<VCard
|
<VCard
|
||||||
:width="props.width || '100%'"
|
:width="props.width || '100%'"
|
||||||
:variant="isDownloaded ? 'outlined' : 'flat'"
|
:variant="isDownloaded ? 'outlined' : 'flat'"
|
||||||
@click="handleAddDownload(props.torrent)"
|
@click="handleAddDownload(props.torrent)"
|
||||||
class="h-full cursor-pointer transition-transform hover:-translate-y-1 duration-300 d-flex flex-column overflow-hidden torrent-card"
|
class="app-hover-lift-card h-full cursor-pointer d-flex flex-column overflow-hidden torrent-card"
|
||||||
:class="{ 'border-success border-2 opacity-85': isDownloaded }"
|
:class="{ 'border-success border-2 opacity-85': isDownloaded }"
|
||||||
hover
|
hover
|
||||||
>
|
>
|
||||||
@@ -316,12 +317,20 @@ watch(
|
|||||||
inset-inline-end: 0;
|
inset-inline-end: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.torrent-card-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.torrent-card-hover-area:hover .torrent-card {
|
||||||
|
transform: translate3d(0, -0.25rem, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* 卡片悬停效果 */
|
/* 卡片悬停效果 */
|
||||||
.torrent-card {
|
.torrent-card {
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.torrent-card:hover {
|
.torrent-card-hover-area:hover .torrent-card {
|
||||||
border-color: rgba(var(--v-theme-primary), 0.3);
|
border-color: rgba(var(--v-theme-primary), 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,10 +115,11 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="w-100">
|
<!-- Hover 命中区域保持静止,避免列表项上浮后底边反复触发 mouseleave。 -->
|
||||||
|
<div class="torrent-item-hover-area w-100">
|
||||||
<VListItem
|
<VListItem
|
||||||
:value="props.torrent?.torrent_info?.enclosure"
|
:value="props.torrent?.torrent_info?.enclosure"
|
||||||
class="pa-3 mb-2 rounded torrent-item transition-all duration-300 hover:-translate-y-1 overflow-hidden"
|
class="app-hover-lift-card pa-3 mb-2 rounded torrent-item overflow-hidden"
|
||||||
:class="{ 'border-start border-success border-3 opacity-85': isDownloaded }"
|
:class="{ 'border-start border-success border-3 opacity-85': isDownloaded }"
|
||||||
@click="handleAddDownload"
|
@click="handleAddDownload"
|
||||||
>
|
>
|
||||||
@@ -262,11 +263,19 @@ watch(
|
|||||||
inset-inline-end: 0;
|
inset-inline-end: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.torrent-item-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.torrent-item-hover-area:hover .torrent-item {
|
||||||
|
transform: translate3d(0, -0.25rem, 0);
|
||||||
|
}
|
||||||
|
|
||||||
.torrent-item {
|
.torrent-item {
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.torrent-item:hover {
|
.torrent-item-hover-area:hover .torrent-item {
|
||||||
border-color: rgba(var(--v-theme-primary), 0.3);
|
border-color: rgba(var(--v-theme-primary), 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,14 +127,16 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VCard
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
:class="[
|
<div class="user-card-hover-area h-full">
|
||||||
'transition-transform duration-300 hover:-translate-y-1',
|
<VCard
|
||||||
!props.user.is_active ? 'opacity-85 bg-surface-lighten-1' : '',
|
:class="[
|
||||||
]"
|
'app-hover-lift-card',
|
||||||
class="user-card flex flex-column h-full"
|
!props.user.is_active ? 'opacity-85 bg-surface-lighten-1' : '',
|
||||||
@click="editUser"
|
]"
|
||||||
>
|
class="user-card flex flex-column h-full"
|
||||||
|
@click="editUser"
|
||||||
|
>
|
||||||
<div class="user-card__body flex-grow flex-grow-1">
|
<div class="user-card__body flex-grow flex-grow-1">
|
||||||
<!-- 用户头像和基本信息 -->
|
<!-- 用户头像和基本信息 -->
|
||||||
<VCardItem :class="[user.is_superuser ? 'admin-header' : '']">
|
<VCardItem :class="[user.is_superuser ? 'admin-header' : '']">
|
||||||
@@ -302,10 +304,19 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
</div>
|
</div>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.user-card-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-card-hover-area:hover .user-card {
|
||||||
|
transform: translate3d(0, -0.25rem, 0);
|
||||||
|
}
|
||||||
|
|
||||||
.user-card {
|
.user-card {
|
||||||
block-size: 100%;
|
block-size: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,17 +95,18 @@ function doDelete() {
|
|||||||
<div class="h-full">
|
<div class="h-full">
|
||||||
<VHover>
|
<VHover>
|
||||||
<template #default="hover">
|
<template #default="hover">
|
||||||
<VCard
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
v-bind="hover.props"
|
<div v-bind="hover.props" class="workflow-share-card-hover-area h-full">
|
||||||
:key="props.workflow?.id"
|
<VCard
|
||||||
class="workflow-share-card flex flex-col h-full cursor-pointer overflow-hidden"
|
:key="props.workflow?.id"
|
||||||
:class="{
|
class="workflow-share-card app-hover-lift-card flex flex-col h-full cursor-pointer overflow-hidden"
|
||||||
'workflow-share-card--hovering': hover.isHovering,
|
:class="{
|
||||||
}"
|
'app-hover-lift-card--hovering': hover.isHovering,
|
||||||
min-height="150"
|
}"
|
||||||
:style="{ background: gradientStyle }"
|
min-height="150"
|
||||||
@click="showForkWorkflow"
|
:style="{ background: gradientStyle }"
|
||||||
>
|
@click="showForkWorkflow"
|
||||||
|
>
|
||||||
<div class="h-full flex flex-col">
|
<div class="h-full flex flex-col">
|
||||||
<VCardText class="flex items-center pa-3 pb-1 grow">
|
<VCardText class="flex items-center pa-3 pb-1 grow">
|
||||||
<div class="flex flex-col justify-center w-full">
|
<div class="flex flex-col justify-center w-full">
|
||||||
@@ -134,20 +135,16 @@ function doDelete() {
|
|||||||
{{ dateText }}
|
{{ dateText }}
|
||||||
</VCardText>
|
</VCardText>
|
||||||
</div>
|
</div>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</VHover>
|
</VHover>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
// 阴影需要落在实际卡片上,不能被额外的 overflow 容器裁掉。
|
.workflow-share-card-hover-area {
|
||||||
.workflow-share-card {
|
inline-size: 100%;
|
||||||
transition: transform 0.3s ease, box-shadow 0.2s ease;
|
|
||||||
transform: translateZ(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.workflow-share-card--hovering {
|
|
||||||
transform: translate3d(0, -0.25rem, 0);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -220,14 +220,15 @@ const resolveProgress = (item: Workflow) => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="h-full">
|
<div class="h-full">
|
||||||
<VHover v-slot="hover">
|
<VHover v-slot="hover">
|
||||||
<VCard
|
<!-- Hover 命中区域保持静止,避免卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
v-bind="hover.props"
|
<div v-bind="hover.props" class="workflow-task-card-hover-area h-full">
|
||||||
class="mx-auto h-full"
|
<VCard
|
||||||
@click="handleFlow(workflow)"
|
class="app-hover-lift-card mx-auto h-full"
|
||||||
:ripple="false"
|
@click="handleFlow(workflow)"
|
||||||
:loading="loading"
|
:ripple="false"
|
||||||
:class="{ 'transition transform-cpu duration-300 -translate-y-1': hover.isHovering }"
|
:loading="loading"
|
||||||
>
|
:class="{ 'app-hover-lift-card--hovering': hover.isHovering }"
|
||||||
|
>
|
||||||
<VCardItem
|
<VCardItem
|
||||||
class="px-2 py-2"
|
class="px-2 py-2"
|
||||||
:style="{
|
:style="{
|
||||||
@@ -367,7 +368,14 @@ const resolveProgress = (item: Workflow) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
</div>
|
||||||
</VHover>
|
</VHover>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.workflow-task-card-hover-area {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -184,6 +184,16 @@ html[data-theme-radius='extra'] {
|
|||||||
box-shadow: var(--app-surface-shadow) !important;
|
box-shadow: var(--app-surface-shadow) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 统一卡片上浮反馈;hover 命中区域应放在静止外层,避免上浮后底边反复触发 mouseleave。
|
||||||
|
.app-hover-lift-card {
|
||||||
|
transition: transform 0.3s ease, box-shadow 0.2s ease;
|
||||||
|
transform: translateZ(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-hover-lift-card--hovering {
|
||||||
|
transform: translate3d(0, -0.25rem, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// 全局页面与 overlay 动效:短距离、轻缩放,保持快速但不生硬。
|
// 全局页面与 overlay 动效:短距离、轻缩放,保持快速但不生硬。
|
||||||
.mp-page-route {
|
.mp-page-route {
|
||||||
inline-size: 100%;
|
inline-size: 100%;
|
||||||
|
|||||||
@@ -157,11 +157,12 @@ onMounted(() => {
|
|||||||
<VCardText>
|
<VCardText>
|
||||||
<p class="text-body-2 text-medium-emphasis mb-4">{{ t('setupWizard.preferences.quickPresetsDesc') }}</p>
|
<p class="text-body-2 text-medium-emphasis mb-4">{{ t('setupWizard.preferences.quickPresetsDesc') }}</p>
|
||||||
<VRow>
|
<VRow>
|
||||||
<VCol v-for="(preset, key) in presetConfigs" :key="key" cols="12" sm="6" md="3">
|
<!-- Hover 命中区域保持静止,避免预设卡片上浮后底边反复触发 mouseleave。 -->
|
||||||
|
<VCol v-for="(preset, key) in presetConfigs" :key="key" class="preset-card-hover-area" cols="12" sm="6" md="3">
|
||||||
<VCard
|
<VCard
|
||||||
:color="selectedPreset === key ? preset.color : 'default'"
|
:color="selectedPreset === key ? preset.color : 'default'"
|
||||||
:variant="selectedPreset === key ? 'tonal' : 'outlined'"
|
:variant="selectedPreset === key ? 'tonal' : 'outlined'"
|
||||||
class="cursor-pointer preset-card"
|
class="app-hover-lift-card cursor-pointer preset-card"
|
||||||
@click="selectPreset(key)"
|
@click="selectPreset(key)"
|
||||||
>
|
>
|
||||||
<VCardText class="text-center pa-4">
|
<VCardText class="text-center pa-4">
|
||||||
@@ -218,11 +219,10 @@ onMounted(() => {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.cursor-pointer {
|
.cursor-pointer {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.preset-card:hover {
|
.preset-card-hover-area:hover .preset-card {
|
||||||
transform: translateY(-4px);
|
transform: translate3d(0, -0.25rem, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.preset-card:active {
|
.preset-card:active {
|
||||||
|
|||||||
Reference in New Issue
Block a user