UI polish: hover lift, skeleton loaders, empty states, badge contrast, transitions
Card & row interactions: - NoteCard, TaskCard, ProjectCard: translateY(-2px) lift on hover + extended transitions - Kanban task cards (ProjectView), note rows: same lift treatment - Task rows in flat/grouped list: soft indigo bg tint on hover - Chat conversation items: left-border accent + bg tint on hover (was border-only) - HomeView project mini-cards: translateY(-2px) lift on hover Global feedback: - Buttons: scale(0.97) on :active press (theme.css, :not(:disabled) scoped) - TagPill: color → primary + indigo bg tint on hover - StatusBadge: increased opacity 15% → 22% + stronger text color for readability Loading & empty states: - TasksListView: shimmer skeleton loader (6 rows) + rich empty state with CTA - ProjectListView: shimmer skeleton cards (4) + rich empty state with CTA - HomeView: section-empty messages for overdue/high-priority/notes sections - ProjectView kanban columns: dashed-border styled empty state Transitions & graph: - WorkspaceView panels: panel-fade opacity transition on show/hide (v-if inner wrap) - GraphView D3 nodes: grow to r*1.3 + bold label on mouseover (150ms transition) - Milestone action buttons: base opacity 0 → 0.35 for discoverability Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -150,13 +150,16 @@ function truncate(text: string | null, max = 120): string {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p v-if="loading" class="loading-msg">Loading...</p>
|
||||
<div v-if="loading" class="skeleton-grid">
|
||||
<div class="skeleton-card" v-for="i in 4" :key="i"></div>
|
||||
</div>
|
||||
<p v-else-if="error" class="error-msg">{{ error }}</p>
|
||||
|
||||
<div v-else-if="filteredProjects.length === 0" class="empty-state">
|
||||
<div v-else-if="filteredProjects.length === 0" class="empty-state-rich">
|
||||
<div class="empty-icon">◈</div>
|
||||
<p class="empty-title">No projects yet</p>
|
||||
<p class="empty-subtitle">Create your first project to organize tasks and notes.</p>
|
||||
<button class="btn-cta" @click="openNewProjectModal">+ New Project</button>
|
||||
<p class="empty-sub">Organise your notes and tasks into a project</p>
|
||||
<button class="empty-action" @click="openNewProjectModal">New project →</button>
|
||||
</div>
|
||||
|
||||
<div v-else class="projects-grid">
|
||||
@@ -327,32 +330,28 @@ function truncate(text: string | null, max = 120): string {
|
||||
color: var(--color-danger);
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
margin-top: 3rem;
|
||||
.empty-state-rich { text-align: center; padding: 3rem 1rem; color: var(--color-text-muted); }
|
||||
.empty-icon { font-size: 2.5rem; margin-bottom: 0.75rem; opacity: 0.3; }
|
||||
.empty-title { font-size: 1rem; font-weight: 600; color: var(--color-text-secondary); margin: 0 0 0.35rem; }
|
||||
.empty-sub { font-size: 0.85rem; margin: 0 0 1rem; }
|
||||
.empty-action { display: inline-block; padding: 0.4rem 1rem; border: 1px solid var(--color-primary); border-radius: var(--radius-sm); color: var(--color-primary); background: none; cursor: pointer; font-size: 0.85rem; transition: background 0.15s, color 0.15s; }
|
||||
.empty-action:hover { background: var(--color-primary); color: #fff; }
|
||||
|
||||
.skeleton-card {
|
||||
height: 140px;
|
||||
border-radius: var(--radius-md);
|
||||
background: linear-gradient(90deg, var(--color-bg-secondary) 25%, var(--color-border) 50%, var(--color-bg-secondary) 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton-shimmer 1.4s ease infinite;
|
||||
}
|
||||
.empty-title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
margin: 0 0 0.25rem;
|
||||
color: var(--color-text);
|
||||
@keyframes skeleton-shimmer {
|
||||
0% { background-position: 200% 0; }
|
||||
100% { background-position: -200% 0; }
|
||||
}
|
||||
.empty-subtitle {
|
||||
color: var(--color-text-muted);
|
||||
margin: 0 0 1rem;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
.btn-cta {
|
||||
display: inline-block;
|
||||
padding: 0.45rem 1rem;
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: var(--radius-sm);
|
||||
text-decoration: none;
|
||||
font-size: 0.9rem;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
.skeleton-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.projects-grid {
|
||||
@@ -367,7 +366,7 @@ function truncate(text: string | null, max = 120): string {
|
||||
border-radius: var(--radius-md);
|
||||
padding: 1rem 1.1rem;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.15s, box-shadow 0.15s;
|
||||
transition: border-color 0.15s, box-shadow 0.15s, transform 0.18s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
@@ -375,6 +374,7 @@ function truncate(text: string | null, max = 120): string {
|
||||
.project-card:hover {
|
||||
border-color: var(--color-primary);
|
||||
box-shadow: 0 2px 8px var(--color-shadow);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
|
||||
Reference in New Issue
Block a user