From f5297231c56fbd3c4b28420f375fc82bce092425 Mon Sep 17 00:00:00 2001 From: Jaya Krishna Namburu Date: Wed, 8 May 2024 08:22:10 +0200 Subject: [PATCH] feat: Add support for `backdrop-filter` property in style panel (#3317) ## Description This PR adds support for using `backdrop-filter` property in the style-panel. Here are more details on the property to test it around. https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter ## Steps for reproduction 1. Add an element to the canvas. 2. Click on the "+" icon in the style panel next to the `Backdrop Filters` section. 3. Edit the default filter that is added. 4. Swap the layers and publish the project. ## 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 - [x] made a self-review - [x] added inline comments where things may be not obvious (the "why", not "what") ## Before merging - [x] tested locally and on preview environment (preview dev login: 5de6) --- .../backdrop-filter/backdrop-filter.tsx | 115 ++++++++++++++++++ .../sections/filter/filter-content.tsx | 21 +--- .../sections/filter/filter-layer.tsx | 5 +- .../style-panel/sections/filter/filter.tsx | 27 +++- .../features/style-panel/sections/sections.ts | 2 + .../features/style-panel/style-layer-utils.ts | 5 +- .../style-panel/style-layers-list.tsx | 2 + 7 files changed, 154 insertions(+), 23 deletions(-) create mode 100644 apps/builder/app/builder/features/style-panel/sections/backdrop-filter/backdrop-filter.tsx diff --git a/apps/builder/app/builder/features/style-panel/sections/backdrop-filter/backdrop-filter.tsx b/apps/builder/app/builder/features/style-panel/sections/backdrop-filter/backdrop-filter.tsx new file mode 100644 index 000000000000..17226abed734 --- /dev/null +++ b/apps/builder/app/builder/features/style-panel/sections/backdrop-filter/backdrop-filter.tsx @@ -0,0 +1,115 @@ +import { CollapsibleSectionRoot } from "~/builder/shared/collapsible-section"; +import type { SectionProps } from "../shared/section"; +import type { + FunctionValue, + StyleProperty, + TupleValue, +} from "@webstudio-is/css-engine"; +import { useState } from "react"; +import { + SectionTitle, + SectionTitleButton, + SectionTitleLabel, + Tooltip, + Flex, + Text, +} from "@webstudio-is/design-system"; +import { PropertyName } from "../../shared/property-name"; +import { getStyleSource } from "../../shared/style-info"; +import { getDots } from "../../shared/collapsible-section"; +import { InfoCircleIcon, PlusIcon } from "@webstudio-is/icons"; +import { addLayer } from "../../style-layer-utils"; +import { parseFilter } from "@webstudio-is/css-data"; +import { LayersList } from "../../style-layers-list"; +import { FilterLayer } from "../filter/filter-layer"; + +export const properties = ["backdropFilter"] satisfies Array; + +const property: StyleProperty = properties[0]; +const label = "Backdrop Filters"; +const INITIAL_BACKDROP_FILTER = "blur(0px)"; + +export const Section = (props: SectionProps) => { + const { currentStyle, deleteProperty } = props; + const [isOpen, setIsOpen] = useState(false); + const value = currentStyle[property]?.value; + const sectionStyleSource = + value?.type === "unparsed" || value?.type === "guaranteedInvalid" + ? undefined + : getStyleSource(currentStyle[property]); + + return ( + + } + onClick={() => { + addLayer( + property, + parseFilter(INITIAL_BACKDROP_FILTER), + currentStyle, + props.createBatchUpdate + ); + setIsOpen(true); + }} + /> + + } + > + + {label} + + } + onReset={() => deleteProperty(property)} + /> + + } + > + {value?.type === "tuple" && value.value.length > 0 && ( + + {...props} + property={property} + layers={value} + renderLayer={(layerProps) => ( + + {label} + backdrop-filter + + Applies graphical effects like blur or color shift to + the area behind an element + + + } + > + + + } + /> + )} + /> + )} + + ); +}; diff --git a/apps/builder/app/builder/features/style-panel/sections/filter/filter-content.tsx b/apps/builder/app/builder/features/style-panel/sections/filter/filter-content.tsx index 90c61a455c77..6ce4df8a61cd 100644 --- a/apps/builder/app/builder/features/style-panel/sections/filter/filter-content.tsx +++ b/apps/builder/app/builder/features/style-panel/sections/filter/filter-content.tsx @@ -7,12 +7,9 @@ import { Flex, theme, Label, - Tooltip, - Text, TextArea, textVariants, } from "@webstudio-is/design-system"; -import { InfoCircleIcon } from "@webstudio-is/icons"; import { useState } from "react"; import type { IntermediateStyleValue } from "../../shared/css-value-input"; import { parseFilter } from "@webstudio-is/css-data"; @@ -23,6 +20,7 @@ type FilterContentProps = { filter: string; onEditLayer: (index: number, layers: LayersValue | TupleValue) => void; deleteProperty: DeleteProperty; + tooltip: JSX.Element; }; export const FilterSectionContent = ({ @@ -30,6 +28,7 @@ export const FilterSectionContent = ({ filter, onEditLayer, deleteProperty, + tooltip, }: FilterContentProps) => { const [intermediateValue, setIntermediateValue] = useState< IntermediateStyleValue | InvalidValue | undefined @@ -73,21 +72,7 @@ export const FilterSectionContent = ({ { diff --git a/apps/builder/app/builder/features/style-panel/sections/filter/filter-layer.tsx b/apps/builder/app/builder/features/style-panel/sections/filter/filter-layer.tsx index 61412a5132fb..cab1e36dd9c0 100644 --- a/apps/builder/app/builder/features/style-panel/sections/filter/filter-layer.tsx +++ b/apps/builder/app/builder/features/style-panel/sections/filter/filter-layer.tsx @@ -11,18 +11,19 @@ import { useMemo } from "react"; import { FunctionValue, toValue } from "@webstudio-is/css-engine"; export const FilterLayer = (props: LayerProps) => { - const { index, id, layer, isHighlighted, onDeleteLayer } = props; + const { index, id, layer, isHighlighted, onDeleteLayer, label } = props; const filter = useMemo(() => toValue(layer), [layer]); return ( } > diff --git a/apps/builder/app/builder/features/style-panel/sections/filter/filter.tsx b/apps/builder/app/builder/features/style-panel/sections/filter/filter.tsx index e6e1b821f1fe..36f75c9eae38 100644 --- a/apps/builder/app/builder/features/style-panel/sections/filter/filter.tsx +++ b/apps/builder/app/builder/features/style-panel/sections/filter/filter.tsx @@ -2,14 +2,16 @@ import { CollapsibleSectionRoot } from "~/builder/shared/collapsible-section"; import type { SectionProps } from "../shared/section"; import { useState } from "react"; import { + Flex, SectionTitle, SectionTitleButton, SectionTitleLabel, Tooltip, + Text, } from "@webstudio-is/design-system"; import { getDots } from "../../shared/collapsible-section"; import { PropertyName } from "../../shared/property-name"; -import { PlusIcon } from "@webstudio-is/icons"; +import { InfoCircleIcon, PlusIcon } from "@webstudio-is/icons"; import { FunctionValue, TupleValue, @@ -83,7 +85,28 @@ export const Section = (props: SectionProps) => { property={property} layers={value} renderLayer={(layerProps) => ( - + + {label} + filter + + Applies graphical effects like blur or color shift to an + element + + + } + > + + + } + /> )} /> )} diff --git a/apps/builder/app/builder/features/style-panel/sections/sections.ts b/apps/builder/app/builder/features/style-panel/sections/sections.ts index 75ea996206b0..e6a6d657a465 100644 --- a/apps/builder/app/builder/features/style-panel/sections/sections.ts +++ b/apps/builder/app/builder/features/style-panel/sections/sections.ts @@ -13,6 +13,7 @@ import * as filter from "./filter/filter"; import * as transitions from "./transitions/transitions"; import * as outline from "./outline/outline"; import * as advanced from "./advanced/advanced"; +import * as backdropFilter from "./backdrop-filter/backdrop-filter"; import type { StyleProperty } from "@webstudio-is/css-engine"; import type { SectionProps } from "./shared/section"; @@ -34,6 +35,7 @@ export const sections = new Map< ["borders", borders], ["boxShadows", boxShadows], ["filter", filter], + ["backdropFilters", backdropFilter], ["transitions", transitions], ["outline", outline], ["advanced", advanced], diff --git a/apps/builder/app/builder/features/style-panel/style-layer-utils.ts b/apps/builder/app/builder/features/style-panel/style-layer-utils.ts index 3320360cdec7..58d3ebe90013 100644 --- a/apps/builder/app/builder/features/style-panel/style-layer-utils.ts +++ b/apps/builder/app/builder/features/style-panel/style-layer-utils.ts @@ -87,7 +87,10 @@ export const addLayer = ( value.value = [...value.value, ...existingValues.value] as T["value"]; } - if (property === "filter" && existingValues?.type === "tuple") { + if ( + (property === "filter" || property === "backdropFilter") && + existingValues?.type === "tuple" + ) { value.value = [ ...value.value, ...(existingValues?.value || []), diff --git a/apps/builder/app/builder/features/style-panel/style-layers-list.tsx b/apps/builder/app/builder/features/style-panel/style-layers-list.tsx index 3c0fa5dfcfee..9dbd0bb95c41 100644 --- a/apps/builder/app/builder/features/style-panel/style-layers-list.tsx +++ b/apps/builder/app/builder/features/style-panel/style-layers-list.tsx @@ -26,6 +26,8 @@ export type LayerProps = { id: string; index: number; layer: LayerType; + label: string; + tooltip: JSX.Element; isHighlighted: boolean; disabled?: boolean; onLayerHide: (index: number) => void;