88 lines
2.7 KiB
TypeScript
88 lines
2.7 KiB
TypeScript
import { Component } from '@angular/core';
|
|
import { faCheckCircle, faTimesCircle } from '@fortawesome/free-regular-svg-icons';
|
|
import { Toast, ToastService } from './toast.service';
|
|
|
|
@Component({
|
|
selector: 'app-toasts',
|
|
standalone: false,
|
|
template: `
|
|
<div class="toasts" aria-live="polite">
|
|
<div *ngFor="let toast of toastService.toasts" class="toast" [class.err]="toast.error">
|
|
<fa-icon [icon]="toast.error ? faTimesCircle : faCheckCircle" class="t-icon"></fa-icon>
|
|
<span class="t-msg">{{ toast.message }}</span>
|
|
<button *ngIf="toast.actionLabel" type="button" class="t-act" (click)="toastService.runAction(toast)">
|
|
{{ toast.actionLabel }}
|
|
</button>
|
|
<button type="button" class="t-close" (click)="toastService.dismiss(toast.id)" aria-label="关闭">
|
|
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
`,
|
|
styles: [`
|
|
:host { display: block; }
|
|
.toasts {
|
|
position: fixed;
|
|
right: 20px;
|
|
bottom: 20px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
z-index: 60;
|
|
}
|
|
.toast {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
background: var(--surface);
|
|
border: 1px solid var(--border);
|
|
border-left: 3px solid var(--accent);
|
|
border-radius: 8px;
|
|
padding: 11px 14px;
|
|
font-size: 13px;
|
|
color: var(--fg);
|
|
box-shadow: 0 8px 24px oklch(30% 0.02 240 / 0.14);
|
|
min-width: 260px;
|
|
max-width: min(420px, calc(100vw - 40px));
|
|
animation: toast-in 0.25s ease;
|
|
}
|
|
.toast.err { border-left-color: var(--danger); }
|
|
.t-icon { flex: none; color: var(--accent-strong); }
|
|
.toast.err .t-icon { color: var(--danger); }
|
|
.t-msg { flex: 1; }
|
|
.t-act {
|
|
flex: none;
|
|
border: none;
|
|
background: none;
|
|
color: var(--accent-strong);
|
|
font-size: 12.5px;
|
|
font-weight: 550;
|
|
padding: 2px 4px;
|
|
border-radius: 4px;
|
|
white-space: nowrap;
|
|
}
|
|
.t-act:hover { background: var(--accent-tint); }
|
|
.t-close {
|
|
flex: none;
|
|
width: 20px;
|
|
height: 20px;
|
|
display: grid;
|
|
place-items: center;
|
|
border: none;
|
|
background: none;
|
|
color: var(--muted);
|
|
border-radius: 4px;
|
|
}
|
|
.t-close:hover { background: var(--bg); color: var(--fg); }
|
|
@keyframes toast-in {
|
|
from { opacity: 0; transform: translateY(8px); }
|
|
}
|
|
`]
|
|
})
|
|
export class ToastsComponent {
|
|
faCheckCircle = faCheckCircle;
|
|
faTimesCircle = faTimesCircle;
|
|
|
|
constructor(public toastService: ToastService) {}
|
|
}
|