Improves bounds corner touch targets on mobile

This commit is contained in:
Steve Ruiz 2021-05-30 14:39:53 +01:00
parent 2af0d7b3a7
commit 03d0eadb6e
6 changed files with 80 additions and 67 deletions

View file

@ -28,7 +28,7 @@ export default function Bounds() {
if (!bounds) return null if (!bounds) return null
if (!isSelecting) return null if (!isSelecting) return null
const size = (isMobile().any ? 12 : 8) / zoom // Touch target size const size = (isMobile().any ? 10 : 8) / zoom // Touch target size
return ( return (
<g <g

View file

@ -1,6 +1,6 @@
import useHandleEvents from "hooks/useBoundsHandleEvents" import useHandleEvents from 'hooks/useBoundsHandleEvents'
import styled from "styles" import styled from 'styles'
import { Corner, Bounds } from "types" import { Corner, Bounds } from 'types'
export default function CornerHandle({ export default function CornerHandle({
size, size,
@ -17,27 +17,41 @@ export default function CornerHandle({
const isLeft = corner === Corner.TopLeft || corner === Corner.BottomLeft const isLeft = corner === Corner.TopLeft || corner === Corner.BottomLeft
return ( return (
<StyledCorner <g>
corner={corner} <StyledCorner
x={(isLeft ? 0 : bounds.width) - size / 2} corner={corner}
y={(isTop ? 0 : bounds.height) - size / 2} x={(isLeft ? 0 : bounds.width) - size}
width={size} y={(isTop ? 0 : bounds.height) - size}
height={size} width={size * 2}
{...events} height={size * 2}
/> {...events}
/>
<StyledCornerInner
x={(isLeft ? 0 : bounds.width) - size / 2}
y={(isTop ? 0 : bounds.height) - size / 2}
width={size}
height={size}
pointerEvents="none"
/>
</g>
) )
} }
const StyledCorner = styled("rect", { const StyledCorner = styled('rect', {
stroke: "$bounds", stroke: 'none',
fill: "#fff", fill: 'transparent',
zStrokeWidth: 2,
variants: { variants: {
corner: { corner: {
[Corner.TopLeft]: { cursor: "nwse-resize" }, [Corner.TopLeft]: { cursor: 'nwse-resize' },
[Corner.TopRight]: { cursor: "nesw-resize" }, [Corner.TopRight]: { cursor: 'nesw-resize' },
[Corner.BottomRight]: { cursor: "nwse-resize" }, [Corner.BottomRight]: { cursor: 'nwse-resize' },
[Corner.BottomLeft]: { cursor: "nesw-resize" }, [Corner.BottomLeft]: { cursor: 'nesw-resize' },
}, },
}, },
}) })
const StyledCornerInner = styled('rect', {
stroke: '$bounds',
fill: '#fff',
zStrokeWidth: 2,
})

View file

@ -1,6 +1,6 @@
import useHandleEvents from "hooks/useBoundsHandleEvents" import useHandleEvents from 'hooks/useBoundsHandleEvents'
import styled from "styles" import styled from 'styles'
import { Edge, Bounds } from "types" import { Edge, Bounds } from 'types'
export default function EdgeHandle({ export default function EdgeHandle({
size, size,
@ -28,15 +28,15 @@ export default function EdgeHandle({
) )
} }
const StyledEdge = styled("rect", { const StyledEdge = styled('rect', {
stroke: "none", stroke: 'none',
fill: "none", fill: 'none',
variants: { variants: {
edge: { edge: {
[Edge.Top]: { cursor: "ns-resize" }, [Edge.Top]: { cursor: 'ns-resize' },
[Edge.Right]: { cursor: "ew-resize" }, [Edge.Right]: { cursor: 'ew-resize' },
[Edge.Bottom]: { cursor: "ns-resize" }, [Edge.Bottom]: { cursor: 'ns-resize' },
[Edge.Left]: { cursor: "ew-resize" }, [Edge.Left]: { cursor: 'ew-resize' },
}, },
}, },
}) })

View file

@ -1,11 +1,11 @@
import Editor, { Monaco } from "@monaco-editor/react" import Editor, { Monaco } from '@monaco-editor/react'
import useTheme from "hooks/useTheme" import useTheme from 'hooks/useTheme'
import prettier from "prettier/standalone" import prettier from 'prettier/standalone'
import parserTypeScript from "prettier/parser-typescript" import parserTypeScript from 'prettier/parser-typescript'
import codeAsString from "./code-as-string" import codeAsString from './code-as-string'
import React, { useCallback, useEffect, useRef } from "react" import React, { useCallback, useEffect, useRef } from 'react'
import styled from "styles" import styled from 'styles'
import { IMonaco, IMonacoEditor } from "types" import { IMonaco, IMonacoEditor } from 'types'
interface Props { interface Props {
value: string value: string
@ -48,7 +48,7 @@ export default function CodeEditor({
checkJs: false, checkJs: false,
strict: false, strict: false,
noLib: true, noLib: true,
lib: ["es6"], lib: ['es6'],
target: monaco.languages.typescript.ScriptTarget.ES2015, target: monaco.languages.typescript.ScriptTarget.ES2015,
allowNonTsExtensions: true, allowNonTsExtensions: true,
}) })
@ -69,13 +69,13 @@ export default function CodeEditor({
monaco.languages.typescript.javascriptDefaults.addExtraLib(codeAsString) monaco.languages.typescript.javascriptDefaults.addExtraLib(codeAsString)
monaco.languages.registerDocumentFormattingEditProvider("javascript", { monaco.languages.registerDocumentFormattingEditProvider('javascript', {
async provideDocumentFormattingEdits(model) { async provideDocumentFormattingEdits(model) {
const text = prettier.format(model.getValue(), { const text = prettier.format(model.getValue(), {
parser: "typescript", parser: 'typescript',
plugins: [parserTypeScript], plugins: [parserTypeScript],
singleQuote: true, singleQuote: true,
trailingComma: "es5", trailingComma: 'es5',
semi: false, semi: false,
}) })
@ -114,12 +114,12 @@ export default function CodeEditor({
(e: React.KeyboardEvent<HTMLDivElement>) => { (e: React.KeyboardEvent<HTMLDivElement>) => {
onKey && onKey() onKey && onKey()
e.stopPropagation() e.stopPropagation()
const metaKey = navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey const metaKey = navigator.platform.match('Mac') ? e.metaKey : e.ctrlKey
if (e.key === "s" && metaKey) { if (e.key === 's' && metaKey) {
const editor = rEditor.current const editor = rEditor.current
if (!editor) return if (!editor) return
editor editor
.getAction("editor.action.formatDocument") .getAction('editor.action.formatDocument')
.run() .run()
.then(() => .then(() =>
onSave(rEditor.current?.getModel().getValue(), rEditor.current) onSave(rEditor.current?.getModel().getValue(), rEditor.current)
@ -127,10 +127,10 @@ export default function CodeEditor({
e.preventDefault() e.preventDefault()
} }
if (e.key === "p" && metaKey) { if (e.key === 'p' && metaKey) {
e.preventDefault() e.preventDefault()
} }
if (e.key === "d" && metaKey) { if (e.key === 'd' && metaKey) {
e.preventDefault() e.preventDefault()
} }
}, },
@ -167,7 +167,7 @@ export default function CodeEditor({
), ),
options: { options: {
isWholeLine: true, isWholeLine: true,
className: "editorLineError", className: 'editorLineError',
}, },
}, },
]) ])
@ -176,7 +176,7 @@ export default function CodeEditor({
useEffect(() => { useEffect(() => {
const monaco = rMonaco.current const monaco = rMonaco.current
if (!monaco) return if (!monaco) return
monaco.editor.setTheme(theme === "dark" ? "vs-dark" : "light") monaco.editor.setTheme(theme === 'dark' ? 'vs-dark' : 'light')
}, [theme]) }, [theme])
useEffect(() => { useEffect(() => {
@ -194,7 +194,7 @@ export default function CodeEditor({
height="100%" height="100%"
language="javascript" language="javascript"
value={value} value={value}
theme={theme === "dark" ? "vs-dark" : "light"} theme={theme === 'dark' ? 'vs-dark' : 'light'}
beforeMount={handleBeforeMount} beforeMount={handleBeforeMount}
onMount={handleMount} onMount={handleMount}
onChange={handleChange} onChange={handleChange}
@ -203,12 +203,12 @@ export default function CodeEditor({
) )
} }
const EditorContainer = styled("div", { const EditorContainer = styled('div', {
height: "100%", height: '100%',
pointerEvents: "all", pointerEvents: 'all',
userSelect: "all", userSelect: 'all',
".editorLineError": { '.editorLineError': {
backgroundColor: "$lineError", backgroundColor: '$lineError',
}, },
}) })

View file

@ -40,9 +40,11 @@ const Layout = styled('div', {
left: 0, left: 0,
bottom: 0, bottom: 0,
right: 0, right: 0,
height: '100%',
width: '100%',
display: 'grid', display: 'grid',
gridTemplateRows: '1fr auto 40px', gridTemplateRows: '1fr auto 144px',
gridTemplateColumns: 'minmax(50%, 400px) 1fr auto', gridTemplateColumns: 'minmax(0, 720px) 1fr auto',
gridTemplateAreas: ` gridTemplateAreas: `
"leftPanels main rightPanels" "leftPanels main rightPanels"
"tools tools tools" "tools tools tools"
@ -59,11 +61,11 @@ const LeftPanels = styled('main', {
}) })
const RightPanels = styled('main', { const RightPanels = styled('main', {
display: 'grid',
gridArea: 'rightPanels', gridArea: 'rightPanels',
gridTemplateRows: 'auto',
height: 'fit-content',
justifyContent: 'flex-end',
padding: 8, padding: 8,
gap: 8, // display: 'grid',
// gridTemplateRows: 'auto',
// height: 'fit-content',
// justifyContent: 'flex-end',
// gap: 8,
}) })

View file

@ -13,10 +13,7 @@ export const Root = styled('div', {
variants: { variants: {
isOpen: { isOpen: {
true: { true: {},
width: 'auto',
minWidth: 300,
},
false: { false: {
height: 34, height: 34,
width: 34, width: 34,