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', () => { ...@@ -54,7 +54,7 @@ describe('ButtonComponent', () => {
expect(component.clickEmitter.emit).toHaveBeenCalled(); expect(component.clickEmitter.emit).toHaveBeenCalled();
}); });
it('should NOT emit click', () => { it('should NOT emit click if button is disabled', () => {
component.disabled = true; component.disabled = true;
fixture.detectChanges(); fixture.detectChanges();
......
...@@ -31,18 +31,18 @@ import { SpinnerIconComponent } from '../icons/spinner-icon/spinner-icon.compone ...@@ -31,18 +31,18 @@ import { SpinnerIconComponent } from '../icons/spinner-icon/spinner-icon.compone
export const buttonVariants = cva( export const buttonVariants = cva(
[ [
'flex items-center gap-3 rounded-lg text-sm font-medium box-border', '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: { variants: {
variant: { 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: 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: 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: 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: { size: {
medium: 'h-9 py-2 px-4 min-w-32', medium: 'h-9 py-2 px-4 min-w-32',
...@@ -50,11 +50,11 @@ export const buttonVariants = cva( ...@@ -50,11 +50,11 @@ export const buttonVariants = cva(
}, },
disabled: { disabled: {
false: null, false: null,
true: ['opacity-70', 'cursor-not-allowed'], true: '[&]:outline-disabled-button cursor-not-allowed',
}, },
destructive: { destructive: {
false: 'outline-focus', false: null,
true: 'outline-destructive', true: '[&]:outline-destructive',
}, },
}, },
defaultVariants: { defaultVariants: {
...@@ -66,19 +66,34 @@ export const buttonVariants = cva( ...@@ -66,19 +66,34 @@ export const buttonVariants = cva(
{ {
variant: 'primary', variant: 'primary',
destructive: true, destructive: true,
class: class: '[&]:hover:bg-destructive-primary-hover [&]:bg-destructive [&]:focus-visible:bg-destructive-primary-hover',
'[&]:hover:enabled:bg-destructive-primary-hover [&]:bg-destructive [&]:outline-destructive [&]:focus-visible:bg-destructive-primary-hover',
}, },
{ {
variant: 'outline', variant: 'outline',
destructive: true, destructive: true,
class: 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', variant: 'ghost',
destructive: true, 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>; ...@@ -98,17 +113,22 @@ export type ButtonVariants = VariantProps<typeof buttonVariants>;
[attr.data-test-class]="dataTestClass" [attr.data-test-class]="dataTestClass"
(click)="onClick()" (click)="onClick()"
> >
<ng-content *ngIf="!isLoading" select="[icon]"></ng-content> @if (isLoading) {
<ods-spinner-icon *ngIf="isLoading" [size]="spinnerSize" data-test-class="spinner"></ods-spinner-icon> <ods-spinner-icon [class]="isDisabled && 'fill-disabled-button'" [size]="spinnerSize" data-test-class="spinner" />
<div *ngIf="text" class="flex-grow">{{ text }}</div> } @else {
<ng-content select="[icon]" />
}
@if (text) {
<p class="flex-grow">{{ text }}</p>
}
</button>`, </button>`,
}) })
export class ButtonComponent { export class ButtonComponent {
@Input() text: string = ''; @Input() text: string = '';
@Input() dataTestId: string = ''; @Input() dataTestId: string = '';
@Input() dataTestClass: string = ''; @Input() dataTestClass: string = '';
@Input() disabled: boolean = false; @Input({ transform: booleanAttribute }) disabled: boolean = false;
@Input() isLoading: boolean = false; @Input({ transform: booleanAttribute }) isLoading: boolean = false;
@Input({ transform: booleanAttribute }) destructive: boolean = false; @Input({ transform: booleanAttribute }) destructive: boolean = false;
@Input() variant: ButtonVariants['variant']; @Input() variant: ButtonVariants['variant'];
@Input() size: ButtonVariants['size']; @Input() size: ButtonVariants['size'];
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
import { NgClass } from '@angular/common'; import { NgClass } from '@angular/common';
import { Component, Input } from '@angular/core'; import { Component, Input } from '@angular/core';
import { twMerge } from 'tailwind-merge';
import { IconVariants, iconVariants } from '../iconVariants'; import { IconVariants, iconVariants } from '../iconVariants';
@Component({ @Component({
...@@ -33,8 +34,7 @@ import { IconVariants, iconVariants } from '../iconVariants'; ...@@ -33,8 +34,7 @@ import { IconVariants, iconVariants } from '../iconVariants';
template: ` template: `
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
[ngClass]="iconVariants({ size })" [ngClass]="twMerge('animate-spin fill-primary text-gray-200 dark:text-gray-600', iconVariants({ size }), class)"
class="animate-spin fill-primary text-gray-200 dark:text-gray-600"
aria-hidden="true" aria-hidden="true"
viewBox="0 0 100 100" viewBox="0 0 100 100"
fill="none" fill="none"
...@@ -53,6 +53,8 @@ import { IconVariants, iconVariants } from '../iconVariants'; ...@@ -53,6 +53,8 @@ import { IconVariants, iconVariants } from '../iconVariants';
}) })
export class SpinnerIconComponent { export class SpinnerIconComponent {
@Input() size: IconVariants['size'] = 'full'; @Input() size: IconVariants['size'] = 'full';
@Input() class: string;
iconVariants = iconVariants; readonly iconVariants = iconVariants;
readonly twMerge = twMerge;
} }
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
--color-disabled: 206 14% 95%; --color-disabled: 206 14% 95%;
--color-disabled-dark: 208 12% 65%; --color-disabled-dark: 208 12% 65%;
--color-disabled-button: 0 0% 42%;
--color-destructive: 360, 71%, 49%, 1; --color-destructive: 360, 71%, 49%, 1;
--color-destructive-hover: 360, 71%, 49%, 0.07; --color-destructive-hover: 360, 71%, 49%, 0.07;
...@@ -59,6 +60,7 @@ ...@@ -59,6 +60,7 @@
--color-disabled: 206 14% 15%; --color-disabled: 206 14% 15%;
--color-disabled-dark: 208 12% 33%; --color-disabled-dark: 208 12% 33%;
--color-disabled-button: 0 0% 68%;
--color-destructive: 360, 71%, 49%, 1; --color-destructive: 360, 71%, 49%, 1;
--color-destructive-hover: 360, 71%, 49%, 0.2; --color-destructive-hover: 360, 71%, 49%, 0.2;
......
...@@ -146,6 +146,7 @@ module.exports = { ...@@ -146,6 +146,7 @@ module.exports = {
focus: 'hsl(var(--color-focus))', focus: 'hsl(var(--color-focus))',
disabled: { disabled: {
dark: 'hsl(var(--color-disabled-dark) / <alpha-value>)', dark: 'hsl(var(--color-disabled-dark) / <alpha-value>)',
button: 'hsl(var(--color-disabled-button) / <alpha-value>)',
DEFAULT: 'hsl(var(--color-disabled) / <alpha-value>)', DEFAULT: 'hsl(var(--color-disabled) / <alpha-value>)',
}, },
destructive: 'hsla(var(--color-destructive))', destructive: 'hsla(var(--color-destructive))',
......
<ods-button-with-spinner [disabled]="disabled" text="Weiterleiten" variant="outline" dataTestId="forwarding-button"> <ods-button-with-spinner
<ods-forward-vorgang-icon icon class="fill-primary" /> [disabled]="disabled"
text="Weiterleiten"
[tooltip]="tooltip"
tooltipPosition="above"
dataTestId="forwarding-button"
>
<ods-forward-vorgang-icon icon class="fill-whitetext" />
</ods-button-with-spinner> </ods-button-with-spinner>
...@@ -23,4 +23,20 @@ describe('ForwardingButtonComponent', () => { ...@@ -23,4 +23,20 @@ describe('ForwardingButtonComponent', () => {
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); 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 { Component, Input } from '@angular/core';
import { ButtonWithSpinnerComponent } from '@ods/component'; import { ButtonWithSpinnerComponent } from '@ods/component';
import { ForwardVorgangIconComponent } from '@ods/system'; import { ForwardVorgangIconComponent, TooltipDirective } from '@ods/system';
@Component({ @Component({
selector: 'alfa-forwarding-button', selector: 'alfa-forwarding-button',
standalone: true, standalone: true,
imports: [ButtonWithSpinnerComponent, ForwardVorgangIconComponent], imports: [ButtonWithSpinnerComponent, ForwardVorgangIconComponent, TooltipDirective],
templateUrl: './forwarding-button.component.html', templateUrl: './forwarding-button.component.html',
}) })
export class ForwardingButtonComponent { 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"> <div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-primary">Vorgang weiterleiten</h1> <h1 class="text-xl font-semibold text-primary">Vorgang weiterleiten</h1>
<ods-cancel-dialog-button showAsIconButton="true" /> <ods-cancel-dialog-button showAsIconButton="true" />
...@@ -6,11 +6,9 @@ ...@@ -6,11 +6,9 @@
@if (!selectedSearchResult) { @if (!selectedSearchResult) {
<alfa-search-zustaendige-stelle-form-container cdkFocusInitial focusOnSearchField="true" data-test-id="zufi-search" /> <alfa-search-zustaendige-stelle-form-container cdkFocusInitial focusOnSearchField="true" data-test-id="zufi-search" />
<div class="h-[calc(50vh)]"></div>
} @else { } @else {
<alfa-forwarding-item-in-dialog <alfa-forwarding-item-in-dialog [organisationsEinheitResource]="selectedSearchResult" data-test-id="forwarding-item" />
[organisationsEinheitResource]="selectedSearchResult"
data-test-id="forwarding-item"
/>
} }
<div class="flex gap-4"> <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