Diff
Modified: trunk/LayoutTests/ChangeLog (286875 => 286876)
--- trunk/LayoutTests/ChangeLog 2021-12-10 22:01:57 UTC (rev 286875)
+++ trunk/LayoutTests/ChangeLog 2021-12-10 22:15:52 UTC (rev 286876)
@@ -1,3 +1,16 @@
+2021-12-10 Razvan Caliman <rcali...@apple.com>
+
+ Web Inspector: Computed Panel: Group CSS variables by value type
+ https://bugs.webkit.org/show_bug.cgi?id=233563
+ <rdar://82978905>
+
+ Reviewed by Devin Rousso and Patrick Angle.
+
+ Check logic for grouping CSS variables by value type in Web Inspector.
+
+ * inspector/css/variableStylesByType-expected.txt: Added.
+ * inspector/css/variableStylesByType.html: Added.
+
2021-12-10 Chris Dumez <cdu...@apple.com>
Improve <type="datetime-local"> value parsing and sanitization
Added: trunk/LayoutTests/inspector/css/variableStylesByType-expected.txt (0 => 286876)
--- trunk/LayoutTests/inspector/css/variableStylesByType-expected.txt (rev 0)
+++ trunk/LayoutTests/inspector/css/variableStylesByType-expected.txt 2021-12-10 22:15:52 UTC (rev 286876)
@@ -0,0 +1,30 @@
+Test for DOMNodeStyles.variableStylesByType
+
+
+== Running test suite: DOMNodeStyles.variableStylesByType
+-- Running test case: DOMNodeStyles.variableStylesByType.Colors
+PASS: Should have "colors" variables group.
+PASS: Group should include all expected variables.
+
+-- Running test case: DOMNodeStyles.variableStylesByType.Dimensions
+PASS: Should have "dimensions" variables group.
+PASS: Group should include all expected variables.
+
+-- Running test case: DOMNodeStyles.variableStylesByType.Numbers
+PASS: Should have "numbers" variables group.
+PASS: Group should include all expected variables.
+
+-- Running test case: DOMNodeStyles.variableStylesByType.Other
+PASS: Should have "other" variables group.
+PASS: Group should include all expected variables.
+
+-- Running test case: DOMNodeStyles.variableStylesByType.Mixed
+PASS: Should have "colors" variables group.
+PASS: Group should include all expected variables.
+PASS: Should have "dimensions" variables group.
+PASS: Group should include all expected variables.
+PASS: Should have "numbers" variables group.
+PASS: Group should include all expected variables.
+PASS: Should have "other" variables group.
+PASS: Group should include all expected variables.
+
Added: trunk/LayoutTests/inspector/css/variableStylesByType.html (0 => 286876)
--- trunk/LayoutTests/inspector/css/variableStylesByType.html (rev 0)
+++ trunk/LayoutTests/inspector/css/variableStylesByType.html 2021-12-10 22:15:52 UTC (rev 286876)
@@ -0,0 +1,181 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+
+function test()
+{
+ let suite = InspectorTest.createAsyncSuite("DOMNodeStyles.variableStylesByType");
+
+ function addTestCase({name, description, selector, expected})
+ {
+ suite.addTestCase({
+ name,
+ description,
+ async test() {
+ let documentNode = await WI.domManager.requestDocument();
+ let nodeId = await documentNode.querySelector(selector);
+ let domNode = await WI.domManager.nodeForId(nodeId);
+ InspectorTest.assert(domNode, `Should find DOM Node for selector '${selector}'.`);
+
+ let cssStyles = WI.cssManager.stylesForNode(domNode);
+ await cssStyles.refreshIfNeeded();
+
+ let styleGroups = cssStyles.variableStylesByType;
+ for (let {groupType, variables} of expected) {
+ let propertyNames = styleGroups.get(groupType).properties.map(property => property.name);
+ InspectorTest.expectTrue(styleGroups.has(groupType), `Should have "${groupType}" variables group.`);
+ InspectorTest.expectShallowEqual(propertyNames.sort(), variables.sort(), "Group should include all expected variables.");
+ }
+ },
+ });
+ }
+
+ addTestCase({
+ name: "DOMNodeStyles.variableStylesByType.Colors",
+ description: "Check that variables with color values are correctly identified.",
+ selector: "#colors",
+ expected: [
+ {
+ groupType: WI.DOMNodeStyles.VariablesGroupType.Colors,
+ variables: ["--colorName", "--colorHEX", "--colorRGB", "--colorRGBA", "--colorHSL", "--colorHSLA"],
+ },
+ ],
+ });
+
+ addTestCase({
+ name: "DOMNodeStyles.variableStylesByType.Dimensions",
+ description: "Check that variables with dimension values are correctly identified.",
+ selector: "#dimensions",
+ expected: [
+ {
+ groupType: WI.DOMNodeStyles.VariablesGroupType.Dimensions,
+ variables: ["--dimensionPX", "--dimensionPercent", "--dimensionFloat", "--dimensionNegative", "--dimensionNegativeFloat"],
+ },
+ ],
+ });
+
+ addTestCase({
+ name: "DOMNodeStyles.variableStylesByType.Numbers",
+ description: "Check that variables with number values are correctly identified.",
+ selector: "#numbers",
+ expected: [
+ {
+ groupType: WI.DOMNodeStyles.VariablesGroupType.Numbers,
+ variables: ["--number", "--numberFloat", "--numberNegative", "--numberNegativeFloat"],
+ },
+ ],
+ });
+
+ addTestCase({
+ name: "DOMNodeStyles.variableStylesByType.Other",
+ description: "Check that variables with values with unmatched types are placed in the fallback group.",
+ selector: "#other",
+ expected: [
+ {
+ groupType: WI.DOMNodeStyles.VariablesGroupType.Other,
+ variables: ["--shadow", "--font-family", "--font-shorthand", "--keyword"],
+ },
+ ],
+ });
+
+ addTestCase({
+ name: "DOMNodeStyles.variableStylesByType.Mixed",
+ description: "Check that all type groups have variables allocated.",
+ selector: "#mixed",
+ expected: [
+ {
+ groupType: WI.DOMNodeStyles.VariablesGroupType.Colors,
+ variables: ["--color"],
+ },
+ {
+ groupType: WI.DOMNodeStyles.VariablesGroupType.Dimensions,
+ variables: ["--dimension"],
+ },
+ {
+ groupType: WI.DOMNodeStyles.VariablesGroupType.Numbers,
+ variables: ["--number"],
+ },
+ {
+ groupType: WI.DOMNodeStyles.VariablesGroupType.Other,
+ variables: ["--font-family"],
+ },
+ ],
+ });
+
+ suite.runTestCasesAndFinish();
+}
+</script>
+<style>
+
+div#colors {
+ --colorName: black;
+ --colorHEX: #000;
+ --colorRGB: rgb(0, 0, 0);
+ --colorRGBA: rgba(0, 0, 0, 1);
+ --colorHSL: hsl(0, 0%, 0%);
+ --colorHSLA: hsla(0, 0%, 0%, 1);
+
+ /* should not match any below */
+ --shadow: 1px 1px black;
+ --dimensionPX: 100px;
+ --number: 100;
+}
+
+div#dimensions {
+ --dimensionPX: 100px;
+ --dimensionPercent: 100%;
+ --dimensionFloat: 1.0%;
+ --dimensionNegative: -100px;
+ --dimensionNegativeFloat: -1.0%;
+
+ /* should not match any below */
+ --shadow: 1px 1px black;
+ --color: black;
+ --number: 100;
+ --numberFloat: 1.0;
+ --numberNegativeFloat: -1.0;
+}
+
+div#numbers {
+ --number: 100;
+ --numberFloat: 1.0;
+ --numberNegative: -100;
+ --numberNegativeFloat: -1.0;
+
+ /* should not match any below */
+ --shadow: 1px 1px black;
+ --dimensionPX: 100px;
+ --dimensionPercent: 100%;
+ --dimensionNegative: -100px;
+ --dimensionNegativeFloat: -1.0%;
+}
+
+div#other {
+ --shadow: 1px 1px black;
+ --font-family: sans-serif;
+ --font-shorthand: 16px / 1.6 sans-serif;
+ --keyword: inherit;
+}
+
+div#mixed {
+ --color: black;
+ --dimension: 100px;
+ --number: 100;
+ --font-family: sans-serif;
+}
+
+</style>
+</head>
+<body _onload_="runTest();">
+<p>Test for DOMNodeStyles.variableStylesByType</p>
+<div>
+ <div id="colors"></div>
+ <div id="dimensions"></div>
+ <div id="numbers"></div>
+ <div id="other"></div>
+ <div id="mixed"></div>
+</div>
+</body>
+</html>
\ No newline at end of file
Modified: trunk/Source/WebInspectorUI/ChangeLog (286875 => 286876)
--- trunk/Source/WebInspectorUI/ChangeLog 2021-12-10 22:01:57 UTC (rev 286875)
+++ trunk/Source/WebInspectorUI/ChangeLog 2021-12-10 22:15:52 UTC (rev 286876)
@@ -1,3 +1,87 @@
+2021-12-10 Razvan Caliman <rcali...@apple.com>
+
+ Web Inspector: Computed Panel: Group CSS variables by value type
+ https://bugs.webkit.org/show_bug.cgi?id=233563
+ <rdar://82978905>
+
+ Reviewed by Devin Rousso and Patrick Angle.
+
+ Add the ability to view CSS variables in the Computed styles details sidebar panel
+ groupped by value type in a few sections: "colors", "dimensions", "numbers" and a
+ catch-all group of "other".
+
+ * Localizations/en.lproj/localizedStrings.js:
+ * UserInterface/Models/DOMNodeStyles.js:
+ (WI.DOMNodeStyles):
+ (WI.DOMNodeStyles.prototype.variableStylesByType):
+ Iterate on-demand over all CSS variables found in the node's computed styles
+ and assign each to a group depending on its value type:
+ - color
+ - dimension (number followed by a CSS unit-like string)
+ - number
+ - other
+
+ Additional groups and refinements will come in follow-up patches.
+
+ (WI.DOMNodeStyles.prototype.refresh.fetchedComputedStyle):
+ The map of CSS variable groups gets invalidated when there's a significant
+ change in the node's computed style. This supports the use case where previously
+ empty groups become populated or, conversely, become empty.
+
+ * UserInterface/Views/ComputedStyleDetailsPanel.js:
+ (WI.ComputedStyleDetailsPanel):
+ (WI.ComputedStyleDetailsPanel.prototype.refresh):
+ (WI.ComputedStyleDetailsPanel.prototype.applyFilter):
+ (WI.ComputedStyleDetailsPanel.prototype.initialLayout):
+ No longer generate the elements for laying out CSS variables during `initialLayout()`
+ but handle them during `layout()`. This support mutating the DOM for laying out
+ either one top-level list of CSS variables (ungrouped) or multiple lists of CSS variable
+ groups depeding on the grouping mode selected at runtime.
+
+ * UserInterface/Views/ComputedStyleDetailsPanel.css:
+ (.sidebar > .panel.details.css-style > .content > .computed .details-section > .content):
+ Ensure both top-level and nested details sections overwrite styles. CSS variables groups are in nested details sections.
+
+ (.sidebar > .panel.details.css-style > .content > .computed .details-section.computed-style-variables .computed-property-item):
+ Adapt stylesheet to account for using `WI.ComputedStyleSection` instead of `WI.SpreadsheetCSSStyleDeclarationEditor`
+
+ (.sidebar > .panel.details.css-style > .content > .computed > .details-section.computed-style-variables .scope-bar.computed-style-variables-grouping-mode):
+ (.sidebar > .panel.details.css-style > .content > .computed > .details-section.computed-style-variables .scope-bar.computed-style-variables-grouping-mode.default-item-selected:not(:hover)):
+ (.sidebar > .panel.details.css-style > .content > .computed > .details-section.computed-style-variables .scope-bar.computed-style-variables-grouping-mode.default-item-selected:hover):
+ Reuse the visual treatment from SourcesNavigationSidebarPanel.css to avoid highlighting the default grouping mode scope bar item.
+
+ (.sidebar > .panel.details.css-style > .content > .computed > .details-section > .content): Deleted.
+ (.sidebar > .panel.details.css-style > .content > .computed .property): Deleted.
+
+ (WI.ComputedStyleDetailsPanel.prototype.layout):
+ Skip destroying and rebuilding sections whose data sources change during
+ `WI.ComputedStyleDetailsPanel.refresh()` and which handle layout internally.
+ We need to remove and rebuild just the sections for CSS variables because
+ layout is requested in response to changing the CSS variables grouping mode.
+
+ (WI.ComputedStyleDetailsPanel.prototype._createVariablesStyleSection):
+ Replaces the use of `WI.SpreadsheetCSSStyleDeclarationEditor` for rendering CSS variables with
+ `WI.ComputedStyleSection` which is already used for rendering CSS properties.
+ It's a lighter-weight View that's fit for purpose.
+
+ (WI.ComputedStyleDetailsPanel.prototype._renderVariablesStyleSectionGroup):
+ Use a generic renderer for CSS variable sections that can be reused for any group type.
+
+ (WI.ComputedStyleDetailsPanel.prototype._handleDetailsSectionCollapsedStateChanged):
+ Generalize handling collapsed state change events for all sections, current and future.
+
+ (WI.ComputedStyleDetailsPanel.prototype._handleEditorFilterApplied):
+ Generalize handling filtering events for all sections, current and future.
+
+ (WI.ComputedStyleDetailsPanel.prototype._handleVariablesGroupingModeScopeBarSelectionChanged):
+ (WI.ComputedStyleDetailsPanel.prototype._handleVariablesGroupingSettingChanged):
+ (WI.ComputedStyleDetailsPanel.prototype._handlePropertiesSectionCollapsedStateChanged): Deleted.
+ (WI.ComputedStyleDetailsPanel.prototype._handleVariablesSectionCollapsedStateChanged): Deleted.
+ * UserInterface/Views/ComputedStyleSection.js:
+ (WI.ComputedStyleSection):
+ Change the default value of `_styleTraces` to null instead of an empty array so that
+ `WI.ComputedStyleSection.layout()` doesn't attempt to access it like a `Map`.
+
2021-12-10 Nikita Vasilyev <nvasil...@apple.com>
Web Inspector: Add a swatch for align-items and align-self
Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (286875 => 286876)
--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2021-12-10 22:01:57 UTC (rev 286875)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2021-12-10 22:15:52 UTC (rev 286876)
@@ -244,6 +244,8 @@
localizedStrings["Busy"] = "Busy";
localizedStrings["By Path"] = "By Path";
localizedStrings["By Type"] = "By Type";
+/* Label for button to show CSS variables grouped by type */
+localizedStrings["By Type @ Computed Style variables grouping mode"] = "By Type";
localizedStrings["Byte Range %s\u2013%s"] = "Byte Range %s\u2013%s";
localizedStrings["Bytes Received"] = "Bytes Received";
localizedStrings["Bytes Sent"] = "Bytes Sent";
@@ -340,6 +342,8 @@
localizedStrings["Collapse blackboxed call frames @ Experimental Settings"] = "Collapse blackboxed call frames";
localizedStrings["Collapse columns"] = "Collapse columns";
localizedStrings["Collect garbage"] = "Collect garbage";
+/* Section header for the group of CSS variables with colors as values */
+localizedStrings["Colors @ Computed Style variables section"] = "Colors";
localizedStrings["Comment"] = "Comment";
/* Property value for `font-variant-ligatures: common-ligatures`. */
localizedStrings["Common @ Font Details Sidebar Property Value"] = "Common";
@@ -469,6 +473,8 @@
/* Property value for `font-variant-numeric: diagonal-fractions`. */
localizedStrings["Diagonal Fractions @ Font Details Sidebar Property Value"] = "Diagonal Fractions";
localizedStrings["Dimensions"] = "Dimensions";
+/* Section header for the group of CSS variables with dimensions as values */
+localizedStrings["Dimensions @ Computed style variables section"] = "Dimensions";
localizedStrings["Disable Audit"] = "Disable Audit";
localizedStrings["Disable Breakpoint"] = "Disable Breakpoint";
localizedStrings["Disable Breakpoints"] = "Disable Breakpoints";
@@ -1007,6 +1013,8 @@
localizedStrings["Not found"] = "Not found";
/* Title of icon indicating that the selected audit has not been run yet. */
localizedStrings["Not yet run @ Audit Tab - Test Case"] = "Not yet run";
+/* Section header for the group of CSS variables with numbers as values */
+localizedStrings["Numbers @ Computed Style variables section"] = "Numbers";
/* Property title for `font-variant-numeric`. */
localizedStrings["Numeric @ Font Details Sidebar Property"] = "Numeric";
localizedStrings["Object Graph"] = "Object Graph";
@@ -1041,6 +1049,8 @@
localizedStrings["Originally %s"] = "Originally %s";
localizedStrings["Originator"] = "Originator";
localizedStrings["Other"] = "Other";
+/* Section header for the generic group of CSS variables */
+localizedStrings["Other @ Computed Style variables section"] = "Other";
localizedStrings["Other Issue"] = "Other Issue";
localizedStrings["Other Threads"] = "Other Threads";
localizedStrings["Other: %s"] = "Other: %s";
@@ -1589,6 +1599,10 @@
/* Break (pause) on uncaught (unhandled) exceptions */
localizedStrings["Uncaught Exceptions @ _javascript_ Breakpoint"] = "Uncaught Exceptions";
localizedStrings["Undefined custom element"] = "Undefined custom element";
+/* Label for button to show CSS variables ungrouped */
+localizedStrings["Ungrouped @ Computed Style variables grouping mode"] = "Ungrouped";
+/* Section header for ungrouped CSS variables */
+localizedStrings["Ungrouped @ Computed Style variables section"] = "Ungrouped";
/* Property value for `font-variant-capitals: unicase`. */
localizedStrings["Unicase @ Font Details Sidebar Property Value"] = "Unicase";
localizedStrings["Unique"] = "Unique";
Modified: trunk/Source/WebInspectorUI/UserInterface/Models/DOMNodeStyles.js (286875 => 286876)
--- trunk/Source/WebInspectorUI/UserInterface/Models/DOMNodeStyles.js 2021-12-10 22:01:57 UTC (rev 286875)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/DOMNodeStyles.js 2021-12-10 22:15:52 UTC (rev 286876)
@@ -48,6 +48,7 @@
this._propertyNameToEffectivePropertyMap = {};
this._usedCSSVariables = new Set;
this._allCSSVariables = new Set;
+ this._variableStylesByType = null;
this._pendingRefreshTask = null;
this.refresh();
@@ -144,6 +145,67 @@
return WI.DOMNodeStyles.uniqueOrderedStyles(this._orderedStyles);
}
+ get variableStylesByType()
+ {
+ if (this._variableStylesByType)
+ return this._variableStylesByType;
+
+ let properties = this._computedStyle?.properties;
+ if (!properties)
+ return new Map;
+
+ // Will iterate in order through type checkers for each CSS variable to identify its type.
+ // The catch-all "other" must always be last.
+ const typeCheckFunctions = [
+ {
+ type: WI.DOMNodeStyles.VariablesGroupType.Colors,
+ checker: (property) => WI.Color.fromString(property.value),
+ },
+ {
+ type: WI.DOMNodeStyles.VariablesGroupType.Dimensions,
+ // FIXME: <https://webkit.org/b/233576> build RegExp from `WI.CSSCompletions.lengthUnits`.
+ checker: (property) => /^-?\d+(\.\d+)?\D+$/.test(property.value),
+ },
+ {
+ type: WI.DOMNodeStyles.VariablesGroupType.Numbers,
+ checker: (property) => /^-?\d+(\.\d+)?$/.test(property.value),
+ },
+ {
+ type: WI.DOMNodeStyles.VariablesGroupType.Other,
+ checker: (property) => true,
+ },
+ ];
+
+ let variablesForType = {};
+ for (let property of properties) {
+ if (!property.isVariable)
+ continue;
+
+ for (let {type, checker} of typeCheckFunctions) {
+ if (checker(property)) {
+ variablesForType[type] ||= [];
+ variablesForType[type].push(property);
+ break;
+ }
+ }
+ }
+
+ this._variableStylesByType = new Map;
+ for (let {type} of typeCheckFunctions) {
+ if (!variablesForType[type]?.length)
+ continue;
+
+ const ownerStyleSheet = null;
+ const id = null;
+ const inherited = false;
+ const text = null;
+ let style = new WI.CSSStyleDeclaration(this, ownerStyleSheet, id, WI.CSSStyleDeclaration.Type.Computed, this._node, inherited, text, variablesForType[type]);
+ this._variableStylesByType.set(type, style);
+ }
+
+ return this._variableStylesByType;
+ }
+
refreshIfNeeded()
{
if (this._pendingRefreshTask)
@@ -315,6 +377,9 @@
}
}
+ if (significantChange)
+ this._variableStylesByType = null;
+
this._previousStylesMap = null;
this._includeUserAgentRulesOnNextRefresh = false;
@@ -992,3 +1057,11 @@
NeedsRefresh: "dom-node-styles-needs-refresh",
Refreshed: "dom-node-styles-refreshed"
};
+
+WI.DOMNodeStyles.VariablesGroupType = {
+ Ungrouped: "ungrouped",
+ Colors: "colors",
+ Dimensions: "dimensions",
+ Numbers: "numbers",
+ Other: "other",
+};
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ComputedStyleDetailsPanel.css (286875 => 286876)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ComputedStyleDetailsPanel.css 2021-12-10 22:01:57 UTC (rev 286875)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ComputedStyleDetailsPanel.css 2021-12-10 22:15:52 UTC (rev 286876)
@@ -32,7 +32,8 @@
background-color: var(--background-color);
}
-.sidebar > .panel.details.css-style > .content > .computed > .details-section > .content {
+/* Ensure that font is overwritten for both top-level and nested details sections. */
+.sidebar > .panel.details.css-style > .content > .computed .details-section > .content {
font: 12px -webkit-system-font, sans-serif;
}
@@ -45,8 +46,7 @@
padding-bottom: 3px;
}
-.sidebar > .panel.details.css-style > .content > .computed .property {
- position: relative;
+.sidebar > .panel.details.css-style > .content > .computed .details-section.computed-style-variables .computed-property-item {
text-indent: -13px; /* width of "--" in `11px Menlo` */
}
@@ -59,3 +59,18 @@
.sidebar > .panel.details.css-style > .content > .computed > .details-section.computed-style-variables .property:not(:hover) .go-to-arrow {
display: none;
}
+
+.sidebar > .panel.details.css-style > .content > .computed > .details-section.computed-style-variables .scope-bar.computed-style-variables-grouping-mode {
+ margin-top: -1px;
+ font-weight: normal;
+}
+
+.sidebar > .panel.details.css-style > .content > .computed > .details-section.computed-style-variables .scope-bar.computed-style-variables-grouping-mode.default-item-selected:not(:hover) {
+ --scope-bar-text-color-override: var(--text-color);
+ --scope-bar-background-color-override: transparent;
+ --scope-bar-border-color-override: transparent;
+}
+
+.sidebar > .panel.details.css-style > .content > .computed > .details-section.computed-style-variables .scope-bar.computed-style-variables-grouping-mode.default-item-selected:hover {
+ --scope-bar-background-opacity-override: 0.5;
+}
\ No newline at end of file
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ComputedStyleDetailsPanel.js (286875 => 286876)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ComputedStyleDetailsPanel.js 2021-12-10 22:01:57 UTC (rev 286875)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ComputedStyleDetailsPanel.js 2021-12-10 22:15:52 UTC (rev 286876)
@@ -33,8 +33,32 @@
this._computedStylePreferShorthandsSetting = new WI.Setting("computed-style-use-shorthands", false);
this._filterText = null;
+ this._detailsSectionByStyleSectionMap = new Map;
+ this._variablesStyleSectionForGroupTypeMap = new Map;
}
+ // Static
+
+ static displayNameForVariablesGroupType(variablesGroupType)
+ {
+ switch (variablesGroupType) {
+ case WI.DOMNodeStyles.VariablesGroupType.Colors:
+ return WI.UIString("Colors", "Colors @ Computed Style variables section", "Section header for the group of CSS variables with colors as values");
+
+ case WI.DOMNodeStyles.VariablesGroupType.Dimensions:
+ return WI.UIString("Dimensions", "Dimensions @ Computed style variables section", "Section header for the group of CSS variables with dimensions as values");
+
+ case WI.DOMNodeStyles.VariablesGroupType.Numbers:
+ return WI.UIString("Numbers", "Numbers @ Computed Style variables section", "Section header for the group of CSS variables with numbers as values");
+
+ case WI.DOMNodeStyles.VariablesGroupType.Other:
+ return WI.UIString("Other", "Other @ Computed Style variables section", "Section header for the generic group of CSS variables");
+ }
+
+ console.assert(false, "Unknown group type", variablesGroupType);
+ return "";
+ }
+
// Public
get minimumWidth()
@@ -42,6 +66,12 @@
return this._boxModelDiagramRow?.minimumWidth ?? 0;
}
+ get variablesGroupingMode()
+ {
+ console.assert(this._variablesGroupingModeScopeBar.selectedItems[0], "No selected variables grouping mode", this._variablesGroupingModeScopeBar.selectedItems);
+ return this._variablesGroupingModeScopeBar.selectedItems[0].id;
+ }
+
refresh(significantChange)
{
// We only need to do a rebuild on significant changes. Other changes are handled
@@ -54,12 +84,33 @@
this._computedStyleSection.styleTraces = this._computePropertyTraces(this.nodeStyles.uniqueOrderedStyles);
this._computedStyleSection.style = this.nodeStyles.computedStyle;
this._propertiesSection.element.classList.toggle("hidden", !this._computedStyleSection.propertiesToRender.length);
+ this._boxModelDiagramRow.nodeStyles = this.nodeStyles;
- this._variablesTextEditor.style = this.nodeStyles.computedStyle;
- this._variablesSection.element.classList.toggle("hidden", !this._variablesTextEditor.propertiesToRender.length);
+ let styleGroups = new Map;
- this._boxModelDiagramRow.nodeStyles = this.nodeStyles;
+ switch (this.variablesGroupingMode) {
+ case WI.ComputedStyleDetailsPanel.VariablesGroupingMode.Ungrouped:
+ styleGroups.set(this._variablesStyleSectionForGroupTypeMap.get(WI.DOMNodeStyles.VariablesGroupType.Ungrouped), this.nodeStyles.computedStyle);
+ break;
+ case WI.ComputedStyleDetailsPanel.VariablesGroupingMode.ByType:
+ styleGroups = this.nodeStyles.variableStylesByType;
+ break;
+ }
+
+ for (let [type, style] of styleGroups) {
+ let variablesStyleSection = this._variablesStyleSectionForGroupTypeMap.get(type);
+ if (!variablesStyleSection) {
+ this.needsLayout();
+ break;
+ }
+
+ variablesStyleSection.style = style;
+
+ let detailsSection = this._detailsSectionByStyleSectionMap.get(variablesStyleSection);
+ detailsSection.element.classList.toggle("hidden", !variablesStyleSection.propertiesToRender.length);
+ }
+
if (this._filterText)
this.applyFilter(this._filterText);
@@ -73,8 +124,8 @@
if (!this.didInitialLayout)
return;
- this._computedStyleSection.applyFilter(filterText);
- this._variablesTextEditor.applyFilter(filterText);
+ for (let styleSection of this._detailsSectionByStyleSectionMap.keys())
+ styleSection.applyFilter(filterText);
}
// SpreadsheetCSSStyleDeclarationEditor delegate
@@ -118,28 +169,27 @@
let propertiesRow = new WI.DetailsSectionRow;
let propertiesGroup = new WI.DetailsSectionGroup([propertiesRow]);
this._propertiesSection = new WI.DetailsSection("computed-style-properties", WI.UIString("Properties"), [propertiesGroup], propertyFiltersElement);
- this._propertiesSection.addEventListener(WI.DetailsSection.Event.CollapsedStateChanged, this._handlePropertiesSectionCollapsedStateChanged, this);
+ this._propertiesSection.addEventListener(WI.DetailsSection.Event.CollapsedStateChanged, this._handleDetailsSectionCollapsedStateChanged, this);
this.addSubview(this._computedStyleSection);
propertiesRow.element.appendChild(this._computedStyleSection.element);
+ this._detailsSectionByStyleSectionMap.set(this._computedStyleSection, this._propertiesSection);
- this._variablesTextEditor = new WI.SpreadsheetCSSStyleDeclarationEditor(this);
- this._variablesTextEditor.propertyVisibilityMode = WI.SpreadsheetCSSStyleDeclarationEditor.PropertyVisibilityMode.HideNonVariables;
- this._variablesTextEditor.hideFilterNonMatchingProperties = true;
- this._variablesTextEditor.sortPropertiesByName = true;
- this._variablesTextEditor.addEventListener(WI.SpreadsheetCSSStyleDeclarationEditor.Event.FilterApplied, this._handleEditorFilterApplied, this);
- this._variablesTextEditor.element.dir = "ltr";
+ let variablesGroupingModeScopeBarItems = [
+ new WI.ScopeBarItem(WI.ComputedStyleDetailsPanel.VariablesGroupingMode.Ungrouped, WI.UIString("Ungrouped", "Ungrouped @ Computed Style variables grouping mode", "Label for button to show CSS variables ungrouped")),
+ new WI.ScopeBarItem(WI.ComputedStyleDetailsPanel.VariablesGroupingMode.ByType, WI.UIString("By Type", "By Type @ Computed Style variables grouping mode", "Label for button to show CSS variables grouped by type"))
+ ];
- let variablesRow = new WI.DetailsSectionRow;
- let variablesGroup = new WI.DetailsSectionGroup([variablesRow]);
- this._variablesSection = new WI.DetailsSection("computed-style-variables", WI.UIString("Variables"), [variablesGroup]);
- this._variablesSection.addEventListener(WI.DetailsSection.Event.CollapsedStateChanged, this._handleVariablesSectionCollapsedStateChanged, this);
+ const shouldGroupNonExclusiveItems = true;
+ this._variablesGroupingModeScopeBar = new WI.ScopeBar("computed-style-variables-grouping-mode", variablesGroupingModeScopeBarItems, variablesGroupingModeScopeBarItems[0], shouldGroupNonExclusiveItems);
+ this._variablesGroupingModeScopeBar.addEventListener(WI.ScopeBar.Event.SelectionChanged, this._handleVariablesGroupingModeScopeBarSelectionChanged, this);
- this.addSubview(this._variablesTextEditor);
+ this._variablesRow = new WI.DetailsSectionRow;
+ let variablesGroup = new WI.DetailsSectionGroup([this._variablesRow]);
+ this._variablesSection = new WI.DetailsSection("computed-style-variables", WI.UIString("Variables"), [variablesGroup], this._variablesGroupingModeScopeBar.element);
+ this._variablesSection.addEventListener(WI.DetailsSection.Event.CollapsedStateChanged, this._handleDetailsSectionCollapsedStateChanged, this);
- variablesRow.element.appendChild(this._variablesTextEditor.element);
-
this.element.appendChild(this._propertiesSection.element);
this.element.appendChild(this._variablesSection.element);
@@ -147,6 +197,46 @@
this._computedStylePreferShorthandsSetting.addEventListener(WI.Setting.Event.Changed, this._handleUseShorthandsSettingChanged, this);
}
+ layout()
+ {
+ super.layout();
+
+ for (let [styleSection, detailsSection] of this._detailsSectionByStyleSectionMap) {
+ // The details section for computed properties is updated in-place by WI.ComputedStyleDetailsPanel.refresh().
+ if (styleSection === this._computedStyleSection)
+ continue;
+
+ // WI.ComputedStyleSection is a view but its element is attached to a WI.DetailsSection which isn't. Reparent it before removing.
+ // FIXME: <https://webkit.org/b/152269> - Web Inspector: Convert DetailsSection classes to use View
+ this.element.appendChild(styleSection.element);
+ this.removeSubview(styleSection);
+ styleSection.element.remove();
+
+ // The top-level details section for variables needs to be preserved because it's the host of nested details sections for variables groups.
+ if (detailsSection === this._variablesSection)
+ continue;
+
+ detailsSection.element.remove();
+ this._detailsSectionByStyleSectionMap.delete(styleSection);
+ }
+
+ this._variablesStyleSectionForGroupTypeMap.clear();
+
+ switch (this.variablesGroupingMode) {
+ case WI.ComputedStyleDetailsPanel.VariablesGroupingMode.Ungrouped:
+ this._renderVariablesStyleSectionGroup(this.nodeStyles.computedStyle, WI.DOMNodeStyles.VariablesGroupType.Ungrouped);
+ break;
+
+ case WI.ComputedStyleDetailsPanel.VariablesGroupingMode.ByType:
+ for (let [type, style] of this.nodeStyles.variableStylesByType)
+ this._renderVariablesStyleSectionGroup(style, type, WI.ComputedStyleDetailsPanel.displayNameForVariablesGroupType(type));
+ break;
+ }
+
+ if (this._filterText)
+ this.applyFilter(this._filterText);
+ }
+
filterDidChange(filterBar)
{
this.applyFilter(filterBar.filters.text);
@@ -154,6 +244,35 @@
// Private
+ _renderVariablesStyleSectionGroup(style, groupType, label)
+ {
+ let variablesStyleSection = new WI.ComputedStyleSection(this);
+ variablesStyleSection.propertyVisibilityMode = WI.ComputedStyleSection.PropertyVisibilityMode.HideNonVariables;
+ variablesStyleSection.hideFilterNonMatchingProperties = true;
+ variablesStyleSection.addEventListener(WI.ComputedStyleSection.Event.FilterApplied, this._handleEditorFilterApplied, this);
+ variablesStyleSection.element.dir = "ltr";
+ variablesStyleSection.style = style;
+
+ this.addSubview(variablesStyleSection);
+
+ let detailsSection;
+ if (!label) {
+ this._variablesRow.element.appendChild(variablesStyleSection.element);
+ detailsSection = this._variablesSection;
+ } else {
+ let detailsSectionRow = new WI.DetailsSectionRow;
+ let detailsSectionGroup = new WI.DetailsSectionGroup([detailsSectionRow]);
+ detailsSection = new WI.DetailsSection(`computed-style-variables-group-${groupType}`, label, [detailsSectionGroup]);
+ detailsSection.addEventListener(WI.DetailsSection.Event.CollapsedStateChanged, this._handleDetailsSectionCollapsedStateChanged, this);
+
+ detailsSectionRow.element.appendChild(variablesStyleSection.element);
+ this._variablesRow.element.appendChild(detailsSection.element);
+ }
+
+ this._detailsSectionByStyleSectionMap.set(variablesStyleSection, detailsSection);
+ this._variablesStyleSectionForGroupTypeMap.set(groupType, variablesStyleSection);
+ }
+
_computePropertyTraces(orderedDeclarations)
{
let result = new Map();
@@ -171,28 +290,23 @@
return result;
}
- _handlePropertiesSectionCollapsedStateChanged(event)
+ _handleEditorFilterApplied(event)
{
- if (event && event.data && !event.data.collapsed)
- this._computedStyleSection.needsLayout();
+ let section = this._detailsSectionByStyleSectionMap.get(event.target);
+ section?.element.classList.toggle("hidden", !event.data.matches);
}
- _handleVariablesSectionCollapsedStateChanged(event)
+ _handleDetailsSectionCollapsedStateChanged(event)
{
- if (event && event.data && !event.data.collapsed)
- this._variablesTextEditor.needsLayout();
- }
+ if (event.data.collapsed)
+ return;
- _handleEditorFilterApplied(event)
- {
- let section = null;
- if (event.target === this._computedStyleSection)
- section = this._propertiesSection;
- else if (event.target === this._variablesTextEditor)
- section = this._variablesSection;
-
- if (section)
- section.element.classList.toggle("hidden", !event.data.matches);
+ for (let [styleSection, detailsSection] of this._detailsSectionByStyleSectionMap) {
+ if (event.target === detailsSection) {
+ styleSection.needsLayout();
+ return;
+ }
+ }
}
_handleShowAllSettingChanged(event)
@@ -204,6 +318,15 @@
{
this._computedStyleSection.showsShorthandsInsteadOfLonghands = this._computedStylePreferShorthandsSetting.value;
}
+
+ _handleVariablesGroupingModeScopeBarSelectionChanged(event)
+ {
+ this.needsLayout();
+ }
};
WI.ComputedStyleDetailsPanel.StyleClassName = "computed";
+WI.ComputedStyleDetailsPanel.VariablesGroupingMode = {
+ Ungrouped: "ungrouped",
+ ByType: "by-type",
+};
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ComputedStyleSection.js (286875 => 286876)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ComputedStyleSection.js 2021-12-10 22:01:57 UTC (rev 286875)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ComputedStyleSection.js 2021-12-10 22:15:52 UTC (rev 286876)
@@ -34,7 +34,7 @@
this._delegate = delegate;
this._style = null;
- this._styleTraces = [];
+ this._styleTraces = null;
this._propertyViews = [];
this._showsImplicitProperties = false;