@@ -6,7 +6,13 @@ import {
66 DropdownMenuContent ,
77 DropdownMenuGroup ,
88 DropdownMenuItem ,
9+ DropdownMenuPortal ,
10+ DropdownMenuRadioGroup ,
11+ DropdownMenuRadioItem ,
912 DropdownMenuSeparator ,
13+ DropdownMenuSub ,
14+ DropdownMenuSubContent ,
15+ DropdownMenuSubTrigger ,
1016 DropdownMenuTrigger ,
1117} from "@/components/ui/dropdown-menu" ;
1218import {
@@ -21,14 +27,19 @@ import {
2127 useSidebar ,
2228} from "@/components/ui/sidebar" ;
2329import { UserAvatar } from "@/components/userAvatar" ;
30+ import { useKeymapType } from "@/hooks/useKeymapType" ;
31+ import { KeymapType } from "@/lib/types" ;
2432import { cn } from "@/lib/utils" ;
25- import { ArrowLeftToLineIcon , ArrowRightToLineIcon , ChevronsUpDown , LogOut , SettingsIcon } from "lucide-react" ;
33+ import {
34+ ArrowLeftToLineIcon , ArrowRightToLineIcon , ChevronsUpDown , CodeIcon ,
35+ Laptop , LogIn , LogOut , Moon , SettingsIcon , Sun , UserIcon
36+ } from "lucide-react" ;
2637import { Session } from "next-auth" ;
2738import { signOut } from "next-auth/react" ;
39+ import { useTheme } from "next-themes" ;
2840import Link from "next/link" ;
2941import posthog from "posthog-js" ;
30- import { ReactNode , useEffect , useRef , useState } from "react" ;
31- import { AppearanceDropdownMenuGroup } from "../../components/appearanceDropdownMenuGroup" ;
42+ import { ReactNode , useEffect , useMemo , useRef , useState } from "react" ;
3243
3344interface SidebarBaseProps {
3445 session : Session | null ;
@@ -72,8 +83,10 @@ export function SidebarBase({ session, collapsible = "icon", headerContent, chil
7283 </ SidebarContent >
7384 < SidebarFooter className = "border-t border-sidebar-border" >
7485 { collapsible !== "none" && < CollapseSidebarButton /> }
75- { session && (
86+ { session ? (
7687 < MeControlDropdownMenu session = { session } />
88+ ) : (
89+ < GuestDropdownMenu />
7790 ) }
7891 </ SidebarFooter >
7992 { collapsible !== "none" && < SidebarRail /> }
@@ -176,3 +189,106 @@ const MeControlDropdownMenu = ({
176189 </ SidebarMenu >
177190 )
178191}
192+
193+ const GuestDropdownMenu = ( ) => {
194+ return (
195+ < SidebarMenu >
196+ < SidebarMenuItem >
197+ < DropdownMenu >
198+ < DropdownMenuTrigger asChild >
199+ < SidebarMenuButton
200+ size = "lg"
201+ className = "data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
202+ >
203+ < div className = "flex h-8 w-8 items-center justify-center rounded-full bg-muted flex-shrink-0" >
204+ < UserIcon className = "h-4 w-4 text-muted-foreground" />
205+ </ div >
206+ < div className = "grid flex-1 text-left text-sm leading-tight" >
207+ < span className = "truncate font-semibold" > Guest</ span >
208+ < span className = "truncate text-xs text-muted-foreground" > Not signed in</ span >
209+ </ div >
210+ < ChevronsUpDown className = "ml-auto size-4" />
211+ </ SidebarMenuButton >
212+ </ DropdownMenuTrigger >
213+ < DropdownMenuContent className = "w-64" side = "top" align = "start" sideOffset = { 4 } >
214+ < AppearanceDropdownMenuGroup />
215+ < DropdownMenuSeparator />
216+ < DropdownMenuItem asChild >
217+ < a href = "/login" >
218+ < LogIn className = "h-4 w-4 mr-2" />
219+ < span > Sign in</ span >
220+ </ a >
221+ </ DropdownMenuItem >
222+ </ DropdownMenuContent >
223+ </ DropdownMenu >
224+ </ SidebarMenuItem >
225+ </ SidebarMenu >
226+ ) ;
227+ }
228+
229+
230+ const AppearanceDropdownMenuGroup = ( ) => {
231+ const { theme : _theme , setTheme } = useTheme ( ) ;
232+ const [ keymapType , setKeymapType ] = useKeymapType ( ) ;
233+
234+ const theme = useMemo ( ( ) => {
235+ return _theme ?? "light" ;
236+ } , [ _theme ] ) ;
237+
238+ const ThemeIcon = useMemo ( ( ) => {
239+ switch ( theme ) {
240+ case "light" :
241+ return < Sun className = "h-4 w-4 mr-2" /> ;
242+ case "dark" :
243+ return < Moon className = "h-4 w-4 mr-2" /> ;
244+ case "system" :
245+ return < Laptop className = "h-4 w-4 mr-2" /> ;
246+ default :
247+ return < Laptop className = "h-4 w-4 mr-2" /> ;
248+ }
249+ } , [ theme ] ) ;
250+
251+ return (
252+ < DropdownMenuGroup >
253+ < DropdownMenuSub >
254+ < DropdownMenuSubTrigger >
255+ { ThemeIcon }
256+ < span > Theme</ span >
257+ </ DropdownMenuSubTrigger >
258+ < DropdownMenuPortal >
259+ < DropdownMenuSubContent >
260+ < DropdownMenuRadioGroup value = { theme } onValueChange = { setTheme } >
261+ < DropdownMenuRadioItem value = "light" >
262+ Light
263+ </ DropdownMenuRadioItem >
264+ < DropdownMenuRadioItem value = "dark" >
265+ Dark
266+ </ DropdownMenuRadioItem >
267+ < DropdownMenuRadioItem value = "system" >
268+ System
269+ </ DropdownMenuRadioItem >
270+ </ DropdownMenuRadioGroup >
271+ </ DropdownMenuSubContent >
272+ </ DropdownMenuPortal >
273+ </ DropdownMenuSub >
274+ < DropdownMenuSub >
275+ < DropdownMenuSubTrigger >
276+ < CodeIcon className = "h-4 w-4 mr-2" />
277+ < span > Code navigation</ span >
278+ </ DropdownMenuSubTrigger >
279+ < DropdownMenuPortal >
280+ < DropdownMenuSubContent >
281+ < DropdownMenuRadioGroup value = { keymapType } onValueChange = { ( value ) => setKeymapType ( value as KeymapType ) } >
282+ < DropdownMenuRadioItem value = "default" >
283+ Default
284+ </ DropdownMenuRadioItem >
285+ < DropdownMenuRadioItem value = "vim" >
286+ Vim
287+ </ DropdownMenuRadioItem >
288+ </ DropdownMenuRadioGroup >
289+ </ DropdownMenuSubContent >
290+ </ DropdownMenuPortal >
291+ </ DropdownMenuSub >
292+ </ DropdownMenuGroup >
293+ )
294+ }
0 commit comments