diff --git a/ui/src/components/health/health-priority-card.tsx b/ui/src/components/health/health-priority-card.tsx index 9c817807..b74df697 100644 --- a/ui/src/components/health/health-priority-card.tsx +++ b/ui/src/components/health/health-priority-card.tsx @@ -127,14 +127,20 @@ export function HealthPriorityCard({ check }: HealthPriorityCardProps) { {(check.fix || check.fixable) && (
{check.fix}
+ {/*
+ * Always-visible copy button. The previous design hid it behind
+ * group-hover, which excluded keyboard users and touch-only
+ * devices (no hover state on mobile = effectively unreachable).
+ */}
diff --git a/ui/src/components/health/health-status-ribbon.tsx b/ui/src/components/health/health-status-ribbon.tsx
index 320ece6d..5e6c9867 100644
--- a/ui/src/components/health/health-status-ribbon.tsx
+++ b/ui/src/components/health/health-status-ribbon.tsx
@@ -1,3 +1,4 @@
+import { useEffect, useState } from 'react';
import { Cpu, RefreshCw, Terminal, Copy } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
@@ -41,6 +42,18 @@ export function HealthStatusRibbon({
}: HealthStatusRibbonProps) {
const { t } = useTranslation();
+ // formatRelativeTime reads Date.now() during render. Without a ticking
+ // re-render, the "last scan" label freezes at whatever it showed on mount
+ // and never advances to "1 minute ago", "2 hours ago", etc. — even though
+ // the underlying lastScan timestamp is stale. Force a re-render every
+ // second; the cost is negligible (one tiny component) and the UX win is
+ // a label that actually behaves like a relative timestamp.
+ const [, setTick] = useState(0);
+ useEffect(() => {
+ const interval = setInterval(() => setTick((n) => n + 1), 1000);
+ return () => clearInterval(interval);
+ }, []);
+
const copyDoctorCommand = () => {
navigator.clipboard.writeText('ccs doctor');
toast.success(t('health.copied'));