78244c3197
Build & Push Docker Image / build (push) Successful in 2m25s
- 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
38 lines
1.0 KiB
TypeScript
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>
|
|
);
|
|
}
|