[fix] remove CSS radius calculations (#1823)

This PR fixes some creative use of CSS in setting the radius property of
various SVGs. While this use is supported in all browsers, it was
confusing CSS processors. Moving these out of CSS and into JavaScript
seems to be a pretty minor trade. Closes
https://github.com/tldraw/tldraw/issues/1775.

### Change Type

- [x] `patch` — Bug fix

### Test Plan

1. Ensure that borders and handles adjust their radii correctly when
zoomed in or out.
This commit is contained in:
Steve Ruiz 2023-08-25 18:22:52 +02:00 committed by GitHub
parent 162f68b71a
commit b203967341
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 44 additions and 21 deletions

View file

@ -2173,6 +2173,8 @@ export type TLGridComponent = ComponentType<{
export type TLHandleComponent = ComponentType<{
shapeId: TLShapeId;
handle: TLHandle;
zoom: number;
isCoarse: boolean;
className?: string;
}>;

View file

@ -478,7 +478,6 @@ input,
.tl-mobile-rotate__bg {
pointer-events: all;
r: calc(max(calc(14px * var(--tl-scale)), 20px / max(1, var(--tl-zoom))));
cursor: var(--tl-cursor-grab);
}
@ -505,14 +504,12 @@ input,
stroke: transparent;
pointer-events: all;
cursor: var(--tl-cursor-grabbing);
r: calc(12px / var(--tl-zoom));
}
.tl-handle__fg {
fill: var(--color-background);
stroke: var(--color-selection-stroke);
stroke-width: calc(1.5px * var(--tl-scale));
r: calc(4px * var(--tl-scale));
pointer-events: none;
}
@ -540,10 +537,6 @@ input,
.tl-handle__create {
opacity: 1;
}
.tl-handle__create > .tl-handle__fg {
r: calc(3px * var(--tl-scale));
}
}
/* ------------------ Bounds Detail ----------------- */
@ -554,14 +547,16 @@ input,
background-size: cover;
width: 100%;
height: 100%;
pointer-events: all;
}
.tl-image-container,
.tl-video-container,
.tl-embed-container {
width: 100%;
height: 100%;
pointer-events: all;
/* background-color: var(--color-background); */
display: flex;
justify-content: center;
align-items: center;
@ -573,7 +568,6 @@ input,
top: calc(var(--scale) * 8px);
right: calc(var(--scale) * 8px);
font-size: 10px;
scale: var(--scale);
transform-origin: top right;
background-color: var(--color-background);
padding: 2px 4px;
@ -1095,7 +1089,7 @@ input,
}
.tl-text-label[data-isediting='true'] {
background-color: none;
background-color: transparent;
min-height: auto;
}
@ -1504,7 +1498,7 @@ it from receiving any pointer events or affecting the cursor. */
position: absolute;
inset: 0px;
z-index: 600;
pointer-events: auto;
pointer-events: all;
}
.tl-error-boundary__content {
@ -1618,10 +1612,6 @@ it from receiving any pointer events or affecting the cursor. */
.tl-canvas__mobile .tl-handle__hint {
opacity: 1;
}
.tl-canvas__mobile .tl-handle__bg {
r: calc(20px / var(--tl-zoom));
}
}
.tl-hidden {

View file

@ -185,6 +185,7 @@ function HandlesWrapper() {
const { Handles } = useEditorComponents()
const zoomLevel = useValue('zoomLevel', () => editor.zoomLevel, [editor])
const isCoarse = useValue('coarse pointer', () => editor.instanceState.isCoarsePointer, [editor])
const onlySelectedShape = useValue('onlySelectedShape', () => editor.onlySelectedShape, [editor])
const isChangingStyle = useValue('isChangingStyle', () => editor.instanceState.isChangingStyle, [
editor,
@ -229,14 +230,32 @@ function HandlesWrapper() {
<Handles>
<g transform={Matrix2d.toCssString(transform)}>
{handlesToDisplay.map((handle) => {
return <HandleWrapper key={handle.id} shapeId={onlySelectedShape.id} handle={handle} />
return (
<HandleWrapper
key={handle.id}
shapeId={onlySelectedShape.id}
handle={handle}
zoom={zoomLevel}
isCoarse={isCoarse}
/>
)
})}
</g>
</Handles>
)
}
function HandleWrapper({ shapeId, handle }: { shapeId: TLShapeId; handle: TLHandle }) {
function HandleWrapper({
shapeId,
handle,
zoom,
isCoarse,
}: {
shapeId: TLShapeId
handle: TLHandle
zoom: number
isCoarse: boolean
}) {
const events = useHandleEvents(shapeId, handle.id)
const { Handle } = useEditorComponents()
@ -244,7 +263,7 @@ function HandleWrapper({ shapeId, handle }: { shapeId: TLShapeId; handle: TLHand
return (
<g aria-label="handle" transform={`translate(${handle.x}, ${handle.y})`} {...events}>
<Handle shapeId={shapeId} handle={handle} />
<Handle shapeId={shapeId} handle={handle} zoom={zoom} isCoarse={isCoarse} />
</g>
)
}

View file

@ -6,11 +6,16 @@ import { ComponentType } from 'react'
export type TLHandleComponent = ComponentType<{
shapeId: TLShapeId
handle: TLHandle
zoom: number
isCoarse: boolean
className?: string
}>
/** @public */
export const DefaultHandle: TLHandleComponent = ({ handle, className }) => {
export const DefaultHandle: TLHandleComponent = ({ handle, isCoarse, className, zoom }) => {
const bgRadius = (isCoarse ? 20 : 12) / zoom
const fgRadius = (handle.type === 'create' && isCoarse ? 3 : 4) / zoom
return (
<g
className={classNames(
@ -22,8 +27,8 @@ export const DefaultHandle: TLHandleComponent = ({ handle, className }) => {
className
)}
>
<circle className="tl-handle__bg" />
<circle className="tl-handle__fg" />
<circle className="tl-handle__bg" r={bgRadius} />
<circle className="tl-handle__fg" r={fgRadius} />
</g>
)
}

View file

@ -1,6 +1,7 @@
import { useEffect } from 'react'
import { useEditor } from './useEditor'
/** @internal */
export function useCoarsePointer() {
const editor = useEditor()
useEffect(() => {