Skip to content

Commit 5a88b40

Browse files
authored
experimental: hide inherited root styles (#4210)
Ref #3399 Root styles are bloating all instances so as a temporary solution we do not show any styles inherited from them in advanced panel.
1 parent 58df4bc commit 5a88b40

File tree

3 files changed

+139
-74
lines changed

3 files changed

+139
-74
lines changed

apps/builder/app/builder/features/style-panel/sections/advanced/advanced.tsx

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { colord } from "colord";
22
import { useEffect, useMemo, useRef, useState, type ReactNode } from "react";
3+
import { useStore } from "@nanostores/react";
34
import { computed } from "nanostores";
45
import { matchSorter } from "match-sorter";
56
import { isFeatureEnabled } from "@webstudio-is/feature-flags";
@@ -20,7 +21,7 @@ import {
2021
properties as propertiesData,
2122
propertyDescriptions,
2223
} from "@webstudio-is/css-data";
23-
import { useStore } from "@nanostores/react";
24+
import { ROOT_INSTANCE_ID } from "@webstudio-is/sdk";
2425
import {
2526
hyphenateProperty,
2627
toValue,
@@ -35,13 +36,20 @@ import { styleConfigByName } from "../../shared/configs";
3536
import { deleteProperty, setProperty } from "../../shared/use-style-data";
3637
import {
3738
$definedStyles,
39+
$matchingBreakpoints,
40+
getDefinedStyles,
3841
useComputedStyleDecl,
3942
useComputedStyles,
4043
} from "../../shared/model";
4144
import { getDots } from "../../shared/style-section";
4245
import { PropertyInfo } from "../../property-label";
4346
import { sections } from "../sections";
4447
import { ColorPopover } from "../../shared/color-picker";
48+
import {
49+
$selectedInstanceSelector,
50+
$styles,
51+
$styleSourceSelections,
52+
} from "~/shared/nano-states";
4553

4654
// Only here to keep the same section module interface
4755
export const properties = [];
@@ -206,7 +214,7 @@ const AdvancedPropertyLabel = ({ property }: { property: StyleProperty }) => {
206214
);
207215
};
208216

209-
const $customProperties = computed($definedStyles, (definedStyles) => {
217+
const $availableCustomProperties = computed($definedStyles, (definedStyles) => {
210218
const customProperties = new Set<StyleProperty>();
211219
for (const { property } of definedStyles) {
212220
if (property.startsWith("--")) {
@@ -224,7 +232,7 @@ const AdvancedPropertyValue = ({
224232
property: StyleProperty;
225233
}) => {
226234
const styleDecl = useComputedStyleDecl(property);
227-
const customProperties = useStore($customProperties);
235+
const availableCustomProperties = useStore($availableCustomProperties);
228236
const { items } = styleConfigByName(property);
229237
const inputRef = useRef<HTMLInputElement>(null);
230238
useEffect(() => {
@@ -267,7 +275,7 @@ const AdvancedPropertyValue = ({
267275
value: item.name,
268276
})),
269277
// very basic custom properties autocomplete
270-
...Array.from(customProperties).map((name) => ({
278+
...Array.from(availableCustomProperties).map((name) => ({
271279
type: "keyword" as const,
272280
value: name,
273281
})),
@@ -299,23 +307,46 @@ const initialProperties = new Set<StyleProperty>([
299307
"opacity",
300308
]);
301309

302-
const $advancedProperties = computed($definedStyles, (definedStyles) => {
303-
// All properties used by the panels except the advanced panel
304-
const baseProperties = new Set<StyleProperty>([]);
305-
for (const { properties } of sections.values()) {
306-
for (const property of properties) {
307-
baseProperties.add(property);
310+
const $advancedProperties = computed(
311+
[
312+
$selectedInstanceSelector,
313+
$styleSourceSelections,
314+
$matchingBreakpoints,
315+
$styles,
316+
],
317+
(instanceSelector, styleSourceSelections, matchingBreakpoints, styles) => {
318+
if (instanceSelector === undefined) {
319+
return [];
308320
}
309-
}
310-
const advancedProperties = new Set<StyleProperty>(initialProperties);
311-
for (const { property, listed } of definedStyles) {
312-
// exclude properties from style panel UI unless edited in advanced section
313-
if (baseProperties.has(property) === false || listed) {
314-
advancedProperties.add(property);
321+
const instanceAndRootSelector =
322+
instanceSelector[0] === ROOT_INSTANCE_ID
323+
? instanceSelector
324+
: // prevent showing properties inherited from root
325+
// to not bloat advanced panel
326+
instanceSelector;
327+
const definedStyles = getDefinedStyles({
328+
instanceSelector: instanceAndRootSelector,
329+
matchingBreakpoints,
330+
styleSourceSelections,
331+
styles,
332+
});
333+
// All properties used by the panels except the advanced panel
334+
const baseProperties = new Set<StyleProperty>([]);
335+
for (const { properties } of sections.values()) {
336+
for (const property of properties) {
337+
baseProperties.add(property);
338+
}
315339
}
340+
const advancedProperties = new Set<StyleProperty>(initialProperties);
341+
for (const { property, listed } of definedStyles) {
342+
// exclude properties from style panel UI unless edited in advanced section
343+
if (baseProperties.has(property) === false || listed) {
344+
advancedProperties.add(property);
345+
}
346+
}
347+
return Array.from(advancedProperties).reverse();
316348
}
317-
return Array.from(advancedProperties).reverse();
318-
});
349+
);
319350

320351
export const Section = () => {
321352
const [isAdding, setIsAdding] = useState(false);

apps/builder/app/builder/features/style-panel/shared/model.tsx

Lines changed: 60 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import {
99
} from "@webstudio-is/css-engine";
1010
import {
1111
ROOT_INSTANCE_ID,
12+
Styles,
13+
StyleSourceSelections,
1214
type Breakpoint,
1315
type Instance,
1416
type StyleDecl,
@@ -73,7 +75,7 @@ const $instanceComponents = computed(
7375
}
7476
);
7577

76-
const $matchingBreakpoints = computed(
78+
export const $matchingBreakpoints = computed(
7779
[$breakpoints, $selectedBreakpoint],
7880
(breakpoints, selectedBreakpoint) => {
7981
const sortedBreakpoints = Array.from(breakpoints.values()).sort(
@@ -90,62 +92,76 @@ const $matchingBreakpoints = computed(
9092
}
9193
);
9294

95+
export const getDefinedStyles = ({
96+
instanceSelector,
97+
matchingBreakpoints: matchingBreakpointsArray,
98+
styleSourceSelections,
99+
styles,
100+
}: {
101+
instanceSelector: InstanceSelector;
102+
matchingBreakpoints: Breakpoint["id"][];
103+
styleSourceSelections: StyleSourceSelections;
104+
styles: Styles;
105+
}) => {
106+
const definedStyles = new Set<StyleDecl>();
107+
const inheritedStyleSources = new Set();
108+
const instanceStyleSources = new Set();
109+
const matchingBreakpoints = new Set(matchingBreakpointsArray);
110+
for (const instanceId of instanceSelector) {
111+
const styleSources = styleSourceSelections.get(instanceId)?.values;
112+
if (styleSources) {
113+
for (const styleSourceId of styleSources) {
114+
if (instanceId === instanceSelector[0]) {
115+
instanceStyleSources.add(styleSourceId);
116+
} else {
117+
inheritedStyleSources.add(styleSourceId);
118+
}
119+
}
120+
}
121+
}
122+
for (const styleDecl of styles.values()) {
123+
if (
124+
matchingBreakpoints.has(styleDecl.breakpointId) &&
125+
instanceStyleSources.has(styleDecl.styleSourceId)
126+
) {
127+
definedStyles.add(styleDecl);
128+
}
129+
const inherited =
130+
properties[styleDecl.property as keyof typeof properties]?.inherited ??
131+
// custom properties are always inherited
132+
true;
133+
if (
134+
matchingBreakpoints.has(styleDecl.breakpointId) &&
135+
inheritedStyleSources.has(styleDecl.styleSourceId) &&
136+
inherited
137+
) {
138+
definedStyles.add(styleDecl);
139+
}
140+
}
141+
return definedStyles;
142+
};
143+
93144
export const $definedStyles = computed(
94145
[
95146
$selectedInstanceSelector,
96147
$styleSourceSelections,
97148
$matchingBreakpoints,
98149
$styles,
99150
],
100-
(
101-
instanceSelector,
102-
styleSourceSelections,
103-
matchingBreakpointsArray,
104-
styles
105-
) => {
106-
const definedProperties = new Set<StyleDecl>();
151+
(instanceSelector, styleSourceSelections, matchingBreakpoints, styles) => {
107152
if (instanceSelector === undefined) {
108-
return definedProperties;
153+
return new Set<StyleDecl>();
109154
}
110155
const instanceAndRootSelector =
111156
instanceSelector[0] === ROOT_INSTANCE_ID
112157
? instanceSelector
113158
: [...instanceSelector, ROOT_INSTANCE_ID];
114-
const inheritedStyleSources = new Set();
115-
const instanceStyleSources = new Set();
116-
const matchingBreakpoints = new Set(matchingBreakpointsArray);
117-
for (const instanceId of instanceAndRootSelector) {
118-
const styleSources = styleSourceSelections.get(instanceId)?.values;
119-
if (styleSources) {
120-
for (const styleSourceId of styleSources) {
121-
if (instanceId === instanceAndRootSelector[0]) {
122-
instanceStyleSources.add(styleSourceId);
123-
} else {
124-
inheritedStyleSources.add(styleSourceId);
125-
}
126-
}
127-
}
128-
}
129-
for (const styleDecl of styles.values()) {
130-
if (
131-
matchingBreakpoints.has(styleDecl.breakpointId) &&
132-
instanceStyleSources.has(styleDecl.styleSourceId)
133-
) {
134-
definedProperties.add(styleDecl);
135-
}
136-
const inherited =
137-
properties[styleDecl.property as keyof typeof properties]?.inherited ??
138-
// custom properties are always inherited
139-
true;
140-
if (
141-
matchingBreakpoints.has(styleDecl.breakpointId) &&
142-
inheritedStyleSources.has(styleDecl.styleSourceId) &&
143-
inherited
144-
) {
145-
definedProperties.add(styleDecl);
146-
}
147-
}
148-
return definedProperties;
159+
return getDefinedStyles({
160+
instanceSelector: instanceAndRootSelector,
161+
matchingBreakpoints,
162+
styleSourceSelections,
163+
styles,
164+
});
149165
}
150166
);
151167

apps/builder/app/builder/features/style-panel/style-source-section.tsx

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -401,21 +401,39 @@ const pasteStyles = async (
401401
const text = await navigator.clipboard.readText();
402402
const parsedStyles = parseCss(`selector{${text}}`);
403403
const breakpointId = $selectedBreakpoint.get()?.id;
404-
if (breakpointId === undefined) {
404+
const instanceId = $selectedInstanceSelector.get()?.[0];
405+
if (breakpointId === undefined || instanceId === undefined) {
405406
return;
406407
}
407-
serverSyncStore.createTransaction([$styles], (styles) => {
408-
for (const { property, value } of parsedStyles) {
409-
const styleDecl: StyleDecl = {
410-
breakpointId,
411-
styleSourceId,
412-
state,
413-
property,
414-
value,
415-
};
416-
styles.set(getStyleDeclKey(styleDecl), styleDecl);
408+
serverSyncStore.createTransaction(
409+
[$styles, $styleSources, $styleSourceSelections],
410+
(styles, styleSources, styleSourceSelections) => {
411+
// add local style source if does not exist yet
412+
if (styleSources.has(styleSourceId) === false) {
413+
styleSources.set(styleSourceId, { type: "local", id: styleSourceId });
414+
let styleSourceSelection = styleSourceSelections.get(instanceId);
415+
// create new style source selection
416+
if (styleSourceSelection === undefined) {
417+
styleSourceSelection = { instanceId, values: [styleSourceId] };
418+
styleSourceSelections.set(instanceId, styleSourceSelection);
419+
}
420+
// append style source to existing selection
421+
if (styleSourceSelection.values.includes(styleSourceId) === false) {
422+
styleSourceSelection.values.push(styleSourceId);
423+
}
424+
}
425+
for (const { property, value } of parsedStyles) {
426+
const styleDecl: StyleDecl = {
427+
breakpointId,
428+
styleSourceId,
429+
state,
430+
property,
431+
value,
432+
};
433+
styles.set(getStyleDeclKey(styleDecl), styleDecl);
434+
}
417435
}
418-
});
436+
);
419437
};
420438

421439
const clearStyles = (styleSourceId: StyleSource["id"]) => {

0 commit comments

Comments
 (0)