mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-02-24 04:00:59 +01:00
web: optimize ui for mobile & tablet form factor
This commit is contained in:
committed by
Abdullah Atta
parent
f7de4c9084
commit
5ef7e39e17
@@ -58,9 +58,8 @@ export default function MobileAppEffects({
|
||||
overlay.style.pointerEvents = "none";
|
||||
}
|
||||
},
|
||||
onChange: (e, { slide, lastSlide }) => {
|
||||
if (!lastSlide || !isMobile) return;
|
||||
toggleSideMenu(slide?.index === 1 ? true : false);
|
||||
onChange: (e, { slide }) => {
|
||||
toggleSideMenu(slide?.index === 0 ? true : false);
|
||||
setIsEditorOpen(slide?.index === 3 ? true : false);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -125,19 +125,23 @@ function DesktopAppContents({ show, setShow }: DesktopAppContentsProps) {
|
||||
const middlePane = useRef<ImperativePanelHandle>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (show) middlePane.current?.expand();
|
||||
else middlePane.current?.collapse();
|
||||
}, [show]);
|
||||
setIsNarrow(isTablet);
|
||||
}, [isTablet]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isFocusMode) {
|
||||
const middlePaneSize = middlePane.current?.getSize() || 20;
|
||||
navPane.current?.collapse();
|
||||
// the middle pane has to be resized because collapsing the nav
|
||||
// pane increases the middle pane's size every time.
|
||||
middlePane.current?.resize(middlePaneSize);
|
||||
} else navPane.current?.expand();
|
||||
}, [isFocusMode]);
|
||||
// useEffect(() => {
|
||||
// if (show) middlePane.current?.expand();
|
||||
// else middlePane.current?.collapse();
|
||||
// }, [show]);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (isFocusMode) {
|
||||
// const middlePaneSize = middlePane.current?.getSize() || 20;
|
||||
// navPane.current?.collapse();
|
||||
// // the middle pane has to be resized because collapsing the nav
|
||||
// // pane increases the middle pane's size every time.
|
||||
// middlePane.current?.resize(middlePaneSize);
|
||||
// } else navPane.current?.expand();
|
||||
// }, [isFocusMode]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -148,45 +152,67 @@ function DesktopAppContents({ show, setShow }: DesktopAppContentsProps) {
|
||||
}}
|
||||
>
|
||||
<PanelGroup autoSaveId="global-panel-group" direction="horizontal">
|
||||
<Panel
|
||||
ref={navPane}
|
||||
className="nav-pane"
|
||||
defaultSize={10}
|
||||
minSize={3.5}
|
||||
onResize={(size) => setIsNarrow(size <= 5)}
|
||||
collapsible
|
||||
collapsedSize={3.5}
|
||||
>
|
||||
<NavigationMenu
|
||||
toggleNavigationContainer={(state) => {
|
||||
setShow(state || !show);
|
||||
}}
|
||||
isTablet={isNarrow}
|
||||
/>
|
||||
</Panel>
|
||||
<PanelResizeHandle className="panel-resize-handle" />
|
||||
<Panel
|
||||
ref={middlePane}
|
||||
className="middle-pane"
|
||||
collapsible
|
||||
defaultSize={20}
|
||||
>
|
||||
<ScopedThemeProvider
|
||||
className="listMenu"
|
||||
scope="list"
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
flex: 1,
|
||||
bg: "background",
|
||||
borderRight: "1px solid var(--separator)"
|
||||
}}
|
||||
>
|
||||
<CachedRouter />
|
||||
</ScopedThemeProvider>
|
||||
</Panel>
|
||||
<PanelResizeHandle className="panel-resize-handle" />
|
||||
<Panel className="editor-pane" defaultSize={70}>
|
||||
{!isFocusMode && isTablet ? (
|
||||
<Flex sx={{ width: 50 }}>
|
||||
<NavigationMenu
|
||||
toggleNavigationContainer={(state) => {
|
||||
setShow(state || !show);
|
||||
}}
|
||||
isTablet={isNarrow}
|
||||
/>
|
||||
</Flex>
|
||||
) : (
|
||||
!isFocusMode && (
|
||||
<>
|
||||
<Panel
|
||||
ref={navPane}
|
||||
order={1}
|
||||
className="nav-pane"
|
||||
defaultSize={10}
|
||||
minSize={3.5}
|
||||
// maxSize={isNarrow ? 5 : undefined}
|
||||
onResize={(size) => setIsNarrow(size <= 5)}
|
||||
collapsible
|
||||
collapsedSize={3.5}
|
||||
>
|
||||
<NavigationMenu
|
||||
toggleNavigationContainer={(state) => {
|
||||
setShow(state || !show);
|
||||
}}
|
||||
isTablet={isNarrow}
|
||||
/>
|
||||
</Panel>
|
||||
<PanelResizeHandle className="panel-resize-handle" />
|
||||
</>
|
||||
)
|
||||
)}
|
||||
{!isFocusMode && show && (
|
||||
<>
|
||||
<Panel
|
||||
ref={middlePane}
|
||||
className="middle-pane"
|
||||
order={2}
|
||||
collapsible
|
||||
defaultSize={20}
|
||||
>
|
||||
<ScopedThemeProvider
|
||||
className="listMenu"
|
||||
scope="list"
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
flex: 1,
|
||||
bg: "background",
|
||||
borderRight: "1px solid var(--separator)"
|
||||
}}
|
||||
>
|
||||
<CachedRouter />
|
||||
</ScopedThemeProvider>
|
||||
</Panel>
|
||||
<PanelResizeHandle className="panel-resize-handle" />
|
||||
</>
|
||||
)}
|
||||
<Panel className="editor-pane" order={3} defaultSize={70}>
|
||||
<Flex
|
||||
sx={{
|
||||
display: "flex",
|
||||
|
||||
@@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import { Button, Flex, Text } from "@theme-ui/components";
|
||||
import { useState } from "react";
|
||||
import {
|
||||
ArrowLeft,
|
||||
Cross,
|
||||
EditorFullWidth,
|
||||
EditorNormalWidth,
|
||||
@@ -74,6 +75,7 @@ import { useStore as useUserStore } from "../../stores/user-store";
|
||||
import { db } from "../../common/db";
|
||||
import { showPublishView } from "../publish-view";
|
||||
import { restrictToHorizontalAxis } from "@dnd-kit/modifiers";
|
||||
import useMobile from "../../hooks/use-mobile";
|
||||
|
||||
export function EditorActionBar() {
|
||||
const editorMargins = useEditorStore((store) => store.editorMargins);
|
||||
@@ -89,6 +91,8 @@ export function EditorActionBar() {
|
||||
const monographs = useMonographStore((store) => store.monographs);
|
||||
const isNotePublished =
|
||||
activeSession && db.monographs.isPublished(activeSession.id);
|
||||
const isMobile = useMobile();
|
||||
const setIsEditorOpen = useAppStore((store) => store.setIsEditorOpen);
|
||||
|
||||
const tools = [
|
||||
{
|
||||
@@ -107,6 +111,7 @@ export function EditorActionBar() {
|
||||
title: isNotePublished ? "Published" : "Publish",
|
||||
icon: isNotePublished ? Published : Publish,
|
||||
hidden: !isLoggedIn,
|
||||
hideOnMobile: true,
|
||||
enabled:
|
||||
activeSession &&
|
||||
(activeSession.type === "default" || activeSession.type === "readonly"),
|
||||
@@ -120,6 +125,7 @@ export function EditorActionBar() {
|
||||
title: editorMargins ? "Disable editor margins" : "Enable editor margins",
|
||||
icon: editorMargins ? EditorNormalWidth : EditorFullWidth,
|
||||
enabled: true,
|
||||
hideOnMobile: true,
|
||||
onClick: () => useEditorStore.getState().toggleEditorMargins()
|
||||
},
|
||||
{
|
||||
@@ -187,7 +193,24 @@ export function EditorActionBar() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<TabStrip />
|
||||
{isMobile ? (
|
||||
<Flex sx={{ flex: 1 }}>
|
||||
<Button
|
||||
variant={"secondary"}
|
||||
sx={{
|
||||
height: "100%",
|
||||
bg: "transparent",
|
||||
borderRadius: 0,
|
||||
flexShrink: 0
|
||||
}}
|
||||
onClick={() => setIsEditorOpen(false)}
|
||||
>
|
||||
<ArrowLeft size={18} />
|
||||
</Button>
|
||||
</Flex>
|
||||
) : (
|
||||
<TabStrip />
|
||||
)}
|
||||
{tools.map((tool) => (
|
||||
<Button
|
||||
data-test-id={tool.title}
|
||||
|
||||
@@ -630,8 +630,8 @@ function EditorChrome(props: PropsWithChildren<EditorProps>) {
|
||||
maxWidth: editorMargins ? "min(100%, 850px)" : "auto",
|
||||
width: "100%"
|
||||
}}
|
||||
pl={6}
|
||||
pr={6}
|
||||
pl={[2, 2, 6]}
|
||||
pr={[2, 2, 6]}
|
||||
onClick={onRequestFocus}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -59,6 +59,8 @@ import { writeToClipboard } from "../../utils/clipboard";
|
||||
import { useEditorStore } from "../../stores/editor-store";
|
||||
import { parseInternalLink } from "@notesnook/core";
|
||||
import Skeleton from "react-loading-skeleton";
|
||||
import useMobile from "../../hooks/use-mobile";
|
||||
import useTablet from "../../hooks/use-tablet";
|
||||
|
||||
export type OnChangeHandler = (
|
||||
content: () => string,
|
||||
@@ -89,6 +91,7 @@ type TipTapProps = {
|
||||
readonly?: boolean;
|
||||
nonce?: number;
|
||||
isMobile?: boolean;
|
||||
isTablet?: boolean;
|
||||
downloadOptions?: DownloadOptions;
|
||||
fontSize: number;
|
||||
fontFamily: string;
|
||||
@@ -127,6 +130,7 @@ function TipTap(props: TipTapProps) {
|
||||
readonly,
|
||||
nonce,
|
||||
isMobile,
|
||||
isTablet,
|
||||
downloadOptions,
|
||||
fontSize,
|
||||
fontFamily
|
||||
@@ -361,7 +365,12 @@ function TipTap(props: TipTapProps) {
|
||||
>
|
||||
<Toolbar
|
||||
editor={editor}
|
||||
location={isMobile ? "bottom" : "top"}
|
||||
location={"top"}
|
||||
sx={
|
||||
isTablet || isMobile
|
||||
? { overflowX: "scroll", flexWrap: "nowrap" }
|
||||
: {}
|
||||
}
|
||||
tools={toolbarConfig}
|
||||
defaultFontFamily={fontFamily}
|
||||
defaultFontSize={fontSize}
|
||||
@@ -385,6 +394,8 @@ function TiptapWrapper(
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const editorContainerRef = useRef<HTMLDivElement>();
|
||||
const { editorConfig } = useEditorConfig();
|
||||
const isMobile = useMobile();
|
||||
const isTablet = useTablet();
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (
|
||||
@@ -425,6 +436,8 @@ function TiptapWrapper(
|
||||
>
|
||||
<TipTap
|
||||
{...props}
|
||||
isMobile={isMobile}
|
||||
isTablet={isTablet}
|
||||
onLoad={(editor) => {
|
||||
if (!isHydrating) {
|
||||
onLoad?.(editor);
|
||||
|
||||
@@ -256,7 +256,7 @@ function ListContainer(props: ListContainerProps) {
|
||||
height: 45
|
||||
}}
|
||||
>
|
||||
<Plus color="static" />
|
||||
<Plus color="accentForeground" />
|
||||
</Button>
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
@@ -40,8 +40,8 @@ function Notice() {
|
||||
cursor: "pointer",
|
||||
borderRadius: "default",
|
||||
":hover": { bg: "hover" },
|
||||
alignItems: "center",
|
||||
minWidth: 250
|
||||
alignItems: "center"
|
||||
// minWidth: 250
|
||||
}}
|
||||
p={1}
|
||||
onClick={() => NoticeData.action()}
|
||||
@@ -53,11 +53,30 @@ function Notice() {
|
||||
color="accent"
|
||||
sx={{ bg: "shade", mr: 2, p: 2, borderRadius: 80 }}
|
||||
/>
|
||||
<Flex variant="columnCenter" sx={{ alignItems: "flex-start" }}>
|
||||
<Text variant="body" sx={{ fontSize: "body" }}>
|
||||
<Flex
|
||||
variant="columnCenter"
|
||||
sx={{ alignItems: "flex-start", overflow: "hidden" }}
|
||||
>
|
||||
<Text
|
||||
variant="body"
|
||||
sx={{
|
||||
fontSize: "body",
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis"
|
||||
}}
|
||||
>
|
||||
{NoticeData.title}
|
||||
</Text>
|
||||
<Text variant="subBody" sx={{ display: "block" }}>
|
||||
<Text
|
||||
variant="subBody"
|
||||
sx={{
|
||||
display: "block",
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis"
|
||||
}}
|
||||
>
|
||||
{NoticeData.subtitle}
|
||||
</Text>
|
||||
</Flex>
|
||||
|
||||
@@ -91,7 +91,6 @@ export default function useSlider(
|
||||
const slideToIndex = useCallback(
|
||||
(index: number) => {
|
||||
if (!slides || !ref.current || index >= slides.length) return;
|
||||
console.log(slides[index].offset, slides[index].width);
|
||||
const slider = ref.current;
|
||||
setTimeout(() => {
|
||||
slider.scrollTo({
|
||||
|
||||
@@ -198,10 +198,9 @@ class AppStore extends BaseStore<AppStore> {
|
||||
};
|
||||
|
||||
toggleSideMenu = (toggleState: boolean) => {
|
||||
console.log("toggling side menu");
|
||||
this.set(
|
||||
(state) =>
|
||||
(state.isSideMenuOpen =
|
||||
toggleState != null ? toggleState : !state.isSideMenuOpen)
|
||||
(state) => (state.isSideMenuOpen = toggleState ?? !state.isSideMenuOpen)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -92,11 +92,11 @@ export function Toolbar(props: ToolbarProps) {
|
||||
<Flex
|
||||
className={["editor-toolbar", className].join(" ")}
|
||||
sx={{
|
||||
...sx,
|
||||
flexWrap: isMobile ? "nowrap" : "wrap",
|
||||
overflowX: isMobile ? "auto" : "hidden",
|
||||
bg: "background",
|
||||
borderRadius: isMobile ? "0px" : "default"
|
||||
borderRadius: isMobile ? "0px" : "default",
|
||||
...sx
|
||||
}}
|
||||
{...flexProps}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user