[PM-10934] Remove last form-field bottom border (#10751)
* match API of new CL FormField component * remove readonly border for additional options component * remove readonly border for last autofill option * remove readonly border for last custom-field form field * remove readonly border for when collection,org or folder is available * add `ReadOnlyCipherCardComponent` to handle readonly border * remove readonly border for the last identity form field * remove readonly border for the last card form field * remove readonly border for the last login form field * remove unneeded true value
This commit is contained in:
parent
192fd885d5
commit
3e9fb2009e
|
@ -1,6 +1,7 @@
|
||||||
import { coerceBooleanProperty } from "@angular/cdk/coercion";
|
import { coerceBooleanProperty } from "@angular/cdk/coercion";
|
||||||
import {
|
import {
|
||||||
AfterContentChecked,
|
AfterContentChecked,
|
||||||
|
booleanAttribute,
|
||||||
Component,
|
Component,
|
||||||
ContentChild,
|
ContentChild,
|
||||||
ContentChildren,
|
ContentChildren,
|
||||||
|
@ -38,6 +39,13 @@ export class BitFormFieldComponent implements AfterContentChecked {
|
||||||
return this._disableMargin;
|
return this._disableMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTE: Placeholder to match the API of the form-field component in the `ps/extension` branch,
|
||||||
|
* no functionality is implemented as of now.
|
||||||
|
*/
|
||||||
|
@Input({ transform: booleanAttribute })
|
||||||
|
disableReadOnlyBorder = false;
|
||||||
|
|
||||||
@HostBinding("class")
|
@HostBinding("class")
|
||||||
get classList() {
|
get classList() {
|
||||||
return ["tw-block"].concat(this.disableMargin ? [] : ["tw-mb-6"]);
|
return ["tw-block"].concat(this.disableMargin ? [] : ["tw-mb-6"]);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<h2 bitTypography="h6">{{ "additionalOptions" | i18n }}</h2>
|
<h2 bitTypography="h6">{{ "additionalOptions" | i18n }}</h2>
|
||||||
</bit-section-header>
|
</bit-section-header>
|
||||||
<bit-card class="[&_bit-form-field:last-of-type]:tw-mb-0">
|
<bit-card class="[&_bit-form-field:last-of-type]:tw-mb-0">
|
||||||
<bit-form-field>
|
<bit-form-field disableReadOnlyBorder>
|
||||||
<bit-label>{{ "note" | i18n }}</bit-label>
|
<bit-label>{{ "note" | i18n }}</bit-label>
|
||||||
<textarea readonly bitInput aria-readonly="true">{{ notes }}</textarea>
|
<textarea readonly bitInput aria-readonly="true">{{ notes }}</textarea>
|
||||||
<button
|
<button
|
||||||
|
|
|
@ -4,7 +4,11 @@
|
||||||
</bit-section-header>
|
</bit-section-header>
|
||||||
<bit-card>
|
<bit-card>
|
||||||
<ng-container *ngFor="let login of loginUris; let last = last">
|
<ng-container *ngFor="let login of loginUris; let last = last">
|
||||||
<bit-form-field [disableMargin]="last" data-testid="autofill-view-list">
|
<bit-form-field
|
||||||
|
[disableMargin]="last"
|
||||||
|
[disableReadOnlyBorder]="last"
|
||||||
|
data-testid="autofill-view-list"
|
||||||
|
>
|
||||||
<bit-label>
|
<bit-label>
|
||||||
{{ "website" | i18n }}
|
{{ "website" | i18n }}
|
||||||
</bit-label>
|
</bit-label>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<bit-section-header>
|
<bit-section-header>
|
||||||
<h2 bitTypography="h6">{{ setSectionTitle }}</h2>
|
<h2 bitTypography="h6">{{ setSectionTitle }}</h2>
|
||||||
</bit-section-header>
|
</bit-section-header>
|
||||||
<bit-card class="[&_bit-form-field:last-of-type]:tw-mb-0">
|
<read-only-cipher-card>
|
||||||
<bit-form-field *ngIf="card.cardholderName">
|
<bit-form-field *ngIf="card.cardholderName">
|
||||||
<bit-label>{{ "cardholderName" | i18n }}</bit-label>
|
<bit-label>{{ "cardholderName" | i18n }}</bit-label>
|
||||||
<input
|
<input
|
||||||
|
@ -81,5 +81,5 @@
|
||||||
data-testid="copy-code"
|
data-testid="copy-code"
|
||||||
></button>
|
></button>
|
||||||
</bit-form-field>
|
</bit-form-field>
|
||||||
</bit-card>
|
</read-only-cipher-card>
|
||||||
</bit-section>
|
</bit-section>
|
||||||
|
|
|
@ -13,6 +13,8 @@ import {
|
||||||
IconButtonModule,
|
IconButtonModule,
|
||||||
} from "@bitwarden/components";
|
} from "@bitwarden/components";
|
||||||
|
|
||||||
|
import { ReadOnlyCipherCardComponent } from "../read-only-cipher-card/read-only-cipher-card.component";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-card-details-view",
|
selector: "app-card-details-view",
|
||||||
templateUrl: "card-details-view.component.html",
|
templateUrl: "card-details-view.component.html",
|
||||||
|
@ -26,6 +28,7 @@ import {
|
||||||
TypographyModule,
|
TypographyModule,
|
||||||
FormFieldModule,
|
FormFieldModule,
|
||||||
IconButtonModule,
|
IconButtonModule,
|
||||||
|
ReadOnlyCipherCardComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class CardDetailsComponent {
|
export class CardDetailsComponent {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*ngFor="let field of fields; let last = last"
|
*ngFor="let field of fields; let last = last"
|
||||||
[ngClass]="{ 'tw-mb-4': !last }"
|
[ngClass]="{ 'tw-mb-4': !last }"
|
||||||
>
|
>
|
||||||
<bit-form-field *ngIf="field.type === fieldType.Text">
|
<bit-form-field *ngIf="field.type === fieldType.Text" [disableReadOnlyBorder]="last">
|
||||||
<bit-label>{{ field.name }}</bit-label>
|
<bit-label>{{ field.name }}</bit-label>
|
||||||
<input readonly bitInput type="text" [value]="field.value" aria-readonly="true" />
|
<input readonly bitInput type="text" [value]="field.value" aria-readonly="true" />
|
||||||
<button
|
<button
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
[appA11yTitle]="'copyValue' | i18n"
|
[appA11yTitle]="'copyValue' | i18n"
|
||||||
></button>
|
></button>
|
||||||
</bit-form-field>
|
</bit-form-field>
|
||||||
<bit-form-field *ngIf="field.type === fieldType.Hidden">
|
<bit-form-field *ngIf="field.type === fieldType.Hidden" [disableReadOnlyBorder]="last">
|
||||||
<bit-label>{{ field.name }}</bit-label>
|
<bit-label>{{ field.name }}</bit-label>
|
||||||
<input readonly bitInput type="password" [value]="field.value" aria-readonly="true" />
|
<input readonly bitInput type="password" [value]="field.value" aria-readonly="true" />
|
||||||
<button bitSuffix type="button" bitIconButton bitPasswordInputToggle></button>
|
<button bitSuffix type="button" bitIconButton bitPasswordInputToggle></button>
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
/>
|
/>
|
||||||
<bit-label> {{ field.name }} </bit-label>
|
<bit-label> {{ field.name }} </bit-label>
|
||||||
</bit-form-control>
|
</bit-form-control>
|
||||||
<bit-form-field *ngIf="field.type === fieldType.Linked">
|
<bit-form-field *ngIf="field.type === fieldType.Linked" [disableReadOnlyBorder]="last">
|
||||||
<bit-label> {{ "linked" | i18n }}: {{ field.name }} </bit-label>
|
<bit-label> {{ "linked" | i18n }}: {{ field.name }} </bit-label>
|
||||||
<input
|
<input
|
||||||
readonly
|
readonly
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
<bit-card>
|
<bit-card>
|
||||||
<bit-form-field
|
<bit-form-field
|
||||||
[disableMargin]="!cipher.collectionIds?.length && !cipher.organizationId && !cipher.folderId"
|
[disableMargin]="!cipher.collectionIds?.length && !cipher.organizationId && !cipher.folderId"
|
||||||
|
[disableReadOnlyBorder]="
|
||||||
|
!cipher.collectionIds?.length && !cipher.organizationId && !cipher.folderId
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<bit-label>
|
<bit-label>
|
||||||
{{ "itemName" | i18n }}
|
{{ "itemName" | i18n }}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<bit-section-header>
|
<bit-section-header>
|
||||||
<h2 bitTypography="h6">{{ "loginCredentials" | i18n }}</h2>
|
<h2 bitTypography="h6">{{ "loginCredentials" | i18n }}</h2>
|
||||||
</bit-section-header>
|
</bit-section-header>
|
||||||
<bit-card class="[&_bit-form-field:last-of-type]:tw-mb-0">
|
<read-only-cipher-card>
|
||||||
<bit-form-field *ngIf="cipher.login.username">
|
<bit-form-field *ngIf="cipher.login.username">
|
||||||
<bit-label>
|
<bit-label>
|
||||||
{{ "username" | i18n }}
|
{{ "username" | i18n }}
|
||||||
|
@ -132,5 +132,5 @@
|
||||||
class="disabled:tw-cursor-default"
|
class="disabled:tw-cursor-default"
|
||||||
></button>
|
></button>
|
||||||
</bit-form-field>
|
</bit-form-field>
|
||||||
</bit-card>
|
</read-only-cipher-card>
|
||||||
</bit-section>
|
</bit-section>
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
} from "@bitwarden/components";
|
} from "@bitwarden/components";
|
||||||
|
|
||||||
import { BitTotpCountdownComponent } from "../../components/totp-countdown/totp-countdown.component";
|
import { BitTotpCountdownComponent } from "../../components/totp-countdown/totp-countdown.component";
|
||||||
|
import { ReadOnlyCipherCardComponent } from "../read-only-cipher-card/read-only-cipher-card.component";
|
||||||
|
|
||||||
type TotpCodeValues = {
|
type TotpCodeValues = {
|
||||||
totpCode: string;
|
totpCode: string;
|
||||||
|
@ -41,6 +42,7 @@ type TotpCodeValues = {
|
||||||
BadgeModule,
|
BadgeModule,
|
||||||
ColorPasswordModule,
|
ColorPasswordModule,
|
||||||
BitTotpCountdownComponent,
|
BitTotpCountdownComponent,
|
||||||
|
ReadOnlyCipherCardComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class LoginCredentialsViewComponent {
|
export class LoginCredentialsViewComponent {
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<bit-card class="[&_bit-form-field:last-of-type]:tw-mb-0">
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</bit-card>
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { AfterViewInit, Component, ContentChildren, QueryList } from "@angular/core";
|
||||||
|
|
||||||
|
import { CardComponent, BitFormFieldComponent } from "@bitwarden/components";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "read-only-cipher-card",
|
||||||
|
templateUrl: "./read-only-cipher-card.component.html",
|
||||||
|
standalone: true,
|
||||||
|
imports: [CardComponent],
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* A thin wrapper around the `bit-card` component that disables the bottom border for the last form field.
|
||||||
|
*/
|
||||||
|
export class ReadOnlyCipherCardComponent implements AfterViewInit {
|
||||||
|
@ContentChildren(BitFormFieldComponent) formFields: QueryList<BitFormFieldComponent>;
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
// Disable the bottom border for the last form field
|
||||||
|
if (this.formFields.last) {
|
||||||
|
// Delay model update until next change detection cycle
|
||||||
|
setTimeout(() => {
|
||||||
|
this.formFields.last.disableReadOnlyBorder = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
<h2 bitTypography="h6">{{ "personalDetails" | i18n }}</h2>
|
<h2 bitTypography="h6">{{ "personalDetails" | i18n }}</h2>
|
||||||
</bit-section-header>
|
</bit-section-header>
|
||||||
|
|
||||||
<bit-card class="[&_bit-form-field:last-of-type]:tw-mb-0">
|
<read-only-cipher-card>
|
||||||
<bit-form-field *ngIf="cipher.identity.fullName">
|
<bit-form-field *ngIf="cipher.identity.fullName">
|
||||||
<bit-label>{{ "name" | i18n }}</bit-label>
|
<bit-label>{{ "name" | i18n }}</bit-label>
|
||||||
<input bitInput [value]="cipher.identity.fullName" readonly data-testid="name" />
|
<input bitInput [value]="cipher.identity.fullName" readonly data-testid="name" />
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
[valueLabel]="'company' | i18n"
|
[valueLabel]="'company' | i18n"
|
||||||
></button>
|
></button>
|
||||||
</bit-form-field>
|
</bit-form-field>
|
||||||
</bit-card>
|
</read-only-cipher-card>
|
||||||
</bit-section>
|
</bit-section>
|
||||||
|
|
||||||
<bit-section *ngIf="showIdentificationDetails">
|
<bit-section *ngIf="showIdentificationDetails">
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
<h2 bitTypography="h6">{{ "identification" | i18n }}</h2>
|
<h2 bitTypography="h6">{{ "identification" | i18n }}</h2>
|
||||||
</bit-section-header>
|
</bit-section-header>
|
||||||
|
|
||||||
<bit-card class="[&_bit-form-field:last-of-type]:tw-mb-0">
|
<read-only-cipher-card>
|
||||||
<bit-form-field *ngIf="cipher.identity.ssn">
|
<bit-form-field *ngIf="cipher.identity.ssn">
|
||||||
<bit-label>{{ "ssn" | i18n }}</bit-label>
|
<bit-label>{{ "ssn" | i18n }}</bit-label>
|
||||||
<input bitInput type="password" [value]="cipher.identity.ssn" readonly data-testid="ssn" />
|
<input bitInput type="password" [value]="cipher.identity.ssn" readonly data-testid="ssn" />
|
||||||
|
@ -111,7 +111,7 @@
|
||||||
[valueLabel]="'licenseNumber' | i18n"
|
[valueLabel]="'licenseNumber' | i18n"
|
||||||
></button>
|
></button>
|
||||||
</bit-form-field>
|
</bit-form-field>
|
||||||
</bit-card>
|
</read-only-cipher-card>
|
||||||
</bit-section>
|
</bit-section>
|
||||||
|
|
||||||
<bit-section *ngIf="showContactDetails">
|
<bit-section *ngIf="showContactDetails">
|
||||||
|
@ -119,7 +119,7 @@
|
||||||
<h2 bitTypography="h6">{{ "contactInfo" | i18n }}</h2>
|
<h2 bitTypography="h6">{{ "contactInfo" | i18n }}</h2>
|
||||||
</bit-section-header>
|
</bit-section-header>
|
||||||
|
|
||||||
<bit-card class="[&_bit-form-field:last-of-type]:tw-mb-0">
|
<read-only-cipher-card>
|
||||||
<bit-form-field *ngIf="cipher.identity.email">
|
<bit-form-field *ngIf="cipher.identity.email">
|
||||||
<bit-label>{{ "email" | i18n }}</bit-label>
|
<bit-label>{{ "email" | i18n }}</bit-label>
|
||||||
<input bitInput [value]="cipher.identity.email" readonly data-testid="email" />
|
<input bitInput [value]="cipher.identity.email" readonly data-testid="email" />
|
||||||
|
@ -166,5 +166,5 @@
|
||||||
[valueLabel]="'address' | i18n"
|
[valueLabel]="'address' | i18n"
|
||||||
></button>
|
></button>
|
||||||
</bit-form-field>
|
</bit-form-field>
|
||||||
</bit-card>
|
</read-only-cipher-card>
|
||||||
</bit-section>
|
</bit-section>
|
||||||
|
|
|
@ -12,6 +12,8 @@ import {
|
||||||
TypographyModule,
|
TypographyModule,
|
||||||
} from "@bitwarden/components";
|
} from "@bitwarden/components";
|
||||||
|
|
||||||
|
import { ReadOnlyCipherCardComponent } from "../read-only-cipher-card/read-only-cipher-card.component";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
standalone: true,
|
standalone: true,
|
||||||
selector: "app-view-identity-sections",
|
selector: "app-view-identity-sections",
|
||||||
|
@ -25,6 +27,7 @@ import {
|
||||||
TypographyModule,
|
TypographyModule,
|
||||||
FormFieldModule,
|
FormFieldModule,
|
||||||
IconButtonModule,
|
IconButtonModule,
|
||||||
|
ReadOnlyCipherCardComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class ViewIdentitySectionsComponent implements OnInit {
|
export class ViewIdentitySectionsComponent implements OnInit {
|
||||||
|
|
Loading…
Reference in New Issue