@@ -74,6 +74,8 @@ import {
7474 Hourglass ,
7575 X ,
7676 SlidersHorizontal ,
77+ LayoutGrid ,
78+ Rows3 ,
7779} from "lucide-react" ;
7880import { useTranslation } from "react-i18next" ;
7981import AccountUsageModal from "../components/AccountUsageModal" ;
@@ -165,6 +167,27 @@ function persistAccountVisibleColumns(
165167 }
166168}
167169
170+ const ACCOUNT_VIEW_MODE_KEY = "codex2api:accounts:view-mode" ;
171+ type AccountViewMode = "table" | "grid" ;
172+
173+ function getInitialAccountViewMode ( ) : AccountViewMode {
174+ try {
175+ const raw = window . localStorage . getItem ( ACCOUNT_VIEW_MODE_KEY ) ;
176+ if ( raw === "grid" || raw === "table" ) return raw ;
177+ } catch {
178+ // ignore
179+ }
180+ return "table" ;
181+ }
182+
183+ function persistAccountViewMode ( mode : AccountViewMode ) {
184+ try {
185+ window . localStorage . setItem ( ACCOUNT_VIEW_MODE_KEY , mode ) ;
186+ } catch {
187+ // ignore
188+ }
189+ }
190+
168191function getInitialAnalysisVisibility ( ) : boolean {
169192 try {
170193 return (
@@ -496,6 +519,9 @@ export default function Accounts() {
496519 const [ visibleColumns , setVisibleColumns ] = useState <
497520 Record < AccountTableColumn , boolean >
498521 > ( getInitialAccountVisibleColumns ) ;
522+ const [ viewMode , setViewMode ] = useState < AccountViewMode > (
523+ getInitialAccountViewMode ,
524+ ) ;
499525 const fileInputRef = useRef < HTMLInputElement > ( null ) ;
500526 const jsonInputRef = useRef < HTMLInputElement > ( null ) ;
501527 const jsonAtInputRef = useRef < HTMLInputElement > ( null ) ;
@@ -636,6 +662,10 @@ export default function Accounts() {
636662 persistAccountVisibleColumns ( visibleColumns ) ;
637663 } , [ visibleColumns ] ) ;
638664
665+ useEffect ( ( ) => {
666+ persistAccountViewMode ( viewMode ) ;
667+ } , [ viewMode ] ) ;
668+
639669 useEffect ( ( ) => {
640670 if ( groupFilter === null ) return ;
641671 if ( ! allGroups . some ( ( group ) => group . id === groupFilter ) ) {
@@ -2674,7 +2704,39 @@ export default function Accounts() {
26742704 < FolderOpen className = "size-3.5" />
26752705 { t ( "accounts.groupManage" ) }
26762706 </ Button >
2677- < div className = "ml-auto shrink-0" >
2707+ < div className = "ml-auto flex shrink-0 items-center gap-1.5" >
2708+ < div className = "hidden lg:inline-flex items-center rounded-md border border-border bg-muted/50 p-0.5" >
2709+ < button
2710+ type = "button"
2711+ onClick = { ( ) => setViewMode ( "table" ) }
2712+ title = { t ( "accounts.viewModeTable" ) }
2713+ aria-label = { t ( "accounts.viewModeTable" ) }
2714+ aria-pressed = { viewMode === "table" }
2715+ className = { `inline-flex items-center gap-1 rounded-sm px-2 py-1 text-[12px] font-medium transition-colors ${
2716+ viewMode === "table"
2717+ ? "bg-background text-foreground shadow-sm"
2718+ : "text-muted-foreground hover:text-foreground"
2719+ } `}
2720+ >
2721+ < Rows3 className = "size-3.5" />
2722+ { t ( "accounts.viewModeTable" ) }
2723+ </ button >
2724+ < button
2725+ type = "button"
2726+ onClick = { ( ) => setViewMode ( "grid" ) }
2727+ title = { t ( "accounts.viewModeGrid" ) }
2728+ aria-label = { t ( "accounts.viewModeGrid" ) }
2729+ aria-pressed = { viewMode === "grid" }
2730+ className = { `inline-flex items-center gap-1 rounded-sm px-2 py-1 text-[12px] font-medium transition-colors ${
2731+ viewMode === "grid"
2732+ ? "bg-background text-foreground shadow-sm"
2733+ : "text-muted-foreground hover:text-foreground"
2734+ } `}
2735+ >
2736+ < LayoutGrid className = "size-3.5" />
2737+ { t ( "accounts.viewModeGrid" ) }
2738+ </ button >
2739+ </ div >
26782740 < ColumnSettingsMenu
26792741 columns = { visibleColumns }
26802742 onToggle = { ( column ) =>
@@ -2818,7 +2880,13 @@ export default function Accounts() {
28182880 </ Button >
28192881 }
28202882 >
2821- < div className = "grid gap-3 lg:hidden" >
2883+ < div
2884+ className = {
2885+ viewMode === "grid"
2886+ ? "grid gap-3 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5"
2887+ : "grid gap-3 lg:hidden"
2888+ }
2889+ >
28222890 { pagedAccounts . map ( ( account , index ) => {
28232891 const isSelected = selected . has ( account . id ) ;
28242892 return (
@@ -2851,7 +2919,9 @@ export default function Accounts() {
28512919 } ) }
28522920 </ div >
28532921
2854- < div className = "data-table-shell hidden lg:block" >
2922+ < div
2923+ className = { `data-table-shell hidden lg:block ${ viewMode === "grid" ? "lg:hidden" : "" } ` }
2924+ >
28552925 < Table >
28562926 < TableHeader >
28572927 < TableRow >
0 commit comments