diff --git a/packages/button/src/spectrum-config.js b/packages/button/src/spectrum-config.js index eee0529b866..fbd8574147c 100644 --- a/packages/button/src/spectrum-config.js +++ b/packages/button/src/spectrum-config.js @@ -47,6 +47,11 @@ const config = { selector: '.spectrum-FieldButton--quiet', name: 'quiet', }, + { + type: 'boolean', + selector: '.is-focused', + name: 'focused', + }, ], classes: [ { diff --git a/packages/button/src/spectrum-fieldbutton.css b/packages/button/src/spectrum-fieldbutton.css index bacc665911e..8f6260ea6b1 100644 --- a/packages/button/src/spectrum-fieldbutton.css +++ b/packages/button/src/spectrum-fieldbutton.css @@ -133,7 +133,7 @@ THIS FILE IS MACHINE GENERATED. DO NOT EDIT */ ); } .button:focus-visible, -.button.is-focused { +:host([focused]) .button { /* .spectrum-FieldButton.focus-ring, * .spectrum-FieldButton.is-focused */ background-color: var( @@ -156,7 +156,7 @@ THIS FILE IS MACHINE GENERATED. DO NOT EDIT */ ); } .button:focus-visible.is-placeholder, -.button.is-focused.is-placeholder { +:host([focused]) .button.is-placeholder { /* .spectrum-FieldButton.focus-ring.is-placeholder, * .spectrum-FieldButton.is-focused.is-placeholder */ color: var( @@ -188,7 +188,7 @@ THIS FILE IS MACHINE GENERATED. DO NOT EDIT */ ); } :host([invalid]) .button:focus-visible, -:host([invalid]) .button.is-focused { +:host([invalid][focused]) .button { /* .spectrum-FieldButton.is-invalid.focus-ring, * .spectrum-FieldButton.is-invalid.is-focused */ border-color: var( @@ -251,7 +251,7 @@ THIS FILE IS MACHINE GENERATED. DO NOT EDIT */ ); } :host([quiet]) .button:focus-visible, -:host([quiet]) .button.is-focused { +:host([quiet][focused]) .button { /* .spectrum-FieldButton--quiet.focus-ring, * .spectrum-FieldButton--quiet.is-focused */ background-color: var( @@ -265,7 +265,7 @@ THIS FILE IS MACHINE GENERATED. DO NOT EDIT */ ); } :host([quiet]) .button:focus-visible.is-placeholder, -:host([quiet]) .button.is-focused.is-placeholder { +:host([quiet][focused]) .button.is-placeholder { /* .spectrum-FieldButton--quiet.focus-ring.is-placeholder, * .spectrum-FieldButton--quiet.is-focused.is-placeholder */ color: var( @@ -287,9 +287,9 @@ THIS FILE IS MACHINE GENERATED. DO NOT EDIT */ ); } :host([quiet]) .button.is-selected:focus-visible, -:host([quiet]) .button.is-selected.is-focused, +:host([quiet][focused]) .button.is-selected, :host([quiet]) .button:active:focus-visible, -:host([quiet]) .button:active.is-focused { +:host([quiet][focused]) .button:active { /* .spectrum-FieldButton--quiet.is-selected.focus-ring, * .spectrum-FieldButton--quiet.is-selected.is-focused, * .spectrum-FieldButton--quiet:active.focus-ring, @@ -305,7 +305,7 @@ THIS FILE IS MACHINE GENERATED. DO NOT EDIT */ ); } :host([quiet][invalid]) .button:focus-visible, -:host([quiet][invalid]) .button.is-focused { +:host([quiet][invalid][focused]) .button { /* .spectrum-FieldButton--quiet.is-invalid.focus-ring, * .spectrum-FieldButton--quiet.is-invalid.is-focused */ box-shadow: 0 2px 0 0 diff --git a/packages/dropdown/src/Dropdown.ts b/packages/dropdown/src/Dropdown.ts index 78dde73b7e3..5c6e6e6ceca 100644 --- a/packages/dropdown/src/Dropdown.ts +++ b/packages/dropdown/src/Dropdown.ts @@ -82,6 +82,9 @@ export class DropdownBase extends Focusable { @property({ type: Boolean, reflect: true }) public disabled = false; + @property({ type: Boolean, reflect: true }) + public focused = false; + @property({ type: Boolean, reflect: true }) public invalid = false; @@ -145,11 +148,12 @@ export class DropdownBase extends Focusable { return this.button; } - public click(): void { - this.focusElement.click(); + public forceFocusVisible(): void { + this.focused = true; } public onButtonBlur(): void { + this.focused = false; (this.target as HTMLButtonElement).removeEventListener( 'keydown', this.onKeydown diff --git a/packages/dropdown/src/dropdown.css b/packages/dropdown/src/dropdown.css index 60302b0e2b3..dda6e95747a 100644 --- a/packages/dropdown/src/dropdown.css +++ b/packages/dropdown/src/dropdown.css @@ -14,3 +14,25 @@ governing permissions and limitations under the License. sp-popover { display: none; } + +/** + * The accessibility team would prefer that it be possible to override the :focus-visible + * heuristics in _some_ cases, like when clicking an `sp-field-label`... + * + * From Picker + **/ +:host([focused]:not([quiet])) #button #label.placeholder { + /* .spectrum-Picker-trigger.focus-ring .spectrum-Picker-label.is-placeholder */ + color: var( + --spectrum-picker-placeholder-text-color-key-focus, + var(--spectrum-alias-placeholder-text-color-hover) + ); +} + +:host([focused]:not([quiet])) #button .dropdown { + /* .spectrum-Picker-trigger.focus-ring .spectrum-Picker-icon */ + color: var( + --spectrum-picker-icon-color-key-focus, + var(--spectrum-alias-icon-color-focus) + ); +} diff --git a/packages/field-label/src/FieldLabel.ts b/packages/field-label/src/FieldLabel.ts index 9ffc231e440..24aae4a96d3 100644 --- a/packages/field-label/src/FieldLabel.ts +++ b/packages/field-label/src/FieldLabel.ts @@ -25,6 +25,8 @@ import asterickIconStyles from '@spectrum-web-components/icon/src/spectrum-icon- import styles from './field-label.css.js'; +type AcceptsFocusVisisble = HTMLElement & { forceFocusVisible?(): void }; + /** * @element sp-field-label */ @@ -55,6 +57,15 @@ export class FieldLabel extends SpectrumElement { private handleClick(): void { if (!this.target || this.disabled) return; this.target.focus(); + const parent = this.getRootNode() as ShadowRoot; + const target = this.target as AcceptsFocusVisisble; + const targetParent = target.getRootNode() as ShadowRoot; + const targetHost = targetParent.host as AcceptsFocusVisisble; + if (targetParent.isSameNode(parent) && target.forceFocusVisible) { + target.forceFocusVisible(); + } else if (targetHost && targetHost.forceFocusVisible) { + targetHost.forceFocusVisible(); + } } private async manageFor(): Promise {