feat: support WelcomeScreen customization API (#6048)

This commit is contained in:
David Luzar 2023-01-12 15:49:28 +01:00 committed by GitHub
parent 0982da38fe
commit 599a8f3c6f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 715 additions and 379 deletions

View file

@ -283,15 +283,12 @@ const deviceContextInitialValue = {
};
const DeviceContext = React.createContext<Device>(deviceContextInitialValue);
DeviceContext.displayName = "DeviceContext";
export const useDevice = () => useContext<Device>(DeviceContext);
export const ExcalidrawContainerContext = React.createContext<{
container: HTMLDivElement | null;
id: string | null;
}>({ container: null, id: null });
ExcalidrawContainerContext.displayName = "ExcalidrawContainerContext";
export const useExcalidrawContainer = () =>
useContext(ExcalidrawContainerContext);
const ExcalidrawElementsContext = React.createContext<
readonly NonDeletedExcalidrawElement[]
@ -309,7 +306,9 @@ ExcalidrawAppStateContext.displayName = "ExcalidrawAppStateContext";
const ExcalidrawSetAppStateContext = React.createContext<
React.Component<any, AppState>["setState"]
>(() => {});
>(() => {
console.warn("unitialized ExcalidrawSetAppStateContext context!");
});
ExcalidrawSetAppStateContext.displayName = "ExcalidrawSetAppStateContext";
const ExcalidrawActionManagerContext = React.createContext<ActionManager>(
@ -317,6 +316,9 @@ const ExcalidrawActionManagerContext = React.createContext<ActionManager>(
);
ExcalidrawActionManagerContext.displayName = "ExcalidrawActionManagerContext";
export const useDevice = () => useContext<Device>(DeviceContext);
export const useExcalidrawContainer = () =>
useContext(ExcalidrawContainerContext);
export const useExcalidrawElements = () =>
useContext(ExcalidrawElementsContext);
export const useExcalidrawAppState = () =>
@ -598,6 +600,8 @@ class App extends React.Component<AppProps, AppState> {
id={this.id}
onImageAction={this.onImageAction}
renderWelcomeScreen={
!this.state.isLoading &&
this.props.UIOptions.welcomeScreen &&
this.state.showWelcomeScreen &&
this.state.activeTool.type === "selection" &&
!this.scene.getElementsIncludingDeleted().length

View file

@ -14,6 +14,7 @@ import {
ExcalidrawProps,
BinaryFiles,
UIChildrenComponents,
UIWelcomeScreenComponents,
} from "../types";
import { isShallowEqual, muteFSAbortError, getReactChildren } from "../utils";
import { SelectedShapeActions, ShapesSwitcher } from "./Actions";
@ -45,12 +46,10 @@ import { useDevice } from "../components/App";
import { Stats } from "./Stats";
import { actionToggleStats } from "../actions/actionToggleStats";
import Footer from "./footer/Footer";
import { WelcomeScreenMenuArrow, WelcomeScreenTopToolbarArrow } from "./icons";
import WelcomeScreen from "./WelcomeScreen";
import WelcomeScreen from "./welcome-screen/WelcomeScreen";
import { hostSidebarCountersAtom } from "./Sidebar/Sidebar";
import { jotaiScope } from "../jotai";
import { useAtom } from "jotai";
import WelcomeScreenDecor from "./WelcomeScreenDecor";
import MainMenu from "./mainMenu/MainMenu";
interface LayerUIProps {
@ -111,8 +110,24 @@ const LayerUI = ({
getReactChildren<UIChildrenComponents>(children, {
Menu: true,
FooterCenter: true,
WelcomeScreen: true,
});
const [WelcomeScreenComponents] = getReactChildren<UIWelcomeScreenComponents>(
renderWelcomeScreen
? (
childrenComponents?.WelcomeScreen ?? (
<WelcomeScreen>
<WelcomeScreen.Center />
<WelcomeScreen.Hints.MenuHint />
<WelcomeScreen.Hints.ToolbarHint />
<WelcomeScreen.Hints.HelpHint />
</WelcomeScreen>
)
)?.props?.children
: null,
);
const renderJSONExportDialog = () => {
if (!UIOptions.canvasActions.export) {
return null;
@ -213,15 +228,10 @@ const LayerUI = ({
};
const renderCanvasActions = () => (
<div style={{ position: "relative" }}>
<WelcomeScreenDecor
shouldRender={renderWelcomeScreen && !appState.isLoading}
>
<div className="virgil WelcomeScreen-decor WelcomeScreen-decor--menu-pointer">
{WelcomeScreenMenuArrow}
<div>{t("welcomeScreen.menuHints")}</div>
</div>
</WelcomeScreenDecor>
{renderMenu()}
{WelcomeScreenComponents.MenuHint}
{/* wrapping to Fragment stops React from occasionally complaining
about identical Keys */}
<>{renderMenu()}</>
</div>
);
@ -258,9 +268,7 @@ const LayerUI = ({
return (
<FixedSideContainer side="top">
{renderWelcomeScreen && !appState.isLoading && (
<WelcomeScreen appState={appState} actionManager={actionManager} />
)}
{WelcomeScreenComponents.Center}
<div className="App-menu App-menu_top">
<Stack.Col
gap={6}
@ -275,17 +283,7 @@ const LayerUI = ({
<Section heading="shapes" className="shapes-section">
{(heading: React.ReactNode) => (
<div style={{ position: "relative" }}>
<WelcomeScreenDecor
shouldRender={renderWelcomeScreen && !appState.isLoading}
>
<div className="virgil WelcomeScreen-decor WelcomeScreen-decor--top-toolbar-pointer">
<div className="WelcomeScreen-decor--top-toolbar-pointer__label">
{t("welcomeScreen.toolbarHints")}
</div>
{WelcomeScreenTopToolbarArrow}
</div>
</WelcomeScreenDecor>
{WelcomeScreenComponents.ToolbarHint}
<Stack.Col gap={4} align="start">
<Stack.Row
gap={1}
@ -420,24 +418,22 @@ const LayerUI = ({
)}
{device.isMobile && (
<MobileMenu
renderWelcomeScreen={renderWelcomeScreen}
appState={appState}
elements={elements}
actionManager={actionManager}
renderJSONExportDialog={renderJSONExportDialog}
renderImageExportDialog={renderImageExportDialog}
setAppState={setAppState}
onCollabButtonClick={onCollabButtonClick}
onLockToggle={() => onLockToggle()}
onPenModeToggle={onPenModeToggle}
canvas={canvas}
isCollaborating={isCollaborating}
onImageAction={onImageAction}
renderTopRightUI={renderTopRightUI}
renderCustomStats={renderCustomStats}
renderSidebars={renderSidebars}
device={device}
renderMenu={renderMenu}
welcomeScreenCenter={WelcomeScreenComponents.Center}
/>
)}
@ -462,13 +458,12 @@ const LayerUI = ({
>
{renderFixedSideContainer()}
<Footer
renderWelcomeScreen={renderWelcomeScreen}
appState={appState}
actionManager={actionManager}
showExitZenModeBtn={showExitZenModeBtn}
footerCenter={childrenComponents.FooterCenter}
welcomeScreenHelp={WelcomeScreenComponents.HelpHint}
/>
{appState.showStats && (
<Stats
appState={appState}

View file

@ -1,5 +1,10 @@
import React from "react";
import { AppState, Device, ExcalidrawProps } from "../types";
import {
AppState,
Device,
ExcalidrawProps,
UIWelcomeScreenComponents,
} from "../types";
import { ActionManager } from "../actions/manager";
import { t } from "../i18n";
import Stack from "./Stack";
@ -17,7 +22,6 @@ import { LibraryButton } from "./LibraryButton";
import { PenModeButton } from "./PenModeButton";
import { Stats } from "./Stats";
import { actionToggleStats } from "../actions";
import WelcomeScreen from "./WelcomeScreen";
type MobileMenuProps = {
appState: AppState;
@ -26,11 +30,9 @@ type MobileMenuProps = {
renderImageExportDialog: () => React.ReactNode;
setAppState: React.Component<any, AppState>["setState"];
elements: readonly NonDeletedExcalidrawElement[];
onCollabButtonClick?: () => void;
onLockToggle: () => void;
onPenModeToggle: () => void;
canvas: HTMLCanvasElement | null;
isCollaborating: boolean;
onImageAction: (data: { insertOnCanvasDirectly: boolean }) => void;
renderTopRightUI?: (
@ -40,8 +42,8 @@ type MobileMenuProps = {
renderCustomStats?: ExcalidrawProps["renderCustomStats"];
renderSidebars: () => JSX.Element | null;
device: Device;
renderWelcomeScreen?: boolean;
renderMenu: () => React.ReactNode;
welcomeScreenCenter: UIWelcomeScreenComponents["Center"];
};
export const MobileMenu = ({
@ -52,21 +54,18 @@ export const MobileMenu = ({
onLockToggle,
onPenModeToggle,
canvas,
isCollaborating,
onImageAction,
renderTopRightUI,
renderCustomStats,
renderSidebars,
device,
renderWelcomeScreen,
renderMenu,
welcomeScreenCenter,
}: MobileMenuProps) => {
const renderToolbar = () => {
return (
<FixedSideContainer side="top" className="App-top-bar">
{renderWelcomeScreen && !appState.isLoading && (
<WelcomeScreen appState={appState} actionManager={actionManager} />
)}
{welcomeScreenCenter}
<Section heading="shapes">
{(heading: React.ReactNode) => (
<Stack.Col gap={4} align="center">
@ -74,20 +73,6 @@ export const MobileMenu = ({
<Island padding={1} className="App-toolbar App-toolbar--mobile">
{heading}
<Stack.Row gap={1}>
{/* <PenModeButton
checked={appState.penMode}
onChange={onPenModeToggle}
title={t("toolBar.penMode")}
isMobile
penDetected={appState.penDetected}
/>
<LockButton
checked={appState.activeTool.locked}
onChange={onLockToggle}
title={t("toolBar.lock")}
isMobile
/>
<div className="App-toolbar__divider"></div> */}
<ShapesSwitcher
appState={appState}
canvas={canvas}
@ -109,7 +94,6 @@ export const MobileMenu = ({
title={t("toolBar.penMode")}
isMobile
penDetected={appState.penDetected}
// penDetected={true}
/>
<LockButton
checked={appState.activeTool.locked}

View file

@ -1,121 +0,0 @@
import { actionLoadScene, actionShortcuts } from "../actions";
import { ActionManager } from "../actions/manager";
import { getShortcutFromShortcutName } from "../actions/shortcuts";
import { isExcalidrawPlusSignedUser } from "../constants";
import { t } from "../i18n";
import { AppState } from "../types";
import { ExcalLogo, HelpIcon, LoadIcon, PlusPromoIcon } from "./icons";
import "./WelcomeScreen.scss";
const WelcomeScreenItem = ({
label,
shortcut,
onClick,
icon,
link,
}: {
label: string;
shortcut: string | null;
onClick?: () => void;
icon: JSX.Element;
link?: string;
}) => {
if (link) {
return (
<a
className="WelcomeScreen-item"
href={link}
target="_blank"
rel="noreferrer"
>
<div className="WelcomeScreen-item__label">
{icon}
{label}
</div>
</a>
);
}
return (
<button className="WelcomeScreen-item" type="button" onClick={onClick}>
<div className="WelcomeScreen-item__label">
{icon}
{label}
</div>
{shortcut && (
<div className="WelcomeScreen-item__shortcut">{shortcut}</div>
)}
</button>
);
};
const WelcomeScreen = ({
appState,
actionManager,
}: {
appState: AppState;
actionManager: ActionManager;
}) => {
let subheadingJSX;
if (isExcalidrawPlusSignedUser) {
subheadingJSX = t("welcomeScreen.switchToPlusApp")
.split(/(Excalidraw\+)/)
.map((bit, idx) => {
if (bit === "Excalidraw+") {
return (
<a
style={{ pointerEvents: "all" }}
href={`${process.env.REACT_APP_PLUS_APP}?utm_source=excalidraw&utm_medium=app&utm_content=welcomeScreenSignedInUser`}
key={idx}
>
Excalidraw+
</a>
);
}
return bit;
});
} else {
subheadingJSX = t("welcomeScreen.data");
}
return (
<div className="WelcomeScreen-container">
<div className="WelcomeScreen-logo virgil WelcomeScreen-decor">
{ExcalLogo} Excalidraw
</div>
<div className="virgil WelcomeScreen-decor WelcomeScreen-decor--subheading">
{subheadingJSX}
</div>
<div className="WelcomeScreen-items">
{!appState.viewModeEnabled && (
<WelcomeScreenItem
// TODO barnabasmolnar/editor-redesign
// do we want the internationalized labels here that are currently
// in use elsewhere or new ones?
label={t("buttons.load")}
onClick={() => actionManager.executeAction(actionLoadScene)}
shortcut={getShortcutFromShortcutName("loadScene")}
icon={LoadIcon}
/>
)}
<WelcomeScreenItem
onClick={() => actionManager.executeAction(actionShortcuts)}
label={t("helpDialog.title")}
shortcut="?"
icon={HelpIcon}
/>
{!isExcalidrawPlusSignedUser && (
<WelcomeScreenItem
link="https://plus.excalidraw.com/plus?utm_source=excalidraw&utm_medium=app&utm_content=welcomeScreenGuest"
label="Try Excalidraw Plus!"
shortcut={null}
icon={PlusPromoIcon}
/>
)}
</div>
</div>
);
};
export default WelcomeScreen;

View file

@ -1,11 +0,0 @@
import { ReactNode } from "react";
const WelcomeScreenDecor = ({
children,
shouldRender,
}: {
children: ReactNode;
shouldRender: boolean;
}) => (shouldRender ? <>{children}</> : null);
export default WelcomeScreenDecor;

View file

@ -1,8 +1,11 @@
import clsx from "clsx";
import { actionShortcuts } from "../../actions";
import { ActionManager } from "../../actions/manager";
import { t } from "../../i18n";
import { AppState, UIChildrenComponents } from "../../types";
import {
AppState,
UIChildrenComponents,
UIWelcomeScreenComponents,
} from "../../types";
import {
ExitZenModeAction,
FinalizeAction,
@ -11,23 +14,21 @@ import {
} from "../Actions";
import { useDevice } from "../App";
import { HelpButton } from "../HelpButton";
import { WelcomeScreenHelpArrow } from "../icons";
import { Section } from "../Section";
import Stack from "../Stack";
import WelcomeScreenDecor from "../WelcomeScreenDecor";
const Footer = ({
appState,
actionManager,
showExitZenModeBtn,
renderWelcomeScreen,
footerCenter,
welcomeScreenHelp,
}: {
appState: AppState;
actionManager: ActionManager;
showExitZenModeBtn: boolean;
renderWelcomeScreen: boolean;
footerCenter: UIChildrenComponents["FooterCenter"];
welcomeScreenHelp: UIWelcomeScreenComponents["HelpHint"];
}) => {
const device = useDevice();
const showFinalize =
@ -79,17 +80,8 @@ const Footer = ({
})}
>
<div style={{ position: "relative" }}>
<WelcomeScreenDecor
shouldRender={renderWelcomeScreen && !appState.isLoading}
>
<div className="virgil WelcomeScreen-decor WelcomeScreen-decor--help-pointer">
<div>{t("welcomeScreen.helpHints")}</div>
{WelcomeScreenHelpArrow}
</div>
</WelcomeScreenDecor>
{welcomeScreenHelp}
<HelpButton
title={t("helpDialog.title")}
onClick={() => actionManager.executeAction(actionShortcuts)}
/>
</div>

View file

@ -0,0 +1,176 @@
import { actionLoadScene, actionShortcuts } from "../../actions";
import { getShortcutFromShortcutName } from "../../actions/shortcuts";
import { t } from "../../i18n";
import {
useDevice,
useExcalidrawActionManager,
useExcalidrawAppState,
} from "../App";
import { ExcalLogo, HelpIcon, LoadIcon } from "../icons";
const WelcomeScreenMenuItemContent = ({
icon,
shortcut,
children,
}: {
icon?: JSX.Element;
shortcut?: string | null;
children: React.ReactNode;
}) => {
const device = useDevice();
return (
<>
<div className="welcome-screen-menu-item__icon">{icon}</div>
<div className="welcome-screen-menu-item__text">{children}</div>
{shortcut && !device.isMobile && (
<div className="welcome-screen-menu-item__shortcut">{shortcut}</div>
)}
</>
);
};
WelcomeScreenMenuItemContent.displayName = "WelcomeScreenMenuItemContent";
const WelcomeScreenMenuItem = ({
onSelect,
children,
icon,
shortcut,
className = "",
...props
}: {
onSelect: () => void;
children: React.ReactNode;
icon?: JSX.Element;
shortcut?: string | null;
} & React.ButtonHTMLAttributes<HTMLButtonElement>) => {
return (
<button
{...props}
type="button"
className={`welcome-screen-menu-item ${className}`}
onClick={onSelect}
>
<WelcomeScreenMenuItemContent icon={icon} shortcut={shortcut}>
{children}
</WelcomeScreenMenuItemContent>
</button>
);
};
WelcomeScreenMenuItem.displayName = "WelcomeScreenMenuItem";
const WelcomeScreenMenuItemLink = ({
children,
href,
icon,
shortcut,
className = "",
...props
}: {
children: React.ReactNode;
href: string;
icon?: JSX.Element;
shortcut?: string | null;
} & React.AnchorHTMLAttributes<HTMLAnchorElement>) => {
return (
<a
{...props}
className={`welcome-screen-menu-item ${className}`}
href={href}
target="_blank"
rel="noreferrer"
>
<WelcomeScreenMenuItemContent icon={icon} shortcut={shortcut}>
{children}
</WelcomeScreenMenuItemContent>
</a>
);
};
WelcomeScreenMenuItemLink.displayName = "WelcomeScreenMenuItemLink";
const Center = ({ children }: { children?: React.ReactNode }) => {
return (
<div className="welcome-screen-center">
{children || (
<>
<Logo />
<Heading>{t("welcomeScreen.defaults.center_heading")}</Heading>
<Menu>
<MenuItemLoadScene />
<MenuItemHelp />
</Menu>
</>
)}
</div>
);
};
Center.displayName = "Center";
const Logo = ({ children }: { children?: React.ReactNode }) => {
return (
<div className="welcome-screen-center__logo virgil welcome-screen-decor">
{children || <>{ExcalLogo} Excalidraw</>}
</div>
);
};
Logo.displayName = "Logo";
const Heading = ({ children }: { children: React.ReactNode }) => {
return (
<div className="welcome-screen-center__heading welcome-screen-decor virgil">
{children}
</div>
);
};
Heading.displayName = "Heading";
const Menu = ({ children }: { children?: React.ReactNode }) => {
return <div className="welcome-screen-menu">{children}</div>;
};
Menu.displayName = "Menu";
const MenuItemHelp = () => {
const actionManager = useExcalidrawActionManager();
return (
<WelcomeScreenMenuItem
onSelect={() => actionManager.executeAction(actionShortcuts)}
shortcut="?"
icon={HelpIcon}
>
{t("helpDialog.title")}
</WelcomeScreenMenuItem>
);
};
MenuItemHelp.displayName = "MenuItemHelp";
const MenuItemLoadScene = () => {
const appState = useExcalidrawAppState();
const actionManager = useExcalidrawActionManager();
if (appState.viewModeEnabled) {
return null;
}
return (
<WelcomeScreenMenuItem
onSelect={() => actionManager.executeAction(actionLoadScene)}
shortcut={getShortcutFromShortcutName("loadScene")}
icon={LoadIcon}
>
{t("buttons.load")}
</WelcomeScreenMenuItem>
);
};
MenuItemLoadScene.displayName = "MenuItemLoadScene";
// -----------------------------------------------------------------------------
Center.Logo = Logo;
Center.Heading = Heading;
Center.Menu = Menu;
Center.MenuItem = WelcomeScreenMenuItem;
Center.MenuItemLink = WelcomeScreenMenuItemLink;
Center.MenuItemHelp = MenuItemHelp;
Center.MenuItemLoadScene = MenuItemLoadScene;
export { Center };

View file

@ -0,0 +1,42 @@
import { t } from "../../i18n";
import {
WelcomeScreenHelpArrow,
WelcomeScreenMenuArrow,
WelcomeScreenTopToolbarArrow,
} from "../icons";
const MenuHint = ({ children }: { children?: React.ReactNode }) => {
return (
<div className="virgil welcome-screen-decor welcome-screen-decor-hint welcome-screen-decor-hint--menu">
{WelcomeScreenMenuArrow}
<div className="welcome-screen-decor-hint__label">
{children || t("welcomeScreen.defaults.menuHint")}
</div>
</div>
);
};
MenuHint.displayName = "MenuHint";
const ToolbarHint = ({ children }: { children?: React.ReactNode }) => {
return (
<div className="virgil welcome-screen-decor welcome-screen-decor-hint welcome-screen-decor-hint--toolbar">
<div className="welcome-screen-decor-hint__label">
{children || t("welcomeScreen.defaults.toolbarHint")}
</div>
{WelcomeScreenTopToolbarArrow}
</div>
);
};
ToolbarHint.displayName = "ToolbarHint";
const HelpHint = ({ children }: { children?: React.ReactNode }) => {
return (
<div className="virgil welcome-screen-decor welcome-screen-decor-hint welcome-screen-decor-hint--help">
<div>{children || t("welcomeScreen.defaults.helpHint")}</div>
{WelcomeScreenHelpArrow}
</div>
);
};
HelpHint.displayName = "HelpHint";
export { HelpHint, MenuHint, ToolbarHint };

View file

@ -3,29 +3,39 @@
font-family: "Virgil";
}
.WelcomeScreen-logo {
display: flex;
align-items: center;
column-gap: 0.75rem;
font-size: 2.25rem;
// WelcomeSreen common
// ---------------------------------------------------------------------------
svg {
width: 1.625rem;
height: auto;
}
}
.WelcomeScreen-decor {
.welcome-screen-decor {
pointer-events: none;
color: var(--color-gray-40);
}
&--subheading {
font-size: 1.125rem;
text-align: center;
&.theme--dark {
.welcome-screen-decor {
color: var(--color-gray-60);
}
}
// WelcomeScreen.Hints
// ---------------------------------------------------------------------------
.welcome-screen-decor-hint {
@media (max-height: 599px) {
display: none !important;
}
&--help-pointer {
@media (max-width: 1024px), (max-width: 800px) {
.welcome-screen-decor {
&--help,
&--menu {
display: none;
}
}
}
&--help {
display: flex;
position: absolute;
right: 0;
@ -49,7 +59,7 @@
}
}
&--top-toolbar-pointer {
&--toolbar {
position: absolute;
top: 100%;
left: 50%;
@ -58,7 +68,7 @@
display: flex;
align-items: baseline;
&__label {
.welcome-screen-decor-hint__label {
width: 120px;
position: relative;
top: -0.5rem;
@ -74,7 +84,7 @@
}
}
&--menu-pointer {
&--menu {
position: absolute;
width: 320px;
font-size: 1rem;
@ -95,10 +105,19 @@
transform: scaleX(-1);
}
}
@media (max-width: 860px) {
.welcome-screen-decor-hint__label {
max-width: 160px;
}
}
}
}
.WelcomeScreen-container {
// WelcomeSreen.Center
// ---------------------------------------------------------------------------
.welcome-screen-center {
display: flex;
flex-direction: column;
gap: 2rem;
@ -112,7 +131,24 @@
bottom: 1rem;
}
.WelcomeScreen-items {
.welcome-screen-center__logo {
display: flex;
align-items: center;
column-gap: 0.75rem;
font-size: 2.25rem;
svg {
width: 1.625rem;
height: auto;
}
}
.welcome-screen-center__heading {
font-size: 1.125rem;
text-align: center;
}
.welcome-screen-menu {
display: flex;
flex-direction: column;
gap: 2px;
@ -120,7 +156,7 @@
align-items: center;
}
.WelcomeScreen-item {
.welcome-screen-menu-item {
box-sizing: border-box;
pointer-events: all;
@ -128,8 +164,10 @@
color: var(--color-gray-50);
font-size: 0.875rem;
width: 100%;
min-width: 300px;
display: flex;
max-width: 400px;
display: grid;
align-items: center;
justify-content: space-between;
@ -140,44 +178,49 @@
border-radius: var(--border-radius-md);
&__label {
grid-template-columns: calc(var(--default-icon-size) + 0.5rem) 1fr 3rem;
&__text {
display: flex;
align-items: center;
margin-right: auto;
text-align: left;
column-gap: 0.5rem;
}
svg {
width: var(--default-icon-size);
height: var(--default-icon-size);
}
&__icon {
width: var(--default-icon-size);
height: var(--default-icon-size);
}
&__shortcut {
margin-left: auto;
color: var(--color-gray-40);
font-size: 0.75rem;
}
}
&:not(:active) .WelcomeScreen-item:hover {
&:not(:active) .welcome-screen-menu-item:hover {
text-decoration: none;
background: var(--color-gray-10);
.WelcomeScreen-item__shortcut {
.welcome-screen-menu-item__shortcut {
color: var(--color-gray-50);
}
.WelcomeScreen-item__label {
.welcome-screen-menu-item__text {
color: var(--color-gray-100);
}
}
.WelcomeScreen-item:active {
.welcome-screen-menu-item:active {
background: var(--color-gray-20);
.WelcomeScreen-item__shortcut {
.welcome-screen-menu-item__shortcut {
color: var(--color-gray-50);
}
.WelcomeScreen-item__label {
.welcome-screen-menu-item__text {
color: var(--color-gray-100);
}
@ -185,7 +228,7 @@
color: var(--color-promo) !important;
&:hover {
.WelcomeScreen-item__label {
.welcome-screen-menu-item__text {
color: var(--color-promo) !important;
}
}
@ -193,11 +236,7 @@
}
&.theme--dark {
.WelcomeScreen-decor {
color: var(--color-gray-60);
}
.WelcomeScreen-item {
.welcome-screen-menu-item {
color: var(--color-gray-60);
&__shortcut {
@ -205,69 +244,41 @@
}
}
&:not(:active) .WelcomeScreen-item:hover {
&:not(:active) .welcome-screen-menu-item:hover {
background: var(--color-gray-85);
.WelcomeScreen-item__shortcut {
.welcome-screen-menu-item__shortcut {
color: var(--color-gray-50);
}
.WelcomeScreen-item__label {
.welcome-screen-menu-item__text {
color: var(--color-gray-10);
}
}
.WelcomeScreen-item:active {
.welcome-screen-menu-item:active {
background-color: var(--color-gray-90);
.WelcomeScreen-item__label {
.welcome-screen-menu-item__text {
color: var(--color-gray-10);
}
}
}
// Can tweak these values but for an initial effort, it looks OK to me
@media (max-width: 1024px) {
.WelcomeScreen-decor {
&--help-pointer,
&--menu-pointer {
display: none;
}
}
}
// @media (max-height: 400px) {
// .WelcomeScreen-container {
// margin-top: 0;
// }
// }
@media (max-height: 599px) {
.WelcomeScreen-container {
.welcome-screen-center {
margin-top: 4rem;
}
}
@media (min-height: 600px) and (max-height: 900px) {
.WelcomeScreen-container {
.welcome-screen-center {
margin-top: 8rem;
}
}
@media (max-height: 630px) {
.WelcomeScreen-decor--top-toolbar-pointer {
display: none;
}
}
@media (max-height: 500px) {
.WelcomeScreen-container {
@media (max-height: 500px), (max-width: 320px) {
.welcome-screen-center {
display: none;
}
}
// @media (max-height: 740px) {
// .WelcomeScreen-decor {
// &--help-pointer,
// &--top-toolbar-pointer,
// &--menu-pointer {
// display: none;
// }
// }
// }
// ---------------------------------------------------------------------------
}

View file

@ -0,0 +1,17 @@
import { Center } from "./WelcomeScreen.Center";
import { MenuHint, ToolbarHint, HelpHint } from "./WelcomeScreen.Hints";
import "./WelcomeScreen.scss";
const WelcomeScreen = (props: { children: React.ReactNode }) => {
// NOTE this component is used as a dummy wrapper to retrieve child props
// from, and will never be rendered to DOM directly. As such, we can't
// do anything here (use hooks and such)
return null;
};
WelcomeScreen.displayName = "WelcomeScreen";
WelcomeScreen.Center = Center;
WelcomeScreen.Hints = { MenuHint, ToolbarHint, HelpHint };
export default WelcomeScreen;