@@ -46,6 +46,14 @@ export function AccountPicker({
4646 } ) ,
4747 [ queryClient ]
4848 ) ;
49+ const onAccountChange = useCallback (
50+ ( id : string ) => {
51+ if ( id === selectedId ) return ;
52+ setSelectedAccountId ( id ) ;
53+ void refetchAccountScoped ( ) ;
54+ } ,
55+ [ selectedId , setSelectedAccountId , refetchAccountScoped ]
56+ ) ;
4957
5058 // Default to the first account when the URL has no valid account_id (fixes the
5159 // "no account → 401" first load). `replace` so it doesn't add a history entry.
@@ -62,20 +70,29 @@ export function AccountPicker({
6270 } , [ profiles , selectedId , setSelectedAccountId , refetchAccountScoped ] ) ;
6371
6472 if ( ! accountsEnabled ) return null ;
65- // While accounts load, show a disabled, empty picker (building icon only) rather than
66- // a bare skeleton block — keeps the footer row stable and reads as "account selector,
67- // loading". Once loaded with no accounts, render nothing.
73+
74+ // A size-9 icon tile — the collapsed-rail footprint. Shared by the loading placeholder
75+ // (muted) and the single-account display (solid, with the name as a tooltip).
76+ const iconTile = ( opts ?: { muted ?: boolean ; title ?: string | undefined } ) => (
77+ < div
78+ title = { opts ?. title }
79+ className = { cn ( 'flex size-9 items-center justify-center' , className ) }
80+ >
81+ < Building2
82+ className = { cn (
83+ 'size-5 shrink-0' ,
84+ opts ?. muted ? 'text-muted-foreground' : 'text-foreground'
85+ ) }
86+ />
87+ </ div >
88+ ) ;
89+
90+ // While accounts load, show a disabled, empty picker (icon only) instead of a skeleton
91+ // block — keeps the row stable and reads as a loading account selector.
6892 if ( isLoading ) {
69- if ( collapsed ) {
70- return (
71- < div
72- className = { cn ( 'flex size-9 items-center justify-center' , className ) }
73- >
74- < Building2 className = "text-muted-foreground size-5 shrink-0" />
75- </ div >
76- ) ;
77- }
78- return (
93+ return collapsed ? (
94+ iconTile ( { muted : true } )
95+ ) : (
7996 < Select disabled >
8097 < SelectTrigger
8198 aria-label = "Account"
@@ -88,31 +105,27 @@ export function AccountPicker({
88105 </ Select >
89106 ) ;
90107 }
91- if ( profiles . length === 0 ) return null ;
92108
93- const select = ( id : string ) => {
94- if ( id === selectedId ) return ;
95- setSelectedAccountId ( id ) ;
96- void refetchAccountScoped ( ) ;
97- } ;
109+ if ( profiles . length === 0 ) return null ;
98110
99111 const current = profiles . find ( p => p . account . id === selectedId ) ;
112+ const single = profiles . length === 1 ;
113+ const options = (
114+ < SelectContent >
115+ { profiles . map ( p => (
116+ < SelectItem key = { p . account . id } value = { p . account . id } >
117+ { p . account . name }
118+ </ SelectItem >
119+ ) ) }
120+ </ SelectContent >
121+ ) ;
100122
101123 if ( collapsed ) {
102124 // Single account → static icon; multiple → an icon-only trigger whose dropdown pops
103- // out beside the collapsed rail (Radix positions it to stay in view).
104- if ( profiles . length === 1 ) {
105- return (
106- < div
107- title = { current ?. account . name }
108- className = { cn ( 'flex size-9 items-center justify-center' , className ) }
109- >
110- < Building2 className = "text-foreground size-5 shrink-0" />
111- </ div >
112- ) ;
113- }
125+ // out beside the collapsed rail (Radix keeps it in view).
126+ if ( single ) return iconTile ( { title : current ?. account . name } ) ;
114127 return (
115- < Select value = { selectedId ?? '' } onValueChange = { select } >
128+ < Select value = { selectedId ?? '' } onValueChange = { onAccountChange } >
116129 < SelectTrigger
117130 aria-label = "Account"
118131 className = { cn (
@@ -122,23 +135,17 @@ export function AccountPicker({
122135 >
123136 < Building2 className = "text-foreground size-5 shrink-0" />
124137 </ SelectTrigger >
125- < SelectContent >
126- { profiles . map ( p => (
127- < SelectItem key = { p . account . id } value = { p . account . id } >
128- { p . account . name }
129- </ SelectItem >
130- ) ) }
131- </ SelectContent >
138+ { options }
132139 </ Select >
133140 ) ;
134141 }
135142
136- // A single account needs no switcher — show it as static context.
137- if ( profiles . length === 1 ) {
143+ // A single account needs no switcher — show it as static context, matching the New Chat
144+ // button's size + spacing (size-5 icon, p-2, medium weight).
145+ if ( single ) {
138146 return (
139147 < div
140148 className = { cn (
141- // Match the New Chat button's size + spacing (size-5 icon, p-2, medium weight).
142149 'text-foreground flex items-center gap-2 p-2 text-sm font-medium select-none' ,
143150 className
144151 ) }
@@ -150,7 +157,7 @@ export function AccountPicker({
150157 }
151158
152159 return (
153- < Select value = { selectedId ?? '' } onValueChange = { select } >
160+ < Select value = { selectedId ?? '' } onValueChange = { onAccountChange } >
154161 < SelectTrigger
155162 className = { cn ( 'w-full gap-2 rounded-md font-medium' , className ) }
156163 aria-label = "Account"
@@ -162,13 +169,7 @@ export function AccountPicker({
162169 < SelectValue placeholder = "Select account" />
163170 </ span >
164171 </ SelectTrigger >
165- < SelectContent >
166- { profiles . map ( p => (
167- < SelectItem key = { p . account . id } value = { p . account . id } >
168- { p . account . name }
169- </ SelectItem >
170- ) ) }
171- </ SelectContent >
172+ { options }
172173 </ Select >
173174 ) ;
174175}
0 commit comments