feat(ui): replace text loading states with skeleton loaders
Add skeleton CSS classes to main.css for consistent loading UI Apply skeleton loading states to Admin, Habitat, Item, Pokemon, Recipe, and Auth views Improve perceived performance and accessibility during data fetching
This commit is contained in:
@@ -5,7 +5,7 @@ import DetailSection from '../components/DetailSection.vue';
|
||||
import EditMeta from '../components/EditMeta.vue';
|
||||
import EntityChips from '../components/EntityChips.vue';
|
||||
import PageHeader from '../components/PageHeader.vue';
|
||||
import StatusMessage from '../components/StatusMessage.vue';
|
||||
import Skeleton from '../components/Skeleton.vue';
|
||||
import { api, type PokemonDetail } from '../services/api';
|
||||
|
||||
const route = useRoute();
|
||||
@@ -81,7 +81,62 @@ onMounted(async () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<StatusMessage v-if="!pokemon" :duration="0">加载中</StatusMessage>
|
||||
<section v-if="!pokemon" class="page-stack" aria-busy="true" aria-label="正在加载 Pokemon 详情">
|
||||
<div class="page-header page-header--skeleton" aria-hidden="true">
|
||||
<div class="page-header__copy">
|
||||
<Skeleton width="142px" />
|
||||
<Skeleton width="280px" height="46px" />
|
||||
<Skeleton width="220px" />
|
||||
<Skeleton width="310px" />
|
||||
</div>
|
||||
<div class="page-header__actions">
|
||||
<Skeleton variant="box" width="88px" height="36px" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-grid" aria-hidden="true">
|
||||
<section class="detail-section skeleton-detail-section">
|
||||
<div class="detail-section__header">
|
||||
<Skeleton width="56px" height="24px" />
|
||||
</div>
|
||||
<div class="detail-section__body">
|
||||
<div class="skeleton-chip-row">
|
||||
<Skeleton v-for="index in 2" :key="index" width="74px" class="skeleton-chip" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="detail-section skeleton-detail-section">
|
||||
<div class="detail-section__header">
|
||||
<Skeleton width="92px" height="24px" />
|
||||
</div>
|
||||
<div class="detail-section__body">
|
||||
<div class="skeleton-chip-row">
|
||||
<Skeleton v-for="index in 4" :key="index" width="82px" class="skeleton-chip" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="detail-section skeleton-detail-section">
|
||||
<div class="detail-section__header">
|
||||
<Skeleton width="68px" height="24px" />
|
||||
</div>
|
||||
<div class="detail-section__body">
|
||||
<ul class="row-list appearance-list skeleton-row-list">
|
||||
<li v-for="index in 3" :key="index" class="skeleton-appearance-row">
|
||||
<Skeleton width="96px" />
|
||||
<div class="skeleton-summary">
|
||||
<div v-for="line in 4" :key="line">
|
||||
<Skeleton width="56px" />
|
||||
<Skeleton :width="line === 4 ? '70%' : '48%'" />
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
<section v-else class="page-stack">
|
||||
<PageHeader :title="`#${pokemon.id} ${pokemon.name}`" :subtitle="`喜欢的环境:${pokemon.environment.name}`">
|
||||
<template #kicker>Pokédex Detail</template>
|
||||
|
||||
Reference in New Issue
Block a user