feat(10-06): update StorageBrowser — skeleton rows, EmptyState, BreadcrumbBar swap
- Replace FolderBreadcrumb import with BreadcrumbBar + EmptyState imports - Replace <FolderBreadcrumb> with <BreadcrumbBar :root-label="mode === 'cloud' ? 'Cloud' : 'Home'"> - Replace Loading… div with 5 animated skeleton rows (animate-pulse, grid-cols-[2rem_1fr_6rem_8rem_6rem]) - Replace inline empty-state divs with three <EmptyState> blocks (search/in-folder/root) - UX-02 skeleton tests green (4/4)
This commit is contained in:
@@ -4,8 +4,9 @@
|
||||
<!-- ── Sticky toolbar ──────────────────────────────────────────────── -->
|
||||
<div class="sticky top-0 z-10 bg-white border-b border-gray-100">
|
||||
<div class="px-6 py-3 flex items-center gap-3 flex-wrap">
|
||||
<FolderBreadcrumb
|
||||
<BreadcrumbBar
|
||||
:segments="breadcrumb"
|
||||
:root-label="mode === 'cloud' ? 'Cloud' : 'Home'"
|
||||
@navigate="$emit('breadcrumb-navigate', $event)"
|
||||
/>
|
||||
<div class="ml-auto flex items-center gap-2 shrink-0">
|
||||
@@ -223,25 +224,46 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Empty state -->
|
||||
<div
|
||||
v-if="!loading && folders.length === 0 && files.length === 0 && !showNewFolderInput"
|
||||
class="px-4 py-10 text-center text-gray-300"
|
||||
>
|
||||
<p class="text-gray-400 text-sm">{{ emptyMessage }}</p>
|
||||
<p class="text-xs mt-1">{{ emptyHint }}</p>
|
||||
</div>
|
||||
<template v-if="loading">
|
||||
<div
|
||||
v-for="n in 5"
|
||||
:key="`sk-${n}`"
|
||||
class="px-4 py-2.5 grid grid-cols-[2rem_1fr_6rem_8rem_6rem] gap-3 items-center border-b border-gray-100"
|
||||
>
|
||||
<div class="w-7 h-7 bg-gray-100 rounded-lg animate-pulse"></div>
|
||||
<div class="h-4 bg-gray-100 rounded animate-pulse w-2/3"></div>
|
||||
<div class="h-3 bg-gray-100 rounded animate-pulse hidden md:block"></div>
|
||||
<div class="h-3 bg-gray-100 rounded animate-pulse hidden sm:block"></div>
|
||||
<div class="w-14 h-3 bg-gray-100 rounded animate-pulse"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Search no-results -->
|
||||
<div
|
||||
v-else-if="searchQuery && files.length === 0 && folders.length === 0"
|
||||
class="px-4 py-10 text-center text-sm text-gray-400"
|
||||
<EmptyState
|
||||
v-else-if="searchQuery && folders.length === 0 && files.length === 0"
|
||||
icon="search"
|
||||
:headline="`No results for "${searchQuery}"`"
|
||||
subtext="Try a different search term or clear the filter."
|
||||
>
|
||||
No items match "{{ searchQuery }}".
|
||||
</div>
|
||||
<template #cta>
|
||||
<button @click="$emit('search-change', '')" class="mt-3 text-sm text-indigo-600 hover:underline">
|
||||
Clear search
|
||||
</button>
|
||||
</template>
|
||||
</EmptyState>
|
||||
|
||||
<!-- Loading -->
|
||||
<div v-if="loading" class="py-6 text-center text-sm text-gray-400">Loading…</div>
|
||||
<EmptyState
|
||||
v-else-if="breadcrumb.length > 0 && folders.length === 0 && files.length === 0 && !showNewFolderInput"
|
||||
icon="document"
|
||||
:headline="emptyMessage"
|
||||
:subtext="emptyHint"
|
||||
/>
|
||||
|
||||
<EmptyState
|
||||
v-else-if="folders.length === 0 && files.length === 0 && !showNewFolderInput"
|
||||
icon="folder"
|
||||
:headline="emptyMessage"
|
||||
:subtext="emptyHint"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -249,7 +271,8 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, nextTick, onMounted, onUnmounted } from 'vue'
|
||||
import FolderBreadcrumb from '../folders/FolderBreadcrumb.vue'
|
||||
import BreadcrumbBar from '../ui/BreadcrumbBar.vue'
|
||||
import EmptyState from '../ui/EmptyState.vue'
|
||||
import SearchBar from '../documents/SearchBar.vue'
|
||||
import SortControls from '../documents/SortControls.vue'
|
||||
import DropZone from '../upload/DropZone.vue'
|
||||
|
||||
Reference in New Issue
Block a user