1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-10 13:23:34 +00:00

[CL-133] add skip links to bit-layout (#7213)

* Add light LinkType to link directive

* add skip link to bit-layout; update i18n for all apps

* install storybook interaction testing packages

* update storybook config

* add skiplink story to bit-layout

* update route and focus logic

* remove focus ring
This commit is contained in:
Will Martin
2023-12-15 09:06:05 -05:00
committed by GitHub
parent b73d73b508
commit e102919c2f
10 changed files with 642 additions and 7 deletions

View File

@@ -1,3 +1,18 @@
<div
class="tw-fixed tw-z-50 tw-w-full tw-flex tw-justify-center tw-opacity-0 focus-within:tw-opacity-100 tw-pointer-events-none focus-within:tw-pointer-events-auto"
>
<nav class="tw-bg-background-alt3 tw-rounded-md tw-rounded-t-none tw-py-2 tw-text-alt2">
<a
bitLink
class="tw-mx-6 focus-visible:before:!tw-ring-0"
[fragment]="mainContentId"
[routerLink]="[]"
(click)="focusMainContent()"
linkType="light"
>{{ "skipToContent" | i18n }}</a
>
</nav>
</div>
<div class="tw-flex tw-w-full">
<aside
[ngStyle]="
@@ -12,7 +27,11 @@
>
<ng-content select="[slot=sidebar]"></ng-content>
</aside>
<main class="tw-ml-60 tw-min-h-screen tw-min-w-0 tw-flex-1 tw-bg-background tw-p-6">
<main
[id]="mainContentId"
tabindex="-1"
class="tw-ml-60 tw-min-h-screen tw-min-w-0 tw-flex-1 tw-bg-background tw-p-6"
>
<ng-content></ng-content>
</main>
</div>

View File

@@ -1,5 +1,8 @@
import { CommonModule } from "@angular/common";
import { Component, Input } from "@angular/core";
import { RouterModule } from "@angular/router";
import { LinkModule } from "../link";
import { SharedModule } from "../shared";
export type LayoutVariant = "primary" | "secondary";
@@ -7,8 +10,14 @@ export type LayoutVariant = "primary" | "secondary";
selector: "bit-layout",
templateUrl: "layout.component.html",
standalone: true,
imports: [CommonModule],
imports: [SharedModule, LinkModule, RouterModule],
})
export class LayoutComponent {
protected mainContentId = "main-content";
@Input() variant: LayoutVariant = "primary";
focusMainContent() {
document.getElementById(this.mainContentId)?.focus();
}
}

View File

@@ -1,5 +1,6 @@
import { RouterTestingModule } from "@angular/router/testing";
import { Meta, StoryObj, componentWrapperDecorator, moduleMetadata } from "@storybook/angular";
import { userEvent } from "@storybook/testing-library";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@@ -30,6 +31,7 @@ export default {
provide: I18nService,
useFactory: () => {
return new I18nMockService({
skipToContent: "Skip to content",
submenu: "submenu",
toggleCollapse: "toggle collapse",
});
@@ -134,6 +136,13 @@ export const WithContent: Story = {
}),
};
export const SkipLinks: Story = {
...WithContent,
play: async () => {
await userEvent.tab();
},
};
export const Secondary: Story = {
render: (args) => ({
props: args,

View File

@@ -1,6 +1,6 @@
import { Input, HostBinding, Directive } from "@angular/core";
export type LinkType = "primary" | "secondary" | "contrast";
export type LinkType = "primary" | "secondary" | "contrast" | "light";
const linkStyles: Record<LinkType, string[]> = {
primary: [
@@ -21,6 +21,12 @@ const linkStyles: Record<LinkType, string[]> = {
"focus-visible:before:tw-ring-text-contrast",
"disabled:!tw-text-contrast/60",
],
light: [
"!tw-text-alt2",
"hover:!tw-text-alt2",
"focus-visible:before:tw-ring-text-alt2",
"disabled:!tw-text-alt2/60",
],
};
const commonStyles = [