this repo has no description
at filter-styling 105 lines 3.2 kB view raw
1import { A } from "@solidjs/router"; 2import { 3 Accessor, 4 createContext, 5 createSignal, 6 JSX, 7 onCleanup, 8 onMount, 9 Setter, 10 Show, 11 useContext, 12} from "solid-js"; 13import { addToClipboard } from "../utils/copy"; 14 15const MenuContext = createContext<{ 16 showMenu: Accessor<boolean>; 17 setShowMenu: Setter<boolean>; 18}>(); 19 20export const MenuProvider = (props: { children?: JSX.Element }) => { 21 const [showMenu, setShowMenu] = createSignal(false); 22 const value = { showMenu, setShowMenu }; 23 24 return <MenuContext.Provider value={value}>{props.children}</MenuContext.Provider>; 25}; 26 27export const CopyMenu = (props: { copyContent: string; label: string; icon?: string }) => { 28 const ctx = useContext(MenuContext); 29 30 return ( 31 <button 32 onClick={() => { 33 addToClipboard(props.copyContent); 34 ctx?.setShowMenu(false); 35 }} 36 class="flex items-center gap-1.5 rounded-lg p-1 whitespace-nowrap hover:bg-neutral-200/50 active:bg-neutral-200/50 dark:hover:bg-neutral-700 dark:active:bg-neutral-700" 37 > 38 <Show when={props.icon}> 39 <span class={"iconify shrink-0 " + props.icon}></span> 40 </Show> 41 <span class="whitespace-nowrap">{props.label}</span> 42 </button> 43 ); 44}; 45 46export const NavMenu = (props: { href: string; label: string; icon: string; newTab?: boolean }) => { 47 const ctx = useContext(MenuContext); 48 49 return ( 50 <A 51 href={props.href} 52 onClick={() => ctx?.setShowMenu(false)} 53 class="flex items-center gap-1.5 rounded-lg p-1 hover:bg-neutral-200/50 active:bg-neutral-200/50 dark:hover:bg-neutral-700 dark:active:bg-neutral-700" 54 target={props.newTab ? "_blank" : undefined} 55 > 56 <span class={"iconify shrink-0 " + props.icon}></span> 57 <span class="whitespace-nowrap">{props.label}</span> 58 </A> 59 ); 60}; 61 62export const DropdownMenu = (props: { 63 icon: string; 64 buttonClass?: string; 65 menuClass?: string; 66 children?: JSX.Element; 67}) => { 68 const ctx = useContext(MenuContext); 69 const [menu, setMenu] = createSignal<HTMLDivElement>(); 70 const [menuButton, setMenuButton] = createSignal<HTMLButtonElement>(); 71 72 const clickEvent = (event: MouseEvent) => { 73 const target = event.target as Node; 74 if (!menuButton()?.contains(target) && !menu()?.contains(target)) ctx?.setShowMenu(false); 75 }; 76 77 onMount(() => window.addEventListener("click", clickEvent)); 78 onCleanup(() => window.removeEventListener("click", clickEvent)); 79 80 return ( 81 <div class="relative"> 82 <button 83 class={ 84 "flex items-center hover:bg-neutral-200 active:bg-neutral-200 dark:hover:bg-neutral-700 dark:active:bg-neutral-700 " + 85 props.buttonClass 86 } 87 ref={setMenuButton} 88 onClick={() => ctx?.setShowMenu(!ctx?.showMenu())} 89 > 90 <span class={"iconify " + props.icon}></span> 91 </button> 92 <Show when={ctx?.showMenu()}> 93 <div 94 ref={setMenu} 95 class={ 96 "dark:bg-dark-300 dark:shadow-dark-800 absolute right-0 z-20 flex flex-col rounded-lg border-[0.5px] border-neutral-300 bg-neutral-50 shadow-md dark:border-neutral-700 " + 97 props.menuClass 98 } 99 > 100 {props.children} 101 </div> 102 </Show> 103 </div> 104 ); 105};