Fix toolbar positioning on scale (#2042)

## Description

fixes Toolbar positioning if canvas has zoomed
https://discord.com/channels/955905230107738152/1137141681007886388

## Steps for reproduction

1. click button
2. expect xyz

## Code Review

- [ ] hi @kof, I need you to do
  - conceptual review (architecture, feature-correctness)
  - detailed review (read every line)
  - test it on preview

## Before requesting a review

- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")

## Before merging

- [ ] tested locally and on preview environment (preview dev login:
5de6)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio-builder/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env.example`
and the `builder/env-check.js` if mandatory
This commit is contained in:
Ivan Starkov authored and GitHub committed 2023-08-05 21:19:09 +03:00
1 parent 1b4b2db376
commit f5ffdd643f
1 file changed
+22 -12
@@ -14,6 +14,7 @@ import {
import { selectedInstanceSelectorStore } from "~/shared/nano-states";
import { type TextToolbarState, textToolbarStore } from "~/shared/nano-states";
import type { Publish } from "~/shared/pubsub";
import { scaleStore } from "~/builder/shared/nano-states";
type Format =
| "bold"
@@ -30,25 +31,31 @@ declare module "~/shared/pubsub" {
}
}
const getRectForRelativeRect = (parent: DOMRect, rel: DOMRect) => {
const getRectForRelativeRect = (
parent: DOMRect,
rel: DOMRect,
scale: number
) => {
const scaleRatio = scale / 100;
return {
x: parent.x + rel.x,
y: parent.y + rel.y,
width: rel.width,
height: rel.height,
top: parent.top + rel.top,
left: parent.left + rel.left,
bottom: parent.top + rel.bottom,
right: parent.left + rel.right,
x: parent.x + rel.x * scaleRatio,
y: parent.y + rel.y * scaleRatio,
width: rel.width * scaleRatio,
height: rel.height * scaleRatio,
top: parent.top + rel.top * scaleRatio,
left: parent.left + rel.left * scaleRatio,
bottom: parent.top + rel.bottom * scaleRatio,
right: parent.left + rel.right * scaleRatio,
};
};
type ToolbarProps = {
state: TextToolbarState;
onToggle: (value: Format) => void;
scale: number;
};
const Toolbar = ({ state, onToggle }: ToolbarProps) => {
const Toolbar = ({ state, onToggle, scale }: ToolbarProps) => {
const rootRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
@@ -60,7 +67,8 @@ const Toolbar = ({ state, onToggle }: ToolbarProps) => {
const parent = rootRef.current.parentElement;
const newRect = getRectForRelativeRect(
parent.getBoundingClientRect(),
state.selectionRect
state.selectionRect,
scale
);
const reference = {
getBoundingClientRect: () => newRect,
@@ -74,7 +82,7 @@ const Toolbar = ({ state, onToggle }: ToolbarProps) => {
floating.style.transform = `translate(${x}px, ${y}px)`;
});
}
}, [state.selectionRect]);
}, [state.selectionRect, scale]);
const isCleared =
state.isBold === false &&
@@ -183,6 +191,7 @@ type TextToolbarProps = {
export const TextToolbar = ({ publish }: TextToolbarProps) => {
const textToolbar = useStore(textToolbarStore);
const scale = useStore(scaleStore);
const selectedInstanceSelector = useStore(selectedInstanceSelectorStore);
if (
@@ -195,6 +204,7 @@ export const TextToolbar = ({ publish }: TextToolbarProps) => {
return (
<Toolbar
state={textToolbar}
scale={scale}
onToggle={(value) =>
publish({
type: "formatTextToolbar",