From f95ccf134d906934d5c1d60960dcba6026424e13 Mon Sep 17 00:00:00 2001 From: talksik Date: Wed, 8 Apr 2026 08:21:54 -0700 Subject: [PATCH] remove grid view for streams - Reduces surface area - Reduces options for people (less cognitive load) - One way to use the product - List view works better for keyboard shortcuts - List view has basics such as recency --- js/src/features/network-root.tsx | 29 +---------- .../features/particles/particle-grid-view.tsx | 51 ------------------- js/src/hooks/use-stream-keyboard-nav.ts | 19 ++----- js/src/stores/view-mode-store.ts | 36 ------------- 4 files changed, 6 insertions(+), 129 deletions(-) delete mode 100644 js/src/features/particles/particle-grid-view.tsx delete mode 100644 js/src/stores/view-mode-store.ts diff --git a/js/src/features/network-root.tsx b/js/src/features/network-root.tsx index 7cc8d54..29bcf80 100644 --- a/js/src/features/network-root.tsx +++ b/js/src/features/network-root.tsx @@ -1,14 +1,11 @@ import { useCallback, useMemo, useState } from "react"; import { useNavigate, useParams } from "react-router-dom"; -import { List, LayoutGrid, CircleDot, CircleCheckBig } from "lucide-react"; +import { CircleDot, CircleCheckBig } from "lucide-react"; import { particlePath } from "@/lib/particle-path"; import { ParticleListView } from "@/features/particles/particle-list-view"; -import { ParticleGridView } from "@/features/particles/particle-grid-view"; import ControlsIndicator from "@/features/compose/controls-indicator"; import { ComposeOverlay } from "./compose/compose-overlay"; import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; -import { useViewModeStore } from "@/stores/view-mode-store"; import { useStreamParticles } from "@/hooks/use-stream-particles"; import { useStreamKeyboardNav } from "@/hooks/use-stream-keyboard-nav"; import { useDockBadge } from "@/hooks/use-dock-badge"; @@ -22,8 +19,6 @@ export default function NetworkRoot() { const { networkId } = useParams(); const navigate = useNavigate(); const path = particlePath(networkId!, []); - const viewMode = useViewModeStore((s) => s.viewMode); - const setViewMode = useViewModeStore((s) => s.setViewMode); const { streams, isLoading } = useStreamParticles(path); const userId = useAuthStore((s) => s.user?.id); @@ -38,7 +33,6 @@ export default function NetworkRoot() { const { selectedIndex } = useStreamKeyboardNav({ streams: filteredStreams, - viewMode, enabled: !composeActive, onNavigate: useCallback( (streamId: string) => navigate(`/${networkId}/${streamId}`), @@ -59,30 +53,11 @@ export default function NetworkRoot() { Closed - { - if (v) setViewMode(v as "list" | "grid"); - }} - size="sm" - > - - - - - - - {/* Scrollable content */}
- {viewMode === "list" ? ( - - ) : ( - - )} +
diff --git a/js/src/features/particles/particle-grid-view.tsx b/js/src/features/particles/particle-grid-view.tsx deleted file mode 100644 index 252f38f..0000000 --- a/js/src/features/particles/particle-grid-view.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { useNavigate } from "react-router-dom"; -import { Radio } from "lucide-react"; -import { Progress } from "@/components/ui/progress"; -import type { StreamParticle } from "@/hooks/use-stream-particles"; -import { StreamCard } from "@/features/particles/stream-card"; -import { StreamContextMenu } from "@/features/particles/stream-context-menu"; - -interface ParticleGridViewProps { - streams: StreamParticle[]; - networkId: string; - isLoading: boolean; - selectedIndex?: number | null; -} - -export function ParticleGridView({ streams, networkId, isLoading, selectedIndex }: ParticleGridViewProps) { - const navigate = useNavigate(); - - if (isLoading) { - return ; - } - - if (streams.length === 0) { - return ( -
- -

- No recent streams yet. Start a conversation using the keyboard - shortcuts below. -

-
- ); - } - - return ( -
- {streams.map((stream, index) => ( - -
el?.scrollIntoView({ block: "nearest" }) : undefined}> - navigate(`/${networkId}/${stream.id}`)} - isSelected={index === selectedIndex} - shortcutKey={index < 9 ? index + 1 : undefined} - /> -
-
- ))} -
- ); -} diff --git a/js/src/hooks/use-stream-keyboard-nav.ts b/js/src/hooks/use-stream-keyboard-nav.ts index 8b615b4..7725e7c 100644 --- a/js/src/hooks/use-stream-keyboard-nav.ts +++ b/js/src/hooks/use-stream-keyboard-nav.ts @@ -2,25 +2,21 @@ import { useEffect, useState } from "react"; interface UseStreamKeyboardNavOptions { streams: Array<{ id: string }>; - viewMode: "list" | "grid"; enabled: boolean; onNavigate: (streamId: string) => void; - gridColumns?: number; } export function useStreamKeyboardNav({ streams, - viewMode, enabled, onNavigate, - gridColumns = 3, }: UseStreamKeyboardNavOptions) { const [selectedIndex, setSelectedIndex] = useState(null); // Reset selection to first item when streams change or view mode switches useEffect(() => { setSelectedIndex(streams.length > 0 ? 0 : null); - }, [streams.length, viewMode]); + }, [streams.length]); useEffect(() => { if (!enabled || streams.length === 0) return; @@ -63,15 +59,8 @@ export function useStreamKeyboardNav({ // Arrow keys: move selection let delta: number | null = null; - if (viewMode === "list") { - if (e.key === "ArrowDown") delta = 1; - else if (e.key === "ArrowUp") delta = -1; - } else { - if (e.key === "ArrowDown") delta = gridColumns; - else if (e.key === "ArrowUp") delta = -gridColumns; - else if (e.key === "ArrowRight") delta = 1; - else if (e.key === "ArrowLeft") delta = -1; - } + if (e.key === "ArrowDown") delta = 1; + else if (e.key === "ArrowUp") delta = -1; if (delta !== null) { e.preventDefault(); @@ -87,7 +76,7 @@ export function useStreamKeyboardNav({ // components (ToggleGroup, etc.) consume them for their own navigation. window.addEventListener("keydown", handleKeyDown, true); return () => window.removeEventListener("keydown", handleKeyDown, true); - }, [enabled, viewMode, gridColumns, streams, onNavigate]); + }, [enabled, streams, onNavigate]); return { selectedIndex }; } diff --git a/js/src/stores/view-mode-store.ts b/js/src/stores/view-mode-store.ts deleted file mode 100644 index 4eb9da2..0000000 --- a/js/src/stores/view-mode-store.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { create } from "zustand"; - -type ViewMode = "list" | "grid"; - -const STORAGE_KEY = "llink:view-mode"; - -function loadViewMode(): ViewMode { - try { - const stored = localStorage.getItem(STORAGE_KEY); - if (stored === "grid") return "grid"; - return "list"; - } catch { - return "list"; - } -} - -function saveViewMode(mode: ViewMode) { - try { - localStorage.setItem(STORAGE_KEY, mode); - } catch { - // Storage unavailable - } -} - -interface ViewModeState { - viewMode: ViewMode; - setViewMode: (mode: ViewMode) => void; -} - -export const useViewModeStore = create((set) => ({ - viewMode: loadViewMode(), - setViewMode: (mode) => { - saveViewMode(mode); - set({ viewMode: mode }); - }, -}));