team-switcher.tsx 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import * as React from 'react'
  2. import { ChevronsUpDown, Plus } from 'lucide-react'
  3. import {
  4. DropdownMenu,
  5. DropdownMenuContent,
  6. DropdownMenuItem,
  7. DropdownMenuLabel,
  8. DropdownMenuSeparator,
  9. DropdownMenuShortcut,
  10. DropdownMenuTrigger,
  11. } from '@/components/ui/dropdown-menu'
  12. import {
  13. SidebarMenu,
  14. SidebarMenuButton,
  15. SidebarMenuItem,
  16. useSidebar,
  17. } from '@/components/ui/sidebar'
  18. type TeamSwitcherProps = {
  19. teams: {
  20. name: string
  21. logo: React.ElementType
  22. plan: string
  23. }[]
  24. }
  25. export function TeamSwitcher({ teams }: TeamSwitcherProps) {
  26. const { isMobile } = useSidebar()
  27. const [activeTeam, setActiveTeam] = React.useState(teams[0])
  28. return (
  29. <SidebarMenu>
  30. <SidebarMenuItem>
  31. <DropdownMenu>
  32. <DropdownMenuTrigger asChild>
  33. <SidebarMenuButton
  34. size='lg'
  35. className='data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground'
  36. >
  37. <div className='flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground'>
  38. <activeTeam.logo className='size-4' />
  39. </div>
  40. <div className='grid flex-1 text-start text-sm leading-tight'>
  41. <span className='truncate font-semibold'>
  42. {activeTeam.name}
  43. </span>
  44. <span className='truncate text-xs'>{activeTeam.plan}</span>
  45. </div>
  46. <ChevronsUpDown className='ms-auto' />
  47. </SidebarMenuButton>
  48. </DropdownMenuTrigger>
  49. <DropdownMenuContent
  50. className='w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg'
  51. align='start'
  52. side={isMobile ? 'bottom' : 'right'}
  53. sideOffset={4}
  54. >
  55. <DropdownMenuLabel className='text-xs text-muted-foreground'>
  56. Teams
  57. </DropdownMenuLabel>
  58. {teams.map((team, index) => (
  59. <DropdownMenuItem
  60. key={team.name}
  61. onClick={() => setActiveTeam(team)}
  62. className='gap-2 p-2'
  63. >
  64. <div className='flex size-6 items-center justify-center rounded-sm border'>
  65. <team.logo className='size-4 shrink-0' />
  66. </div>
  67. {team.name}
  68. <DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>
  69. </DropdownMenuItem>
  70. ))}
  71. <DropdownMenuSeparator />
  72. <DropdownMenuItem className='gap-2 p-2'>
  73. <div className='flex size-6 items-center justify-center rounded-md border bg-background'>
  74. <Plus className='size-4' />
  75. </div>
  76. <div className='font-medium text-muted-foreground'>Add team</div>
  77. </DropdownMenuItem>
  78. </DropdownMenuContent>
  79. </DropdownMenu>
  80. </SidebarMenuItem>
  81. </SidebarMenu>
  82. )
  83. }