mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 01:03:35 +00:00
[EC-474] Add hidden char count toggle to web and desktop (#3262)
* feat-web: add hidden char count toggle * Added toggle char count for desktop * Use Tailwind and Component Library, add i18n * Hide char count when password is hidden * Initial proposal * Update colors per design spec for all clients Also make variable names consistent across clients * Remove unused scss * Add styling * Set fixed with for password count elements * Add separate wrapped stories * Fix alignment of first char when wrapped * Minor refactors * Make naming consistent * Add Figma url * add barrel files * Use CL component * Fix template * Remove duplicate style * Use ColorPasswordComponent in web, remove old pipe Also remove styling and move pipe out of jslib-module given that it's no longer shared by all Angular clients * Run prettier * Remove unused scss vars * Undo unnecessary changes * Remove unnecessary changes * Fix styling * Fix selector * Collect show password event * Fix incorrect background in dark mode * Fix linting * Use color password for password history * Add char count to hidden custom fields in desktop * Fix char count background in web: take 2 * Update service name * Add missing label toggleCharacterCount for desktop Co-authored-by: Daniel James Smith <djsmith@web.de> Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
This commit is contained in:
committed by
GitHub
parent
87f2908e3e
commit
35b33335fb
@@ -18,9 +18,11 @@ import {
|
||||
IconButtonModule,
|
||||
IconModule,
|
||||
MenuModule,
|
||||
LinkModule,
|
||||
NavigationModule,
|
||||
TableModule,
|
||||
TabsModule,
|
||||
ColorPasswordModule,
|
||||
} from "@bitwarden/components";
|
||||
|
||||
// Register the locales for the application
|
||||
@@ -58,6 +60,8 @@ import "./locales";
|
||||
NavigationModule,
|
||||
TableModule,
|
||||
TabsModule,
|
||||
LinkModule,
|
||||
ColorPasswordModule,
|
||||
|
||||
// Web specific
|
||||
],
|
||||
@@ -85,6 +89,8 @@ import "./locales";
|
||||
NavigationModule,
|
||||
TableModule,
|
||||
TabsModule,
|
||||
LinkModule,
|
||||
ColorPasswordModule,
|
||||
|
||||
// Web specific
|
||||
],
|
||||
|
||||
@@ -6,18 +6,10 @@
|
||||
</app-callout>
|
||||
<div class="card card-generated bg-light my-4">
|
||||
<div class="card-body">
|
||||
<div
|
||||
*ngIf="type === 'password'"
|
||||
class="generated-wrapper"
|
||||
[innerHTML]="password | colorPassword"
|
||||
<bit-color-password
|
||||
[password]="type === 'password' ? password : username"
|
||||
appSelectCopy
|
||||
></div>
|
||||
<div
|
||||
*ngIf="type === 'username'"
|
||||
class="generated-wrapper"
|
||||
[innerHTML]="username | colorPassword"
|
||||
appSelectCopy
|
||||
></div>
|
||||
></bit-color-password>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" role="radiogroup" aria-labelledby="typeHeading">
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
<div class="modal-body" *ngIf="history.length">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item d-flex" *ngFor="let h of history">
|
||||
<div class="password-row">
|
||||
<div
|
||||
class="text-monospace generated-wrapper"
|
||||
[innerHTML]="h.password | colorPassword"
|
||||
<div class="tw-min-w-0">
|
||||
<bit-color-password
|
||||
[password]="h.password"
|
||||
class="tw-block tw-font-mono"
|
||||
appSelectCopy
|
||||
></div>
|
||||
></bit-color-password>
|
||||
<small class="text-muted">{{ h.date | date: "medium" }}</small>
|
||||
</div>
|
||||
<div class="ml-auto">
|
||||
|
||||
@@ -128,6 +128,15 @@
|
||||
title="{{ 'loading' | i18n }}"
|
||||
></i>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
class="d-block bwi-icon-above-input"
|
||||
appStopClick
|
||||
[appA11yTitle]="'toggleCharacterCount' | i18n"
|
||||
(click)="togglePasswordCount()"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-fw bwi-numbered-list" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
@@ -169,6 +178,18 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="showPasswordCount" class="tw-mb-4">
|
||||
<label>{{ "passwordCharacterCount" | i18n }}</label>
|
||||
<div class="tw-flex tw-justify-between">
|
||||
<bit-color-password
|
||||
[password]="cipher.login.password"
|
||||
[showCount]="true"
|
||||
></bit-color-password>
|
||||
<button type="button" bitLink (click)="togglePasswordCount()">
|
||||
{{ "hide" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-row">
|
||||
<div class="tw-mb-4 tw-w-1/2">
|
||||
<label for="loginTotp">{{ "authenticatorKeyTotp" | i18n }}</label>
|
||||
@@ -870,7 +891,7 @@
|
||||
<div class="ml-3" *ngIf="viewingPasswordHistory">
|
||||
<div *ngFor="let ph of cipher.passwordHistory">
|
||||
{{ ph.lastUsedDate | date: "short" }} -
|
||||
<span class="generated-wrapper text-monospace ml-2">{{ ph.password }}</span>
|
||||
<bit-color-password [password]="ph.password"></bit-color-password>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -35,6 +35,7 @@ export class AddEditComponent extends BaseAddEditComponent implements OnInit, On
|
||||
hasPasswordHistory = false;
|
||||
viewingPasswordHistory = false;
|
||||
viewOnly = false;
|
||||
showPasswordCount = false;
|
||||
|
||||
protected totpInterval: number;
|
||||
protected override componentName = "app-vault-add-edit";
|
||||
@@ -104,6 +105,26 @@ export class AddEditComponent extends BaseAddEditComponent implements OnInit, On
|
||||
this.cipher.favorite = !this.cipher.favorite;
|
||||
}
|
||||
|
||||
togglePassword() {
|
||||
super.togglePassword();
|
||||
|
||||
// Hide password count when password is hidden to be safe
|
||||
if (!this.showPassword && this.showPasswordCount) {
|
||||
this.togglePasswordCount();
|
||||
}
|
||||
}
|
||||
|
||||
togglePasswordCount() {
|
||||
this.showPasswordCount = !this.showPasswordCount;
|
||||
|
||||
if (this.editMode && this.showPasswordCount) {
|
||||
this.eventCollectionService.collect(
|
||||
EventType.Cipher_ClientToggledPasswordVisible,
|
||||
this.cipherId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
launch(uri: LoginUriView) {
|
||||
if (!uri.canLaunch) {
|
||||
return;
|
||||
|
||||
@@ -5487,6 +5487,17 @@
|
||||
"multiSelectClearAll": {
|
||||
"message": "Clear all"
|
||||
},
|
||||
"toggleCharacterCount": {
|
||||
"message": "Toggle character count",
|
||||
"description": "'Character count' describes a feature that displays a number next to each character of the password."
|
||||
},
|
||||
"passwordCharacterCount": {
|
||||
"message": "Password character count",
|
||||
"description": "'Character count' describes a feature that displays a number next to each character of the password."
|
||||
},
|
||||
"hide": {
|
||||
"message": "Hide"
|
||||
},
|
||||
"projects":{
|
||||
"message": "Projects"
|
||||
},
|
||||
|
||||
@@ -1,31 +1,3 @@
|
||||
.generated-wrapper {
|
||||
min-width: 0;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.password-row {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.password-letter {
|
||||
@include themify($themes) {
|
||||
color: themed("pwLetter");
|
||||
}
|
||||
}
|
||||
|
||||
.password-number {
|
||||
@include themify($themes) {
|
||||
color: themed("pwNumber");
|
||||
}
|
||||
}
|
||||
|
||||
.password-special {
|
||||
@include themify($themes) {
|
||||
color: themed("pwSpecial");
|
||||
}
|
||||
}
|
||||
|
||||
app-generator {
|
||||
#lengthRange {
|
||||
width: 100%;
|
||||
|
||||
@@ -201,9 +201,6 @@ $themes: (
|
||||
navBackgroundAlt: $secondary-alt,
|
||||
navOrgBackgroundColor: #fbfbfb,
|
||||
navWeight: 600,
|
||||
pwLetter: $body-color,
|
||||
pwNumber: #007fde,
|
||||
pwSpecial: #c40800,
|
||||
pwStrengthBackground: #e9ecef,
|
||||
separator: $secondary,
|
||||
separatorHr: rgb(0, 0, 0, 0.1),
|
||||
@@ -313,9 +310,6 @@ $themes: (
|
||||
navBackgroundAlt: $darkDarkBlue1,
|
||||
navOrgBackgroundColor: #161c26,
|
||||
navWeight: 400,
|
||||
pwLetter: $white,
|
||||
pwNumber: #52bdfb,
|
||||
pwSpecial: #ff7c70,
|
||||
pwStrengthBackground: $darkBlue2,
|
||||
separator: $darkBlue1,
|
||||
separatorHr: $darkBlue1,
|
||||
|
||||
Reference in New Issue
Block a user