Skip to content

Commit 0e68ea4

Browse files
Kateryna ProkopenkoDevtools-frontend LUCI CQ
authored andcommitted
[DevToolsUIKit] Deprecate SelectMenu() and <devtools-select-menu>
Bug: 14335836 Change-Id: I851a8d3ff361d742c8cb048982650835826fa0d0 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6578342 Reviewed-by: Liviu Rau <liviurau@chromium.org> Commit-Queue: Kateryna Prokopenko <kprokopenko@chromium.org> Auto-Submit: Kateryna Prokopenko <kprokopenko@chromium.org> Reviewed-by: Alex Rudenko <alexrudenko@chromium.org> Reviewed-by: Kim-Anh Tran <kimanh@chromium.org>
1 parent 856d5f8 commit 0e68ea4

File tree

9 files changed

+112
-1
lines changed

9 files changed

+112
-1
lines changed

docs/styleguide/ux/components.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ button.addEventListener('click', event => onClick(event));
137137
* [Icon
138138
buttons](https://www.figma.com/design/A5iQBBNAe5zPFpJvUzUgW8/CDT-design-kit?node-id=571-616&m=dev)
139139

140-
## Combo Boxes
140+
## Combo Boxes and Single Select menus
141141

142142
![Combo Box component](images/combo-box-variations.png)
143143

@@ -167,6 +167,7 @@ Usage with lit-html:
167167
```js
168168
html`<select aria-label="Choose your champion"
169169
@onchange=${onChange}>
170+
<option hidden value="Choose your champion"></option>
170171
<option jslog=${VisualLogging.item('hamster').track({click: true})}
171172
value="Hamster">Hamster</option>
172173
<option jslog=${VisualLogging.item('mouse').track({click: true})}

eslint.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,7 @@ export default defineConfig([
612612
'rulesdir/no-bound-component-methods': 'error',
613613
'rulesdir/no-adopted-style-sheets': 'error',
614614
'rulesdir/no-customized-builtin-elements': 'error',
615+
'rulesdir/no-deprecated-component-usages': 'error',
615616
'rulesdir/no-self-closing-custom-element-tagnames': 'error',
616617
'rulesdir/no-a-tags-in-lit': 'error',
617618
'rulesdir/check-css-import': 'error',

front_end/panels/recorder/components/RecordingView.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,7 @@ export class RecordingView extends HTMLElement {
844844
const currentConverter = this.#getCurrentConverter();
845845
const converterFormatName = currentConverter?.getFormatName();
846846
// clang-format off
847+
/* eslint-disable rulesdir/no-deprecated-component-usages */
847848
return html`
848849
<devtools-split-view
849850
direction="auto"
@@ -907,6 +908,7 @@ export class RecordingView extends HTMLElement {
907908
</div>
908909
</devtools-split-view>
909910
`;
911+
/* eslint-enable rulesdir/no-deprecated-component-usages */
910912
// clang-format on
911913
}
912914

front_end/panels/timeline/components/CPUThrottlingSelector.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ export class CPUThrottlingSelector extends HTMLElement {
163163
const calibrationLabel = hasCalibratedOnce ? i18nString(UIStrings.recalibrate) : i18nString(UIStrings.calibrate);
164164

165165
// clang-format off
166+
/* eslint-disable rulesdir/no-deprecated-component-usages */
166167
const output = html`
167168
<style>${cpuThrottlingSelectorStyles}</style>
168169
<devtools-select-menu
@@ -206,6 +207,7 @@ export class CPUThrottlingSelector extends HTMLElement {
206207
</devtools-select-menu>
207208
${recommendedInfoEl}
208209
`;
210+
/* eslint-enable rulesdir/no-deprecated-component-usages */
209211
// clang-format on
210212
Lit.render(output, this.#shadow, {host: this});
211213
};

front_end/panels/timeline/components/LiveMetricsView.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ export class LiveMetricsView extends LegacyWrapper.LegacyWrapper.WrappableCompon
687687
// If there is no data at all we should force users to switch pages or reconfigure CrUX.
688688
const shouldDisable = !this.#cruxManager.pageResult?.['url-ALL'] && !this.#cruxManager.pageResult?.['origin-ALL'];
689689

690+
/* eslint-disable rulesdir/no-deprecated-component-usages */
690691
return html`
691692
<devtools-select-menu
692693
id="page-scope-select"
@@ -714,6 +715,7 @@ export class LiveMetricsView extends LegacyWrapper.LegacyWrapper.WrappableCompon
714715
</devtools-menu-item>
715716
</devtools-select-menu>
716717
`;
718+
/* eslint-enable rulesdir/no-deprecated-component-usages */
717719
}
718720

719721
#getDeviceScopeDisplayName(deviceScope: CrUXManager.DeviceScope): string {
@@ -768,6 +770,7 @@ export class LiveMetricsView extends LegacyWrapper.LegacyWrapper.WrappableCompon
768770
const currentDeviceLabel = this.#getLabelForDeviceOption(this.#cruxManager.fieldDeviceOption);
769771

770772
// clang-format off
773+
/* eslint-disable rulesdir/no-deprecated-component-usages */
771774
return html`
772775
<devtools-select-menu
773776
id="device-scope-select"
@@ -793,6 +796,7 @@ export class LiveMetricsView extends LegacyWrapper.LegacyWrapper.WrappableCompon
793796
})}
794797
</devtools-select-menu>
795798
`;
799+
/* eslint-enable rulesdir/no-deprecated-component-usages */
796800
// clang-format on
797801
}
798802

front_end/panels/timeline/components/NetworkThrottlingSelector.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ export class NetworkThrottlingSelector extends HTMLElement {
181181
}
182182

183183
// clang-format off
184+
/* eslint-disable rulesdir/no-deprecated-component-usages */
184185
const output = html`
185186
<style>${networkThrottlingSelectorStyles}</style>
186187
<devtools-select-menu
@@ -231,6 +232,7 @@ export class NetworkThrottlingSelector extends HTMLElement {
231232
</devtools-select-menu>
232233
${recommendedInfoEl}
233234
`;
235+
/* eslint-enable rulesdir/no-deprecated-component-usages */
234236
// clang-format on
235237
Lit.render(output, this.#shadow, {host: this});
236238
};

front_end/ui/components/menus/SelectMenu.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ type TitleCallback = () => Lit.TemplateResult;
7878

7979
const deployMenuArrow = new URL('../../../Images/triangle-down.svg', import.meta.url).toString();
8080

81+
/**
82+
* @deprecated use `<select>` instead.
83+
*/
8184
export class SelectMenu extends HTMLElement {
8285
readonly #shadow = this.attachShadow({mode: 'open'});
8386
#button: SelectMenuButton|null = null;
@@ -207,6 +210,7 @@ export class SelectMenu extends HTMLElement {
207210
const buttonLabel = this.#getButtonText();
208211
if (!this.sideButton) {
209212
// clang-format off
213+
/* eslint-disable rulesdir/no-deprecated-component-usages */
210214
return html`
211215
<devtools-select-menu-button
212216
@selectmenubuttontrigger=${this.#showMenu}
@@ -217,10 +221,12 @@ export class SelectMenu extends HTMLElement {
217221
${buttonLabel}
218222
</devtools-select-menu-button>
219223
`;
224+
/* eslint-enable rulesdir/no-deprecated-component-usages */
220225
// clang-format on
221226
}
222227

223228
// clang-format off
229+
/* eslint-disable rulesdir/no-deprecated-component-usages */
224230
return html`
225231
<button id="side-button" @click=${this.#sideButtonClicked} ?disabled=${this.disabled}>
226232
${buttonLabel}
@@ -235,6 +241,7 @@ export class SelectMenu extends HTMLElement {
235241
.disabled=${this.disabled}>
236242
</devtools-select-menu-button>
237243
`;
244+
/* eslint-enable rulesdir/no-deprecated-component-usages */
238245
// clang-format on
239246
}
240247

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2025 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import type {TSESTree} from '@typescript-eslint/utils';
6+
7+
import {createRule} from './utils/ruleCreator.ts';
8+
9+
export default createRule({
10+
name: 'no-deprecated-component-usages',
11+
meta: {
12+
type: 'problem',
13+
docs: {
14+
description: 'Disallow usage of deprecated component implementations.',
15+
category: 'Possible Errors',
16+
},
17+
messages: {
18+
noDevToolsSelectMenu:
19+
'Usage of this component implementation is deprecated. Please refer to the UX style guide (docs/styleguide/ux/components.md) for recomended implementation.',
20+
},
21+
schema: [], // no options
22+
},
23+
defaultOptions: [],
24+
create(context) {
25+
const forbiddenString = '<devtools-select-menu';
26+
27+
return {
28+
Literal(node: TSESTree.Literal) {
29+
if (typeof node.value === 'string' && node.value.includes(forbiddenString)) {
30+
context.report({
31+
node,
32+
messageId: 'noDevToolsSelectMenu',
33+
});
34+
}
35+
},
36+
TemplateElement(node: TSESTree.TemplateElement) {
37+
if (node.value.raw.includes(forbiddenString)) {
38+
context.report({
39+
node,
40+
messageId: 'noDevToolsSelectMenu',
41+
});
42+
}
43+
},
44+
};
45+
},
46+
});
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2025 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
import rule from '../lib/no-deprecated-component-usages.ts';
5+
6+
import {RuleTester} from './utils/RuleTester.ts';
7+
8+
new RuleTester().run('no-deprecated-component-usages', rule, {
9+
valid: [
10+
{
11+
code: `
12+
const menu = document.querySelector('devtools-select-menu');
13+
`,
14+
filename: 'test/e2e/folder/file.ts',
15+
},
16+
{
17+
code: `
18+
document.querySelector('devtools-select-menu')?.click();
19+
`,
20+
filename: 'test/e2e/folder/file.ts',
21+
},
22+
],
23+
24+
invalid: [
25+
{
26+
code: `
27+
const output = html\`
28+
<style></style>
29+
<devtools-select-menu
30+
@selectmenuselected${() => {}}
31+
.buttonTitle=${'Click me'}
32+
.title=${'Button to click'}>
33+
<devtools-menu-item>${'Item'}</devtools-menu-item>
34+
</devtools-select-menu>
35+
\`;
36+
`,
37+
filename: 'test/e2e/folder/file.ts',
38+
errors: [
39+
{
40+
messageId: 'noDevToolsSelectMenu',
41+
},
42+
],
43+
},
44+
45+
],
46+
});

0 commit comments

Comments
 (0)