LocalDropdown.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import { FlaskConical, Settings } from 'lucide-react'
  2. import { useTheme } from 'next-themes'
  3. import Link from 'next/link'
  4. import { useRouter } from 'next/router'
  5. import {
  6. cn,
  7. DropdownMenu,
  8. DropdownMenuContent,
  9. DropdownMenuGroup,
  10. DropdownMenuItem,
  11. DropdownMenuLabel,
  12. DropdownMenuRadioGroup,
  13. DropdownMenuRadioItem,
  14. DropdownMenuSeparator,
  15. DropdownMenuTrigger,
  16. singleThemes,
  17. Theme,
  18. } from 'ui'
  19. import { ButtonTooltip } from '../ui/ButtonTooltip'
  20. import { useFeaturePreviewModal } from './App/FeaturePreview/FeaturePreviewContext'
  21. import { ProfileImage } from '@/components/ui/ProfileImage'
  22. import { useTrack } from '@/lib/telemetry/track'
  23. import { useAppStateSnapshot } from '@/state/app-state'
  24. export const LocalDropdown = ({
  25. triggerClassName,
  26. contentClassName,
  27. }: {
  28. triggerClassName?: string
  29. contentClassName?: string
  30. }) => {
  31. const router = useRouter()
  32. const { theme, setTheme } = useTheme()
  33. const appStateSnapshot = useAppStateSnapshot()
  34. const { toggleFeaturePreviewModal } = useFeaturePreviewModal()
  35. const track = useTrack()
  36. return (
  37. <DropdownMenu
  38. onOpenChange={(open) => {
  39. if (open) track('header_local_dropdown_opened')
  40. }}
  41. >
  42. <DropdownMenuTrigger className={cn('border shrink-0 px-3', triggerClassName)} asChild>
  43. <ButtonTooltip
  44. type="default"
  45. className="[&>span]:flex px-0 py-0 rounded-full overflow-hidden h-8 w-8"
  46. tooltip={{ content: { text: 'Settings' } }}
  47. >
  48. <ProfileImage className="w-8 h-8 rounded-md" />
  49. <span className="sr-only">Settings</span>
  50. </ButtonTooltip>
  51. </DropdownMenuTrigger>
  52. <DropdownMenuContent side="bottom" align="end" className={cn('w-44', contentClassName)}>
  53. <DropdownMenuItem className="flex gap-2 cursor-pointer" asChild>
  54. <Link
  55. href="/account/me"
  56. onClick={() => {
  57. if (router.pathname !== '/account/me') {
  58. appStateSnapshot.setLastRouteBeforeVisitingAccountPage(router.asPath)
  59. }
  60. }}
  61. >
  62. <Settings size={14} strokeWidth={1.5} className="text-foreground-lighter" />
  63. Preferences
  64. </Link>
  65. </DropdownMenuItem>
  66. <DropdownMenuItem
  67. className="flex gap-2 cursor-pointer"
  68. onClick={() => toggleFeaturePreviewModal(true)}
  69. onSelect={() => toggleFeaturePreviewModal(true)}
  70. >
  71. <FlaskConical size={14} strokeWidth={1.5} className="text-foreground-lighter" />
  72. Feature previews
  73. </DropdownMenuItem>
  74. <DropdownMenuSeparator />
  75. <DropdownMenuGroup>
  76. <DropdownMenuLabel>Theme</DropdownMenuLabel>
  77. <DropdownMenuRadioGroup
  78. value={theme}
  79. onValueChange={(value) => {
  80. setTheme(value)
  81. }}
  82. >
  83. {singleThemes.map((theme: Theme) => (
  84. <DropdownMenuRadioItem
  85. key={theme.value}
  86. value={theme.value}
  87. className="cursor-pointer"
  88. >
  89. {theme.name}
  90. </DropdownMenuRadioItem>
  91. ))}
  92. </DropdownMenuRadioGroup>
  93. </DropdownMenuGroup>
  94. </DropdownMenuContent>
  95. </DropdownMenu>
  96. )
  97. }