Skip to content

Commit 325eff1

Browse files
authored
feat: support css variables in transitions (#4317)
Ref #3399 - stop filtering when open combobox suggestions - prevent showing selected description when highlight css variable - support css variables in duration - support css variables in delay Also replaced select with css value input for easing. Had to get rid from out easings presets though now we can use easings from css variables which I think a better trade. Presets will make sense with dedicated UI for easings like https://www.easing.dev. ![Screenshot 2024-10-19 at 21 55 02](https://github.com/user-attachments/assets/4cdbb799-d01c-4c3f-93dc-c54e9723635e)
1 parent 8545ca7 commit 325eff1

File tree

6 files changed

+78
-263
lines changed

6 files changed

+78
-263
lines changed

apps/builder/app/builder/features/style-panel/sections/transitions/transition-content.tsx

Lines changed: 67 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,16 @@ import {
1818
} from "@webstudio-is/design-system";
1919
import { InfoCircleIcon } from "@webstudio-is/icons";
2020
import { properties, propertyDescriptions } from "@webstudio-is/css-data";
21-
import type { StyleUpdateOptions } from "../../shared/use-style-data";
2221
import { type IntermediateStyleValue } from "../../shared/css-value-input";
2322
import { CssValueInputContainer } from "../../shared/css-value-input";
2423
import { parseCssFragment } from "../../shared/css-fragment";
2524
import { PropertyInlineLabel } from "../../property-label";
2625
import { TransitionProperty } from "./transition-property";
27-
import { TransitionTiming } from "./transition-timing";
28-
import { useComputedStyles } from "../../shared/model";
29-
import { editRepeatedStyleItem } from "../../shared/repeated-style";
26+
import { $availableVariables, useComputedStyles } from "../../shared/model";
27+
import {
28+
editRepeatedStyleItem,
29+
setRepeatedStyleItem,
30+
} from "../../shared/repeated-style";
3031

3132
const getLayer = (value: undefined | StyleValue, index: number) =>
3233
value?.type === "layers" ? value.value[index] : undefined;
@@ -86,15 +87,12 @@ export const TransitionContent = ({ index }: { index: number }) => {
8687
);
8788
};
8889

89-
const handlePropertyUpdate = (
90-
params: {
91-
property?: StyleValue;
92-
timing?: StyleValue;
93-
delay?: StyleValue;
94-
duration?: StyleValue;
95-
},
96-
options: StyleUpdateOptions = { isEphemeral: false }
97-
) => {
90+
const updateIntermediateValue = (params: {
91+
property?: StyleValue;
92+
timing?: StyleValue;
93+
delay?: StyleValue;
94+
duration?: StyleValue;
95+
}) => {
9896
const shorthand = toValue({
9997
type: "tuple",
10098
value: [
@@ -108,12 +106,6 @@ export const TransitionContent = ({ index }: { index: number }) => {
108106
type: "intermediate",
109107
value: shorthand,
110108
});
111-
editRepeatedStyleItem(
112-
styles,
113-
index,
114-
parseCssFragment(shorthand, ["transition"]),
115-
options
116-
);
117109
};
118110

119111
return (
@@ -134,7 +126,10 @@ export const TransitionContent = ({ index }: { index: number }) => {
134126
/>
135127
<TransitionProperty
136128
value={property ?? properties.transitionProperty.initial}
137-
onChange={(property) => handlePropertyUpdate({ property })}
129+
onChange={(value) => {
130+
updateIntermediateValue({ duration: value });
131+
setRepeatedStyleItem(transitionProperty, index, value);
132+
}}
138133
/>
139134

140135
<PropertyInlineLabel
@@ -143,23 +138,21 @@ export const TransitionContent = ({ index }: { index: number }) => {
143138
properties={["transitionDuration"]}
144139
/>
145140
<CssValueInputContainer
146-
key={"transitionDuration"}
147-
property={"transitionDuration"}
141+
property="transitionDuration"
148142
styleSource="local"
143+
getOptions={() => $availableVariables.get()}
149144
value={duration ?? properties.transitionDuration.initial}
150145
deleteProperty={() => {}}
151146
setValue={(value, options) => {
152147
if (value === undefined) {
153148
return;
154149
}
155-
156-
if (value.type === "unit") {
157-
handlePropertyUpdate({ duration: value }, options);
158-
return;
150+
if (value.type === "layers") {
151+
[value] = value.value;
159152
}
160-
161-
if (value.type === "layers" && value.value[0].type === "unit") {
162-
handlePropertyUpdate({ duration: value.value[0] }, options);
153+
if (value.type === "unit" || value.type === "var") {
154+
updateIntermediateValue({ duration: value });
155+
setRepeatedStyleItem(transitionDuration, index, value, options);
163156
}
164157
}}
165158
/>
@@ -170,32 +163,65 @@ export const TransitionContent = ({ index }: { index: number }) => {
170163
properties={["transitionDelay"]}
171164
/>
172165
<CssValueInputContainer
173-
property={"transitionDelay"}
174-
key={"transitionDelay"}
166+
property="transitionDelay"
175167
styleSource="local"
168+
getOptions={() => $availableVariables.get()}
176169
value={delay ?? properties.transitionDelay.initial}
177170
deleteProperty={() => {}}
178171
setValue={(value, options) => {
179172
if (value === undefined) {
180173
return;
181174
}
182-
183-
if (value.type === "unit") {
184-
handlePropertyUpdate({ delay: value }, options);
185-
return;
175+
if (value.type === "layers") {
176+
[value] = value.value;
186177
}
187-
188-
if (value.type === "layers" && value.value[0].type === "unit") {
189-
handlePropertyUpdate({ delay: value.value[0] }, options);
178+
if (value.type === "unit" || value.type === "var") {
179+
updateIntermediateValue({ delay: value });
180+
setRepeatedStyleItem(transitionDelay, index, value, options);
190181
}
191182
}}
192183
/>
193184

194-
<TransitionTiming
195-
timing={timingFunction ?? properties.transitionTimingFunction.initial}
196-
onTimingSelection={handlePropertyUpdate}
185+
<PropertyInlineLabel
186+
label="Easing"
187+
description={propertyDescriptions.transitionTimingFunction}
188+
properties={["transitionTimingFunction"]}
189+
/>
190+
<CssValueInputContainer
191+
property="transitionTimingFunction"
192+
styleSource="local"
193+
getOptions={() => [
194+
{ type: "keyword", value: "linear" },
195+
{ type: "keyword", value: "ease" },
196+
{ type: "keyword", value: "ease-in" },
197+
{ type: "keyword", value: "ease-out" },
198+
{ type: "keyword", value: "ease-in-out" },
199+
{ type: "keyword", value: "step-start" },
200+
{ type: "keyword", value: "step-end" },
201+
...$availableVariables.get(),
202+
]}
203+
value={timingFunction ?? properties.transitionTimingFunction.initial}
204+
deleteProperty={() => {}}
205+
setValue={(value, options) => {
206+
if (value === undefined) {
207+
return;
208+
}
209+
if (value.type === "layers") {
210+
[value] = value.value;
211+
}
212+
if (value.type === "keyword" || value.type === "var") {
213+
updateIntermediateValue({ timing: value });
214+
setRepeatedStyleItem(
215+
transitionTimingFunction,
216+
index,
217+
value,
218+
options
219+
);
220+
}
221+
}}
197222
/>
198223
</Grid>
224+
199225
<Separator css={{ gridColumn: "span 2" }} />
200226
<Flex
201227
direction="column"

apps/builder/app/builder/features/style-panel/sections/transitions/transition-timing.tsx

Lines changed: 0 additions & 130 deletions
This file was deleted.

apps/builder/app/builder/features/style-panel/sections/transitions/transition-utils.ts

Lines changed: 0 additions & 71 deletions
This file was deleted.

0 commit comments

Comments
 (0)