feat: add transitions and micro-interactions across all views

- Page transitions with slide-up/fade on route changes (App.vue)
- NavRail sliding active indicator with spring-like easing
- List enter/leave/move animations on Entries, Projects, Clients, Timer
- Modal enter/leave transitions with scale+fade on all dialogs
- Dropdown transitions with overshoot on all select/picker components
- Button feedback (scale on hover/active), card hover lift effects
- Timer pulse on start, glow on stop, floating empty state icons
- Content fade-in on Dashboard, Reports, Calendar, Timesheet
- Tag chip enter/leave animations in AppTagInput
- Progress bar smooth width transitions
- Implementation plan document
This commit is contained in:
Your Name
2026-02-18 11:33:58 +02:00
parent c66e71f57d
commit a3a6ab2fdf
16 changed files with 2115 additions and 144 deletions

View File

@@ -12,11 +12,12 @@
</div>
<!-- Projects Grid -->
<div v-if="projectsStore.projects.length > 0" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<TransitionGroup v-if="projectsStore.projects.length > 0" name="list" tag="div" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div
v-for="project in projectsStore.projects"
v-for="(project, index) in projectsStore.projects"
:key="project.id"
class="group bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] hover:bg-bg-elevated transition-all duration-150 cursor-pointer"
class="group bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] card-hover cursor-pointer"
:style="{ transitionDelay: `${index * 30}ms` }"
@click="openEditDialog(project)"
>
<div class="flex border-l-[2px] hover:border-l-[3px] rounded-l-lg transition-all duration-150" :style="{ borderLeftColor: project.color }">
@@ -54,7 +55,7 @@
</div>
<div class="w-full bg-bg-elevated rounded-full h-1">
<div
class="h-1 rounded-full transition-all"
class="h-1 rounded-full progress-bar"
:class="getBudgetPct(project) > 90 ? 'bg-status-error' : getBudgetPct(project) > 75 ? 'bg-status-warning' : 'bg-accent'"
:style="{ width: Math.min(getBudgetPct(project), 100) + '%' }"
/>
@@ -63,11 +64,11 @@
</div>
</div>
</div>
</div>
</TransitionGroup>
<!-- Empty State -->
<div v-else class="flex flex-col items-center justify-center py-16">
<FolderKanban class="w-12 h-12 text-text-tertiary" :stroke-width="1.5" />
<FolderKanban class="w-12 h-12 text-text-tertiary animate-float" :stroke-width="1.5" />
<p class="text-sm text-text-secondary mt-4">No projects yet</p>
<p class="text-xs text-text-tertiary mt-2 max-w-xs text-center">Projects organize your time entries and set billing rates for clients.</p>
<button
@@ -79,12 +80,13 @@
</div>
<!-- Create/Edit Dialog -->
<Transition name="modal">
<div
v-if="showDialog"
class="fixed inset-0 bg-black/70 backdrop-blur-[4px] flex items-center justify-center p-4 z-50"
@click.self="tryCloseDialog"
>
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-md p-6 animate-modal-enter max-h-[calc(100vh-2rem)] overflow-y-auto">
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-md p-6 max-h-[calc(100vh-2rem)] overflow-y-auto">
<h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">
{{ editingProject ? 'Edit Project' : 'Create Project' }}
</h2>
@@ -240,14 +242,16 @@
</form>
</div>
</div>
</Transition>
<!-- Delete Confirmation Dialog -->
<Transition name="modal">
<div
v-if="showDeleteDialog"
class="fixed inset-0 bg-black/70 backdrop-blur-[4px] flex items-center justify-center p-4 z-50"
@click.self="cancelDelete"
>
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-sm p-6 animate-modal-enter">
<div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-sm p-6">
<h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-2">Delete Project</h2>
<p class="text-[0.75rem] text-text-secondary mb-6">
Are you sure you want to delete "{{ projectToDelete?.name }}"? This action cannot be undone.
@@ -268,6 +272,7 @@
</div>
</div>
</div>
</Transition>
<AppDiscardDialog :show="showDiscardDialog" @cancel="cancelDiscard" @discard="confirmDiscard" />
</div>