Skip to content

Commit

Permalink
make collaborators vertical & support custom topRight UI
Browse files Browse the repository at this point in the history
  • Loading branch information
dwelle committed Mar 6, 2021
1 parent 38d7ed9 commit aca997b
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 6 deletions.
8 changes: 7 additions & 1 deletion src/components/App.tsx
Expand Up @@ -418,7 +418,12 @@ class App extends React.Component<ExcalidrawProps, AppState> {
zenModeEnabled,
} = this.state;

const { onCollabButtonClick, onExportToBackend, renderFooter } = this.props;
const {
onCollabButtonClick,
onExportToBackend,
renderFooter,
renderTopRight,
} = this.props;

const DEFAULT_PASTE_X = canvasDOMWidth / 2;
const DEFAULT_PASTE_Y = canvasDOMHeight / 2;
Expand Down Expand Up @@ -458,6 +463,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
isCollaborating={this.props.isCollaborating || false}
onExportToBackend={onExportToBackend}
renderCustomFooter={renderFooter}
renderTopRight={renderTopRight}
viewModeEnabled={viewModeEnabled}
showExitZenModeBtn={
typeof this.props?.zenModeEnabled === "undefined" && zenModeEnabled
Expand Down
16 changes: 16 additions & 0 deletions src/components/LayerUI.tsx
Expand Up @@ -60,6 +60,7 @@ interface LayerUIProps {
appState: AppState,
canvas: HTMLCanvasElement | null,
) => void;
renderTopRight?: (isMobile: boolean) => JSX.Element;
renderCustomFooter?: (isMobile: boolean) => JSX.Element;
viewModeEnabled: boolean;
onHomeButtonClick?: () => void;
Expand Down Expand Up @@ -318,6 +319,7 @@ const LayerUI = ({
isCollaborating,
onExportToBackend,
renderCustomFooter,
renderTopRight,
viewModeEnabled,
onHomeButtonClick,
}: LayerUIProps) => {
Expand Down Expand Up @@ -516,10 +518,22 @@ const LayerUI = ({
)}
</Section>
)}
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
paddingRight: "var(--space-factor)",
}}
>
{renderTopRight?.(isMobile)}
</div>
<UserList
className={clsx("zen-mode-transition", {
"transition-right": zenModeEnabled,
})}
layout="vertical"
collaborators={appState.collaborators}
>
{appState.collaborators.size > 0 &&
Array.from(appState.collaborators)
Expand Down Expand Up @@ -670,6 +684,8 @@ const areEqual = (prev: LayerUIProps, next: LayerUIProps) => {

const keys = Object.keys(prevAppState) as (keyof Partial<AppState>)[];
return (
prev.renderCustomFooter === next.renderCustomFooter &&
prev.renderTopRight === next.renderTopRight &&
prev.langCode === next.langCode &&
prev.elements === next.elements &&
keys.every((key) => prevAppState[key] === nextAppState[key])
Expand Down
6 changes: 5 additions & 1 deletion src/components/MobileMenu.tsx
Expand Up @@ -160,7 +160,11 @@ export const MobileMenu = ({
{appState.collaborators.size > 0 && (
<fieldset>
<legend>{t("labels.collaborators")}</legend>
<UserList mobile>
<UserList
mobile
layout="horizontal"
collaborators={appState.collaborators}
>
{Array.from(appState.collaborators)
// Collaborator is either not initialized or is actually the current user.
.filter(
Expand Down
34 changes: 32 additions & 2 deletions src/components/UserList.scss
@@ -1,16 +1,46 @@
.excalidraw {
$marginTop: 60px;
// eye-balled
$bottomOffset: 60px;

.UserList {
pointer-events: none;
/*github corner*/
padding: var(--space-factor);
display: flex;
flex-wrap: wrap;
justify-content: flex-end;

overflow: hidden;
border-radius: 60px;

&.layout-vertical {
grid-column: 3;
flex-direction: column-reverse;
position: absolute;
top: $marginTop;
right: var(--space-factor);
max-height: calc(
100vh - var(--space-factor) - #{$marginTop} - #{$bottomOffset} +
var(--itemOffset)
);

.Avatar {
width: 2.4rem;
height: 2.4rem;
}

padding-bottom: max(calc(var(--itemOffset) * -1), 0px);
}
}

.UserList > * {
pointer-events: all;
margin: 0 0 var(--space-factor) var(--space-factor);
}
.UserList.layout-vertical > * {
margin-bottom: var(--itemOffset);
}
.UserList.layout-horizontal > * {
margin-right: var(--itemOffset);
}

.UserList_mobile {
Expand Down
25 changes: 23 additions & 2 deletions src/components/UserList.tsx
Expand Up @@ -2,16 +2,37 @@ import "./UserList.scss";

import React from "react";
import clsx from "clsx";
import { AppState } from "../types";

type UserListProps = {
children: React.ReactNode;
className?: string;
mobile?: boolean;
collaborators: AppState["collaborators"];
layout: "vertical" | "horizontal";
};

export const UserList = ({ children, className, mobile }: UserListProps) => {
export const UserList = ({
children,
className,
mobile,
collaborators = new Map(),
layout,
}: UserListProps) => {
const threshold = layout === "vertical" ? 6 : 3;
const offset =
collaborators.size > threshold
? Math.min(collaborators.size - threshold, 15) * -2
: 4;
return (
<div className={clsx("UserList", className, { UserList_mobile: mobile })}>
<div
className={clsx(`UserList layout-${layout}`, className, {
UserList_mobile: mobile,
})}
style={{
["--itemOffset" as any]: `${offset}px`,
}}
>
{children}
</div>
);
Expand Down
2 changes: 2 additions & 0 deletions src/packages/excalidraw/index.tsx
Expand Up @@ -29,6 +29,7 @@ const Excalidraw = (props: ExcalidrawProps) => {
zenModeEnabled,
gridModeEnabled,
onHomeButtonClick,
renderTopRight,
} = props;

useEffect(() => {
Expand Down Expand Up @@ -69,6 +70,7 @@ const Excalidraw = (props: ExcalidrawProps) => {
zenModeEnabled={zenModeEnabled}
gridModeEnabled={gridModeEnabled}
onHomeButtonClick={onHomeButtonClick}
renderTopRight={renderTopRight}
/>
</IsMobileProvider>
</InitializeApp>
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Expand Up @@ -191,6 +191,7 @@ export interface ExcalidrawProps {
appState: AppState,
canvas: HTMLCanvasElement | null,
) => void;
renderTopRight?: (isMobile: boolean) => JSX.Element;
renderFooter?: (isMobile: boolean) => JSX.Element;
langCode?: Language["code"];
viewModeEnabled?: boolean;
Expand Down

0 comments on commit aca997b

Please sign in to comment.