Skip to content
Snippets Groups Projects
Commit 0c239881 authored by Alexander Reifschneider's avatar Alexander Reifschneider
Browse files

OZG-725 Add styling

Sub-Task: OZG-7894
parent 8bb29032
No related branches found
No related tags found
1 merge request!103OZG-725-ui-styling
Showing
with 90 additions and 35 deletions
......@@ -54,7 +54,7 @@ describe('ButtonComponent', () => {
expect(component.clickEmitter.emit).toHaveBeenCalled();
});
it('should NOT emit click', () => {
it('should NOT emit click if button is disabled', () => {
component.disabled = true;
fixture.detectChanges();
......
......@@ -31,18 +31,18 @@ import { SpinnerIconComponent } from '../icons/spinner-icon/spinner-icon.compone
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',
'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 outline-focus',
],
{
variants: {
variant: {
primary: 'bg-primary text-whitetext shadow-md hover:enabled:bg-primary-hover focus-visible:bg-primary-hover',
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:enabled:bg-ghost-hover focus-visible:bg-ghost-hover focus-visible:border-background-200',
'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:enabled:bg-ghost-hover focus-visible:bg-ghost-hover focus-visible:border-background-200',
'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:enabled:bg-ghost-hover text-primary focus-visible:border-background-200 focus-visible:bg-ghost-hover font-semibold [&]:focus-visible:outline-offset-1',
'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',
......@@ -50,11 +50,11 @@ export const buttonVariants = cva(
},
disabled: {
false: null,
true: ['opacity-70', 'cursor-not-allowed'],
true: '[&]:outline-disabled-button cursor-not-allowed',
},
destructive: {
false: 'outline-focus',
true: 'outline-destructive',
false: null,
true: '[&]:outline-destructive',
},
},
defaultVariants: {
......@@ -66,19 +66,34 @@ export const buttonVariants = cva(
{
variant: 'primary',
destructive: true,
class:
'[&]:hover:enabled:bg-destructive-primary-hover [&]:bg-destructive [&]:outline-destructive [&]:focus-visible:bg-destructive-primary-hover',
class: '[&]:hover:bg-destructive-primary-hover [&]:bg-destructive [&]:focus-visible:bg-destructive-primary-hover',
},
{
variant: 'outline',
destructive: true,
class:
'[&]:border-destructive [&]:text-destructive [&]:hover:enabled:bg-destructive-hover [&]:focus-visible:bg-destructive-hover',
'[&]:border-destructive [&]:text-destructive [&]:hover:bg-destructive-hover [&]:focus-visible:bg-destructive-hover',
},
{
variant: 'ghost',
destructive: true,
class: '[&]:text-destructive [&]:hover:enabled:bg-destructive-hover [&]:focus-visible:bg-destructive-hover',
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',
},
],
},
......@@ -98,17 +113,22 @@ export type ButtonVariants = VariantProps<typeof buttonVariants>;
[attr.data-test-class]="dataTestClass"
(click)="onClick()"
>
<ng-content *ngIf="!isLoading" select="[icon]"></ng-content>
<ods-spinner-icon *ngIf="isLoading" [size]="spinnerSize" data-test-class="spinner"></ods-spinner-icon>
<div *ngIf="text" class="flex-grow">{{ text }}</div>
@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() disabled: boolean = false;
@Input() isLoading: boolean = false;
@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'];
......
......@@ -24,6 +24,7 @@
import { NgClass } from '@angular/common';
import { Component, Input } from '@angular/core';
import { twMerge } from 'tailwind-merge';
import { IconVariants, iconVariants } from '../iconVariants';
@Component({
......@@ -33,8 +34,7 @@ import { IconVariants, iconVariants } from '../iconVariants';
template: `
<svg
xmlns="http://www.w3.org/2000/svg"
[ngClass]="iconVariants({ size })"
class="animate-spin fill-primary text-gray-200 dark:text-gray-600"
[ngClass]="twMerge('animate-spin fill-primary text-gray-200 dark:text-gray-600', iconVariants({ size }), class)"
aria-hidden="true"
viewBox="0 0 100 100"
fill="none"
......@@ -53,6 +53,8 @@ import { IconVariants, iconVariants } from '../iconVariants';
})
export class SpinnerIconComponent {
@Input() size: IconVariants['size'] = 'full';
@Input() class: string;
iconVariants = iconVariants;
readonly iconVariants = iconVariants;
readonly twMerge = twMerge;
}
......@@ -18,6 +18,7 @@
--color-disabled: 206 14% 95%;
--color-disabled-dark: 208 12% 65%;
--color-disabled-button: 0 0% 42%;
--color-destructive: 360, 71%, 49%, 1;
--color-destructive-hover: 360, 71%, 49%, 0.07;
......@@ -59,6 +60,7 @@
--color-disabled: 206 14% 15%;
--color-disabled-dark: 208 12% 33%;
--color-disabled-button: 0 0% 68%;
--color-destructive: 360, 71%, 49%, 1;
--color-destructive-hover: 360, 71%, 49%, 0.2;
......
......@@ -146,6 +146,7 @@ module.exports = {
focus: 'hsl(var(--color-focus))',
disabled: {
dark: 'hsl(var(--color-disabled-dark) / <alpha-value>)',
button: 'hsl(var(--color-disabled-button) / <alpha-value>)',
DEFAULT: 'hsl(var(--color-disabled) / <alpha-value>)',
},
destructive: 'hsla(var(--color-destructive))',
......
<ods-button-with-spinner [disabled]="disabled" text="Weiterleiten" variant="outline" dataTestId="forwarding-button">
<ods-forward-vorgang-icon icon class="fill-primary" />
<ods-button-with-spinner
[disabled]="disabled"
text="Weiterleiten"
[tooltip]="tooltip"
tooltipPosition="above"
dataTestId="forwarding-button"
>
<ods-forward-vorgang-icon icon class="fill-whitetext" />
</ods-button-with-spinner>
......@@ -23,4 +23,20 @@ describe('ForwardingButtonComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
describe('component', () => {
describe('set disabled', () => {
it('should set tooltip text', () => {
component.disabled = true;
expect(component.tooltip).not.toBe('');
});
it('should set empty tooltip', () => {
component.disabled = false;
expect(component.tooltip).toBe('');
});
});
});
});
import { Component, Input } from '@angular/core';
import { ButtonWithSpinnerComponent } from '@ods/component';
import { ForwardVorgangIconComponent } from '@ods/system';
import { ForwardVorgangIconComponent, TooltipDirective } from '@ods/system';
@Component({
selector: 'alfa-forwarding-button',
standalone: true,
imports: [ButtonWithSpinnerComponent, ForwardVorgangIconComponent],
imports: [ButtonWithSpinnerComponent, ForwardVorgangIconComponent, TooltipDirective],
templateUrl: './forwarding-button.component.html',
})
export class ForwardingButtonComponent {
@Input() disabled: boolean;
@Input() set disabled(value: boolean) {
this._disabled = value;
this.tooltip = value ? 'Bitte ein Amt oder Stelle auswählen' : '';
}
public tooltip: string;
private _disabled: boolean;
get disabled() {
return this._disabled;
}
}
<div class="flex w-[620px] max-w-full flex-col gap-4 bg-background-100 p-8">
<div class="flex w-[860px] max-w-full flex-col gap-4 bg-background-100 p-8">
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-primary">Vorgang weiterleiten</h1>
<ods-cancel-dialog-button showAsIconButton="true" />
......@@ -6,11 +6,9 @@
@if (!selectedSearchResult) {
<alfa-search-zustaendige-stelle-form-container cdkFocusInitial focusOnSearchField="true" data-test-id="zufi-search" />
<div class="h-[calc(50vh)]"></div>
} @else {
<alfa-forwarding-item-in-dialog
[organisationsEinheitResource]="selectedSearchResult"
data-test-id="forwarding-item"
/>
<alfa-forwarding-item-in-dialog [organisationsEinheitResource]="selectedSearchResult" data-test-id="forwarding-item" />
}
<div class="flex gap-4">
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment