Skip to content

Commit

Permalink
feat: Add support for backdrop-filter property in style panel (#3317)
Browse files Browse the repository at this point in the history
## 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)
  • Loading branch information
JayaKrishnaNamburu authored May 8, 2024
1 parent c196150 commit f529723
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -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<StyleProperty>;

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 (
<CollapsibleSectionRoot
fullWidth
label={label}
isOpen={isOpen}
onOpenChange={setIsOpen}
trigger={
<SectionTitle
dots={getDots(currentStyle, properties)}
suffix={
<Tooltip content={"Add a backdrop-filter"}>
<SectionTitleButton
prefix={<PlusIcon />}
onClick={() => {
addLayer(
property,
parseFilter(INITIAL_BACKDROP_FILTER),
currentStyle,
props.createBatchUpdate
);
setIsOpen(true);
}}
/>
</Tooltip>
}
>
<PropertyName
title={label}
style={currentStyle}
properties={properties}
description="Backdrop filters are similar to filters, but are applied to the area behind an element. This can be useful for creating frosted glass effects."
label={
<SectionTitleLabel color={sectionStyleSource}>
{label}
</SectionTitleLabel>
}
onReset={() => deleteProperty(property)}
/>
</SectionTitle>
}
>
{value?.type === "tuple" && value.value.length > 0 && (
<LayersList<FunctionValue, TupleValue>
{...props}
property={property}
layers={value}
renderLayer={(layerProps) => (
<FilterLayer
{...layerProps}
key={layerProps.index}
label={label}
tooltip={
<Tooltip
css={{ width: "208px" }}
content={
<Flex gap="2" direction="column">
<Text variant="regularBold">{label}</Text>
<Text variant="monoBold">backdrop-filter</Text>
<Text>
Applies graphical effects like blur or color shift to
the area behind an element
</Text>
</Flex>
}
>
<InfoCircleIcon />
</Tooltip>
}
/>
)}
/>
)}
</CollapsibleSectionRoot>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -23,13 +20,15 @@ type FilterContentProps = {
filter: string;
onEditLayer: (index: number, layers: LayersValue | TupleValue) => void;
deleteProperty: DeleteProperty;
tooltip: JSX.Element;
};

export const FilterSectionContent = ({
index,
filter,
onEditLayer,
deleteProperty,
tooltip,
}: FilterContentProps) => {
const [intermediateValue, setIntermediateValue] = useState<
IntermediateStyleValue | InvalidValue | undefined
Expand Down Expand Up @@ -73,21 +72,7 @@ export const FilterSectionContent = ({
<Label>
<Flex align={"center"} gap={1}>
Code
<Tooltip
content={
<Flex gap="2" direction="column">
<Text variant="regularBold">Filters</Text>
<Text variant="monoBold">filter</Text>
<Text>
Applies graphical effects like
<br />
blur or color shift to an element
</Text>
</Flex>
}
>
<InfoCircleIcon />
</Tooltip>
{tooltip}
</Flex>
</Label>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,19 @@ import { useMemo } from "react";
import { FunctionValue, toValue } from "@webstudio-is/css-engine";

export const FilterLayer = <T extends FunctionValue>(props: LayerProps<T>) => {
const { index, id, layer, isHighlighted, onDeleteLayer } = props;
const { index, id, layer, isHighlighted, onDeleteLayer, label } = props;
const filter = useMemo(() => toValue(layer), [layer]);

return (
<FloatingPanel
title="Filter"
title={label}
content={
<FilterSectionContent
index={index}
filter={filter}
onEditLayer={props.onEditLayer}
deleteProperty={props.deleteProperty}
tooltip={props.tooltip}
/>
}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -83,7 +85,28 @@ export const Section = (props: SectionProps) => {
property={property}
layers={value}
renderLayer={(layerProps) => (
<FilterLayer {...layerProps} key={layerProps.index} />
<FilterLayer
{...layerProps}
key={layerProps.index}
label={label}
tooltip={
<Tooltip
css={{ width: "208px" }}
content={
<Flex gap="2" direction="column">
<Text variant="regularBold">{label}</Text>
<Text variant="monoBold">filter</Text>
<Text>
Applies graphical effects like blur or color shift to an
element
</Text>
</Flex>
}
>
<InfoCircleIcon />
</Tooltip>
}
/>
)}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand All @@ -34,6 +35,7 @@ export const sections = new Map<
["borders", borders],
["boxShadows", boxShadows],
["filter", filter],
["backdropFilters", backdropFilter],
["transitions", transitions],
["outline", outline],
["advanced", advanced],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ export const addLayer = <T extends LayersValue | TupleValue>(
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 || []),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export type LayerProps<LayerType> = {
id: string;
index: number;
layer: LayerType;
label: string;
tooltip: JSX.Element;
isHighlighted: boolean;
disabled?: boolean;
onLayerHide: (index: number) => void;
Expand Down

0 comments on commit f529723

Please sign in to comment.