feat: library sidebar design tweaks (#6582)

This commit is contained in:
David Luzar 2023-05-13 13:18:14 +02:00 committed by GitHub
parent e619e06055
commit fff9d1522a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 128 additions and 68 deletions

View File

@ -1,11 +1,6 @@
@import "open-color/open-color";
.excalidraw {
.library-menu-items-container {
height: 100%;
width: 100%;
}
.layer-ui__library {
display: flex;
flex-direction: column;
@ -70,6 +65,16 @@
align-items: center;
justify-content: center;
gap: 0.625rem;
position: relative;
&--at-bottom::before {
content: "";
width: calc(100% - 1.5rem);
height: 1px;
position: absolute;
top: -1px;
background: var(--sidebar-border-color);
}
}
.library-menu-browse-button {
@ -126,4 +131,20 @@
padding: 0.25rem 0.5rem;
}
}
.layer-ui__library .library-menu-dropdown-container {
position: relative;
&--in-heading {
padding: 0;
position: absolute;
top: 1rem;
right: 0.75rem;
z-index: 1;
.dropdown-menu {
top: 100%;
}
}
}
}

View File

@ -121,12 +121,11 @@ export const LibraryMenuContent = ({
/>
{showBtn && (
<LibraryMenuControlButtons
className="library-menu-control-buttons--at-bottom"
style={{ padding: "16px 12px 0 12px" }}
id={id}
libraryReturnUrl={libraryReturnUrl}
theme={appState.theme}
selectedItems={selectedItems}
onSelectItems={onSelectItems}
/>
)}
</LibraryMenuWrapper>

View File

@ -1,33 +1,33 @@
import { LibraryItem, ExcalidrawProps, UIAppState } from "../types";
import { ExcalidrawProps, UIAppState } from "../types";
import LibraryMenuBrowseButton from "./LibraryMenuBrowseButton";
import { LibraryDropdownMenu } from "./LibraryMenuHeaderContent";
import clsx from "clsx";
export const LibraryMenuControlButtons = ({
selectedItems,
onSelectItems,
libraryReturnUrl,
theme,
id,
style,
children,
className,
}: {
selectedItems: LibraryItem["id"][];
onSelectItems: (id: LibraryItem["id"][]) => void;
libraryReturnUrl: ExcalidrawProps["libraryReturnUrl"];
theme: UIAppState["theme"];
id: string;
style: React.CSSProperties;
children?: React.ReactNode;
className?: string;
}) => {
return (
<div className="library-menu-control-buttons" style={style}>
<div
className={clsx("library-menu-control-buttons", className)}
style={style}
>
<LibraryMenuBrowseButton
id={id}
libraryReturnUrl={libraryReturnUrl}
theme={theme}
/>
<LibraryDropdownMenu
selectedItems={selectedItems}
onSelectItems={onSelectItems}
/>
{children}
</div>
);
};

View File

@ -23,6 +23,7 @@ import { Dialog } from "./Dialog";
import DropdownMenu from "./dropdownMenu/DropdownMenu";
import { isLibraryMenuOpenAtom } from "./LibraryMenu";
import { useUIAppState } from "../context/ui-appState";
import clsx from "clsx";
const getSelectedItems = (
libraryItems: LibraryItems,
@ -37,6 +38,7 @@ export const LibraryDropdownMenuButton: React.FC<{
resetLibrary: () => void;
onSelectItems: (items: LibraryItem["id"][]) => void;
appState: UIAppState;
className?: string;
}> = ({
setAppState,
selectedItems,
@ -45,6 +47,7 @@ export const LibraryDropdownMenuButton: React.FC<{
resetLibrary,
onSelectItems,
appState,
className,
}) => {
const [libraryItemsData] = useAtom(libraryItemsAtom, jotaiScope);
const [isLibraryMenuOpen, setIsLibraryMenuOpen] = useAtom(
@ -236,7 +239,7 @@ export const LibraryDropdownMenuButton: React.FC<{
};
return (
<div style={{ position: "relative" }}>
<div className={clsx("library-menu-dropdown-container", className)}>
{renderLibraryMenu()}
{selectedItems.length > 0 && (
<div className="library-actions-counter">{selectedItems.length}</div>
@ -270,9 +273,11 @@ export const LibraryDropdownMenuButton: React.FC<{
export const LibraryDropdownMenu = ({
selectedItems,
onSelectItems,
className,
}: {
selectedItems: LibraryItem["id"][];
onSelectItems: (id: LibraryItem["id"][]) => void;
className?: string;
}) => {
const { library } = useApp();
const appState = useUIAppState();
@ -308,6 +313,7 @@ export const LibraryDropdownMenu = ({
removeFromLibrary(libraryItemsData.libraryItems)
}
resetLibrary={resetLibrary}
className={className}
/>
);
};

View File

@ -26,6 +26,7 @@
}
.library-menu-items-container {
width: 100%;
display: flex;
flex-grow: 1;
flex-shrink: 1;
@ -35,10 +36,14 @@
height: 100%;
justify-content: center;
margin: 0;
border-bottom: 1px solid var(--sidebar-border-color);
position: relative;
& > div {
padding-left: 0.75rem;
padding-right: 0.75rem;
}
&__row {
display: grid;
grid-template-columns: repeat(4, 1fr);
@ -59,6 +64,9 @@
font-size: 1.125rem;
font-weight: bold;
margin-bottom: 0.75rem;
width: 100%;
padding-right: 4rem; // due to dropdown button
box-sizing: border-box;
&--excal {
margin-top: 2rem;
@ -75,4 +83,11 @@
color: var(--text-primary-color);
}
}
.library-menu-items-private-library-container {
// so that when you toggle between pending item and no items, there's
// no layout shift (this is hardcoded and works only with ENG locale)
min-height: 3.75rem;
width: 100%;
}
}

View File

@ -15,6 +15,7 @@ import { MIME_TYPES } from "../constants";
import Spinner from "./Spinner";
import { duplicateElements } from "../element/newElement";
import { LibraryMenuControlButtons } from "./LibraryMenuControlButtons";
import { LibraryDropdownMenu } from "./LibraryMenuHeaderContent";
import "./LibraryMenuItems.scss";
@ -207,6 +208,11 @@ const LibraryMenuItems = ({
const showBtn = !libraryItems.length && !pendingElements.length;
const isLibraryEmpty =
!pendingElements.length &&
!unpublishedItems.length &&
!publishedItems.length;
return (
<div
className="library-menu-items-container"
@ -218,6 +224,13 @@ const LibraryMenuItems = ({
: { borderBottom: 0 }
}
>
{!isLibraryEmpty && (
<LibraryDropdownMenu
selectedItems={selectedItems}
onSelectItems={onSelectItems}
className="library-menu-dropdown-container--in-heading"
/>
)}
<Stack.Col
className="library-menu-items-container__items"
align="start"
@ -228,47 +241,45 @@ const LibraryMenuItems = ({
}}
>
<>
<div>
{(pendingElements.length > 0 ||
unpublishedItems.length > 0 ||
publishedItems.length > 0) && (
<div className="library-menu-items-container__header">
{t("labels.personalLib")}
</div>
)}
{isLoading && (
<div
style={{
position: "absolute",
top: "var(--container-padding-y)",
right: "var(--container-padding-x)",
transform: "translateY(50%)",
}}
>
<Spinner />
{!isLibraryEmpty && (
<div className="library-menu-items-container__header">
{t("labels.personalLib")}
</div>
)}
{isLoading && (
<div
style={{
position: "absolute",
top: "var(--container-padding-y)",
right: "var(--container-padding-x)",
transform: "translateY(50%)",
}}
>
<Spinner />
</div>
)}
<div className="library-menu-items-private-library-container">
{!pendingElements.length && !unpublishedItems.length ? (
<div className="library-menu-items__no-items">
<div className="library-menu-items__no-items__label">
{t("library.noItems")}
</div>
<div className="library-menu-items__no-items__hint">
{publishedItems.length > 0
? t("library.hint_emptyPrivateLibrary")
: t("library.hint_emptyLibrary")}
</div>
</div>
) : (
renderLibrarySection([
// append pending library item
...(pendingElements.length
? [{ id: null, elements: pendingElements }]
: []),
...unpublishedItems,
])
)}
</div>
{!pendingElements.length && !unpublishedItems.length ? (
<div className="library-menu-items__no-items">
<div className="library-menu-items__no-items__label">
{t("library.noItems")}
</div>
<div className="library-menu-items__no-items__hint">
{publishedItems.length > 0
? t("library.hint_emptyPrivateLibrary")
: t("library.hint_emptyLibrary")}
</div>
</div>
) : (
renderLibrarySection([
// append pending library item
...(pendingElements.length
? [{ id: null, elements: pendingElements }]
: []),
...unpublishedItems,
])
)}
</>
<>
@ -304,9 +315,12 @@ const LibraryMenuItems = ({
id={id}
libraryReturnUrl={libraryReturnUrl}
theme={theme}
selectedItems={selectedItems}
onSelectItems={onSelectItems}
/>
>
<LibraryDropdownMenu
selectedItems={selectedItems}
onSelectItems={onSelectItems}
/>
</LibraryMenuControlButtons>
)}
</Stack.Col>
</div>

View File

@ -46,8 +46,17 @@
justify-content: space-between;
align-items: center;
width: 100%;
padding-top: 1rem;
padding-bottom: 1rem;
padding: 1rem 0.75rem;
position: relative;
&::after {
content: "";
width: calc(100% - 1.5rem);
height: 1px;
background: var(--sidebar-border-color);
position: absolute;
bottom: -1px;
}
}
.sidebar__header__buttons {
@ -89,7 +98,7 @@
display: flex;
flex-direction: column;
flex: 1 1 auto;
padding: 1rem 0.75rem;
padding: 1rem 0;
[role="tabpanel"] {
flex: 1;
@ -161,9 +170,5 @@
border: none;
}
}
.sidebar__header {
border-bottom: 1px solid var(--sidebar-border-color);
}
}
}