mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 05:43:41 +00:00
Ps/pm 2910/browser header component (#6641)
* Collate browser header concerns into component Header component has a slots field with a left, center, right, and a right-most location for a current account, which will link to an account switcher. * Use feature flag if OK for production eventually * Make sure centered content centered * Allow for disabling header theming for login page visual gitches exist for links and buttons, due to specifications futher down in the header, but those items shouldn't use the `no-theme` option. For now, it's just for the login screen * Select sr-only headers * Fix vault-filter center header component * Correct hover for header buttons/links * Ensure no visual difference when flag is off
This commit is contained in:
2
apps/browser/.gitignore
vendored
2
apps/browser/.gitignore
vendored
@@ -1,3 +1,5 @@
|
|||||||
|
config/local.json
|
||||||
|
|
||||||
# Safari
|
# Safari
|
||||||
dist-safari
|
dist-safari
|
||||||
!src/safari/safari/app/popup/index.html
|
!src/safari/safari/app/popup/index.html
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"dev_flags": {},
|
"dev_flags": {},
|
||||||
"flags": {
|
"flags": {
|
||||||
"showPasswordless": true,
|
"showPasswordless": true,
|
||||||
"enableCipherKeyEncryption": false
|
"enableCipherKeyEncryption": false,
|
||||||
|
"accountSwitching": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<app-header [noTheme]="true"></app-header>
|
||||||
<div class="center-content">
|
<div class="center-content">
|
||||||
<div class="content login-page">
|
<div class="content login-page">
|
||||||
<div class="logo-image"></div>
|
<div class="logo-image"></div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<form (ngSubmit)="submit()">
|
<form (ngSubmit)="submit()">
|
||||||
<header>
|
<app-header>
|
||||||
<div class="left"></div>
|
<div class="left"></div>
|
||||||
<h1 class="center">
|
<h1 class="center">
|
||||||
<span class="title">{{ "verifyIdentity" | i18n }}</span>
|
<span class="title">{{ "verifyIdentity" | i18n }}</span>
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
{{ "unlock" | i18n }}
|
{{ "unlock" | i18n }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</app-header>
|
||||||
<main tabindex="-1">
|
<main tabindex="-1">
|
||||||
<ng-container *ngIf="fido2PopoutSessionData$ | async as fido2Data">
|
<ng-container *ngIf="fido2PopoutSessionData$ | async as fido2Data">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ import { GroupPolicyEnvironment } from "../admin-console/types/group-policy-envi
|
|||||||
|
|
||||||
// required to avoid linting errors when there are no flags
|
// required to avoid linting errors when there are no flags
|
||||||
/* eslint-disable-next-line @typescript-eslint/ban-types */
|
/* eslint-disable-next-line @typescript-eslint/ban-types */
|
||||||
export type Flags = {} & SharedFlags;
|
export type Flags = {
|
||||||
|
accountSwitching?: boolean;
|
||||||
|
} & SharedFlags;
|
||||||
|
|
||||||
// required to avoid linting errors when there are no flags
|
// required to avoid linting errors when there are no flags
|
||||||
/* eslint-disable-next-line @typescript-eslint/ban-types */
|
/* eslint-disable-next-line @typescript-eslint/ban-types */
|
||||||
|
|||||||
14
apps/browser/src/platform/popup/header.component.html
Normal file
14
apps/browser/src/platform/popup/header.component.html
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<header [ngClass]="{ 'no-theme': noTheme }">
|
||||||
|
<div class="header-content">
|
||||||
|
<ng-content select=".sr-only"></ng-content>
|
||||||
|
<ng-content select=".left"></ng-content>
|
||||||
|
<ng-content select=".center"></ng-content>
|
||||||
|
<div class="right">
|
||||||
|
<ng-content select=".right"></ng-content>
|
||||||
|
<ng-container *ngIf="authedAccounts$ | async">
|
||||||
|
TODO: Current Account
|
||||||
|
<!-- <app-current-account></app-current-account> -->
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
27
apps/browser/src/platform/popup/header.component.ts
Normal file
27
apps/browser/src/platform/popup/header.component.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { Component, Input } from "@angular/core";
|
||||||
|
import { Observable, map } from "rxjs";
|
||||||
|
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
|
|
||||||
|
import { flagEnabled } from "../flags";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "app-header",
|
||||||
|
templateUrl: "header.component.html",
|
||||||
|
})
|
||||||
|
export class HeaderComponent {
|
||||||
|
@Input() noTheme = false;
|
||||||
|
authedAccounts$: Observable<boolean>;
|
||||||
|
constructor(accountService: AccountService) {
|
||||||
|
this.authedAccounts$ = accountService.accounts$.pipe(
|
||||||
|
map((accounts) => {
|
||||||
|
if (!flagEnabled("accountSwitching")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.values(accounts).some((a) => a.status !== AuthenticationStatus.LoggedOut);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,7 @@ import { SsoComponent } from "../auth/popup/sso.component";
|
|||||||
import { TwoFactorOptionsComponent } from "../auth/popup/two-factor-options.component";
|
import { TwoFactorOptionsComponent } from "../auth/popup/two-factor-options.component";
|
||||||
import { TwoFactorComponent } from "../auth/popup/two-factor.component";
|
import { TwoFactorComponent } from "../auth/popup/two-factor.component";
|
||||||
import { UpdateTempPasswordComponent } from "../auth/popup/update-temp-password.component";
|
import { UpdateTempPasswordComponent } from "../auth/popup/update-temp-password.component";
|
||||||
|
import { HeaderComponent } from "../platform/popup/header.component";
|
||||||
import { FilePopoutCalloutComponent } from "../tools/popup/components/file-popout-callout.component";
|
import { FilePopoutCalloutComponent } from "../tools/popup/components/file-popout-callout.component";
|
||||||
import { GeneratorComponent } from "../tools/popup/generator/generator.component";
|
import { GeneratorComponent } from "../tools/popup/generator/generator.component";
|
||||||
import { PasswordGeneratorHistoryComponent } from "../tools/popup/generator/password-generator-history.component";
|
import { PasswordGeneratorHistoryComponent } from "../tools/popup/generator/password-generator-history.component";
|
||||||
@@ -121,6 +122,7 @@ import "../platform/popup/locales";
|
|||||||
FolderAddEditComponent,
|
FolderAddEditComponent,
|
||||||
FoldersComponent,
|
FoldersComponent,
|
||||||
VaultFilterComponent,
|
VaultFilterComponent,
|
||||||
|
HeaderComponent,
|
||||||
HintComponent,
|
HintComponent,
|
||||||
HomeComponent,
|
HomeComponent,
|
||||||
LockComponent,
|
LockComponent,
|
||||||
|
|||||||
@@ -176,15 +176,28 @@ cdk-virtual-scroll-viewport::-webkit-scrollbar-thumb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
header:not(bit-callout header) {
|
header:not(bit-callout header) {
|
||||||
min-height: 44px;
|
|
||||||
max-height: 44px;
|
max-height: 44px;
|
||||||
display: flex;
|
display: flex;
|
||||||
border-bottom: 1px solid #000000;
|
|
||||||
|
|
||||||
@include themify($themes) {
|
&:not(.no-theme) {
|
||||||
color: themed("headerColor");
|
min-height: 44px;
|
||||||
background-color: themed("headerBackgroundColor");
|
border-bottom: 1px solid #000000;
|
||||||
border-bottom-color: themed("headerBorderColor");
|
|
||||||
|
@include themify($themes) {
|
||||||
|
color: themed("headerColor");
|
||||||
|
background-color: themed("headerBackgroundColor");
|
||||||
|
border-bottom-color: themed("headerBorderColor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-content {
|
||||||
|
display: flex;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-content > .right,
|
||||||
|
.header-content > .right > .right {
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left,
|
.left,
|
||||||
@@ -230,11 +243,6 @@ header:not(bit-callout header) {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
|
|
||||||
@include themify($themes) {
|
|
||||||
color: themed("headerColor");
|
|
||||||
background-color: themed("headerBackgroundColor");
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
@include themify($themes) {
|
@include themify($themes) {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<header>
|
<app-header>
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<app-pop-out></app-pop-out>
|
<app-pop-out></app-pop-out>
|
||||||
</div>
|
</div>
|
||||||
<h1 class="sr-only">{{ "myVault" | i18n }}</h1>
|
<h1 class="sr-only">{{ "myVault" | i18n }}</h1>
|
||||||
<div class="search">
|
<div class="search center">
|
||||||
<input
|
<input
|
||||||
type="{{ searchTypeSearch ? 'search' : 'text' }}"
|
type="{{ searchTypeSearch ? 'search' : 'text' }}"
|
||||||
placeholder="{{ 'searchVault' | i18n }}"
|
placeholder="{{ 'searchVault' | i18n }}"
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
<i class="bwi bwi-plus bwi-lg bwi-fw" aria-hidden="true"></i>
|
<i class="bwi bwi-plus bwi-lg bwi-fw" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</app-header>
|
||||||
<main tabindex="-1" cdk-scrollable>
|
<main tabindex="-1" cdk-scrollable>
|
||||||
<app-vault-select
|
<app-vault-select
|
||||||
(onVaultSelectionChanged)="vaultFilterChanged()"
|
(onVaultSelectionChanged)="vaultFilterChanged()"
|
||||||
|
|||||||
Reference in New Issue
Block a user