presseportale/resources/views/components/web/live-ticker.blade.php
Kevin Adametz 5b8bdf4182
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run
12-05-2026 Frontend dev
2026-05-12 18:32:33 +02:00

112 lines
4.9 KiB
PHP

@props([
'items' => [],
'marketIndex' => null,
'asideSlides' => null,
])
@php
$items = collect($items)->all();
if (empty($items)) {
$items = [
['time' => '14:32', 'text' => 'Siemens Energy hebt Jahresprognose an'],
['time' => '14:18', 'text' => 'BASF: Restrukturierung in Ludwigshafen abgeschlossen'],
['time' => '13:55', 'text' => 'Deutsche Bahn meldet Rekord bei Fernverkehr'],
];
}
$marketIndex ??= [
'label' => 'DAX',
'value' => '18.247',
'delta' => '+0,8%',
'positive' => true,
];
$asideSlides = collect($asideSlides ?? [
$marketIndex,
[
'label' => 'EUR/USD',
'value' => '1,08',
'delta' => '+0,2%',
'positive' => true,
],
[
'label' => 'Brent Öl',
'value' => '78,40 $',
'delta' => '-0,9%',
'positive' => false,
],
])->values()->all();
@endphp
<div class="bg-topbar-grad text-ink-on-dark" aria-label="Ad-Hoc-Ticker">
<div class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 py-2.5 flex items-center gap-3 sm:gap-5 text-[12.5px]">
<div class="flex items-center gap-3 sm:gap-4 overflow-hidden min-w-0 flex-1">
<span class="flex items-center gap-1.5 text-accent-warm font-bold text-[10.5px] sm:text-[11px] tracking-[0.15em] flex-shrink-0">
<span class="w-[7px] h-[7px] rounded-full bg-accent-warm pulse-dot"></span>
AD-HOC
</span>
<span class="sr-only">
Ad-hoc-Meldungen:
@foreach ($items as $item)
{{ $item['time'] }} {{ $item['text'] }}.
@endforeach
</span>
<div class="overflow-hidden min-w-0 flex-1" aria-hidden="true">
<div class="ticker-marquee-track text-[12px] sm:text-[12.5px] whitespace-nowrap">
@foreach (array_merge($items, $items) as $item)
<span class="inline-flex shrink-0 gap-2 items-baseline">
<span class="font-mono text-[11px] text-ink-on-dark-muted">{{ $item['time'] }}</span>
<span class="text-ink-on-dark">{{ $item['text'] }}</span>
</span>
@endforeach
</div>
</div>
</div>
<span class="hidden sm:inline-block w-px h-[18px] bg-ink-on-dark-rule flex-shrink-0"></span>
{{-- Kein position:absolute: sonst null Breite im Fluss, bis Layout kollabiert --}}
<div class="shrink-0 flex justify-end items-center min-w-0 max-w-[min(92vw,280px)] sm:max-w-[min(42vw,280px)]"
x-data="{
slides: @js($asideSlides),
i: 0,
init() {
if (this.slides.length < 2) {
return;
}
window.setInterval(() => {
this.i = (this.i + 1) % this.slides.length;
}, 5200);
},
}"
aria-live="polite">
<div class="grid min-h-[22px] justify-items-end overflow-hidden [grid-template-columns:minmax(0,max-content)]">
<template x-for="(slide, idx) in slides" :key="idx">
<div x-show="i === idx"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 -translate-y-full"
x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="transition ease-in duration-280"
x-transition:leave-start="opacity-100 translate-y-0"
x-transition:leave-end="opacity-0 translate-y-full"
class="col-start-1 row-start-1 flex items-center gap-2 whitespace-nowrap">
<span class="text-ink-on-dark-muted font-semibold text-[10.5px] tracking-wider" x-text="slide.label"></span>
<span class="text-ink-on-dark font-mono text-[12.5px]" x-text="slide.value"></span>
<span class="font-semibold text-[11.5px] font-mono"
:class="(slide.positive ?? true) ? 'text-gain' : 'text-loss'"
x-text="slide.delta"></span>
<svg width="26" height="10" viewBox="0 0 26 10"
class="hidden sm:inline-block shrink-0"
:class="(slide.positive ?? true) ? 'text-gain' : 'text-loss'"
aria-hidden="true">
<path d="M0,8 L4,7 L8,5 L12,6 L16,4 L20,3 L24,2"
fill="none" stroke="currentColor" stroke-width="1.2" />
</svg>
</div>
</template>
</div>
</div>
</div>
</div>