/* * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung * * Lizenziert unter der EUPL, Version 1.2 oder - sobald * diese von der Europäischen Kommission genehmigt wurden - * Folgeversionen der EUPL ("Lizenz"); * Sie dürfen dieses Werk ausschließlich gemäß * dieser Lizenz nutzen. * Eine Kopie der Lizenz finden Sie hier: * * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 * * Sofern nicht durch anwendbare Rechtsvorschriften * gefordert oder in schriftlicher Form vereinbart, wird * die unter der Lizenz verbreitete Software "so wie sie * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - * ausdrücklich oder stillschweigend - verbreitet. * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { CommonModule } from '@angular/common'; import { booleanAttribute, Component, EventEmitter, Input, Output } from '@angular/core'; import { cva, VariantProps } from 'class-variance-authority'; import { IconVariants } from '../icons/iconVariants'; import { SpinnerIconComponent } from '../icons/spinner-icon/spinner-icon.component'; export const buttonVariants = cva( [ 'flex items-center gap-3 rounded-lg text-sm font-medium box-border', 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 outline-focus', ], { variants: { variant: { primary: 'bg-primary text-whitetext shadow-md hover:bg-primary-hover focus-visible:bg-primary-hover', outline: 'border border-primary bg-background-50 text-primary shadow-md hover:bg-ghost-hover focus-visible:bg-ghost-hover focus-visible:border-background-200', outline_error: 'border border-error bg-background-50 text-error shadow-md hover:bg-ghost-hover focus-visible:bg-ghost-hover focus-visible:border-background-200', ghost: 'border border-transparent hover:bg-ghost-hover text-primary focus-visible:border-background-200 focus-visible:bg-ghost-hover font-semibold [&]:focus-visible:outline-offset-1', }, size: { medium: 'h-9 py-2 px-4 min-w-32', fit: 'h-fit p-2', }, disabled: { false: null, true: '[&]:outline-disabled-button cursor-not-allowed', }, destructive: { false: null, true: '[&]:outline-destructive', }, }, defaultVariants: { variant: 'primary', size: 'medium', disabled: false, }, compoundVariants: [ { variant: 'primary', destructive: true, class: '[&]:hover:bg-destructive-primary-hover [&]:bg-destructive [&]:focus-visible:bg-destructive-primary-hover', }, { variant: 'outline', destructive: true, class: '[&]:border-destructive [&]:text-destructive [&]:hover:bg-destructive-hover [&]:focus-visible:bg-destructive-hover', }, { variant: 'ghost', destructive: true, class: '[&]:text-destructive [&]:hover:bg-destructive-hover [&]:focus-visible:bg-destructive-hover', }, { variant: 'primary', disabled: true, class: '[&]:bg-disabled-button [&]:hover:bg-disabled-button/90 [&]:focus-visible:bg-disabled-button/90', }, { variant: 'outline', disabled: true, class: '[&]:text-disabled-button [&]:border-disabled-button [&]:hover:bg-disabled-button/10 [&]:focus-visible:bg-disabled-button/10', }, { variant: 'ghost', disabled: true, class: '[&]:text-disabled-button [&]:hover:bg-disabled-button/10 [&]:focus-visible:bg-disabled-button/10', }, ], }, ); export type ButtonVariants = VariantProps<typeof buttonVariants>; @Component({ selector: 'ods-button', standalone: true, imports: [CommonModule, SpinnerIconComponent], template: ` <button type="submit" [ngClass]="buttonVariants({ size, variant, disabled: isDisabled, destructive })" [attr.aria-disabled]="isDisabled" [attr.aria-label]="text" [attr.data-test-id]="dataTestId" [attr.data-test-class]="dataTestClass" (click)="onClick()" > @if (isLoading) { <ods-spinner-icon [class]="isDisabled && 'fill-disabled-button'" [size]="spinnerSize" data-test-class="spinner" /> } @else { <ng-content select="[icon]" /> } @if (text) { <p class="flex-grow">{{ text }}</p> } </button>`, }) export class ButtonComponent { @Input() text: string = ''; @Input() dataTestId: string = ''; @Input() dataTestClass: string = ''; @Input({ transform: booleanAttribute }) disabled: boolean = false; @Input({ transform: booleanAttribute }) isLoading: boolean = false; @Input({ transform: booleanAttribute }) destructive: boolean = false; @Input() variant: ButtonVariants['variant']; @Input() size: ButtonVariants['size']; @Input() spinnerSize: IconVariants['size'] = 'medium'; @Output() public clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>(); get isDisabled() { return this.disabled || this.isLoading; } public onClick(): void { if (!this.isDisabled) { this.clickEmitter.emit(); } } readonly buttonVariants = buttonVariants; }