112 lines
4.5 KiB
Plaintext
112 lines
4.5 KiB
Plaintext
component Marquee {
|
|
props {
|
|
size: string = "default"
|
|
color: string = "primary"
|
|
title: string = "Marquee"
|
|
description: string = ""
|
|
items: unknown[] = []
|
|
variant: string = "default"
|
|
class: string = ""
|
|
}
|
|
|
|
state paused: boolean = false
|
|
|
|
view {
|
|
<section
|
|
data-ui-component="Marquee"
|
|
aria-label='{title}'
|
|
class='overflow-hidden border-y border-[var(--wire-color-border)] bg-[var(--wire-color-surface-raised)] {class}'
|
|
>
|
|
<div class="flex items-stretch">
|
|
{#if title}
|
|
<div class="relative z-10 flex shrink-0 items-center gap-2 border-r border-[var(--wire-color-border)] bg-[var(--wire-color-primary)] px-4 py-3 text-[var(--wire-color-on-primary)] sm:px-5">
|
|
<span class="icon-[lucide--megaphone] size-4" aria-hidden="true"></span>
|
|
<span class="text-sm font-bold">{title}</span>
|
|
</div>
|
|
{/if}
|
|
|
|
<div
|
|
class="group relative min-w-0 flex-1 overflow-hidden"
|
|
@mouseenter='paused = true; event.currentTarget.dispatchEvent(new CustomEvent("pause", { bubbles: true }))'
|
|
@mouseleave='paused = false; event.currentTarget.dispatchEvent(new CustomEvent("resume", { bubbles: true }))'
|
|
@focusin='paused = true'
|
|
@focusout='paused = false'
|
|
>
|
|
<div
|
|
class="wire-marquee-track flex w-max min-w-full items-center"
|
|
class:wire-marquee-paused='paused'
|
|
>
|
|
{#each items as item}
|
|
<a
|
|
href='{item.href || "#"}'
|
|
class="flex shrink-0 items-center gap-3 px-5 py-3 text-sm font-medium text-[var(--wire-color-text)] transition hover:bg-[var(--wire-color-primary-soft)] hover:text-[var(--wire-color-primary)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--wire-color-focus)]"
|
|
>
|
|
<span
|
|
class="size-2 shrink-0 rounded-full bg-[var(--wire-color-primary)]"
|
|
class:bg-[var(--wire-color-danger)]='item.color === "danger"'
|
|
class:bg-[var(--wire-color-warning)]='item.color === "warning"'
|
|
class:bg-[var(--wire-color-success)]='item.color === "success"'
|
|
aria-hidden="true"
|
|
></span>
|
|
<span>{item.label || item.title}</span>
|
|
{#if item.meta}
|
|
<span class="text-xs text-[var(--wire-color-text-muted)]">{item.meta}</span>
|
|
{/if}
|
|
</a>
|
|
{:empty}
|
|
<p class="px-5 py-3 text-sm text-[var(--wire-color-text-muted)]">{description || "No announcements available."}</p>
|
|
{/each}
|
|
|
|
{#if items.length > 0}
|
|
{#each items as item}
|
|
<a
|
|
href='{item.href || "#"}'
|
|
aria-hidden="true"
|
|
tabindex="-1"
|
|
class="flex shrink-0 items-center gap-3 px-5 py-3 text-sm font-medium text-[var(--wire-color-text)]"
|
|
>
|
|
<span class="size-2 shrink-0 rounded-full bg-[var(--wire-color-primary)]" aria-hidden="true"></span>
|
|
<span>{item.label || item.title}</span>
|
|
</a>
|
|
{/each}
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
|
|
<button
|
|
type="button"
|
|
aria-label='{paused ? "Resume announcements" : "Pause announcements"}'
|
|
class="flex shrink-0 items-center justify-center border-l border-[var(--wire-color-border)] px-4 text-[var(--wire-color-text-muted)] transition hover:bg-[var(--wire-color-surface-soft)] hover:text-[var(--wire-color-text)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--wire-color-focus)]"
|
|
@click='paused = !paused; event.currentTarget.dispatchEvent(new CustomEvent(paused ? "pause" : "resume", { bubbles: true }))'
|
|
>
|
|
<span class="icon-[lucide--pause] size-4" data-show='!paused' aria-hidden="true"></span>
|
|
<span class="icon-[lucide--play] size-4" data-show='paused' aria-hidden="true"></span>
|
|
</button>
|
|
</div>
|
|
|
|
<slot></slot>
|
|
</section>
|
|
}
|
|
|
|
style {
|
|
.wire-marquee-track {
|
|
animation: wire-marquee 32s linear infinite;
|
|
}
|
|
|
|
.wire-marquee-paused {
|
|
animation-play-state: paused;
|
|
}
|
|
|
|
@keyframes wire-marquee {
|
|
from { transform: translateX(0); }
|
|
to { transform: translateX(-50%); }
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.wire-marquee-track {
|
|
animation: none;
|
|
}
|
|
}
|
|
}
|
|
}
|