1
0
mirror of https://github.com/google/nomulus synced 2026-01-03 03:35:42 +00:00

Improve console accessibility (#2649)

This commit is contained in:
Pavlo Tkach
2025-01-25 19:47:53 -05:00
committed by GitHub
parent 653e092ad4
commit 8987fd37c2
30 changed files with 113 additions and 30 deletions

View File

@@ -7,6 +7,11 @@
></mat-progress-bar> ></mat-progress-bar>
</div> </div>
<mat-sidenav-container class="console-app__container"> <mat-sidenav-container class="console-app__container">
<mat-sidenav-content class="console-app__content-wrapper">
<div class="console-app__content" role="main">
<router-outlet></router-outlet>
</div>
</mat-sidenav-content>
<mat-sidenav <mat-sidenav
[mode]="breakpointObserver.isMobileView() ? 'over' : 'side'" [mode]="breakpointObserver.isMobileView() ? 'over' : 'side'"
[opened]="!breakpointObserver.isMobileView()" [opened]="!breakpointObserver.isMobileView()"
@@ -15,10 +20,5 @@
> >
<app-navigation /> <app-navigation />
</mat-sidenav> </mat-sidenav>
<mat-sidenav-content class="console-app__content-wrapper">
<div class="console-app__content">
<router-outlet></router-outlet>
</div>
</mat-sidenav-content>
</mat-sidenav-container> </mat-sidenav-container>
</div> </div>

View File

@@ -20,12 +20,18 @@ import { AppComponent } from './app.component';
import { MaterialModule } from './material.module'; import { MaterialModule } from './material.module';
import { BackendService } from './shared/services/backend.service'; import { BackendService } from './shared/services/backend.service';
import { AppRoutingModule } from './app-routing.module'; import { AppRoutingModule } from './app-routing.module';
import { AppModule } from './app.module';
describe('AppComponent', () => { describe('AppComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [AppComponent], declarations: [AppComponent],
imports: [MaterialModule, BrowserAnimationsModule, AppRoutingModule], imports: [
MaterialModule,
BrowserAnimationsModule,
AppRoutingModule,
AppModule,
],
providers: [ providers: [
BackendService, BackendService,
provideHttpClient(), provideHttpClient(),
@@ -36,6 +42,7 @@ describe('AppComponent', () => {
it('should create the app', () => { it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const app = fixture.componentInstance; const app = fixture.componentInstance;
expect(app).toBeTruthy(); expect(app).toBeTruthy();
}); });

View File

@@ -21,6 +21,7 @@ import { MaterialModule } from '../material.module';
import { BackendService } from '../shared/services/backend.service'; import { BackendService } from '../shared/services/backend.service';
import { DomainListComponent } from './domainList.component'; import { DomainListComponent } from './domainList.component';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { AppModule } from '../app.module';
describe('DomainListComponent', () => { describe('DomainListComponent', () => {
let component: DomainListComponent; let component: DomainListComponent;
@@ -29,7 +30,12 @@ describe('DomainListComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [DomainListComponent], declarations: [DomainListComponent],
imports: [MaterialModule, BrowserAnimationsModule, FormsModule], imports: [
MaterialModule,
BrowserAnimationsModule,
FormsModule,
AppModule,
],
providers: [ providers: [
BackendService, BackendService,
provideHttpClient(), provideHttpClient(),

View File

@@ -12,6 +12,7 @@
<a <a
[routerLink]="'/home'" [routerLink]="'/home'"
routerLinkActive="active" routerLinkActive="active"
aria-label="Google Registry logo"
class="console-app__logo" class="console-app__logo"
> >
<svg <svg

View File

@@ -17,6 +17,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HeaderComponent } from './header.component'; import { HeaderComponent } from './header.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MaterialModule } from '../material.module'; import { MaterialModule } from '../material.module';
import { ActivatedRoute } from '@angular/router';
import { AppModule, SelectedRegistrarModule } from '../app.module';
import { AppRoutingModule } from '../app-routing.module';
import { BackendService } from '../shared/services/backend.service';
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
describe('HeaderComponent', () => { describe('HeaderComponent', () => {
let component: HeaderComponent; let component: HeaderComponent;
@@ -24,7 +30,19 @@ describe('HeaderComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [MaterialModule, BrowserAnimationsModule], imports: [
SelectedRegistrarModule,
MaterialModule,
BrowserAnimationsModule,
AppRoutingModule,
AppModule,
],
providers: [
BackendService,
{ provide: ActivatedRoute, useValue: {} as ActivatedRoute },
provideHttpClient(),
provideHttpClientTesting(),
],
declarations: [HeaderComponent], declarations: [HeaderComponent],
}).compileComponents(); }).compileComponents();

View File

@@ -16,6 +16,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HomeComponent } from './home.component'; import { HomeComponent } from './home.component';
import { MaterialModule } from '../material.module'; import { MaterialModule } from '../material.module';
import { AppModule } from '../app.module';
describe('HomeComponent', () => { describe('HomeComponent', () => {
let component: HomeComponent; let component: HomeComponent;
@@ -23,7 +24,7 @@ describe('HomeComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [MaterialModule], imports: [MaterialModule, AppModule],
declarations: [HomeComponent], declarations: [HomeComponent],
}).compileComponents(); }).compileComponents();

View File

@@ -6,7 +6,9 @@
<mat-tree-node <mat-tree-node
*matTreeNodeDef="let node" *matTreeNodeDef="let node"
matTreeNodeToggle matTreeNodeToggle
tabindex="0"
(click)="onClick(node)" (click)="onClick(node)"
(keyup.enter)="onClick(node)"
[class.active]="router.url.includes(node.path)" [class.active]="router.url.includes(node.path)"
[elementId]="getElementId(node)" [elementId]="getElementId(node)"
> >

View File

@@ -1,4 +1,8 @@
<div class="console-app__registrar-view"> <div
class="console-app__registrar-view"
cdkTrapFocus
[cdkTrapFocusAutoCapture]="true"
>
<h1 class="mat-headline-4">Registrars</h1> <h1 class="mat-headline-4">Registrars</h1>
<mat-divider></mat-divider> <mat-divider></mat-divider>
<div class="console-app__registrar-view-content"> <div class="console-app__registrar-view-content">

View File

@@ -59,6 +59,8 @@
<mat-row <mat-row
*matRowDef="let row; columns: displayedColumns" *matRowDef="let row; columns: displayedColumns"
(click)="openDetails(row.registrarId)" (click)="openDetails(row.registrarId)"
tabindex="0"
(keyup.enter)="openDetails(row.registrarId)"
></mat-row> ></mat-row>
</mat-table> </mat-table>

View File

@@ -32,7 +32,9 @@
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row> <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row <mat-row
*matRowDef="let row; columns: displayedColumns" *matRowDef="let row; columns: displayedColumns"
tabindex="0"
(click)="openDetails(row)" (click)="openDetails(row)"
(keyup.enter)="openDetails(row)"
></mat-row> ></mat-row>
</mat-table> </mat-table>
} }

View File

@@ -1,4 +1,9 @@
<div class="console-app__contact" *ngIf="contactService.contactInEdit"> <div
class="console-app__contact"
*ngIf="contactService.contactInEdit"
cdkTrapFocus
[cdkTrapFocusAutoCapture]="true"
>
<div class="console-app__contact-controls"> <div class="console-app__contact-controls">
<button <button
mat-icon-button mat-icon-button

View File

@@ -1,4 +1,8 @@
<div class="settings-security__edit-password"> <div
class="settings-security__edit-password"
cdkTrapFocus
[cdkTrapFocusAutoCapture]="true"
>
<p> <p>
<button <button
mat-icon-button mat-icon-button

View File

@@ -42,7 +42,7 @@ describe('SecurityComponent', () => {
fetchSecurityDetailsSpy = fetchSecurityDetailsSpy =
securityServiceSpy.fetchSecurityDetails.and.returnValue(of()); securityServiceSpy.fetchSecurityDetails.and.returnValue(of());
saveSpy = securityServiceSpy.saveChanges; saveSpy = securityServiceSpy.saveChanges.and.returnValue(of());
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [SecurityEditComponent, SecurityComponent], declarations: [SecurityEditComponent, SecurityComponent],

View File

@@ -1,4 +1,8 @@
<div class="settings-security__edit"> <div
class="settings-security__edit"
cdkTrapFocus
[cdkTrapFocusAutoCapture]="true"
>
<h1>IP Allowlist</h1> <h1>IP Allowlist</h1>
<p> <p>
Restrict access to EPP production servers to the following IP/IPv6 Restrict access to EPP production servers to the following IP/IPv6

View File

@@ -10,22 +10,28 @@
<a <a
mat-tab-link mat-tab-link
routerLink="contact" routerLink="contact"
routerLinkActive="active-link" routerLinkActive
queryParamsHandling="merge" queryParamsHandling="merge"
#rla="routerLinkActive"
[active]="rla.isActive"
>Contacts</a >Contacts</a
> >
<a <a
mat-tab-link mat-tab-link
routerLink="whois" routerLink="whois"
routerLinkActive="active-link" routerLinkActive
queryParamsHandling="merge" queryParamsHandling="merge"
#rla2="routerLinkActive"
[active]="rla2.isActive"
>WHOIS Info</a >WHOIS Info</a
> >
<a <a
mat-tab-link mat-tab-link
routerLink="security" routerLink="security"
routerLinkActive="active-link" routerLinkActive
queryParamsHandling="merge" queryParamsHandling="merge"
#rla3="routerLinkActive"
[active]="rla3.isActive"
>Security</a >Security</a
> >
</nav> </nav>

View File

@@ -13,14 +13,6 @@
// limitations under the License. // limitations under the License.
.console-settings { .console-settings {
.mdc-tab {
&.active-link {
border-bottom: 2px solid var(--primary);
.mdc-tab__text-label {
color: var(--primary);
}
}
}
nav { nav {
margin-bottom: 40px; margin-bottom: 40px;
} }

View File

@@ -17,6 +17,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SettingsComponent } from './settings.component'; import { SettingsComponent } from './settings.component';
import { MaterialModule } from '../material.module'; import { MaterialModule } from '../material.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ActivatedRoute } from '@angular/router';
import { AppModule, SelectedRegistrarModule } from '../app.module';
import { BackendService } from '../shared/services/backend.service';
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { AppRoutingModule } from '../app-routing.module';
describe('SettingsComponent', () => { describe('SettingsComponent', () => {
let component: SettingsComponent; let component: SettingsComponent;
@@ -24,7 +30,19 @@ describe('SettingsComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [MaterialModule, BrowserAnimationsModule], imports: [
SelectedRegistrarModule,
MaterialModule,
BrowserAnimationsModule,
AppRoutingModule,
AppModule,
],
providers: [
BackendService,
{ provide: ActivatedRoute, useValue: {} as ActivatedRoute },
provideHttpClient(),
provideHttpClientTesting(),
],
declarations: [SettingsComponent], declarations: [SettingsComponent],
}).compileComponents(); }).compileComponents();

View File

@@ -1,4 +1,9 @@
<div class="console-app__whois-edit" *ngIf="registrarInEdit"> <div
class="console-app__whois-edit"
*ngIf="registrarInEdit"
cdkTrapFocus
[cdkTrapFocusAutoCapture]="true"
>
<button <button
mat-icon-button mat-icon-button
class="console-app__whois-edit-back" class="console-app__whois-edit-back"

View File

@@ -1,4 +1,8 @@
<div class="console-app__user-details"> <div
class="console-app__user-details"
cdkTrapFocus
[cdkTrapFocusAutoCapture]="true"
>
@if(isEditing) { @if(isEditing) {
<h1 class="mat-headline-4">Editing {{ userDetails().emailAddress }}</h1> <h1 class="mat-headline-4">Editing {{ userDetails().emailAddress }}</h1>
<mat-divider></mat-divider> <mat-divider></mat-divider>

View File

@@ -1,4 +1,4 @@
<app-selected-registrar-wrapper> <app-selected-registrar-wrapper cdkTrapFocus [cdkTrapFocusAutoCapture]="true">
@if(isLoading) { @if(isLoading) {
<div class="console-app__users-spinner"> <div class="console-app__users-spinner">
<mat-spinner /> <mat-spinner />

View File

@@ -19,6 +19,8 @@
*matRowDef="let row; columns: displayedColumns" *matRowDef="let row; columns: displayedColumns"
[class.rowSelected]="isRowSelected(row)" [class.rowSelected]="isRowSelected(row)"
(click)="onClick(row)" (click)="onClick(row)"
(keyup.enter)="onClick(row)"
tabindex="0"
></mat-row> ></mat-row>
</mat-table> </mat-table>
</div> </div>

View File

@@ -112,7 +112,7 @@ mat-row:hover {
// Access and define a class with secondary color exposed // Access and define a class with secondary color exposed
.secondary-text { .secondary-text {
color: $secondary-color; color: #575757;
} }
.primary-text { .primary-text {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 72 KiB