Skip to content

Commit 26a2dde

Browse files
committed
fix: centralize updated first focusable selector
1 parent f1a82cb commit 26a2dde

File tree

8 files changed

+37
-15
lines changed

8 files changed

+37
-15
lines changed

packages/dialog/src/Dialog.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
ObserveSlotPresence,
3232
FocusVisiblePolyfillMixin,
3333
} from '@spectrum-web-components/shared';
34+
import { firstFocusableIn } from '@spectrum-web-components/shared/src/first-focusable-in.js';
3435

3536
import styles from './dialog.css.js';
3637

@@ -87,9 +88,7 @@ export class Dialog extends FocusVisiblePolyfillMixin(
8788

8889
public focus(): void {
8990
if (this.shadowRoot) {
90-
const firstFocusable = this.shadowRoot.querySelector(
91-
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"]), [focusable]'
92-
) as SpectrumElement;
91+
const firstFocusable = firstFocusableIn(this.shadowRoot);
9392
if (firstFocusable) {
9493
if (firstFocusable.updateComplete) {
9594
firstFocusable.updateComplete.then(() =>

packages/dialog/src/DialogWrapper.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import '../sp-dialog.js';
2828
import styles from '@spectrum-web-components/modal/src/modal.css.js';
2929
import { Dialog } from './Dialog.js';
3030
import { FocusVisiblePolyfillMixin } from '@spectrum-web-components/shared';
31+
import { firstFocusableIn } from '@spectrum-web-components/shared/src/first-focusable-in.js';
3132

3233
/**
3334
* @element sp-dialog-wrapper
@@ -93,9 +94,7 @@ export class DialogWrapper extends FocusVisiblePolyfillMixin(SpectrumElement) {
9394

9495
public focus(): void {
9596
if (this.shadowRoot) {
96-
const firstFocusable = this.shadowRoot.querySelector(
97-
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"]), [focusable]'
98-
) as SpectrumElement;
97+
const firstFocusable = firstFocusableIn(this.shadowRoot);
9998
if (firstFocusable) {
10099
if (firstFocusable.updateComplete) {
101100
firstFocusable.updateComplete.then(() =>

packages/overlay/src/ActiveOverlay.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
TemplateResult,
2121
} from '@spectrum-web-components/base';
2222
import { reparentChildren } from '@spectrum-web-components/shared';
23+
import { firstFocusableIn } from '@spectrum-web-components/shared/src/first-focusable-in.js';
2324
import { Color, Scale } from '@spectrum-web-components/theme';
2425
import styles from './active-overlay.css.js';
2526
import {
@@ -187,9 +188,7 @@ export class ActiveOverlay extends SpectrumElement {
187188
public dataPopperPlacement?: Placement;
188189

189190
public focus(): void {
190-
const firstFocusable = this.querySelector(
191-
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"]), [focusable]'
192-
) as HTMLElement;
191+
const firstFocusable = firstFocusableIn(this);
193192
if (firstFocusable) {
194193
firstFocusable.focus();
195194
/* c8 ignore next 3 */

packages/overlay/src/OverlayTrigger.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
PropertyValues,
2020
} from '@spectrum-web-components/base';
2121
import type { LongpressEvent } from '@spectrum-web-components/action-button';
22+
import { firstFocusableIn } from '@spectrum-web-components/shared/src/first-focusable-in.js';
2223

2324
import {
2425
Placement,
@@ -243,9 +244,7 @@ export class OverlayTrigger extends LitElement {
243244
if (this.type !== 'modal') {
244245
return;
245246
}
246-
const firstFocusable = overlayContent.querySelector(
247-
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"]), [focusable]'
248-
) as HTMLElement;
247+
const firstFocusable = firstFocusableIn(overlayContent);
249248
if (!firstFocusable) {
250249
overlayContent.tabIndex = 0;
251250
}
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
Copyright 2020 Adobe. All rights reserved.
3+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License. You may obtain a copy
5+
of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
7+
Unless required by applicable law or agreed to in writing, software distributed under
8+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
OF ANY KIND, either express or implied. See the License for the specific language
10+
governing permissions and limitations under the License.
11+
*/
12+
13+
import type { SpectrumElement } from '@spectrum-web-components/base';
14+
15+
const firstFocusableSelector =
16+
'button:not([tabindex="-1"]), [href]:not([tabindex="-1"]), input:not([tabindex="-1"]), select:not([tabindex="-1"]), textarea:not([tabindex="-1"]), [tabindex]:not([tabindex="-1"]), [focusable]:not([tabindex="-1"])';
17+
18+
export const firstFocusableIn = (
19+
root: HTMLElement | ShadowRoot
20+
): SpectrumElement | null => {
21+
const firstFocusable = root.querySelector(
22+
firstFocusableSelector
23+
) as SpectrumElement;
24+
return firstFocusable;
25+
};

packages/shared/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag
1010
governing permissions and limitations under the License.
1111
*/
1212

13+
export * from './first-focusable-in.js';
1314
export * from './focus-visible.js';
1415
export * from './focusable.js';
1516
export * from './get-active-element.js';

packages/tray/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"dependencies": {
4747
"@spectrum-web-components/base": "^0.4.5",
4848
"@spectrum-web-components/modal": "^0.3.8",
49+
"@spectrum-web-components/shared": "^0.12.8",
4950
"@spectrum-web-components/underlay": "^0.6.9",
5051
"tslib": "^2.0.0"
5152
},

packages/tray/src/Tray.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
query,
2020
} from '@spectrum-web-components/base';
2121
import '@spectrum-web-components/underlay/sp-underlay.js';
22+
import { firstFocusableIn } from '@spectrum-web-components/shared/src/first-focusable-in.js';
2223

2324
import modalStyles from '@spectrum-web-components/modal/src/modal.css.js';
2425
import styles from './tray.css.js';
@@ -40,9 +41,7 @@ export class Tray extends SpectrumElement {
4041
private tray!: HTMLDivElement;
4142

4243
public focus(): void {
43-
const firstFocusable = this.querySelector(
44-
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"]), [focusable]'
45-
) as HTMLElement;
44+
const firstFocusable = firstFocusableIn(this);
4645
if (firstFocusable) {
4746
firstFocusable.focus();
4847
} else if (this.children.length === 1) {

0 commit comments

Comments
 (0)