mirror of
https://github.com/bitwarden/browser
synced 2025-12-19 09:43:23 +00:00
[PM-25037] add optional size input to app-vault-icon to prevent zoom issues (#17640)
This commit is contained in:
@@ -45,7 +45,11 @@
|
|||||||
tabindex="0"
|
tabindex="0"
|
||||||
[attr.aria-label]="'viewItem' | i18n"
|
[attr.aria-label]="'viewItem' | i18n"
|
||||||
>
|
>
|
||||||
<app-vault-icon *ngIf="row.iconCipher" [cipher]="row.iconCipher"></app-vault-icon>
|
<app-vault-icon
|
||||||
|
*ngIf="row.iconCipher"
|
||||||
|
[cipher]="row.iconCipher"
|
||||||
|
[size]="24"
|
||||||
|
></app-vault-icon>
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
class="tw-cursor-pointer"
|
class="tw-cursor-pointer"
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
<!-- Applying width and height styles directly to synchronize icon sizing between web/browser/desktop -->
|
<!-- Applying width and height styles directly to synchronize icon sizing between web/browser/desktop -->
|
||||||
<div
|
<div class="tw-flex tw-justify-center tw-items-center" [ngStyle]="iconStyle()" aria-hidden="true">
|
||||||
class="tw-flex tw-justify-center tw-items-center"
|
|
||||||
[ngStyle]="coloredIcon() ? { width: '36px', height: '36px' } : {}"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<ng-container *ngIf="data$ | async as data">
|
<ng-container *ngIf="data$ | async as data">
|
||||||
@if (data.imageEnabled && data.image) {
|
@if (data.imageEnabled && data.image) {
|
||||||
<img
|
<img
|
||||||
@@ -16,7 +12,7 @@
|
|||||||
'tw-invisible tw-absolute': !imageLoaded(),
|
'tw-invisible tw-absolute': !imageLoaded(),
|
||||||
'tw-size-6': !coloredIcon(),
|
'tw-size-6': !coloredIcon(),
|
||||||
}"
|
}"
|
||||||
[ngStyle]="coloredIcon() ? { width: '36px', height: '36px' } : {}"
|
[ngStyle]="iconStyle()"
|
||||||
(load)="imageLoaded.set(true)"
|
(load)="imageLoaded.set(true)"
|
||||||
(error)="imageLoaded.set(false)"
|
(error)="imageLoaded.set(false)"
|
||||||
/>
|
/>
|
||||||
@@ -28,7 +24,7 @@
|
|||||||
'tw-bg-illustration-bg-primary tw-rounded-full':
|
'tw-bg-illustration-bg-primary tw-rounded-full':
|
||||||
data.icon?.startsWith('bwi-') && coloredIcon(),
|
data.icon?.startsWith('bwi-') && coloredIcon(),
|
||||||
}"
|
}"
|
||||||
[ngStyle]="coloredIcon() ? { width: '36px', height: '36px' } : {}"
|
[ngStyle]="iconStyle()"
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
class="tw-text-muted bwi bwi-lg {{ data.icon }}"
|
class="tw-text-muted bwi bwi-lg {{ data.icon }}"
|
||||||
@@ -36,6 +32,7 @@
|
|||||||
color: coloredIcon() ? 'rgb(var(--color-illustration-outline))' : null,
|
color: coloredIcon() ? 'rgb(var(--color-illustration-outline))' : null,
|
||||||
width: data.icon?.startsWith('credit-card') && coloredIcon() ? '36px' : null,
|
width: data.icon?.startsWith('credit-card') && coloredIcon() ? '36px' : null,
|
||||||
height: data.icon?.startsWith('credit-card') && coloredIcon() ? '30px' : null,
|
height: data.icon?.startsWith('credit-card') && coloredIcon() ? '30px' : null,
|
||||||
|
fontSize: size() ? size() + 'px' : null,
|
||||||
}"
|
}"
|
||||||
></i>
|
></i>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ChangeDetectionStrategy, Component, input, signal } from "@angular/core";
|
import { ChangeDetectionStrategy, Component, computed, input, signal } from "@angular/core";
|
||||||
import { toObservable } from "@angular/core/rxjs-interop";
|
import { toObservable } from "@angular/core/rxjs-interop";
|
||||||
import {
|
import {
|
||||||
combineLatest,
|
combineLatest,
|
||||||
@@ -32,8 +32,32 @@ export class IconComponent {
|
|||||||
*/
|
*/
|
||||||
readonly coloredIcon = input<boolean>(false);
|
readonly coloredIcon = input<boolean>(false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional custom size for the icon in pixels.
|
||||||
|
* When provided, forces explicit dimensions on the icon wrapper to prevent layout collapse at different zoom levels.
|
||||||
|
* If not provided, the wrapper has no explicit dimensions and relies on CSS classes (tw-size-6/24px for images).
|
||||||
|
* This can cause the wrapper to collapse when images are loading/hidden, especially at high browser zoom levels.
|
||||||
|
* Reference: default image size is tw-size-6 (24px), coloredIcon uses 36px.
|
||||||
|
*/
|
||||||
|
readonly size = input<number>();
|
||||||
|
|
||||||
readonly imageLoaded = signal(false);
|
readonly imageLoaded = signal(false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computed style object for icon dimensions.
|
||||||
|
* Centralizes the sizing logic to avoid repetition in the template.
|
||||||
|
*/
|
||||||
|
protected readonly iconStyle = computed(() => {
|
||||||
|
if (this.coloredIcon()) {
|
||||||
|
return { width: "36px", height: "36px" };
|
||||||
|
}
|
||||||
|
const size = this.size();
|
||||||
|
if (size) {
|
||||||
|
return { width: size + "px", height: size + "px" };
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
|
||||||
protected data$: Observable<CipherIconDetails>;
|
protected data$: Observable<CipherIconDetails>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|||||||
Reference in New Issue
Block a user