diff --git a/excalidraw-app/App.tsx b/excalidraw-app/App.tsx
index a5d01769cc..ab91d8cc36 100644
--- a/excalidraw-app/App.tsx
+++ b/excalidraw-app/App.tsx
@@ -137,6 +137,9 @@ import { ExcalidrawPlusIframeExport } from "./ExcalidrawPlusIframeExport";
import "./index.scss";
+import { ExcalidrawPlusAppLink } from "./components/ExcalidrawPlusAppLink";
+import { AppSidebar } from "./components/AppSidebar";
+
import type { CollabAPI } from "./collab/Collab";
polyfill();
@@ -850,6 +853,7 @@ const ExcalidrawWrapper = () => {
}
return (
+
{collabError.message &&
}
{
}}
/>
+
+
{errorMessage && (
setErrorMessage("")}>
{errorMessage}
diff --git a/excalidraw-app/components/AppFooter.tsx b/excalidraw-app/components/AppFooter.tsx
index 7d42d46bf8..5e2cb27cb3 100644
--- a/excalidraw-app/components/AppFooter.tsx
+++ b/excalidraw-app/components/AppFooter.tsx
@@ -5,7 +5,6 @@ import { isExcalidrawPlusSignedUser } from "../app_constants";
import { DebugFooter, isVisualDebuggerEnabled } from "./DebugCanvas";
import { EncryptedIcon } from "./EncryptedIcon";
-import { ExcalidrawPlusAppLink } from "./ExcalidrawPlusAppLink";
export const AppFooter = React.memo(
({ onChange }: { onChange: () => void }) => {
@@ -19,11 +18,7 @@ export const AppFooter = React.memo(
}}
>
{isVisualDebuggerEnabled() && }
- {isExcalidrawPlusSignedUser ? (
-
- ) : (
-
- )}
+ {!isExcalidrawPlusSignedUser && }
);
diff --git a/excalidraw-app/components/AppSidebar.scss b/excalidraw-app/components/AppSidebar.scss
new file mode 100644
index 0000000000..ab3156c2d5
--- /dev/null
+++ b/excalidraw-app/components/AppSidebar.scss
@@ -0,0 +1,36 @@
+.excalidraw {
+ .app-sidebar-promo-container {
+ padding: 0.75rem;
+ display: flex;
+ flex-direction: column;
+ text-align: center;
+ gap: 1rem;
+ flex: 1 1 auto;
+ }
+
+ .app-sidebar-promo-image {
+ margin: 1rem 0;
+
+ height: 16.25rem;
+ background-size: contain;
+ background-position: center;
+ background-repeat: no-repeat;
+
+ background-image: radial-gradient(
+ circle,
+ transparent 60%,
+ var(--sidebar-bg-color) 100%
+ ),
+ var(--image-source);
+
+ display: flex;
+ }
+
+ .app-sidebar-promo-text {
+ padding: 0 2rem;
+ }
+
+ .link-button {
+ margin: 0 auto;
+ }
+}
diff --git a/excalidraw-app/components/AppSidebar.tsx b/excalidraw-app/components/AppSidebar.tsx
new file mode 100644
index 0000000000..a722a406ba
--- /dev/null
+++ b/excalidraw-app/components/AppSidebar.tsx
@@ -0,0 +1,73 @@
+import { DefaultSidebar, Sidebar, THEME } from "@excalidraw/excalidraw";
+import {
+ messageCircleIcon,
+ presentationIcon,
+} from "@excalidraw/excalidraw/components/icons";
+import { LinkButton } from "@excalidraw/excalidraw/components/LinkButton";
+import { useUIAppState } from "@excalidraw/excalidraw/context/ui-appState";
+
+import "./AppSidebar.scss";
+
+export const AppSidebar = () => {
+ const { theme } = useUIAppState();
+
+ return (
+
+
+
+ {messageCircleIcon}
+
+
+ {presentationIcon}
+
+
+
+
+
+
+ Make comments with Excalidraw+
+
+
+ Sign up now
+
+
+
+
+
+
+
+ Create presentations with Excalidraw+
+
+
+ Sign up now
+
+
+
+
+ );
+};
diff --git a/excalidraw-app/components/ExcalidrawPlusAppLink.tsx b/excalidraw-app/components/ExcalidrawPlusAppLink.tsx
index 04cd963022..51d856dbfc 100644
--- a/excalidraw-app/components/ExcalidrawPlusAppLink.tsx
+++ b/excalidraw-app/components/ExcalidrawPlusAppLink.tsx
@@ -1,19 +1,22 @@
-import { isExcalidrawPlusSignedUser } from "../app_constants";
-
-export const ExcalidrawPlusAppLink = () => {
- if (!isExcalidrawPlusSignedUser) {
- return null;
- }
+export const ExcalidrawPlusAppLink = ({
+ isSignedIn,
+}: {
+ isSignedIn: boolean;
+}) => {
return (
- Go to Excalidraw+
+ Excalidraw+
);
};
diff --git a/excalidraw-app/index.scss b/excalidraw-app/index.scss
index 9f320775be..aa58d88c05 100644
--- a/excalidraw-app/index.scss
+++ b/excalidraw-app/index.scss
@@ -1,3 +1,5 @@
+@import "../packages/excalidraw/css/variables.module.scss";
+
.excalidraw {
--color-primary-contrast-offset: #625ee0; // to offset Chubb illusion
@@ -9,6 +11,7 @@
display: flex;
justify-content: center;
align-items: flex-start;
+ gap: 0.75rem;
}
.footer-center {
@@ -90,22 +93,31 @@
}
}
-.plus-button {
+.plus-banner {
display: flex;
justify-content: center;
cursor: pointer;
align-items: center;
border: 1px solid var(--color-primary);
- padding: 0.5rem 0.75rem;
+ padding: 0.5rem 0.875rem;
border-radius: var(--border-radius-lg);
background-color: var(--island-bg-color);
- color: var(--color-primary) !important;
text-decoration: none !important;
- font-size: 0.75rem;
+ font-family: var(--ui-font);
+ font-size: 0.8333rem;
box-sizing: border-box;
height: var(--lg-button-size);
+ border: none;
+ box-shadow: 0 0 0 1px var(--color-surface-lowest);
+ background-color: var(--color-surface-low);
+ color: var(--button-color, var(--color-on-surface)) !important;
+
+ &:active {
+ box-shadow: 0 0 0 1px var(--color-brand-active);
+ }
+
&:hover {
background-color: var(--color-primary);
color: white !important;
@@ -117,7 +129,7 @@
}
.theme--dark {
- .plus-button {
+ .plus-banner {
&:hover {
color: black !important;
}
diff --git a/packages/excalidraw/components/FilledButton.tsx b/packages/excalidraw/components/FilledButton.tsx
index 53b30a0469..7d5c4ccfd1 100644
--- a/packages/excalidraw/components/FilledButton.tsx
+++ b/packages/excalidraw/components/FilledButton.tsx
@@ -20,7 +20,7 @@ export type ButtonColor =
export type ButtonSize = "medium" | "large";
export type FilledButtonProps = {
- label: string;
+ label?: string;
children?: React.ReactNode;
onClick?: (event: React.MouseEvent) => void;
diff --git a/packages/excalidraw/components/LayerUI.tsx b/packages/excalidraw/components/LayerUI.tsx
index 4fd6f6d269..f7f5a98e6d 100644
--- a/packages/excalidraw/components/LayerUI.tsx
+++ b/packages/excalidraw/components/LayerUI.tsx
@@ -4,7 +4,6 @@ import React from "react";
import {
CLASSES,
DEFAULT_SIDEBAR,
- MQ_MIN_WIDTH_DESKTOP,
TOOL_TYPE,
arrayToMap,
capitalizeString,
@@ -48,7 +47,7 @@ import MainMenu from "./main-menu/MainMenu";
import { ActiveConfirmDialog } from "./ActiveConfirmDialog";
import { useDevice } from "./App";
import { OverwriteConfirmDialog } from "./OverwriteConfirm/OverwriteConfirm";
-import { LibraryIcon } from "./icons";
+import { sidebarRightIcon } from "./icons";
import { DefaultSidebar } from "./DefaultSidebar";
import { TTDDialog } from "./TTDDialog/TTDDialog";
import { Stats } from "./Stats";
@@ -469,7 +468,7 @@ const LayerUI = ({
{
if (open) {
@@ -481,11 +480,7 @@ const LayerUI = ({
}
}}
tab={DEFAULT_SIDEBAR.defaultTab}
- >
- {appState.stylesPanelMode === "full" &&
- appState.width >= MQ_MIN_WIDTH_DESKTOP &&
- t("toolBar.library")}
-
+ />
{appState.openDialog?.name === "ttd" && }
{/* ------------------------------------------------------------------ */}
diff --git a/packages/excalidraw/components/LinkButton.tsx b/packages/excalidraw/components/LinkButton.tsx
new file mode 100644
index 0000000000..6c53e2da0a
--- /dev/null
+++ b/packages/excalidraw/components/LinkButton.tsx
@@ -0,0 +1,15 @@
+import { FilledButton } from "./FilledButton";
+
+export const LinkButton = ({
+ children,
+ href,
+}: {
+ href: string;
+ children: React.ReactNode;
+}) => {
+ return (
+
+ {children}
+
+ );
+};
diff --git a/packages/excalidraw/components/icons.tsx b/packages/excalidraw/components/icons.tsx
index 3f6c4d1bb1..be84f087a6 100644
--- a/packages/excalidraw/components/icons.tsx
+++ b/packages/excalidraw/components/icons.tsx
@@ -2326,3 +2326,41 @@ export const strokeIcon = createIcon(
,
tablerIconProps,
);
+
+export const chevronLeftIcon = createIcon(
+
+
+
+
+ ,
+ tablerIconProps,
+);
+
+export const sidebarRightIcon = createIcon(
+
+
+
+
+ ,
+ tablerIconProps,
+);
+
+export const messageCircleIcon = createIcon(
+
+
+
+ ,
+ tablerIconProps,
+);
+
+export const presentationIcon = createIcon(
+
+
+
+
+
+
+
+ ,
+ tablerIconProps,
+);
diff --git a/packages/excalidraw/css/styles.scss b/packages/excalidraw/css/styles.scss
index c5b2e12550..8ff2d081dd 100644
--- a/packages/excalidraw/css/styles.scss
+++ b/packages/excalidraw/css/styles.scss
@@ -50,6 +50,11 @@ body.excalidraw-cursor-resize * {
height: 100%;
width: 100%;
+ button {
+ // browser default. Looks kinda good on low-dpi.
+ font-size: 0.8333rem;
+ }
+
button,
label {
@include buttonNoHighlight;
@@ -707,6 +712,11 @@ body.excalidraw-cursor-resize * {
margin-top: 0rem;
}
}
+
+ .link-button {
+ display: flex;
+ text-decoration: none !important;
+ }
}
.ErrorSplash.excalidraw {
diff --git a/public/oss_promo_comments_dark.jpg b/public/oss_promo_comments_dark.jpg
new file mode 100644
index 0000000000..e015f8a6b9
Binary files /dev/null and b/public/oss_promo_comments_dark.jpg differ
diff --git a/public/oss_promo_comments_light.jpg b/public/oss_promo_comments_light.jpg
new file mode 100644
index 0000000000..c8c4507b8e
Binary files /dev/null and b/public/oss_promo_comments_light.jpg differ
diff --git a/public/oss_promo_presentations_dark.svg b/public/oss_promo_presentations_dark.svg
new file mode 100644
index 0000000000..31a0eac6e6
--- /dev/null
+++ b/public/oss_promo_presentations_dark.svg
@@ -0,0 +1 @@
+
diff --git a/public/oss_promo_presentations_light.svg b/public/oss_promo_presentations_light.svg
new file mode 100644
index 0000000000..d9e7c93572
--- /dev/null
+++ b/public/oss_promo_presentations_light.svg
@@ -0,0 +1 @@
+