Skip to content

Commit 9ae74b6

Browse files
danilsomsikovdevtools-frontend-scoped@luci-project-accounts.iam.gserviceaccount.com
authored andcommitted
Use Lit rendering to manage widget host element.
This change introduces a new wrapper around Lit's `render` function that allows managing properties of the container element, such as its attributes, classes, and event listeners. The new `render` function in `front_end/ui/lit/render.ts` accepts `attributes`, `classes`, and `listeners` to be applied to the container as additional options. The function keeps track of previously applied properties and correctly adds, removes, or updates them on subsequent render calls, effectively "adopting" the container element. This new capability is used to refactor several UI components that do not use a shadow DOM. Previously, these components passed properties like CSS classes and `jslog` attributes to the `UI.Widget` constructor. This change moves this logic into the component's render call, co-locating it with the Lit template that defines the component's internal DOM. This makes the rendering logic more self-contained and easier to reason about. Bug: 407751340 Change-Id: I5427bcc7a28f596227af8aeff799825635069617 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/7716198 Reviewed-by: Philip Pfaffe <pfaffe@chromium.org> Commit-Queue: Danil Somsikov <dsv@chromium.org> Auto-Submit: Danil Somsikov <dsv@chromium.org>
1 parent a4c193c commit 9ae74b6

File tree

12 files changed

+274
-30
lines changed

12 files changed

+274
-30
lines changed

config/gni/devtools_grd_files.gni

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2773,6 +2773,7 @@ grd_files_unbundled_sources = [
27732773
"front_end/ui/legacy/treeoutline.css.js",
27742774
"front_end/ui/legacy/viewContainers.css.js",
27752775
"front_end/ui/lit/i18n-template.js",
2776+
"front_end/ui/lit/render.js",
27762777
"front_end/ui/lit/strip-whitespace.js",
27772778
"front_end/ui/visual_logging/Debugging.js",
27782779
"front_end/ui/visual_logging/DomState.js",

front_end/panels/application/components/ProtocolHandlersView.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ const DEFAULT_VIEW: View = (input, _output, target) => {
150150
</div>
151151
${renderProtocolTest(input.protocolHandler, input.queryInputState, input.protocolSelectHandler,
152152
input.queryInputChangeHandler, input.testProtocolClickHandler)}
153-
`, target);
153+
`, target, {container: {classes: ['vbox']}});
154154
// clang-format on
155155
};
156156

@@ -172,7 +172,7 @@ export class ProtocolHandlersView extends UI.Widget.Widget {
172172
#view: View;
173173

174174
constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
175-
super(element, {useShadowDom: false, classes: ['vbox']});
175+
super(element, {useShadowDom: false});
176176
this.#view = view;
177177
}
178178

front_end/panels/network/RequestConditionsDrawer.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,9 @@ interface AffectedCountViewInput {
291291
}
292292
type AffectedCountView = (input: AffectedCountViewInput, output: object, target: HTMLElement) => void;
293293
export const AFFECTED_COUNT_DEFAULT_VIEW: AffectedCountView = (input, output, target) => {
294-
render(html`${i18nString(UIStrings.dAffected, {PH1: input.count})}`, target);
294+
render(
295+
html`${i18nString(UIStrings.dAffected, {PH1: input.count})}`, target,
296+
{container: {classes: ['blocked-url-count']}});
295297
};
296298

297299
function matchesUrl(conditions: SDK.NetworkManager.RequestCondition, url: string): boolean {
@@ -304,7 +306,7 @@ export class AffectedCountWidget extends UI.Widget.Widget {
304306
#lookUpRequestCount?: (condition: SDK.NetworkManager.RequestCondition) => number;
305307

306308
constructor(target?: HTMLElement, view = AFFECTED_COUNT_DEFAULT_VIEW) {
307-
super(target, {classes: ['blocked-url-count']});
309+
super(target);
308310
this.#view = view;
309311
}
310312

front_end/panels/network/RequestPayloadView.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,13 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
289289
</ul>
290290
</li>
291291
</ul>
292-
`}></devtools-tree>
293-
`, target);
292+
`}></devtools-tree>`, target, {
293+
container: {
294+
classes: ['request-payload-view'],
295+
attributes: {
296+
jslog: `${VisualLogging.pane('payload').track({resize: true})}`,
297+
},
298+
}});
294299
// clang-format on
295300
};
296301

@@ -305,7 +310,7 @@ export class RequestPayloadView extends UI.Widget.VBox {
305310
#viewQueryParamSource = false;
306311

307312
constructor(target?: HTMLElement, view = DEFAULT_VIEW) {
308-
super({jslog: `${VisualLogging.pane('payload').track({resize: true})}`, classes: ['request-payload-view']});
313+
super();
309314
this.#view = view;
310315
}
311316

front_end/panels/network/RequestTimingView.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -407,9 +407,9 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
407407
}
408408
}
409409

410-
render(
411-
// clang-format off
412-
html`<style>${networkingTimingTableStyles}</style>
410+
// clang-format off
411+
render(html`
412+
<style>${networkingTimingTableStyles}</style>
413413
<table
414414
class=${classes}
415415
jslog=${VisualLogging.pane('timing').track({
@@ -532,9 +532,8 @@ ${uiI18n.getFormatLocalizedStringTemplate(str_, UIStrings.duringDevelopmentYouCa
532532
html`<devtools-link href="https://web.dev/custom-metrics/#server-timing-api" .jslogContext=${'server-timing-api'}>${i18nString(UIStrings.theServerTimingApi)}</devtools-link>`})}
533533
</td>
534534
</tr>` : nothing}
535-
</table>`,
536-
// clang-format on
537-
target);
535+
</table>`, target, {container: {classes: ['resource-timing-view']}});
536+
// clang-format on
538537
};
539538

540539
export class RequestTimingView extends UI.Widget.VBox {
@@ -543,7 +542,7 @@ export class RequestTimingView extends UI.Widget.VBox {
543542
#lastMinimumBoundary = -1;
544543
readonly #view: View;
545544
constructor(target?: HTMLElement, view = DEFAULT_VIEW) {
546-
super(target, {classes: ['resource-timing-view']});
545+
super(target);
547546
this.#view = view;
548547
}
549548

front_end/panels/performance_monitor/PerformanceMonitor.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -626,8 +626,9 @@ interface ControlPaneInput {
626626
type ControlPaneView = (input: ControlPaneInput, output: object, target: HTMLElement) => void;
627627

628628
const CONTROL_PANE_DEFAULT_VIEW: ControlPaneView = (input, _output, target) => {
629-
render(
630-
input.chartsInfo.map(chartInfo => {
629+
// clang-format off
630+
render(html`
631+
${input.chartsInfo.map(chartInfo => {
631632
const chartName = chartInfo.metrics[0].name;
632633
const active = input.enabledCharts.has(chartName);
633634
const value = input.metricValues.get(chartName) || 0;
@@ -637,8 +638,9 @@ const CONTROL_PANE_DEFAULT_VIEW: ControlPaneView = (input, _output, target) => {
637638
value,
638639
(e: Event) => input.onCheckboxChange(chartName, e),
639640
);
640-
}),
641-
target);
641+
})}
642+
`, target, {container: {classes: ['perfmon-control-pane']}});
643+
// clang-format on
642644
};
643645

644646
export class ControlPane extends UI.Widget.VBox {
@@ -651,7 +653,7 @@ export class ControlPane extends UI.Widget.VBox {
651653
readonly #view: ControlPaneView;
652654

653655
constructor(element: HTMLElement, view = CONTROL_PANE_DEFAULT_VIEW) {
654-
super(element, {useShadowDom: false, classes: ['perfmon-control-pane']});
656+
super(element, {useShadowDom: false});
655657
this.#view = view;
656658

657659
this.#enabledChartsSetting = Common.Settings.Settings.instance().createSetting(

front_end/ui/legacy/EmptyWidget.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const DEFAULT_VIEW: View = (input, output, target) => {
4949
${input.link ? html`<devtools-link href=${input.link} jslogContext=${'learn-more'}>${i18nString(UIStrings.learnMore)}</devtools-link>` : ''}
5050
</div>
5151
${input.extraElements}
52-
</div>`, target);
52+
</div>`, target, {container: {classes: ['empty-view-scroller']}});
5353
// clang-format on
5454
};
5555

@@ -66,7 +66,7 @@ export class EmptyWidget extends VBox {
6666
if (!element && headerOrElement instanceof HTMLElement) {
6767
element = headerOrElement;
6868
}
69-
super(element, {classes: ['empty-view-scroller']});
69+
super(element);
7070
this.#header = header;
7171
this.#text = text;
7272
this.#link = undefined;

front_end/ui/legacy/components/source_frame/XMLView.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -191,19 +191,24 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
191191
}
192192

193193
// clang-format off
194-
render(
195-
html`
194+
render(html`
196195
<style>${xmlViewStyles}</style>
197196
<style>${xmlTreeStyles}</style>
198197
<devtools-tree
199198
class="shadow-xml-view source-code"
200199
.template=${html`
201200
<ul role="tree">
202-
${input.xml.children().map(node => layOutNode(node))}
201+
${input.xml.children().map(node => layOutNode(node))}
203202
</ul>`}
204-
></devtools-tree>`,
205-
// clang-format on
206-
target);
203+
></devtools-tree>`, target, {
204+
container: {
205+
classes: ['shadow-xml-view', 'source-code'],
206+
attributes: {
207+
jslog: `${VisualLogging.pane('xml-view')}`,
208+
},
209+
},
210+
});
211+
// clang-format on
207212
};
208213

209214
function* children(xmlNode: Node|ParentNode|undefined): Generator<Node> {
@@ -272,7 +277,7 @@ export class XMLView extends UI.Widget.Widget implements UI.SearchableView.Searc
272277
#nextJump: SearchResult|undefined;
273278

274279
constructor(target?: HTMLElement, view: View = DEFAULT_VIEW) {
275-
super(target, {jslog: `${VisualLogging.pane('xml-view')}`, classes: ['shadow-xml-view', 'source-code']});
280+
super(target);
276281
this.#view = view;
277282
}
278283

front_end/ui/lit/BUILD.gn

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import("./visibility.gni")
1010
devtools_ui_module("lit") {
1111
sources = [
1212
"i18n-template.ts",
13+
"render.ts",
1314
"strip-whitespace.ts",
1415
]
1516

@@ -48,8 +49,12 @@ devtools_ui_module("unittests") {
4849

4950
sources = [
5051
"i18n-template.test.ts",
52+
"render.test.ts",
5153
"strip-whitespace.test.ts",
5254
]
5355

54-
deps = [ ":bundle" ]
56+
deps = [
57+
":bundle",
58+
"../../testing",
59+
]
5560
}

front_end/ui/lit/lit.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,17 @@ export {
1414
noChange,
1515
nothing,
1616
type PropertyValues,
17-
render,
1817
StaticHtml,
1918
svg,
2019
type TemplateResult,
2120
} from '../../third_party/lit/lit.js';
2221
export {
2322
i18nTemplate,
2423
} from './i18n-template.js';
24+
export {
25+
render,
26+
type RenderOptions,
27+
} from './render.js';
2528
export {
2629
html,
2730
} from './strip-whitespace.js';

0 commit comments

Comments
 (0)