From d8f97d0ee783b0c8171496933b563f1b5dee5eb1 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Sun, 2 Mar 2025 16:34:01 +0100 Subject: [PATCH] Settings dropdown menu --- package-lock.json | 30 +++++ package.json | 1 + src/components/app.tsx | 22 ++- src/components/settingsDropdown.tsx | 41 ++++++ src/components/ui/dropdown-menu.tsx | 201 ++++++++++++++++++++++++++++ 5 files changed, 281 insertions(+), 14 deletions(-) create mode 100644 src/components/settingsDropdown.tsx create mode 100644 src/components/ui/dropdown-menu.tsx diff --git a/package-lock.json b/package-lock.json index fff234f..92246c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@radix-ui/react-collapsible": "^1.1.3", "@radix-ui/react-context-menu": "^2.2.6", "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dropdown-menu": "^2.1.6", "@radix-ui/react-label": "^2.1.2", "@radix-ui/react-popover": "^1.1.6", "@radix-ui/react-select": "^2.1.6", @@ -1026,6 +1027,35 @@ } } }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.6.tgz", + "integrity": "sha512-no3X7V5fD487wab/ZYSHXq3H37u4NVeLDKI/Ks724X/eEFSSEFYZxWgsIlr1UBeEyDaM29HM5x9p1Nv8DuTYPA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-menu": "2.1.6", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-controllable-state": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-focus-guards": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", diff --git a/package.json b/package.json index f3cae07..3b8e1d6 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@radix-ui/react-collapsible": "^1.1.3", "@radix-ui/react-context-menu": "^2.2.6", "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dropdown-menu": "^2.1.6", "@radix-ui/react-label": "^2.1.2", "@radix-ui/react-popover": "^1.1.6", "@radix-ui/react-select": "^2.1.6", diff --git a/src/components/app.tsx b/src/components/app.tsx index 8d0cbd1..b8fed6e 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -18,8 +18,7 @@ import { import { Calendar, LayoutDashboardIcon, Settings } from 'lucide-react'; import Link from 'next/link'; import useSmallScreen from '@/hooks/is-small'; -import ThemeToggle from './themeToggle'; - +import SettingsDropdown from './settingsDropdown'; // Menu items. const items = [ { @@ -34,13 +33,11 @@ const items = [ }, ]; -const footer = [ - { - title: 'Settings', - url: '/settings', - icon: Settings, - }, -]; +const footer: { + title: string; + url: string; + icon: React.ElementType; +}[] = []; export default function App({ children }: { children?: any }) { const isSmall = useSmallScreen(); @@ -77,10 +74,7 @@ export default function App({ children }: { children?: any }) { ))} - - -
- +
@@ -132,7 +126,7 @@ export default function App({ children }: { children?: any }) { ))} - + diff --git a/src/components/settingsDropdown.tsx b/src/components/settingsDropdown.tsx new file mode 100644 index 0000000..0a46721 --- /dev/null +++ b/src/components/settingsDropdown.tsx @@ -0,0 +1,41 @@ +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from '@/components/ui/dropdown-menu'; +import { useTheme } from 'next-themes'; +import { Lightbulb, Settings } from 'lucide-react'; + +export default function SettingsDropdown() { + const { setTheme, theme } = useTheme(); + + return ( + + +
+ +
+
+ + My Account + + Profile + Billing + Team + Subscription + + setTheme(theme === 'light' ? 'dark' : 'light') + } + > + + Switch Theme + + {/* TODO: Make the items functional */} + +
+ ); +} diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..082639f --- /dev/null +++ b/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,201 @@ +"use client" + +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "@/lib/utils" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + svg]:size-4 [&>svg]:shrink-0", + inset && "pl-8", + className + )} + {...props} + /> +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +}