mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feat: new Menu Component API (#6034)
* feat: new Menu Component API * allow valid children types * introduce menu group to group items * Add lang footer * use display name * displayName * define types inside * fix default menu * add json export to menu * fix * simplify expression * put open menu into own compo to optimize perf So that we don't rerun `useOutsideClickHook` (and rebind event listeners all the time) * naming tweaks * rename MenuComponents->MenuDefaultItems and export default items from Menu.Items * import Menu.scss in Menu.tsx * move menu scss to excal app * Don't filter children inside menu group * move E+ out of socials * support style prop for MenuItem and MenuGroup * Support header in menu group and add Excalidraw links header for default items in social section * rename header to title * fix padding for lang * render menu in mobile * review fixes * tweaks * Export collaborators and show in mobile menu * revert .env * lint :p * again lint * show correct actions in view mode for mobile * Whitelist Collaborators Comp * mobile styling * padding * don't show nerds when menu open in mobile * lint :( * hide shortcuts * refactor userlist to support mobile and keep a wrapper comp for excal app * use only UserList * render only on mobile for default items * remove unused hooks * Show collab button in menu when onCollabButtonClick present and hide export when UIOptions.canvasActions.export is false * fix tests * lint * inject userlist inside menu on mobile * revert userlist * move menu socials to default menu * fix collab * use meny in library * Make Menu generic and create hamburgemenu for public excal menu and use menu in library as well * use appState.openMenu for mobile * fix tests * styling fixes and support style and class name in menu content * fix test * rename MenuDefaultItems->DefaultItems * move footer css to its own comp * rename HamburgerMenu -> MainMenu * rename menu -> dropdownMenu and update classes, onClick->onToggle * close main menu when dialog closes * by bye filtering * update docs * fix lint * update example, docs for useDevice and footer in mobile, rename menu ->DropDownMenu everywhere * spec * remove isMenuOpenAtom and set openMenu as canvas for main menu, render decreases in specs :) * [temp] remove cyclic depenedency to fix build * hack- update appstate to sync lang change * Add more specs * wip: rewrite MainMenu footer * fix margin * fix snaps * not needed as lang list no more imported * simplify custom footer rendering * Add DropdownMenuItemLink and DropdownMenuItemCustom and update API, docs * fix `MainMenu.ItemCustom` * naming * use onSelect and base class for custom items * fix lint * fix snap * use custom item for lang * update docs * fix * properly use `MainMenu.ItemCustom` for `LanguageList` * add margin top to custom items * flex Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
parent
08afb857c3
commit
8420aecb34
54 changed files with 1876 additions and 1911 deletions
|
@ -41,26 +41,17 @@ import "./LayerUI.scss";
|
|||
import "./Toolbar.scss";
|
||||
import { PenModeButton } from "./PenModeButton";
|
||||
import { trackEvent } from "../analytics";
|
||||
import { isMenuOpenAtom, useDevice } from "../components/App";
|
||||
import { useDevice } from "../components/App";
|
||||
import { Stats } from "./Stats";
|
||||
import { actionToggleStats } from "../actions/actionToggleStats";
|
||||
import Footer from "./footer/Footer";
|
||||
import {
|
||||
ExportImageIcon,
|
||||
HamburgerMenuIcon,
|
||||
WelcomeScreenMenuArrow,
|
||||
WelcomeScreenTopToolbarArrow,
|
||||
} from "./icons";
|
||||
import { MenuLinks, Separator } from "./MenuUtils";
|
||||
import { useOutsideClickHook } from "../hooks/useOutsideClick";
|
||||
import { WelcomeScreenMenuArrow, WelcomeScreenTopToolbarArrow } from "./icons";
|
||||
import WelcomeScreen from "./WelcomeScreen";
|
||||
import { hostSidebarCountersAtom } from "./Sidebar/Sidebar";
|
||||
import { jotaiScope } from "../jotai";
|
||||
import { useAtom } from "jotai";
|
||||
import { LanguageList } from "../excalidraw-app/components/LanguageList";
|
||||
import WelcomeScreenDecor from "./WelcomeScreenDecor";
|
||||
import { getShortcutFromShortcutName } from "../actions/shortcuts";
|
||||
import MenuItem from "./MenuItem";
|
||||
import MainMenu from "./mainMenu/MainMenu";
|
||||
|
||||
interface LayerUIProps {
|
||||
actionManager: ActionManager;
|
||||
|
@ -103,7 +94,6 @@ const LayerUI = ({
|
|||
showExitZenModeBtn,
|
||||
isCollaborating,
|
||||
renderTopRightUI,
|
||||
|
||||
renderCustomStats,
|
||||
renderCustomSidebar,
|
||||
libraryReturnUrl,
|
||||
|
@ -133,6 +123,7 @@ const LayerUI = ({
|
|||
actionManager={actionManager}
|
||||
exportOpts={UIOptions.canvasActions.export}
|
||||
canvas={canvas}
|
||||
setAppState={setAppState}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -186,9 +177,35 @@ const LayerUI = ({
|
|||
);
|
||||
};
|
||||
|
||||
const [isMenuOpen, setIsMenuOpen] = useAtom(isMenuOpenAtom);
|
||||
const menuRef = useOutsideClickHook(() => setIsMenuOpen(false));
|
||||
|
||||
const renderMenu = () => {
|
||||
return (
|
||||
childrenComponents.Menu || (
|
||||
<MainMenu>
|
||||
<MainMenu.DefaultItems.LoadScene />
|
||||
<MainMenu.DefaultItems.SaveToActiveFile />
|
||||
{UIOptions.canvasActions.export && <MainMenu.DefaultItems.Export />}
|
||||
{UIOptions.canvasActions.saveAsImage && (
|
||||
<MainMenu.DefaultItems.SaveAsImage />
|
||||
)}
|
||||
{onCollabButtonClick && (
|
||||
<MainMenu.DefaultItems.LiveCollaboration
|
||||
onSelect={onCollabButtonClick}
|
||||
isCollaborating={isCollaborating}
|
||||
/>
|
||||
)}
|
||||
<MainMenu.DefaultItems.Help />
|
||||
<MainMenu.DefaultItems.ClearCanvas />
|
||||
<MainMenu.Separator />
|
||||
<MainMenu.Group title="Excalidraw links">
|
||||
<MainMenu.DefaultItems.Socials />
|
||||
</MainMenu.Group>
|
||||
<MainMenu.Separator />
|
||||
<MainMenu.DefaultItems.ToggleTheme />
|
||||
<MainMenu.DefaultItems.ChangeCanvasBackground />
|
||||
</MainMenu>
|
||||
)
|
||||
);
|
||||
};
|
||||
const renderCanvasActions = () => (
|
||||
<div style={{ position: "relative" }}>
|
||||
<WelcomeScreenDecor
|
||||
|
@ -199,87 +216,7 @@ const LayerUI = ({
|
|||
<div>{t("welcomeScreen.menuHints")}</div>
|
||||
</div>
|
||||
</WelcomeScreenDecor>
|
||||
|
||||
<button
|
||||
data-prevent-outside-click
|
||||
className={clsx("menu-button", "zen-mode-transition", {
|
||||
"transition-left": appState.zenModeEnabled,
|
||||
})}
|
||||
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
||||
type="button"
|
||||
data-testid="menu-button"
|
||||
>
|
||||
{HamburgerMenuIcon}
|
||||
</button>
|
||||
|
||||
{isMenuOpen && (
|
||||
<div
|
||||
ref={menuRef}
|
||||
style={{ position: "absolute", top: "100%", marginTop: ".25rem" }}
|
||||
>
|
||||
<Section heading="canvasActions">
|
||||
{/* the zIndex ensures this menu has higher stacking order,
|
||||
see https://github.com/excalidraw/excalidraw/pull/1445 */}
|
||||
<Island
|
||||
className="menu-container"
|
||||
padding={2}
|
||||
style={{ zIndex: 1 }}
|
||||
>
|
||||
{!appState.viewModeEnabled &&
|
||||
actionManager.renderAction("loadScene")}
|
||||
{/* // TODO barnabasmolnar/editor-redesign */}
|
||||
{/* is this fine here? */}
|
||||
{appState.fileHandle &&
|
||||
actionManager.renderAction("saveToActiveFile")}
|
||||
{renderJSONExportDialog()}
|
||||
{UIOptions.canvasActions.saveAsImage && (
|
||||
<MenuItem
|
||||
label={t("buttons.exportImage")}
|
||||
icon={ExportImageIcon}
|
||||
dataTestId="image-export-button"
|
||||
onClick={() => setAppState({ openDialog: "imageExport" })}
|
||||
shortcut={getShortcutFromShortcutName("imageExport")}
|
||||
/>
|
||||
)}
|
||||
{onCollabButtonClick && (
|
||||
<CollabButton
|
||||
isCollaborating={isCollaborating}
|
||||
collaboratorCount={appState.collaborators.size}
|
||||
onClick={onCollabButtonClick}
|
||||
/>
|
||||
)}
|
||||
{actionManager.renderAction("toggleShortcuts", undefined, true)}
|
||||
{!appState.viewModeEnabled &&
|
||||
actionManager.renderAction("clearCanvas")}
|
||||
<Separator />
|
||||
<MenuLinks />
|
||||
<Separator />
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
rowGap: ".5rem",
|
||||
}}
|
||||
>
|
||||
<div>{actionManager.renderAction("toggleTheme")}</div>
|
||||
<div style={{ padding: "0 0.625rem" }}>
|
||||
<LanguageList style={{ width: "100%" }} />
|
||||
</div>
|
||||
{!appState.viewModeEnabled && (
|
||||
<div>
|
||||
<div style={{ fontSize: ".75rem", marginBottom: ".5rem" }}>
|
||||
{t("labels.canvasBackground")}
|
||||
</div>
|
||||
<div style={{ padding: "0 0.625rem" }}>
|
||||
{actionManager.renderAction("changeViewBackgroundColor")}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Island>
|
||||
</Section>
|
||||
</div>
|
||||
)}
|
||||
{renderMenu()}
|
||||
</div>
|
||||
);
|
||||
|
||||
|
@ -410,10 +347,7 @@ const LayerUI = ({
|
|||
},
|
||||
)}
|
||||
>
|
||||
<UserList
|
||||
collaborators={appState.collaborators}
|
||||
actionManager={actionManager}
|
||||
/>
|
||||
<UserList collaborators={appState.collaborators} />
|
||||
{onCollabButtonClick && (
|
||||
<CollabButton
|
||||
isInHamburgerMenu={false}
|
||||
|
@ -466,6 +400,7 @@ const LayerUI = ({
|
|||
/>
|
||||
)}
|
||||
{renderImageExportDialog()}
|
||||
{renderJSONExportDialog()}
|
||||
{appState.pasteDialog.shown && (
|
||||
<PasteChartDialog
|
||||
setAppState={setAppState}
|
||||
|
@ -497,6 +432,7 @@ const LayerUI = ({
|
|||
renderCustomStats={renderCustomStats}
|
||||
renderSidebars={renderSidebars}
|
||||
device={device}
|
||||
renderMenu={renderMenu}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
@ -525,9 +461,8 @@ const LayerUI = ({
|
|||
appState={appState}
|
||||
actionManager={actionManager}
|
||||
showExitZenModeBtn={showExitZenModeBtn}
|
||||
>
|
||||
{childrenComponents.FooterCenter}
|
||||
</Footer>
|
||||
footerCenter={childrenComponents.FooterCenter}
|
||||
/>
|
||||
|
||||
{appState.showStats && (
|
||||
<Stats
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue