feat(fe): standardize loading UI using shimmer SkeletonLoader across QueryStateBoundary and AGENTS.md

This commit is contained in:
2026-08-15 21:44:45 +09:00
parent dff10d305a
commit c320318207
4 changed files with 65 additions and 51 deletions
@@ -40,10 +40,11 @@ defineProps<Props>()
<!-- Table skeleton -->
<template v-else-if="type === 'table'">
<div class="skeleton-table">
<div v-for="i in (rows || 5)" :key="i" class="skeleton-table-row">
<div class="skeleton-cell"></div>
<div class="skeleton-cell"></div>
<div class="skeleton-cell"></div>
<div class="skeleton-table-header">
<div v-for="j in 6" :key="j" class="skeleton-header-cell"></div>
</div>
<div v-for="i in (rows || 6)" :key="i" class="skeleton-table-row">
<div v-for="j in 6" :key="j" class="skeleton-cell"></div>
</div>
</div>
</template>
@@ -63,83 +64,89 @@ defineProps<Props>()
<style scoped>
.skeleton-loader {
animation: pulse var(--transition-slow);
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
gap: var(--ks-space-2);
}
@keyframes pulse {
0% {
opacity: 1;
}
50% {
opacity: 0.6;
}
100% {
opacity: 1;
}
.skeleton-line, .skeleton-cell, .skeleton-header-cell, .skeleton-avatar {
background: linear-gradient(90deg, var(--ks-color-neutral-100) 25%, var(--ks-color-neutral-200) 37%, var(--ks-color-neutral-100) 63%);
background-size: 400% 100%;
animation: skeleton-shimmer 1.4s ease infinite;
border-radius: var(--ks-radius-sm);
}
.skeleton-line {
background: var(--color-background-secondary);
border-radius: var(--border-radius-base);
display: block;
margin-bottom: var(--spacing-2);
}
.skeleton-avatar {
width: 40px;
height: 40px;
border-radius: var(--border-radius-full);
background: var(--color-background-secondary);
flex-shrink: 0;
@keyframes skeleton-shimmer {
0% { background-position: 100% 50%; }
100% { background-position: 0 50%; }
}
.skeleton-card {
padding: var(--spacing-4);
background: var(--color-background-primary);
border: var(--border-width-1) solid var(--color-border-secondary);
border-radius: var(--border-radius-lg);
padding: var(--ks-space-3);
background: #fff;
border: 1px solid var(--ks-color-neutral-200);
border-radius: var(--ks-radius-md);
}
.skeleton-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--spacing-3);
}
.skeleton-body {
display: flex;
flex-direction: column;
gap: var(--spacing-2);
margin-bottom: var(--ks-space-2);
}
.skeleton-table {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
gap: 4px;
border: 1px solid var(--ks-color-neutral-200);
border-radius: var(--ks-radius-md);
padding: 6px;
background: #fff;
}
.skeleton-table-header {
display: grid;
grid-template-columns: 80px 2fr 2fr 1fr 1fr 1.5fr;
gap: 8px;
height: 30px;
align-items: center;
border-bottom: 1px solid var(--ks-color-neutral-200);
padding-bottom: 4px;
}
.skeleton-header-cell {
height: 20px;
border-radius: var(--ks-radius-sm);
}
.skeleton-table-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--spacing-2);
margin-bottom: var(--spacing-3);
grid-template-columns: 80px 2fr 2fr 1fr 1fr 1.5fr;
gap: 8px;
height: 28px;
align-items: center;
}
.skeleton-cell {
height: 20px;
background: var(--color-background-secondary);
border-radius: var(--border-radius-base);
height: 18px;
border-radius: var(--ks-radius-sm);
}
.skeleton-list-item {
display: flex;
gap: var(--spacing-3);
margin-bottom: var(--spacing-3);
gap: var(--ks-space-3);
margin-bottom: var(--ks-space-2);
}
.skeleton-list-content {
flex: 1;
display: flex;
flex-direction: column;
gap: var(--spacing-2);
gap: var(--ks-space-2);
}
</style>