mirror of
https://github.com/bitwarden/browser
synced 2026-02-10 05:30:01 +00:00
Allow custom icons in toasts
This commit is contained in:
@@ -5,7 +5,11 @@
|
||||
[attr.role]="variant === 'error' ? 'alert' : null"
|
||||
>
|
||||
<div class="tw-flex tw-items-center tw-gap-4 tw-px-2 tw-pb-1 tw-pt-2">
|
||||
<i aria-hidden="true" class="bwi tw-text-xl tw-py-1.5 tw-px-2.5 {{ iconClass }}"></i>
|
||||
@if (isIcon(icon)) {
|
||||
<bit-icon class="tw-text-xl tw-py-1.5 tw-px-2.5" [icon]="icon"></bit-icon>
|
||||
} @else {
|
||||
<i aria-hidden="true" class="bwi tw-text-xl tw-py-1.5 tw-px-2.5 {{ iconClass }}"></i>
|
||||
}
|
||||
<div>
|
||||
<span class="tw-sr-only">{{ variant | i18n }}</span>
|
||||
@if (title) {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
|
||||
import { Icon, isIcon } from "../icon";
|
||||
import { IconModule } from "../icon/icon.module";
|
||||
import { IconButtonModule } from "../icon-button";
|
||||
import { SharedModule } from "../shared";
|
||||
import { TypographyModule } from "../typography";
|
||||
@@ -29,9 +31,10 @@ const variants: Record<ToastVariant, { icon: string; bgColor: string }> = {
|
||||
selector: "bit-toast",
|
||||
templateUrl: "toast.component.html",
|
||||
standalone: true,
|
||||
imports: [SharedModule, IconButtonModule, TypographyModule],
|
||||
imports: [SharedModule, IconButtonModule, TypographyModule, IconModule],
|
||||
})
|
||||
export class ToastComponent {
|
||||
/** The variant of the toast */
|
||||
@Input() variant: ToastVariant = "info";
|
||||
|
||||
/**
|
||||
@@ -50,10 +53,25 @@ export class ToastComponent {
|
||||
**/
|
||||
@Input() progressWidth = 0;
|
||||
|
||||
/** An optional icon that overrides the existing variant definition
|
||||
* string if you want to a use a font icon, or an Icon object if you want to use an SVG icon.
|
||||
*/
|
||||
@Input() icon?: string | Icon;
|
||||
|
||||
/** Emits when the user presses the close button */
|
||||
@Output() onClose = new EventEmitter<void>();
|
||||
|
||||
/**
|
||||
* Checks if the provided icon is type of Icon and when that is true returns an Icon
|
||||
*/
|
||||
protected isIcon(icon: unknown): icon is Icon {
|
||||
return isIcon(icon);
|
||||
}
|
||||
|
||||
protected get iconClass(): string {
|
||||
if (typeof this.icon === "string" && this.icon !== "") {
|
||||
return this.icon;
|
||||
}
|
||||
return variants[this.variant].icon;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ export type ToastOptions = {
|
||||
* The duration the toast will persist in milliseconds
|
||||
**/
|
||||
timeout?: number;
|
||||
} & Pick<ToastComponent, "message" | "variant" | "title">;
|
||||
} & Pick<ToastComponent, "message" | "variant" | "title" | "icon">;
|
||||
|
||||
/**
|
||||
* Presents toast notifications
|
||||
@@ -26,6 +26,7 @@ export class ToastService {
|
||||
message: options.message,
|
||||
variant: options.variant,
|
||||
title: options.title,
|
||||
icon: options?.icon,
|
||||
},
|
||||
timeOut:
|
||||
options.timeout != null && options.timeout > 0
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Meta, StoryObj, applicationConfig, moduleMetadata } from "@storybook/an
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
import { ButtonModule } from "../button";
|
||||
import { Icons } from "../icon";
|
||||
import { I18nMockService } from "../utils/i18n-mock.service";
|
||||
|
||||
import { ToastComponent } from "./toast.component";
|
||||
@@ -76,10 +77,10 @@ export const Default: Story = {
|
||||
props: args,
|
||||
template: `
|
||||
<div class="tw-flex tw-flex-col tw-min-w tw-max-w-[--bit-toast-width]">
|
||||
<bit-toast [title]="title" [message]="message" [progressWidth]="progressWidth" (onClose)="onClose()" variant="success"></bit-toast>
|
||||
<bit-toast [title]="title" [message]="message" [progressWidth]="progressWidth" (onClose)="onClose()" variant="info"></bit-toast>
|
||||
<bit-toast [title]="title" [message]="message" [progressWidth]="progressWidth" (onClose)="onClose()" variant="warning"></bit-toast>
|
||||
<bit-toast [title]="title" [message]="message" [progressWidth]="progressWidth" (onClose)="onClose()" variant="error"></bit-toast>
|
||||
<bit-toast [title]="title" [message]="message" [progressWidth]="progressWidth" [icon]="icon" (onClose)="onClose()" variant="success"></bit-toast>
|
||||
<bit-toast [title]="title" [message]="message" [progressWidth]="progressWidth" [icon]="icon" (onClose)="onClose()" variant="info"></bit-toast>
|
||||
<bit-toast [title]="title" [message]="message" [progressWidth]="progressWidth" [icon]="icon" (onClose)="onClose()" variant="warning"></bit-toast>
|
||||
<bit-toast [title]="title" [message]="message" [progressWidth]="progressWidth" [icon]="icon" (onClose)="onClose()" variant="error"></bit-toast>
|
||||
</div>
|
||||
`,
|
||||
}),
|
||||
@@ -99,6 +100,24 @@ export const LongContent: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
export const WithCustomIconFromFont: Story = {
|
||||
...Default,
|
||||
args: {
|
||||
title: "Foo",
|
||||
message: ["With custom icon from font"],
|
||||
icon: "bwi-send-f",
|
||||
},
|
||||
};
|
||||
|
||||
export const WithCustomIconUsingSvg: Story = {
|
||||
...Default,
|
||||
args: {
|
||||
title: "Foo",
|
||||
message: ["With custom svg icon"],
|
||||
icon: Icons.Search,
|
||||
},
|
||||
};
|
||||
|
||||
export const Service: Story = {
|
||||
render: (args) => ({
|
||||
props: {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ToastComponent } from "./toast.component";
|
||||
[title]="options?.payload?.title"
|
||||
[variant]="options?.payload?.variant"
|
||||
[message]="options?.payload?.message"
|
||||
[icon]="options?.payload?.icon"
|
||||
[progressWidth]="width()"
|
||||
(onClose)="remove()"
|
||||
></bit-toast>
|
||||
|
||||
Reference in New Issue
Block a user