pc tracker: Megekko new build (9950X3D/X870E), dated ordered/leaving badges, future slider
All checks were successful
Deploy production / deploy (push) Successful in 1m15s
All checks were successful
Deploy production / deploy (push) Successful in 1m15s
This commit is contained in:
@@ -9,8 +9,16 @@
|
||||
min,
|
||||
max,
|
||||
events,
|
||||
today = max,
|
||||
value = $bindable()
|
||||
}: { min: string; max: string; events: TimelineEvent[]; value: string } = $props();
|
||||
}: {
|
||||
min: string;
|
||||
/** Last day on the slider; later than `today` when parts are ordered but not here yet. */
|
||||
max: string;
|
||||
today?: string;
|
||||
events: TimelineEvent[];
|
||||
value: string;
|
||||
} = $props();
|
||||
|
||||
const DAY = 86_400_000;
|
||||
const toDay = (d: string) => Math.round(Date.parse(`${d}T00:00:00Z`) / DAY);
|
||||
@@ -22,7 +30,12 @@
|
||||
const ticks = $derived(
|
||||
events
|
||||
.filter((e) => e.date >= min && e.date <= max)
|
||||
.map((e) => ({ ...e, day: toDay(e.date), pct: ((toDay(e.date) - lo) / span) * 100 }))
|
||||
.map((e) => ({
|
||||
...e,
|
||||
day: toDay(e.date),
|
||||
pct: ((toDay(e.date) - lo) / span) * 100,
|
||||
upcoming: e.date > today
|
||||
}))
|
||||
);
|
||||
const years = $derived.by(() => {
|
||||
const out: { y: number; pct: number }[] = [];
|
||||
@@ -31,6 +44,8 @@
|
||||
return out;
|
||||
});
|
||||
const current = $derived(toDay(value));
|
||||
/** Where today sits on the track when the slider runs into the future (ordered parts). */
|
||||
const nowPct = $derived(today < max ? ((toDay(today) - lo) / span) * 100 : null);
|
||||
/** Latest change on or before the chosen day. */
|
||||
const last = $derived([...ticks].reverse().find((t) => t.day <= current) ?? null);
|
||||
|
||||
@@ -66,7 +81,9 @@
|
||||
<span class="icon" aria-hidden="true"><History size={16} /></span>
|
||||
<div class="track order-last sm:order-none" bind:clientWidth={width}>
|
||||
<div class="rail"></div>
|
||||
{#if nowPct !== null}<div class="future" style:left="{nowPct}%"></div>{/if}
|
||||
<div class="fill" style:width="{((current - lo) / span) * 100}%"></div>
|
||||
{#if nowPct !== null}<span class="now" style:left="{nowPct}%" title="today"></span>{/if}
|
||||
{#each years.filter((y, i) => width > 520 || i % 2 === 0) as y (y.y)}
|
||||
<span class="year" style:left="{y.pct}%">{y.y}</span>
|
||||
{/each}
|
||||
@@ -76,6 +93,7 @@
|
||||
class="tick"
|
||||
class:past={t.day <= current}
|
||||
class:on={t.day === current}
|
||||
class:upcoming={t.upcoming}
|
||||
style:left="{t.pct}%"
|
||||
aria-label="{shortDate(t.date)}: {eventLabel(t)}"
|
||||
onmouseenter={() => (hover = t)}
|
||||
@@ -105,13 +123,14 @@
|
||||
</div>
|
||||
<div class="when ml-auto sm:ml-0">
|
||||
<span class="date tabular-nums">{shortDate(value)}</span>
|
||||
<button type="button" class="today" disabled={value === max} onclick={() => (value = max)}
|
||||
<button type="button" class="today" disabled={value === today} onclick={() => (value = today)}
|
||||
><RotateCcw size={13} /> today</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<p class="last" aria-live="polite">
|
||||
{#if last}
|
||||
{#if value > today}<span class="soon">upcoming</span> ·
|
||||
{/if}{#if last}
|
||||
<span class="text-[var(--site-text)]">{monthYear(last.date)}</span> · {eventLabel(last)}
|
||||
{:else}
|
||||
before the first part
|
||||
@@ -199,6 +218,36 @@
|
||||
background: var(--site-text);
|
||||
opacity: 0.9;
|
||||
}
|
||||
.tick.upcoming {
|
||||
background: var(--site-bg);
|
||||
box-shadow: inset 0 0 0 1.5px #db2777;
|
||||
opacity: 1;
|
||||
}
|
||||
.future {
|
||||
position: absolute;
|
||||
top: 0.55rem;
|
||||
right: 0;
|
||||
height: 0.3rem;
|
||||
border-radius: 999px;
|
||||
background: repeating-linear-gradient(90deg, #db2777 0 3px, transparent 3px 7px);
|
||||
opacity: 0.55;
|
||||
}
|
||||
.now {
|
||||
position: absolute;
|
||||
top: 0.2rem;
|
||||
z-index: 1;
|
||||
width: 2px;
|
||||
height: 1rem;
|
||||
margin-left: -1px;
|
||||
border-radius: 1px;
|
||||
background: var(--site-text);
|
||||
opacity: 0.7;
|
||||
pointer-events: none;
|
||||
}
|
||||
.soon {
|
||||
color: #db2777;
|
||||
font-weight: 600;
|
||||
}
|
||||
.tick.on,
|
||||
.tick:hover,
|
||||
.tick:focus-visible {
|
||||
|
||||
Reference in New Issue
Block a user