refactor(ui): replace title attrs with Tooltip on interactive elements
Wrap 'Mark done', 'Edit project', 'Generate AI summary' buttons and inline-editable OMG spans with Tooltip component; replace priority dot title attr in KanbanCard; also adds focus-visible ring to 'Mark done' button. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ebd5616498
commit
b8329904e8
4 changed files with 18 additions and 8 deletions
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import Tooltip from '@/components/ui/Tooltip.vue'
|
||||
import type { Task } from '@/types'
|
||||
|
||||
const props = defineProps<{ task: Task; dragging: boolean }>()
|
||||
|
|
@ -32,10 +33,11 @@ const statusLabel: Record<string, string> = {
|
|||
>
|
||||
<div class="flex items-start gap-2">
|
||||
<!-- Priority dot -->
|
||||
<Tooltip :content="`Priority ${task.priority}`">
|
||||
<span
|
||||
:class="['mt-1.5 h-2 w-2 rounded-full shrink-0', priorityDot[task.priority] ?? 'bg-slate-300']"
|
||||
:title="`Priority ${task.priority}`"
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-medium text-slate-800 leading-snug line-clamp-2">{{ task.title }}</p>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import KpiRow from '@/components/dashboard/KpiRow.vue'
|
|||
import TimelineChart from '@/components/dashboard/TimelineChart.vue'
|
||||
import ToolUsageList from '@/components/dashboard/ToolUsageList.vue'
|
||||
import ProjectBreakdown from '@/components/dashboard/ProjectBreakdown.vue'
|
||||
import Tooltip from '@/components/ui/Tooltip.vue'
|
||||
import { useTasksStore } from '@/stores/tasks'
|
||||
import { useDevopsStore } from '@/stores/devops'
|
||||
import { isoDateStr } from '@/lib/utils'
|
||||
|
|
@ -147,18 +148,19 @@ onMounted(async () => {
|
|||
:key="task.id"
|
||||
class="flex items-center gap-2 group py-1"
|
||||
>
|
||||
<Tooltip content="Mark done">
|
||||
<button
|
||||
class="h-4 w-4 shrink-0 rounded border border-border/70 group-hover:border-primary transition-colors flex items-center justify-center"
|
||||
class="h-4 w-4 shrink-0 rounded border border-border/70 group-hover:border-primary transition-colors flex items-center justify-center focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
||||
:class="{ 'opacity-50': completingTask === task.id }"
|
||||
:disabled="!!completingTask"
|
||||
@click="quickComplete(task.id)"
|
||||
title="Mark done"
|
||||
>
|
||||
<svg v-if="completingTask === task.id" class="h-3 w-3 animate-spin text-primary" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</Tooltip>
|
||||
<span class="flex-1 text-xs text-foreground truncate">{{ task.title }}</span>
|
||||
<span
|
||||
v-if="task.status === 'doing'"
|
||||
|
|
|
|||
|
|
@ -191,12 +191,13 @@ function cancelInline() {
|
|||
@keydown.enter="commitInline(entry)"
|
||||
@keydown.escape="cancelInline"
|
||||
/>
|
||||
<Tooltip content="Double-click to edit">
|
||||
<span
|
||||
v-else
|
||||
class="text-sm font-medium text-foreground cursor-pointer hover:text-primary transition-colors"
|
||||
title="Double-click to edit"
|
||||
@dblclick="startInline(entry, 'name')"
|
||||
>{{ entry.name }}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<!-- Client -->
|
||||
|
|
@ -211,13 +212,14 @@ function cancelInline() {
|
|||
@keydown.enter="commitInline(entry)"
|
||||
@keydown.escape="cancelInline"
|
||||
/>
|
||||
<Tooltip content="Double-click to edit">
|
||||
<span
|
||||
v-else
|
||||
class="text-sm text-muted-foreground cursor-pointer hover:text-foreground transition-colors"
|
||||
:class="entry.client ? '' : 'italic opacity-40'"
|
||||
title="Double-click to edit"
|
||||
@dblclick="startInline(entry, 'client')"
|
||||
>{{ entry.client || 'No client' }}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<!-- Job # -->
|
||||
|
|
@ -232,13 +234,14 @@ function cancelInline() {
|
|||
@keydown.enter="commitInline(entry)"
|
||||
@keydown.escape="cancelInline"
|
||||
/>
|
||||
<Tooltip content="Double-click to edit">
|
||||
<span
|
||||
v-else
|
||||
class="text-sm tabular-nums cursor-pointer hover:text-foreground transition-colors"
|
||||
:class="entry.job_number ? 'text-foreground' : 'text-muted-foreground/40 italic'"
|
||||
title="Double-click to edit"
|
||||
@dblclick="startInline(entry, 'job_number')"
|
||||
>{{ entry.job_number || '—' }}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<!-- Actions -->
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import Skeleton from '@/components/ui/Skeleton.vue'
|
|||
import Input from '@/components/ui/Input.vue'
|
||||
import Button from '@/components/ui/Button.vue'
|
||||
import EmptyState from '@/components/ui/EmptyState.vue'
|
||||
import Tooltip from '@/components/ui/Tooltip.vue'
|
||||
import { formatDuration, formatDateTime } from '@/lib/utils'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { toast } from 'vue-sonner'
|
||||
|
|
@ -142,15 +143,16 @@ async function summarizeSession(sessionId: string) {
|
|||
>
|
||||
← All time
|
||||
</button>
|
||||
<Tooltip content="Edit project">
|
||||
<button
|
||||
class="p-1 rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted/40 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
||||
title="Edit project"
|
||||
@click="openEdit"
|
||||
>
|
||||
<svg class="h-3.5 w-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
|
||||
</svg>
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div class="flex items-center gap-3 mt-1 flex-wrap">
|
||||
<span v-if="data.project.client" class="text-sm text-muted-foreground">
|
||||
|
|
@ -369,10 +371,10 @@ async function summarizeSession(sessionId: string) {
|
|||
<p class="text-xs font-medium text-foreground">{{ formatDuration(session.active_hours) }}</p>
|
||||
<p class="text-xs text-muted-foreground">{{ session.commits.length }} commits</p>
|
||||
</div>
|
||||
<Tooltip content="Generate AI summary">
|
||||
<button
|
||||
class="flex h-8 w-8 items-center justify-center rounded text-muted-foreground hover:text-primary transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
||||
:class="{ 'opacity-50 cursor-not-allowed': summarizingSession === session.id }"
|
||||
title="Generate AI summary"
|
||||
@click="summarizeSession(session.id)"
|
||||
>
|
||||
<svg
|
||||
|
|
@ -395,6 +397,7 @@ async function summarizeSession(sessionId: string) {
|
|||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue