1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-24 16:43:27 +00:00

[CL-1022] Update Berry Styles (#18799)

* created 'berry' component

* added 'bit-berry' to 'popup-tab-navigation'

* simplified - removed null checks

* changed 'effectiveSize' to 'computedSize'

* fixed 'accentPrimary' color

* updated to not render berry if 'count' is 0 or negative number

* simplified checking count undefined

* updated computed padding

* switched from `[ngClass]` to `[class]`

* updated 'popup-tab-navigation' berry to use 'danger' variant

* fixed berry positioning in popup-tab-navigation

* updated content logic

* cleanup unused 'ngClass'

* updated conditional rendering of berry

* updated story 'Usage'

* updates with adding berry 'type'

* added type "status" to popup-tab-navigation

* fixed type error

* updated 'Count Behavior' description
This commit is contained in:
Leslie Xiong
2026-02-11 12:21:33 -05:00
committed by jaasen-livefront
parent 9c0365f6d1
commit 03875dcf05
9 changed files with 305 additions and 4 deletions

View File

@@ -0,0 +1,80 @@
import { ChangeDetectionStrategy, Component, computed, input } from "@angular/core";
export type BerryVariant =
| "primary"
| "subtle"
| "success"
| "warning"
| "danger"
| "accentPrimary"
| "contrast";
/**
* The berry component is a compact visual indicator used to display short,
* supplemental status information about another element,
* like a navigation item, button, or icon button.
* They draw users attention to status changes or new notifications.
*
* > `NOTE:` The maximum displayed value is 999. If the value is over 999, a “+” character is appended to indicate more.
*/
@Component({
selector: "bit-berry",
templateUrl: "berry.component.html",
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class BerryComponent {
protected readonly variant = input<BerryVariant>("primary");
protected readonly value = input<number>();
protected readonly type = input<"status" | "count">("count");
protected readonly content = computed(() => {
const value = this.value();
const type = this.type();
if (type === "status" || !value || value < 0) {
return undefined;
}
return value > 999 ? "999+" : `${value}`;
});
protected readonly textColor = computed(() => {
return this.variant() === "contrast" ? "tw-text-fg-dark" : "tw-text-fg-white";
});
protected readonly padding = computed(() => {
return (this.value()?.toString().length ?? 0) > 2 ? "tw-px-1.5 tw-py-0.5" : "";
});
protected readonly containerClasses = computed(() => {
const baseClasses = [
"tw-inline-flex",
"tw-items-center",
"tw-justify-center",
"tw-align-middle",
"tw-text-xxs",
"tw-rounded-full",
];
const typeClasses = {
status: ["tw-h-2", "tw-w-2"],
count: ["tw-h-4", "tw-min-w-4", this.padding()],
};
const variantClass = {
primary: "tw-bg-bg-brand",
subtle: "tw-bg-bg-contrast",
success: "tw-bg-bg-success",
warning: "tw-bg-bg-warning",
danger: "tw-bg-bg-danger",
accentPrimary: "tw-bg-fg-accent-primary-strong",
contrast: "tw-bg-bg-white",
};
return [
...baseClasses,
...typeClasses[this.type()],
variantClass[this.variant()],
this.textColor(),
].join(" ");
});
}