Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/common/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ export const DEFAULT_UI_OPTIONS: AppProps["UIOptions"] = {
tools: {
image: true,
},
uiMode: "minimal",
Comment thread
ArielMn22 marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
};

export const MAX_DECIMALS_FOR_SVG_EXPORT = 2;
Expand Down
5 changes: 5 additions & 0 deletions packages/excalidraw/components/Actions.scss
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,11 @@
margin-inline-start: 0.6em !important;
}

.panning-mode-trigger.dropdown-menu-button--mobile {
width: var(--lg-button-size) !important;
height: var(--lg-button-size) !important;
}

.lock-buttons {
display: flex;

Expand Down
17 changes: 11 additions & 6 deletions packages/excalidraw/components/LayerUI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ const LayerUI = ({
const editorInterface = useEditorInterface();
const stylesPanelMode = useStylesPanelMode();
const isCompactStylesPanel = stylesPanelMode === "compact";
const isMinimalUI = UIOptions.uiMode === "minimal";
const tunnels = useInitializeTunnels();

const spacing = isCompactStylesPanel
Expand Down Expand Up @@ -471,8 +472,8 @@ const LayerUI = ({
{/* render component fallbacks. Can be rendered anywhere as they'll be
tunneled away. We only render tunneled components that actually
have defaults when host do not render anything. */}
<DefaultMainMenu UIOptions={UIOptions} />
{UIOptions.showSidebarTrigger !== false && (
{!isMinimalUI && <DefaultMainMenu UIOptions={UIOptions} />}
{!isMinimalUI && UIOptions.showSidebarTrigger !== false && (
<DefaultSidebar.Trigger
__fallback
icon={sidebarRightIcon}
Expand Down Expand Up @@ -596,6 +597,7 @@ const LayerUI = ({
renderSidebars={renderSidebars}
renderWelcomeScreen={renderWelcomeScreen}
UIOptions={UIOptions}
isMinimalUI={isMinimalUI}
/>
)}
{editorInterface.formFactor !== "phone" && (
Expand All @@ -610,15 +612,18 @@ const LayerUI = ({
: {}
}
>
{renderWelcomeScreen && <tunnels.WelcomeScreenCenterTunnel.Out />}
{renderFixedSideContainer()}
{!isMinimalUI && renderWelcomeScreen && (
<tunnels.WelcomeScreenCenterTunnel.Out />
)}
{!isMinimalUI && renderFixedSideContainer()}
<Footer
appState={appState}
actionManager={actionManager}
showExitZenModeBtn={showExitZenModeBtn}
renderWelcomeScreen={renderWelcomeScreen}
isMinimalUI={isMinimalUI}
/>
{appState.scrolledOutside && (
{!isMinimalUI && appState.scrolledOutside && (
<button
type="button"
className="scroll-back-to-content"
Expand All @@ -632,7 +637,7 @@ const LayerUI = ({
</button>
)}
</div>
{renderSidebars()}
{!isMinimalUI && renderSidebars()}
</>
)}
</>
Expand Down
18 changes: 18 additions & 0 deletions packages/excalidraw/components/MobileMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { SCROLLBAR_WIDTH, SCROLLBAR_MARGIN } from "../scene/scrollbars";
import { ExitViewModeButton, MobileShapeActions } from "./Actions";
import { MobileToolBar } from "./MobileToolBar";
import { FixedSideContainer } from "./FixedSideContainer";
import Footer from "./footer/Footer";

import { Island } from "./Island";

Expand Down Expand Up @@ -46,6 +47,7 @@ type MobileMenuProps = {
renderWelcomeScreen: boolean;
UIOptions: AppProps["UIOptions"];
app: AppClassProperties;
isMinimalUI: boolean;
};

export const MobileMenu = ({
Expand All @@ -61,12 +63,28 @@ export const MobileMenu = ({
UIOptions,
app,
onPenModeToggle,
isMinimalUI,
}: MobileMenuProps) => {
const {
WelcomeScreenCenterTunnel,
MainMenuTunnel,
DefaultSidebarTriggerTunnel,
} = useTunnels();

if (isMinimalUI) {
return (
<div className="layer-ui__wrapper">
<Footer
appState={appState}
actionManager={actionManager}
showExitZenModeBtn={false}
renderWelcomeScreen={false}
isMinimalUI={true}
/>
</div>
);
}
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

const renderAppTopBar = () => {
if (appState.openDialog?.name === "elementLinkSelector") {
return null;
Expand Down
41 changes: 25 additions & 16 deletions packages/excalidraw/components/footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ const Footer = ({
actionManager,
showExitZenModeBtn,
renderWelcomeScreen,
isMinimalUI = false,
}: {
appState: UIAppState;
actionManager: ActionManager;
showExitZenModeBtn: boolean;
renderWelcomeScreen: boolean;
isMinimalUI?: boolean;
}) => {
const { FooterCenterTunnel, WelcomeScreenHelpHintTunnel } = useTunnels();

Expand Down Expand Up @@ -53,23 +55,30 @@ const Footer = ({
</Section>
</Stack.Col>
</div>
<FooterCenterTunnel.Out />
<div
className={clsx("layer-ui__wrapper__footer-right zen-mode-transition", {
"transition-right": appState.zenModeEnabled,
})}
>
<div style={{ position: "relative" }}>
{renderWelcomeScreen && <WelcomeScreenHelpHintTunnel.Out />}
<HelpButton
onClick={() => actionManager.executeAction(actionShortcuts)}
/>
{!isMinimalUI && <FooterCenterTunnel.Out />}
{!isMinimalUI && (
<div
className={clsx(
"layer-ui__wrapper__footer-right zen-mode-transition",
{
"transition-right": appState.zenModeEnabled,
},
)}
>
<div style={{ position: "relative" }}>
{renderWelcomeScreen && <WelcomeScreenHelpHintTunnel.Out />}
<HelpButton
onClick={() => actionManager.executeAction(actionShortcuts)}
/>
</div>
</div>
</div>
<ExitZenModeButton
actionManager={actionManager}
showExitZenModeBtn={showExitZenModeBtn}
/>
)}
{!isMinimalUI && (
<ExitZenModeButton
actionManager={actionManager}
showExitZenModeBtn={showExitZenModeBtn}
/>
)}
</footer>
);
};
Expand Down
1 change: 1 addition & 0 deletions packages/excalidraw/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const ExcalidrawBase = (props: ExcalidrawProps) => {
// compares the same values
const UIOptions: AppProps["UIOptions"] = {
...props.UIOptions,
uiMode: props.UIOptions?.uiMode ?? DEFAULT_UI_OPTIONS.uiMode,
canvasActions: {
...DEFAULT_UI_OPTIONS.canvasActions,
...canvasActions,
Expand Down
10 changes: 5 additions & 5 deletions packages/excalidraw/tests/__snapshots__/excalidraw.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`<Excalidraw/> > <MainMenu/> > should render main menu with host menu items if passed from host 1`] = `
<div
aria-labelledby="radix-:r7t:"
aria-labelledby="radix-:r9l:"
aria-orientation="vertical"
class="dropdown-menu main-menu"
data-align="start"
Expand All @@ -12,7 +12,7 @@ exports[`<Excalidraw/> > <MainMenu/> > should render main menu with host menu it
data-state="open"
data-testid="dropdown-menu"
dir="ltr"
id="radix-:r7u:"
id="radix-:r9m:"
role="menu"
style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); animation: none;"
tabindex="-1"
Expand Down Expand Up @@ -138,7 +138,7 @@ exports[`<Excalidraw/> > <MainMenu/> > should render main menu with host menu it

exports[`<Excalidraw/> > Test UIOptions prop > Test canvasActions > should render menu with default items when "UIOPtions" is "undefined" 1`] = `
<div
aria-labelledby="radix-:rq:"
aria-labelledby="radix-:r18:"
aria-orientation="vertical"
class="dropdown-menu main-menu"
data-align="start"
Expand All @@ -148,7 +148,7 @@ exports[`<Excalidraw/> > Test UIOptions prop > Test canvasActions > should rende
data-state="open"
data-testid="dropdown-menu"
dir="ltr"
id="radix-:rr:"
id="radix-:r19:"
role="menu"
style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); animation: none;"
tabindex="-1"
Expand Down Expand Up @@ -759,7 +759,7 @@ exports[`<Excalidraw/> > Test UIOptions prop > Test canvasActions > should rende
style="width: 1px; height: 1rem; margin: 0px auto;"
/>
<button
aria-controls="radix-:r16:"
aria-controls="radix-:r1k:"
aria-expanded="false"
aria-haspopup="dialog"
aria-label="Canvas background"
Expand Down
8 changes: 8 additions & 0 deletions packages/excalidraw/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -686,12 +686,20 @@ export type CanvasActions = Partial<{
saveAsImage: boolean;
}>;

export type UIMode = "default" | "minimal";

export type UIOptions = Partial<{
dockedSidebarBreakpoint: number;
canvasActions: CanvasActions;
tools: {
image: boolean;
};
/**
* The visibility preset for Excalidraw's built-in UI.
* - `default`: render all built-in controls
* - `minimal`: render only zoom + undo/redo controls
*/
uiMode: UIMode;
/**
* Optionally control the editor form factor and desktop UI mode from the host app.
* If not provided, we will take care of it internally.
Expand Down
Loading