1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-12 06:23:38 +00:00

autofocus improvements

This commit is contained in:
Vicki League
2025-06-25 16:20:38 -04:00
parent 3c47eb8900
commit 40928a9b9b
3 changed files with 58 additions and 5 deletions

View File

@@ -2,7 +2,7 @@
// @ts-strict-ignore
import {
AfterContentChecked,
computed,
booleanAttribute,
Directive,
ElementRef,
input,
@@ -29,9 +29,7 @@ import { FocusableElement } from "../shared/focusable-element";
selector: "[appAutofocus], [bitAutofocus]",
})
export class AutofocusDirective implements AfterContentChecked {
appAutofocus = input<boolean | string>();
private autofocus = computed(() => this.appAutofocus() === "" || this.appAutofocus() === true);
readonly appAutofocus = input(undefined, { transform: booleanAttribute });
// Track if we have already focused the element.
private focused = false;
@@ -52,7 +50,7 @@ export class AutofocusDirective implements AfterContentChecked {
*/
ngAfterContentChecked() {
// We only want to focus the element on initial render and it's not a mobile browser
if (this.focused || !this.autofocus() || Utils.isMobileBrowser) {
if (this.focused || !this.appAutofocus() || Utils.isMobileBrowser) {
return;
}

View File

@@ -0,0 +1,21 @@
import { Meta, Canvas, Primary, Controls, Title, Description } from "@storybook/addon-docs";
import * as stories from "./autofocus.stories";
<Meta of={stories} />
```ts
import { AutofocusDirective } from "@bitwarden/components";
```
<Title />
<Description />
<Primary />
<Controls />
## Accessibility
The autofocus directive has accessibility implications, because it will steal focus from wherever it
would naturally be placed on page load. Please consider whether or not the user truly needs the
element truly needs to be manually focused on their behalf.

View File

@@ -0,0 +1,34 @@
import { Component } from "@angular/core";
import { Meta, moduleMetadata, StoryObj } from "@storybook/angular";
import { FormFieldModule } from "../form-field";
import { AutofocusDirective } from "./autofocus.directive";
@Component({
selector: "autofocus-example",
imports: [FormFieldModule, AutofocusDirective],
template: ` <bit-form-field>
<bit-label>Email</bit-label>
<input bitInput formControlName="email" appAutofocus />
</bit-form-field>`,
})
class AutofocusExampleComponent {}
export default {
title: "Component Library/Form/Autofocus Directive",
component: AutofocusDirective,
decorators: [
moduleMetadata({
imports: [AutofocusExampleComponent],
}),
],
} as Meta;
type Story = StoryObj<AutofocusExampleComponent>;
export const AutofocusField: Story = {
render: (args) => ({
template: `<autofocus-example></autofocus-example>`,
}),
};