feat: add DangerBadge shared component

Renders the 5 HuntEncounter danger tiers as German text plus a
per-tier BEM modifier class, mirroring travel-panel's text+class
danger pattern so color is never the sole signal. Colors map across
the existing 3 semantic tokens (success/warning/danger).
This commit is contained in:
Bastian Wagner
2026-08-19 13:26:58 +02:00
parent 49eb110b25
commit 59269a7608
4 changed files with 106 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
<span
class="danger-badge"
[class.danger-badge--weak]="rating === 'WEAK'"
[class.danger-badge--match]="rating === 'MATCH'"
[class.danger-badge--strong]="rating === 'STRONG'"
[class.danger-badge--very-dangerous]="rating === 'VERY_DANGEROUS'"
[class.danger-badge--deadly]="rating === 'DEADLY'"
>{{ label }}</span
>

View File

@@ -0,0 +1,44 @@
:host {
display: inline-block;
}
.danger-badge {
display: inline-flex;
align-items: center;
padding: var(--ar-space-1) var(--ar-space-2);
border: 1px solid var(--ar-border);
border-radius: var(--ar-radius-sm);
background: var(--ar-panel-muted);
color: var(--ar-text);
font-family: Georgia, 'Times New Roman', serif;
font-size: var(--ar-font-sm);
letter-spacing: 0.02em;
}
.danger-badge--weak {
color: var(--ar-success);
border-color: var(--ar-success);
}
.danger-badge--match {
color: var(--ar-success);
border-color: var(--ar-success);
font-weight: 700;
}
.danger-badge--strong {
color: var(--ar-warning);
border-color: var(--ar-warning);
}
.danger-badge--very-dangerous {
color: var(--ar-danger);
border-color: var(--ar-danger);
}
.danger-badge--deadly {
color: var(--ar-danger);
border-color: var(--ar-danger);
font-weight: 700;
background: color-mix(in srgb, var(--ar-danger) 18%, var(--ar-panel-muted));
}

View File

@@ -0,0 +1,30 @@
import { TestBed } from '@angular/core/testing';
import type { DangerRating } from '../../core/api/game-api.models';
import { DangerBadgeComponent } from './danger-badge.component';
const expectations: Array<{ rating: DangerRating; label: string; modifierClass: string }> = [
{ rating: 'WEAK', label: 'Schwach', modifierClass: 'danger-badge--weak' },
{ rating: 'MATCH', label: 'Passend', modifierClass: 'danger-badge--match' },
{ rating: 'STRONG', label: 'Stark', modifierClass: 'danger-badge--strong' },
{
rating: 'VERY_DANGEROUS',
label: 'Sehr gefährlich',
modifierClass: 'danger-badge--very-dangerous',
},
{ rating: 'DEADLY', label: 'Tödlich', modifierClass: 'danger-badge--deadly' },
];
describe('DangerBadgeComponent', () => {
for (const { rating, label, modifierClass } of expectations) {
it(`renders the German label "${label}" and modifier class for ${rating}`, () => {
const fixture = TestBed.createComponent(DangerBadgeComponent);
fixture.componentRef.setInput('rating', rating);
fixture.detectChanges();
const badge = fixture.nativeElement.querySelector('.danger-badge') as HTMLElement;
expect(badge.textContent?.trim()).toBe(label);
expect(badge.classList.contains(modifierClass)).toBe(true);
});
}
});

View File

@@ -0,0 +1,23 @@
import { Component, Input } from '@angular/core';
import { DangerRating } from '../../core/api/game-api.models';
const DANGER_LABELS: Record<DangerRating, string> = {
WEAK: 'Schwach',
MATCH: 'Passend',
STRONG: 'Stark',
VERY_DANGEROUS: 'Sehr gefährlich',
DEADLY: 'Tödlich',
};
@Component({
selector: 'app-danger-badge',
templateUrl: './danger-badge.component.html',
styleUrl: './danger-badge.component.scss',
})
export class DangerBadgeComponent {
@Input({ required: true }) rating!: DangerRating;
protected get label(): string {
return DANGER_LABELS[this.rating];
}
}