-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6675cba
commit 3c88b3e
Showing
7 changed files
with
208 additions
and
101 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { FeatureFlag } from '@/backend/services/environment.service'; | ||
import { BadgePlus, NotebookPen, Sword } from 'lucide-react'; | ||
import { useSession } from 'next-auth/react'; | ||
import { FaDiceD20 } from 'react-icons/fa6'; | ||
import { NavigationList } from './NavigationList'; | ||
import { Button } from './ui/button'; | ||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from './ui/dropdown-menu'; | ||
|
||
export type AddDropdownProps = { | ||
className?: string; | ||
}; | ||
|
||
const items: NavigationList.Action<typeof DropdownMenuItem>[] = [ | ||
{ | ||
label: 'Campaign', | ||
flag: FeatureFlag.Campaigns, | ||
icon: FaDiceD20, | ||
onClick: () => console.log('Campaign'), | ||
}, | ||
{ | ||
label: 'Game', | ||
flag: FeatureFlag.Games, | ||
icon: NotebookPen, | ||
onClick: () => console.log('Game'), | ||
}, | ||
{ | ||
label: 'Character', | ||
flag: FeatureFlag.Characters, | ||
icon: Sword, | ||
onClick: () => console.log('Character'), | ||
}, | ||
]; | ||
|
||
export function AddDropdown({ className }: AddDropdownProps) { | ||
const { data: session } = useSession(); | ||
|
||
if (!session || !session.user) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<DropdownMenu> | ||
<DropdownMenuTrigger className={className} asChild> | ||
<Button variant="secondary" size="icon"> | ||
<BadgePlus className="size-6" /> | ||
</Button> | ||
</DropdownMenuTrigger> | ||
<DropdownMenuContent className="w-52" align="end"> | ||
<div className="flex flex-col gap-1"> | ||
<NavigationList items={items} as={DropdownMenuItem} flip /> | ||
</div> | ||
</DropdownMenuContent> | ||
</DropdownMenu> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { EnvironmentService, FeatureFlag } from '@/backend/services/environment.service'; | ||
import { cn } from '@/lib/utils'; | ||
import { LucideIcon } from 'lucide-react'; | ||
import Link from 'next/link'; | ||
import { ComponentProps, useMemo } from 'react'; | ||
import { IconType } from 'react-icons'; | ||
import { Button } from './ui/button'; | ||
import { DropdownMenuItem } from './ui/dropdown-menu'; | ||
|
||
export type NavigationListProps<T extends NavigationList.SupportedParent> = { | ||
items: NavigationList.Action<T>[]; | ||
as: T; | ||
flip?: boolean; | ||
variant?: ComponentProps<T>['variant']; | ||
}; | ||
|
||
export function NavigationList<T extends NavigationList.SupportedParent>({ | ||
items, | ||
as, | ||
flip, | ||
variant, | ||
}: NavigationListProps<T>) { | ||
const filteredItems = useMemo(() => { | ||
return items.filter((item) => typeof item.flag === 'undefined' || EnvironmentService.enabled(item.flag)); | ||
}, [items]); | ||
const Component = as; | ||
|
||
return ( | ||
<> | ||
{filteredItems.map((item, index) => { | ||
const baseProps: Pick<ComponentProps<T>, 'variant' | 'className'> = { | ||
variant: item.variant ?? variant, | ||
className: cn('text-sm flex justify-between gap-2', flip && 'flex-row-reverse'), | ||
}; | ||
|
||
const content = ( | ||
<> | ||
{item.icon && <item.icon className="size-6" />} | ||
<span>{item.label}</span> | ||
</> | ||
); | ||
|
||
if (item.href) { | ||
return ( | ||
// TODO: Figure out how to get this to stop freaking out | ||
// @ts-ignore | ||
<Component {...baseProps} key={index} asChild> | ||
<Link href={item.href}>{content}</Link> | ||
</Component> | ||
); | ||
} | ||
|
||
return ( | ||
// TODO: Figure out how to get this to stop freaking out | ||
// @ts-ignore | ||
<Component {...baseProps} key={index} onClick={item.onClick}> | ||
{content} | ||
</Component> | ||
); | ||
})} | ||
</> | ||
); | ||
} | ||
|
||
export namespace NavigationList { | ||
export type SupportedParent = typeof Button | typeof DropdownMenuItem; | ||
|
||
type BaseAction<T extends SupportedParent> = { | ||
label: string; | ||
icon?: LucideIcon | IconType; | ||
flag?: FeatureFlag; | ||
} & Pick<ComponentProps<T>, 'variant'>; | ||
|
||
interface LinkAction<T extends SupportedParent> extends BaseAction<T> { | ||
href: string; | ||
onClick?: never; | ||
} | ||
|
||
interface ButtonAction<T extends SupportedParent> extends BaseAction<T> { | ||
href?: never; | ||
onClick: () => void; | ||
} | ||
|
||
export type Action<T extends SupportedParent> = LinkAction<T> | ButtonAction<T>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
"use client" | ||
|
||
import * as React from "react" | ||
import * as TooltipPrimitive from "@radix-ui/react-tooltip" | ||
|
||
import { cn } from "@/lib/utils" | ||
|
||
const TooltipProvider = TooltipPrimitive.Provider | ||
|
||
const Tooltip = TooltipPrimitive.Root | ||
|
||
const TooltipTrigger = TooltipPrimitive.Trigger | ||
|
||
const TooltipContent = React.forwardRef< | ||
React.ElementRef<typeof TooltipPrimitive.Content>, | ||
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> | ||
>(({ className, sideOffset = 4, ...props }, ref) => ( | ||
<TooltipPrimitive.Content | ||
ref={ref} | ||
sideOffset={sideOffset} | ||
className={cn( | ||
"z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", | ||
className | ||
)} | ||
{...props} | ||
/> | ||
)) | ||
TooltipContent.displayName = TooltipPrimitive.Content.displayName | ||
|
||
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters