ci: dev version includes UTC time (dev-YYYYMMDD-HHmm)
Build & Push Docker Image / build (push) Successful in 2m36s

Phase 1: browse power-up
- faceted filters: tags + features (array containment) and min rating
  on listTools; new ?tags=?features=?minRating= URL params with chips
- global Cmd+K command palette (cmdk) with tool search + navigation
- mini usefulness/usability bars on grid cards, wide cards and table rows
This commit is contained in:
opencode
2026-08-02 11:51:25 +02:00
parent 461eca9a0a
commit 0c27982098
14 changed files with 504 additions and 29 deletions
@@ -0,0 +1,73 @@
import { cn } from "@/lib/utils";
function pct(v: number | null | undefined): number {
if (v == null) return 0;
return Math.max(0, Math.min(5, v)) / 5 * 100;
}
export function MiniBars({
usefulness,
usability,
className,
}: {
usefulness: number | null | undefined;
usability: number | null | undefined;
className?: string;
}) {
const rows = [
{ label: "Usefulness", value: usefulness },
{ label: "Usability", value: usability },
];
return (
<div className={cn("space-y-1 w-full", className)}>
{rows.map(({ label, value }) => (
<div
key={label}
className="flex items-center gap-2"
title={`${label}: ${value != null ? value.toFixed(1) : "N/A"} / 5`}
>
<span className="text-[10px] uppercase tracking-wide text-muted-foreground w-[3.5rem] shrink-0">
{label}
</span>
<div className="flex-1 h-1.5 rounded-full bg-muted overflow-hidden">
<div
className="h-full rounded-full bg-primary/70"
style={{ width: `${pct(value)}%` }}
/>
</div>
<span className="text-[10px] text-muted-foreground tabular-nums w-7 text-right shrink-0">
{value != null ? value.toFixed(1) : ""}
</span>
</div>
))}
</div>
);
}
export function MiniBarStack({
usefulness,
usability,
className,
}: {
usefulness: number | null | undefined;
usability: number | null | undefined;
className?: string;
}) {
return (
<div
className={cn("h-1.5 w-16 rounded-full bg-muted overflow-hidden flex", className)}
title={`Usefulness ${usefulness != null ? usefulness.toFixed(1) : "N/A"} / Usability ${
usability != null ? usability.toFixed(1) : "N/A"
} (of 5)`}
>
<div
className="h-full bg-primary/80"
style={{ width: `${pct(usefulness)}%` }}
/>
<div
className="h-full bg-primary/40"
style={{ width: `${pct(usability)}%` }}
/>
</div>
);
}