Skip to content

Commit

Permalink
ui for mobile
Browse files Browse the repository at this point in the history
  • Loading branch information
sandstone991 committed Jul 4, 2023
1 parent f02ac24 commit 4158dd3
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 40 deletions.
6 changes: 5 additions & 1 deletion src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { IconContext } from "react-icons";

import ToolbarLeft from "./ToolbarLeft";
import { useIsMobile } from "hooks";
import ToolbarLeft from "./ToolbarElementConfig";
import ToolbarUpper from "./ToolbarUpper";
import ZagyDraw from "./ZagyDraw";
import Undo from "./Undo";
import ToolbarLower from "./ToolbarLower";

export default function App() {
useIsMobile();
return (
<div className="box-border">
<IconContext.Provider value={{}}>
<ToolbarUpper />
<ToolbarLeft />
<ToolbarLower />
</IconContext.Provider>
<Undo />
<ZagyDraw />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
FillStyleOptions,
FontSize,
FontTypeOptions,
GlobalConfigOptions,
GlobalElementOptions,
StrokeWidth,
ZagyCanvasElement,
isHanddrawn,
Expand Down Expand Up @@ -133,23 +133,25 @@ const RadioButton: React.FC<{
</div>
);
};

const {
setElements,
setSelectedElements,
setFont,
setFontSize,
setFill,
setFillStyle,
setOpacity,
setStroke,
setStrokeLineDash,
setStrokeWidth,
} = useStore.getState();
export default function ToolbarLeft() {
const {
setElements,
setSelectedElements,
fontSize,
font,
setFont,
setFontSize,
setFill,
setFillStyle,
setOpacity,
setStroke,
setStrokeLineDash,
setStrokeWidth,
} = useStore.getState();
const [font, fontSize] = useStore((state) => [state.font, state.fontSize]);
const selectedElements = useStore((state) => state.selectedElements);
const [isMobile, toolbarElementConfigOpen] = useStore((state) => [
state.isMobile,
state.isToolbarElementConfigOpen,
]);

const ctx = useMemo(() => {
const canvas = document.createElement("canvas");
Expand Down Expand Up @@ -182,7 +184,7 @@ export default function ToolbarLeft() {
};
const handleConfigChange = <T extends keyof CommonConfigOptions>(
k: T,
value: GlobalConfigOptions[T]
value: GlobalElementOptions[T]
) => {
// create hash for check up
const ids = new Set<string>();
Expand Down Expand Up @@ -268,14 +270,15 @@ export default function ToolbarLeft() {
setOpacity(+e.target.value);
};
const baseSize = 1.2;
if (isMobile && !toolbarElementConfigOpen) return null;
return (
<>
<IconContext.Provider
value={{
size: `${baseSize}rem`,
}}>
<div className="scrollbar-thin scrollbar-thumb-zinc-600 bg-primary-600 fixed left-2 top-24 flex max-h-[80%] w-1/5 flex-col gap-1 overflow-auto whitespace-nowrap rounded-md text-xs sm:m-0 sm:w-auto sm:max-w-none">
<div className="text-text-800 mx-auto flex w-fit flex-col gap-2 p-3">
<div className="scrollbar-thin scrollbar-thumb-zinc-600 bg-primary-600 fixed inset-0 m-auto flex max-h-[70%] w-11/12 flex-col gap-1 overflow-auto whitespace-nowrap rounded-md text-xs md:left-2 md:top-20 md:m-0 md:ml-1 md:max-h-[75%] md:w-fit">
<div className="text-text-800 flex w-fit flex-col gap-2 p-3 ">
{commonConf.stroke !== undefined ? (
<InputWithIcon
labelName={"Stroke"}
Expand Down
43 changes: 43 additions & 0 deletions src/components/ToolbarLower.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { commandManager } from "actions/commandManager";
import { useMemo } from "react";
import { IconContext } from "react-icons";
import { BsFillPaletteFill } from "react-icons/bs";
import { MdUndo } from "react-icons/md";
import { useStore } from "store";
const { setIsToolbarElementConfigOpen } = useStore.getState();
const ToolbarLower = () => {
const selectedElements = useStore((state) => state.selectedElements);
const isToolbarElementConfigOpen = useStore((state) => state.isToolbarElementConfigOpen);
const openToolbarELementConfigButton = useMemo(() => {
if (selectedElements.length > 0) {
return (
<button
onClick={() => setIsToolbarElementConfigOpen(!isToolbarElementConfigOpen)}
className="flex h-10 w-full flex-col items-center justify-center">
<BsFillPaletteFill />
</button>
);
}
return null;
}, [selectedElements.length, isToolbarElementConfigOpen]);
return (
<div className="bg-primary-600 fixed inset-x-0 bottom-2 mx-auto flex h-fit w-11/12 items-center justify-stretch rounded-lg p-2 md:invisible">
<IconContext.Provider
value={{
className: "fill-gray-300",
size: "1.5rem",
}}>
<button
className="flex h-10 w-full flex-col items-center justify-center"
onClick={() => {
commandManager.undoCommand();
}}>
<MdUndo />
</button>
{openToolbarELementConfigButton}
</IconContext.Provider>
</div>
);
};

export default ToolbarLower;
16 changes: 8 additions & 8 deletions src/components/ToolbarUpper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ export default function ToolbarUpper() {
"7"
);
return (
<div className="withFira scrollbar-thin scrollbar-thumb-zinc-600 bg-primary-600 fixed left-1/2 top-4 w-11/12 -translate-x-1/2 cursor-default overflow-auto whitespace-nowrap rounded-md py-1 sm:m-0 sm:w-auto sm:max-w-none">
<div className="withFira scrollbar-thin scrollbar-thumb-zinc-600 bg-primary-600 fixed left-1/2 top-4 w-11/12 -translate-x-1/2 cursor-default overflow-auto whitespace-nowrap rounded-md py-1 md:w-6/12 lg:m-0 lg:w-auto lg:max-w-none">
<div className="mx-auto w-fit">
<button
data-testid="default-cursor"
onClick={() => setCursorFn(CursorFn.Default)}
className={clsx(
"relative mx-1 h-12 w-16 cursor-pointer rounded-2xl rounded-l-lg text-xl sm:w-14",
"relative mx-1 h-12 w-12 cursor-pointer rounded-lg text-xl lg:rounded-l-none ",
{
"bg-background-700":
cursorFn === CursorFn.Default || cursorFn === CursorFn.Move,
Expand All @@ -81,7 +81,7 @@ export default function ToolbarUpper() {
<button
data-testid="drag-cursor"
className={clsx(
"relative mx-1 h-12 w-16 cursor-pointer rounded-2xl text-xl sm:w-14",
"relative mx-1 h-12 w-12 cursor-pointer rounded-lg text-xl ",
{
"bg-background-700": cursorFn === CursorFn.Drag,
},
Expand All @@ -103,7 +103,7 @@ export default function ToolbarUpper() {
data-testid="freedraw-cursor"
onClick={() => setCursorFn(CursorFn.FreeDraw)}
className={clsx(
"relative mx-1 h-12 w-16 cursor-pointer rounded-2xl text-xl sm:w-14",
"relative mx-1 h-12 w-12 cursor-pointer rounded-lg text-xl ",
{
"bg-background-700": cursorFn === CursorFn.FreeDraw,
},
Expand All @@ -124,7 +124,7 @@ export default function ToolbarUpper() {
data-testid="rect-cursor"
onClick={() => setCursorFn(CursorFn.Rect)}
className={clsx(
"relative mx-1 h-12 w-16 cursor-pointer rounded-2xl text-xl sm:w-14",
"relative mx-1 h-12 w-12 cursor-pointer rounded-lg text-xl ",
{
"bg-background-700": cursorFn === CursorFn.Rect,
},
Expand All @@ -145,7 +145,7 @@ export default function ToolbarUpper() {
data-testid="line-cursor"
onClick={() => setCursorFn(CursorFn.Line)}
className={clsx(
"relative mx-1 h-12 w-16 cursor-pointer rounded-2xl text-xl sm:w-14",
"relative mx-1 h-12 w-12 cursor-pointer rounded-lg text-xl ",
{
"bg-background-700": cursorFn === CursorFn.Line,
},
Expand All @@ -163,7 +163,7 @@ export default function ToolbarUpper() {
data-testid="text-cursor"
onClick={() => setCursorFn(CursorFn.Text)}
className={clsx(
"relative mx-1 h-12 w-16 cursor-pointer rounded-2xl text-xl sm:w-14",
"relative mx-1 h-12 w-12 cursor-pointer rounded-lg text-xl ",
{
"bg-background-700": cursorFn === CursorFn.Text,
},
Expand All @@ -180,7 +180,7 @@ export default function ToolbarUpper() {
data-testid="erase-cursor"
onClick={() => setCursorFn(CursorFn.Erase)}
className={clsx(
"relative mx-1 h-12 w-16 cursor-pointer rounded-2xl rounded-r-lg text-xl sm:w-14",
"relative mx-1 h-12 w-12 cursor-pointer rounded-lg text-xl lg:rounded-r-none ",
{
"bg-background-700": cursorFn === CursorFn.Erase,
},
Expand Down
2 changes: 1 addition & 1 deletion src/components/Undo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default function Undo() {
return (
<button
data-testid="undo-button"
className="bg-primary-600 fixed bottom-4 left-4 h-fit w-fit rounded-lg p-2"
className="bg-primary-600 invisible fixed bottom-4 right-4 h-fit w-fit rounded-lg p-2 md:visible"
onClick={() => {
commandManager.undoCommand();
return;
Expand Down
3 changes: 2 additions & 1 deletion src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import { useEvent } from "./useEvent";
import { useGlobalEvent } from "./useGlobalEvent";
import { useMultiPhaseEvent } from "./useMultiPhaseEvent";
import { useRenderScene } from "./useRenderScene";
export { useCursor, useEvent, useGlobalEvent, useMultiPhaseEvent, useRenderScene };
import { useIsMobile } from "./useIsMobile";
export { useCursor, useEvent, useGlobalEvent, useMultiPhaseEvent, useRenderScene, useIsMobile };
15 changes: 15 additions & 0 deletions src/hooks/useIsMobile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useCallback } from "react";
import { useStore } from "store";
import { useGlobalEvent } from "./useGlobalEvent";
const { setIsMobile } = useStore.getState();
const useIsMobile = () => {
const isMobileCallback = useCallback(() => {
if (typeof window === "undefined") return false;
if (window.innerWidth > 768) return false;
setIsMobile(true);
}, []);
useGlobalEvent("resize", isMobileCallback);
useGlobalEvent("orientationchange", isMobileCallback);
useGlobalEvent("load", isMobileCallback);
};
export { useIsMobile };
24 changes: 18 additions & 6 deletions src/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { randomSeed } from "roughjs/bin/math";
import {
ZagyCanvasElement,
CursorFn,
GlobalConfigOptions,
GlobalElementOptions,
ZagyCanvasRectElement,
} from "types/general";
import { isElementVisible } from "utils";
import { create } from "zustand";

type ConfigState = Omit<GlobalConfigOptions, "seed"> & { cursorFn: CursorFn };
type ConfigState = Omit<GlobalElementOptions, "seed"> & {
cursorFn: CursorFn;
isToolbarElementConfigOpen: boolean;
isMobile: boolean;
};

export type CanvasState<T extends ZagyCanvasElement = ZagyCanvasElement> = {
width: number;
Expand Down Expand Up @@ -62,9 +67,8 @@ type CanvasActions = {
type ConfigStateActions = {
[K in keyof ConfigState as `set${Capitalize<K & string>}`]: (value: ConfigState[K]) => void;
} & {
getConfigState: () => ConfigState;
getElementConfigState: () => GlobalElementOptions;
};
// non standard but useful

export const useStore = create<
CanvasState &
Expand All @@ -91,6 +95,14 @@ export const useStore = create<
isMouseDown: false,
currentText: "",
isWriting: false,
isToolbarElementConfigOpen: false,
isMobile: false,
setIsMobile: (isMobile) => {
set({ isMobile });
},
setIsToolbarElementConfigOpen: (isToolbarElementConfigOpen) => {
set({ isToolbarElementConfigOpen });
},
setCurrentText: (currentText) => {
set({ currentText });
},
Expand Down Expand Up @@ -147,9 +159,8 @@ export const useStore = create<
font: "minecraft",
fontSize: 24,
opacity: 1,
getConfigState() {
getElementConfigState() {
return {
cursorFn: get().cursorFn,
fill: get().fill,
fillStyle: get().fillStyle,
font: get().font,
Expand All @@ -158,6 +169,7 @@ export const useStore = create<
stroke: get().stroke,
strokeLineDash: get().strokeLineDash,
strokeWidth: get().strokeWidth,
seed: randomSeed(),
};
},
//setConfigState
Expand Down
2 changes: 1 addition & 1 deletion src/types/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export type {
ZagyCanvasLineElement,
ZagyCanvasRectElement,
ZagyCanvasTextElement,
GlobalElementOptions as GlobalConfigOptions,
GlobalElementOptions,
ZagyCanvasHandDrawnElement,
ElementTypes,
Position,
Expand Down
2 changes: 1 addition & 1 deletion src/utils/canvas/generateElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { randomSeed } from "roughjs/bin/math";
import { RoughGenerator } from "roughjs/bin/generator";
import { CACHE_CANVAS_SIZE_THRESHOLD } from "constants/index";

const { getConfigState } = useStore.getState();
const { getElementConfigState: getConfigState } = useStore.getState();
function normalizeHanddrawnOptions(options: Partial<HanddrawnOptions>): HanddrawnOptions {
const globalConfig = getConfigState();
return {
Expand Down
4 changes: 2 additions & 2 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
ZagyCanvasHandDrawnElement,
ZagyCanvasLineElement,
ZagyCanvasRectElement,
GlobalConfigOptions,
GlobalElementOptions,
isRect,
isLine,
isText,
Expand Down Expand Up @@ -271,7 +271,7 @@ export function isEqualArray<T>(a1: T[], a2: T[]): boolean {
}

export type CommonConfigOptions = {
[k in keyof GlobalConfigOptions]?: GlobalConfigOptions[k];
[k in keyof GlobalElementOptions]?: GlobalElementOptions[k];
};

/**
Expand Down

0 comments on commit 4158dd3

Please sign in to comment.