Files
tool-evaluator/artifacts/toolrate/src/components/view-toggle.tsx
T
opencode 78244c3197
Build & Push Docker Image / build (push) Successful in 2m25s
feat: user-chosen browse views with grid/list toggle and profile sync
- view modes grid | table | rows + density cozy/compact, persisted via
  localStorage and shareable ?view=?density= URL params (URL wins)
- table view: sortable columns (name, rating, reviews), new sort options
  name_asc/name_desc/recently_updated (backend enum + handler)
- live debounced search, removable filter chips, '/' focuses search
- virtualization via @tanstack/react-virtual for table and rows views
- profile sync: users.preferences jsonb + GET/PUT /api/auth/me/preferences;
  preference precedence URL > server profile > localStorage > default
- add local rollup/lightningcss/tailwindcss oxide native binaries for macos dev
2026-08-02 09:34:53 +02:00

38 lines
1.0 KiB
TypeScript

import { LayoutGrid, List, Rows3 } from "lucide-react";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
export type ViewMode = "grid" | "table" | "rows";
const OPTIONS: { value: ViewMode; label: string; Icon: typeof LayoutGrid }[] = [
{ value: "grid", label: "Grid", Icon: LayoutGrid },
{ value: "table", label: "Table", Icon: List },
{ value: "rows", label: "Rows", Icon: Rows3 },
];
export function ViewToggle({
value,
onValueChange,
}: {
value: ViewMode;
onValueChange: (v: ViewMode) => void;
}) {
return (
<ToggleGroup
type="single"
value={value}
onValueChange={(v) => {
if (v) onValueChange(v as ViewMode);
}}
variant="outline"
size="sm"
aria-label="View mode"
>
{OPTIONS.map(({ value: v, label, Icon }) => (
<ToggleGroupItem key={v} value={v} aria-label={label} title={label} data-testid={`view-${v}`}>
<Icon className="w-4 h-4" />
</ToggleGroupItem>
))}
</ToggleGroup>
);
}