Skip to content

Commit

Permalink
feat: add shift/option modifiers to spacing and position input popove…
Browse files Browse the repository at this point in the history
…rs (#3924)

Part of #3914

## Description

To allow entering a value from keyboard for all or opposite sides in
spacing and position controls, we now support same modifiers as we use
for drag guesture

## Steps for reproduction

1. open spacing
2. click on padding top number to open input
3. enter value, hold option or shift modifiers, then press enter
4. option places the value into opposite values, top/bottom, left/right,
shift changes all sides

## 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/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
  • Loading branch information
kof authored Aug 12, 2024
1 parent 1c7cfe1 commit 939a2b8
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,20 +93,18 @@ const bigValue = {
} as const;

export const PositionControlComponent = () => {
const { styleInfo, setProperty, deleteProperty, createBatchUpdate } =
useStyleInfo({
left: defaultValue,
right: bigValue,
top: defaultValue,
bottom: defaultValue,
});
const { styleInfo, deleteProperty, createBatchUpdate } = useStyleInfo({
left: defaultValue,
right: bigValue,
top: defaultValue,
bottom: defaultValue,
});

return (
<Box css={{ marginLeft: 100 }}>
<PositionControl
createBatchUpdate={createBatchUpdate}
currentStyle={styleInfo}
setProperty={setProperty}
deleteProperty={deleteProperty}
/>
</Box>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Grid, theme } from "@webstudio-is/design-system";
import { PositionLayout, type PositionProperty } from "./position-layout";
import { movementMapPosition, useKeyboardNavigation } from "../shared/keyboard";
import { useRef, useState, type ComponentProps } from "react";
import { useRef, useState } from "react";
import type {
CreateBatchUpdate,
DeleteProperty,
SetProperty,
} from "../../shared/use-style-data";
import { getStyleSource, type StyleInfo } from "../../shared/style-info";
import { getPositionModifiersGroup, useScrub } from "../shared/scrub";
Expand All @@ -21,12 +20,10 @@ const Cell = ({
onHover,
isPopoverOpen,
onPopoverClose,
onChange,
createBatchUpdate,
}: {
isPopoverOpen: boolean;
onPopoverClose: () => void;
onChange: ComponentProps<typeof InputPopover>["onChange"];
scrubStatus: ReturnType<typeof useScrub>;
currentStyle: StyleInfo;
property: PositionProperty;
Expand All @@ -50,8 +47,8 @@ const Cell = ({
value={finalValue}
isOpen={isPopoverOpen}
property={property}
onChange={onChange}
onClose={onPopoverClose}
createBatchUpdate={createBatchUpdate}
/>
<PositionTooltip
property={property}
Expand Down Expand Up @@ -87,7 +84,6 @@ type HoverTarget = {
};

type PositionControlProps = {
setProperty: SetProperty;
deleteProperty: DeleteProperty;
createBatchUpdate: CreateBatchUpdate;
currentStyle: StyleInfo;
Expand All @@ -97,7 +93,6 @@ export const PositionControl = ({
createBatchUpdate,
currentStyle,
deleteProperty,
setProperty,
}: PositionControlProps) => {
const [hoverTarget, setHoverTarget] = useState<HoverTarget>();

Expand Down Expand Up @@ -192,13 +187,6 @@ export const PositionControl = ({
layoutRef.current?.focus();
}
}}
onChange={(update, options) => {
if (update.operation === "set") {
setProperty(update.property)(update.value, options);
} else {
deleteProperty(update.property, options);
}
}}
createBatchUpdate={createBatchUpdate}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ export const Section = ({
<Grid gap={3} columns={2}>
<PositionControl
currentStyle={currentStyle}
setProperty={setProperty}
deleteProperty={deleteProperty}
createBatchUpdate={createBatchUpdate}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,65 @@ import {
PopoverTrigger,
PopoverContent,
} from "@webstudio-is/design-system";
import type { StyleProperty, StyleValue } from "@webstudio-is/css-engine";
import type { StyleValue } from "@webstudio-is/css-engine";
import {
CssValueInput,
type IntermediateStyleValue,
} from "../../shared/css-value-input";
import type { StyleSource } from "../../shared/style-info";
import type {
CreateBatchUpdate,
StyleUpdate,
StyleUpdateOptions,
} from "../../shared/use-style-data";
import { theme } from "@webstudio-is/design-system";
import { getPositionModifiersGroup, getSpaceModifiersGroup } from "./scrub";
import type { SpaceStyleProperty } from "../space/types";
import type { PositionProperty } from "../position/position-layout";

const slideUpAndFade = keyframes({
"0%": { opacity: 0, transform: "scale(0.8)" },
"100%": { opacity: 1, transform: "scale(1)" },
});

// We need to differentiate between marginTop and top for example.
const isSpace = (property: string) => {
return property.startsWith("margin") || property.startsWith("padding");
};

const Input = ({
styleSource,
value,
property,
onChange,
onClosePopover,
createBatchUpdate,
}: {
styleSource: StyleSource;
property: StyleProperty;
property: SpaceStyleProperty | PositionProperty;
value: StyleValue;
onChange: (update: StyleUpdate, options: StyleUpdateOptions) => void;
onClosePopover: () => void;
createBatchUpdate: CreateBatchUpdate;
}) => {
const [intermediateValue, setIntermediateValue] = useState<
StyleValue | IntermediateStyleValue
>();

const onChange = (
updates: Array<StyleUpdate>,
options: StyleUpdateOptions
) => {
const batch = createBatchUpdate();
for (const update of updates) {
if (update.operation === "set") {
batch.setProperty(update.property)(update.value);
}
if (update.operation === "delete") {
batch.deleteProperty(update.property);
}
}
batch.publish(options);
};

return (
<CssValueInput
styleSource={styleSource}
Expand All @@ -50,38 +75,47 @@ const Input = ({
setIntermediateValue(styleValue);

if (styleValue === undefined) {
onChange({ operation: "delete", property }, { isEphemeral: true });
onChange([{ operation: "delete", property }], { isEphemeral: true });
return;
}

if (styleValue.type !== "intermediate") {
onChange(
{ operation: "set", property, value: styleValue },
{ isEphemeral: true }
);
onChange([{ operation: "set", property, value: styleValue }], {
isEphemeral: true,
});
}
}}
onHighlight={(styleValue) => {
if (styleValue === undefined) {
onChange({ operation: "delete", property }, { isEphemeral: true });
onChange([{ operation: "delete", property }], { isEphemeral: true });
return;
}

onChange(
{ operation: "set", property, value: styleValue },
{ isEphemeral: true }
);
onChange([{ operation: "set", property, value: styleValue }], {
isEphemeral: true,
});
}}
onChangeComplete={({ value, reason }) => {
onChangeComplete={({ value, type, altKey, shiftKey }) => {
const updates: Array<StyleUpdate> = [];
const options = { isEphemeral: false };
const modifiers = { shiftKey, altKey };
const properties = isSpace(property)
? getSpaceModifiersGroup(property as SpaceStyleProperty, modifiers)
: getPositionModifiersGroup(property as PositionProperty, modifiers);

setIntermediateValue(undefined);
onChange({ operation: "set", property, value }, { isEphemeral: false });

if (reason === "blur" || reason === "enter") {
properties.forEach((property) => {
updates.push({ operation: "set", property, value });
});
onChange(updates, options);

if (type === "blur" || type === "enter") {
onClosePopover();
}
}}
onAbort={() => {
onChange({ operation: "delete", property }, { isEphemeral: true });
onChange([{ operation: "delete", property }], { isEphemeral: true });
}}
/>
);
Expand All @@ -108,14 +142,13 @@ export const InputPopover = ({
styleSource,
property,
value,
onChange,
isOpen,
onClose,
}: {
styleSource: StyleSource;
property: StyleProperty;
value: StyleValue;
onChange: ComponentProps<typeof Input>["onChange"];
createBatchUpdate,
}: Pick<
ComponentProps<typeof Input>,
"styleSource" | "property" | "value" | "createBatchUpdate"
> & {
isOpen: boolean;
onClose: () => void;
}) => {
Expand All @@ -136,7 +169,7 @@ export const InputPopover = ({
styleSource={styleSource}
value={value}
property={property}
onChange={onChange}
createBatchUpdate={createBatchUpdate}
onClosePopover={onClose}
/>
</PopoverContentStyled>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type ComponentProps, useState, useRef } from "react";
import { useState, useRef } from "react";
import type { SectionProps } from "../shared/section";
import { SpaceLayout } from "./layout";
import { ValueText } from "../shared/value-text";
Expand All @@ -10,13 +10,11 @@ import { SpaceTooltip } from "./tooltip";
import { getStyleSource } from "../../shared/style-info";
import { CollapsibleSection } from "../../shared/collapsible-section";
import { movementMapSpace, useKeyboardNavigation } from "../shared/keyboard";

import type { CreateBatchUpdate } from "../../shared/use-style-data";

const Cell = ({
isPopoverOpen,
onPopoverClose,
onChange,
onHover,
property,
scrubStatus,
Expand All @@ -25,7 +23,6 @@ const Cell = ({
}: {
isPopoverOpen: boolean;
onPopoverClose: () => void;
onChange: ComponentProps<typeof InputPopover>["onChange"];
onHover: (target: HoverTarget | undefined) => void;
property: SpaceStyleProperty;
scrubStatus: ReturnType<typeof useScrub>;
Expand All @@ -39,7 +36,7 @@ const Cell = ({

// for TypeScript
if (finalValue === undefined) {
return null;
return;
}

return (
Expand All @@ -49,8 +46,8 @@ const Cell = ({
value={finalValue}
isOpen={isPopoverOpen}
property={property}
onChange={onChange}
onClose={onPopoverClose}
createBatchUpdate={createBatchUpdate}
/>
<SpaceTooltip
property={property}
Expand Down Expand Up @@ -83,7 +80,6 @@ const Cell = ({
export { spaceProperties as properties };

export const Section = ({
setProperty,
deleteProperty,
createBatchUpdate,
currentStyle,
Expand Down Expand Up @@ -168,13 +164,6 @@ export const Section = ({
layoutRef.current?.focus();
}
}}
onChange={(update, options) => {
if (update.operation === "set") {
setProperty(update.property)(update.value, options);
} else {
deleteProperty(update.property, options);
}
}}
onHover={handleHover}
property={property}
scrubStatus={scrubStatus}
Expand Down
Loading

0 comments on commit 939a2b8

Please sign in to comment.