Skip to content

Commit

Permalink
fix: close menus (#88)
Browse files Browse the repository at this point in the history
  • Loading branch information
j4k0xb committed Jun 6, 2024
1 parent 12f4f47 commit bc42f4e
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 132 deletions.
2 changes: 1 addition & 1 deletion apps/playground/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import {
import { createStore } from 'solid-js/store';
import Alert from './components/Alert';
import Breadcrumbs from './components/Breadcrumbs';
import Menu from './components/Menu';
import MonacoEditor from './components/MonacoEditor';
import ProgressBar from './components/ProgressBar';
import Sidebar from './components/Sidebar';
import Tab from './components/Tab';
import Menu from './components/menu/Menu';
import { DeobfuscateContextProvider } from './context/DeobfuscateContext';
import { settings } from './hooks/useSettings';
import { useWorkspaces, type Workspace } from './indexeddb';
Expand Down
131 changes: 0 additions & 131 deletions apps/playground/src/components/Menu.tsx

This file was deleted.

124 changes: 124 additions & 0 deletions apps/playground/src/components/menu/Menu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { For, createSignal, onCleanup, onMount } from 'solid-js';
import { setSettings, settings, type Settings } from '../../hooks/useSettings';
import { useWorkspaces, type Workspace } from '../../indexeddb';
import { openFile } from '../../utils/files';
import MenuButton from './MenuButton';
import MenuDropdown from './MenuDropdown';
import MenuHeader from './MenuHeader';
import MenuSetting from './MenuSetting';

interface Props {
onFileOpen?: (content: string) => void;
onSave?: () => void;
onRestore?: (workspace: Workspace) => void;
}

export default function Menu(props: Props) {
const { workspaces } = useWorkspaces();
const [openedMenu, setOpenedMenu] = createSignal<
'file' | 'settings' | undefined
>();
let menuRef: HTMLUListElement | undefined;

onMount(() => {
document.addEventListener('click', onClickOutside);
});

onCleanup(() => {
document.removeEventListener('click', onClickOutside);
});

function onClickOutside(event: MouseEvent) {
if (menuRef && !menuRef.contains(event.target as Node)) {
setOpenedMenu(undefined);
}
}

return (
<ul ref={menuRef} class="menu menu-sm menu-horizontal bg-base-200 w-full">
<MenuHeader
title="File"
open={openedMenu() === 'file'}
onOpen={() => setOpenedMenu('file')}
>
<MenuButton
shortcut={['Ctrl', 'O']}
onClick={() => openFile(props.onFileOpen)}
>
Open File…
</MenuButton>
<MenuDropdown title="Open Recent">
<For each={workspaces()} fallback={<li>No recent files</li>}>
{(workspace) => (
<MenuButton class="whitespace-nowrap">
{new Date(workspace.timestamp).toLocaleString()} -
<code class="overflow-x-clip overflow-ellipsis max-w-36">
{workspace.models[0].value.slice(0, 50)}
</code>
</MenuButton>
)}
</For>
</MenuDropdown>
<MenuButton shortcut={['Ctrl', 'S']} onClick={props.onSave}>
Save
</MenuButton>
</MenuHeader>
<MenuHeader
title="Settings"
open={openedMenu() === 'settings'}
onOpen={() => setOpenedMenu('settings')}
>
<MenuSetting>
Theme
<select
class="select select-sm ml-auto"
value={settings.theme}
onChange={(e) =>
setSettings('theme', e.currentTarget.value as Settings['theme'])
}
>
<option value="dark">Dark</option>
<option value="light">Light</option>
<option value="system">System</option>
</select>
</MenuSetting>
<MenuSetting>
Confirm on Leave
<input
type="checkbox"
class="checkbox checkbox-sm ml-auto"
checked={settings.confirmOnLeave}
onChange={(e) =>
setSettings('confirmOnLeave', e.currentTarget.checked)
}
/>
</MenuSetting>
<MenuSetting>
Workspace History
<input
type="checkbox"
class="checkbox checkbox-sm ml-auto"
checked={settings.workspaceHistory}
onChange={(e) =>
setSettings('workspaceHistory', e.currentTarget.checked)
}
/>
</MenuSetting>
</MenuHeader>
<li>
<a
href="https://github.com/j4k0xb/webcrack"
target="_blank"
class="link link-hover"
>
GitHub
</a>
</li>
<li>
<a href="/docs" target="_blank" class="link link-hover">
Documentation
</a>
</li>
</ul>
);
}
32 changes: 32 additions & 0 deletions apps/playground/src/components/menu/MenuButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Index, Show, type JSX, type ParentProps } from 'solid-js';

interface Props {
shortcut?: string[];
class?: string;
onClick?: () => void;
}

export default function MenuButton(props: ParentProps<Props>) {
const onClick: JSX.EventHandler<HTMLLIElement, MouseEvent> = (event) => {
event.target.closest('details')?.removeAttribute('open');
props.onClick?.();
};

return (
<li onClick={onClick}>
<a class={props.class}>
{props.children}
<span class="ml-auto">
<Index each={props.shortcut}>
{(key, index) => (
<>
<Show when={index > 0}>+</Show>
<kbd class="kbd kbd-xs">{key()}</kbd>
</>
)}
</Index>
</span>
</a>
</li>
);
}
23 changes: 23 additions & 0 deletions apps/playground/src/components/menu/MenuDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { JSX, ParentProps } from 'solid-js';

interface Props {
title: JSX.Element;
}

export default function MenuDropdown(props: ParentProps<Props>) {
return (
<li>
<div class="dropdown dropdown-right dropdown-hover transform-none">
<div tabindex="0" role="button">
{props.title}
</div>
<ul
tabindex="0"
class="dropdown-content z-10 menu ml-0 p-2 shadow bg-base-100 rounded-box"
>
{props.children}
</ul>
</div>
</li>
);
}
24 changes: 24 additions & 0 deletions apps/playground/src/components/menu/MenuHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { JSX, ParentProps } from 'solid-js';

interface Props {
title: JSX.Element;
open?: boolean;
href?: string;
onOpen?: () => void;
}

export default function MenuHeader(props: ParentProps<Props>) {
return (
<li>
<details
open={props.open}
onToggle={(e) => {
if (e.currentTarget.open) props.onOpen?.();
}}
>
<summary>{props.title}</summary>
<ul class="min-w-52 z-10">{props.children}</ul>
</details>
</li>
);
}
9 changes: 9 additions & 0 deletions apps/playground/src/components/menu/MenuSetting.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { ParentProps } from 'solid-js';

export default function MenuSetting(props: ParentProps) {
return (
<li>
<label class="flex items-center">{props.children}</label>
</li>
);
}

0 comments on commit bc42f4e

Please sign in to comment.