From 5dbcb18b6a77d12b02ba3b6a72b218d5e8742bc3 Mon Sep 17 00:00:00 2001
From: Alex <55413326+AlexRubik@users.noreply.github.com>
Date: Tue, 9 Dec 2025 12:16:21 -0500
Subject: [PATCH] [PM-25037] add optional size input to app-vault-icon to
prevent zoom issues (#17640)
---
.../app-table-row-scrollable.component.html | 6 ++++-
.../src/vault/components/icon.component.html | 11 +++-----
.../src/vault/components/icon.component.ts | 26 ++++++++++++++++++-
3 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/shared/app-table-row-scrollable.component.html b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/shared/app-table-row-scrollable.component.html
index 76a03e0c525..0494f77bd46 100644
--- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/shared/app-table-row-scrollable.component.html
+++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/shared/app-table-row-scrollable.component.html
@@ -45,7 +45,11 @@
tabindex="0"
[attr.aria-label]="'viewItem' | i18n"
>
-
+
-
+
@if (data.imageEnabled && data.image) {
@@ -28,7 +24,7 @@
'tw-bg-illustration-bg-primary tw-rounded-full':
data.icon?.startsWith('bwi-') && coloredIcon(),
}"
- [ngStyle]="coloredIcon() ? { width: '36px', height: '36px' } : {}"
+ [ngStyle]="iconStyle()"
>
diff --git a/libs/angular/src/vault/components/icon.component.ts b/libs/angular/src/vault/components/icon.component.ts
index 851cec5656b..1037c9b3974 100644
--- a/libs/angular/src/vault/components/icon.component.ts
+++ b/libs/angular/src/vault/components/icon.component.ts
@@ -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 {
combineLatest,
@@ -32,8 +32,32 @@ export class IconComponent {
*/
readonly coloredIcon = input (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();
+
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;
constructor(
|