mirror of
https://github.com/sendevia/website.git
synced 2026-03-06 07:40:50 +08:00
feat(ArticleMasonry): enhance card animations and accessibility
This commit is contained in:
@@ -52,13 +52,12 @@ const masonryGroups = computed(() => {
|
||||
});
|
||||
|
||||
/**
|
||||
* 计算特定卡片在原始逻辑顺序中的位置
|
||||
* 获取逻辑序号
|
||||
* @param colIndex 列索引
|
||||
* @param rowIndex 列内的行索引
|
||||
* @returns {number} 用于 Tab 导航的顺序索引 (从 1 开始)
|
||||
* @param rowIndex 行索引
|
||||
*/
|
||||
const getTabIndex = (colIndex: number, rowIndex: number): number => {
|
||||
return rowIndex * columnCount.value + colIndex + 1;
|
||||
const getLogicIndex = (colIndex: number, rowIndex: number): number => {
|
||||
return rowIndex * columnCount.value + colIndex;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -82,10 +81,11 @@ const hasDownloadableContent = (item: PostData): boolean => {
|
||||
<template>
|
||||
<div class="ArticleMasonry">
|
||||
<ClientOnly>
|
||||
<div v-for="(column, index) in masonryGroups" :key="index" class="masonry-column">
|
||||
<div v-for="(column, colIndex) in masonryGroups" :key="colIndex" class="masonry-column">
|
||||
<MaterialCard
|
||||
v-for="(item, itemIndex) in column"
|
||||
v-for="(item, rowIndex) in column"
|
||||
:key="item.id"
|
||||
class="entrance"
|
||||
variant="feed"
|
||||
size="m"
|
||||
color="outlined"
|
||||
@@ -95,7 +95,8 @@ const hasDownloadableContent = (item: PostData): boolean => {
|
||||
:date="item.date"
|
||||
:impression="getArticleImage(item)"
|
||||
:downloadable="hasDownloadableContent(item)"
|
||||
:tabindex="getTabIndex(index, itemIndex)"
|
||||
:tabindex="getLogicIndex(colIndex, rowIndex) + 1"
|
||||
:style="{ '--delay': getLogicIndex(colIndex, rowIndex) }"
|
||||
/>
|
||||
</div>
|
||||
</ClientOnly>
|
||||
|
||||
@@ -24,3 +24,14 @@
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes card-entrance {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0px);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 840px) {
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
text-decoration: none;
|
||||
|
||||
overflow: hidden;
|
||||
outline: none;
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
@@ -19,6 +19,8 @@
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
.impression-area {
|
||||
z-index: 1;
|
||||
}
|
||||
@@ -28,6 +30,24 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.entrance {
|
||||
animation: card-entrance var(--md-sys-motion-spring-slow-spatial-duration) calc(min(var(--delay), 20) * 0.08s)
|
||||
var(--md-sys-motion-spring-slow-spatial) forwards;
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
will-change: transform, opacity;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
.content {
|
||||
@include mixin.focus-ring($thickness: 4);
|
||||
|
||||
&::after {
|
||||
background-color: var(--md-sys-state-focus-state-layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.feed {
|
||||
border-radius: var(--md-sys-shape-corner-large);
|
||||
|
||||
@@ -36,6 +56,8 @@
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
|
||||
border-radius: var(--md-sys-shape-corner-large);
|
||||
|
||||
.impression-area {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
@@ -103,14 +125,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:has(img:nth-child(2)) {
|
||||
img:nth-child(2) {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
@@ -162,6 +176,16 @@
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.impression-area .image-container {
|
||||
&:has(img:nth-child(2)) {
|
||||
img:nth-child(2) {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,3 +215,11 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.MaterialCard.entrance {
|
||||
animation: none;
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ span {
|
||||
}
|
||||
|
||||
.MaterialButton,
|
||||
.MaterialCard,
|
||||
.MaterialCard .content,
|
||||
.PrevNext a {
|
||||
&::after {
|
||||
content: "";
|
||||
|
||||
Reference in New Issue
Block a user