made the scrolling work
This commit is contained in:
@@ -18,14 +18,21 @@
|
||||
let eventRefs = $state<Record<number, HTMLElement>>({});
|
||||
|
||||
onMount(() => {
|
||||
// Get the teams endpoint
|
||||
scoreEndpoint = new EventSource('/api/teams');
|
||||
// When the endpoint sends something
|
||||
scoreEndpoint.onmessage = (e) => {
|
||||
// Parse the json
|
||||
const teamsData = JSON.parse(e.data);
|
||||
// If its teams info, then update the teams thing
|
||||
if (teamsData['teams']) teams = teamsData['teams'];
|
||||
};
|
||||
|
||||
// Basically same for events
|
||||
eventEndpoint = new EventSource('/api/registeredEvents');
|
||||
eventEndpoint.onmessage = (e) => {
|
||||
eventTable = JSON.parse(e.data);
|
||||
console.log(eventTable);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -44,20 +51,18 @@
|
||||
}
|
||||
|
||||
// When focusEventId changes, scroll to and highlight that event card
|
||||
// TODO make this scrolling shit work idk
|
||||
$effect(() => {
|
||||
if (focusEventId == null) return;
|
||||
tick().then(() => {
|
||||
// Get focused element
|
||||
const el = eventRefs[focusEventId!];
|
||||
const container = el?.closest('.events-scroll') as HTMLElement;
|
||||
if (el && container) {
|
||||
const elMid = el.offsetTop + el.offsetHeight / 2;
|
||||
const targetScroll = elMid - container.clientHeight / 2 - 60;
|
||||
container.scrollTo({ top: targetScroll, behavior: 'smooth' });
|
||||
el.classList.remove('highlight-pulse');
|
||||
void el.offsetWidth;
|
||||
el.classList.add('highlight-pulse');
|
||||
}
|
||||
// Scroll it to the top of the box
|
||||
el.scrollIntoView({ alignToTop: true, behavior: 'instant', container: 'nearest' });
|
||||
// Wait for that to finish
|
||||
tick().then(() => {
|
||||
// Scroll the window back to the top
|
||||
window.scrollTo(0, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
// Svelte action: measures text overflow and drives CSS marquee
|
||||
@@ -159,10 +164,22 @@
|
||||
<section class="events-scroll">
|
||||
<div class="events">
|
||||
{#each eventTable as event (event.id)}
|
||||
<div class="event-card" bind:this={eventRefs[event.id]}>
|
||||
<div
|
||||
class="event-card"
|
||||
class:ongoing-event={event.state == 1}
|
||||
bind:this={eventRefs[event.id]}
|
||||
>
|
||||
<div class="event-header">
|
||||
<a href="/event/{event.id}" class="event-name goldman">{event.name}</a>
|
||||
<span class="event-division">{event.division}</span>
|
||||
{#if event.state == 1}
|
||||
<span class="event-status goldman">ONGOING</span>
|
||||
{:else if event.state == 2}
|
||||
<span
|
||||
class="event-winner event-status goldman"
|
||||
style="--winner-color:{event.winner.color}">Won By {event.winner.name}</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="brackets">
|
||||
@@ -211,355 +228,3 @@
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- <style> -->
|
||||
<!-- @import url('https://fonts.googleapis.com/css2?family=Black+Ops+One&display=swap'); -->
|
||||
<!---->
|
||||
<!-- :global(html), -->
|
||||
<!-- :global(body) { -->
|
||||
<!-- min-height: 100vh; -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- :global(body > div), /* SvelteKit's root wrapper */ -->
|
||||
<!-- :global(#svelte) { -->
|
||||
<!-- min-height: 100vh; -->
|
||||
<!-- display: flex; -->
|
||||
<!-- flex-direction: column; -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- .page { -->
|
||||
<!-- display: flex; -->
|
||||
<!-- flex-direction: column; -->
|
||||
<!-- max-height: 150vh; -->
|
||||
<!-- max-width: 1000px; -->
|
||||
<!-- margin: 0 auto; -->
|
||||
<!-- width: 100%; -->
|
||||
<!-- } -->
|
||||
<!-- .goldman { -->
|
||||
<!-- font-family: 'Black Ops One', system-ui; -->
|
||||
<!-- font-weight: 400; -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- /* ── Leaderboard ── */ -->
|
||||
<!-- .leaderboard { -->
|
||||
<!-- display: flex; -->
|
||||
<!-- flex-direction: column; -->
|
||||
<!-- gap: 10px; -->
|
||||
<!-- padding: 14px 14px 6px; -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- .score-box { -->
|
||||
<!-- position: relative; -->
|
||||
<!-- overflow: hidden; -->
|
||||
<!-- border-radius: 14px; -->
|
||||
<!-- border: 2px solid var(--c); -->
|
||||
<!-- color: var(--c); -->
|
||||
<!-- background: color-mix(in srgb, var(--c) 10%, transparent); -->
|
||||
<!-- /* Grid stacking: ghost + fg share the same cell */ -->
|
||||
<!-- display: grid; -->
|
||||
<!-- grid-template-columns: 1fr; -->
|
||||
<!-- grid-template-rows: 1fr; -->
|
||||
<!-- text-decoration: none; -->
|
||||
<!-- transition: filter 0.15s ease; -->
|
||||
<!-- } -->
|
||||
<!-- .score-box:hover { -->
|
||||
<!-- filter: brightness(1.15); -->
|
||||
<!-- } -->
|
||||
<!-- .score-box > * { -->
|
||||
<!-- grid-column: 1; -->
|
||||
<!-- grid-row: 1; -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- .winner { -->
|
||||
<!-- aspect-ratio: 2 / 1; -->
|
||||
<!-- border-width: 3px; -->
|
||||
<!-- min-height: 80px; -->
|
||||
<!-- } -->
|
||||
<!-- .runner { -->
|
||||
<!-- aspect-ratio: 4 / 1; -->
|
||||
<!-- min-height: 56px; -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- /* Ghost SVG: fill the cell edge-to-edge, text flush to bottom */ -->
|
||||
<!-- .score-ghost { -->
|
||||
<!-- width: 100%; -->
|
||||
<!-- height: 100%; -->
|
||||
<!-- opacity: 0.18; -->
|
||||
<!-- fill: currentColor; -->
|
||||
<!-- } -->
|
||||
<!-- .ghost-svg { -->
|
||||
<!-- width: 100%; -->
|
||||
<!-- height: 100%; -->
|
||||
<!-- display: block; -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- /* Foreground */ -->
|
||||
<!-- .score-fg { -->
|
||||
<!-- position: relative; -->
|
||||
<!-- z-index: 1; -->
|
||||
<!-- display: flex; -->
|
||||
<!-- align-items: center; -->
|
||||
<!-- justify-content: space-between; -->
|
||||
<!-- padding: 0 14px; -->
|
||||
<!-- gap: 8px; -->
|
||||
<!-- } -->
|
||||
<!-- .score-meta { -->
|
||||
<!-- display: flex; -->
|
||||
<!-- flex-direction: column; -->
|
||||
<!-- min-width: 0; -->
|
||||
<!-- flex: 1; -->
|
||||
<!-- } -->
|
||||
<!-- .score-rank { -->
|
||||
<!-- font-size: 10px; -->
|
||||
<!-- letter-spacing: 1.5px; -->
|
||||
<!-- text-transform: uppercase; -->
|
||||
<!-- opacity: 0.5; -->
|
||||
<!-- line-height: 1; -->
|
||||
<!-- margin-bottom: 3px; -->
|
||||
<!-- } -->
|
||||
<!-- .score-name { -->
|
||||
<!-- font-size: clamp(11px, 3vw, 20px); -->
|
||||
<!-- white-space: nowrap; -->
|
||||
<!-- overflow: hidden; -->
|
||||
<!-- text-overflow: ellipsis; -->
|
||||
<!-- } -->
|
||||
<!-- .score-pts { -->
|
||||
<!-- font-size: clamp(20px, 5.5vw, 40px); -->
|
||||
<!-- letter-spacing: 2px; -->
|
||||
<!-- flex-shrink: 0; -->
|
||||
<!-- } -->
|
||||
<!-- .winner .score-name { -->
|
||||
<!-- font-size: clamp(16px, 5vw, 32px); -->
|
||||
<!-- } -->
|
||||
<!-- .winner .score-pts { -->
|
||||
<!-- font-size: clamp(26px, 7.5vw, 52px); -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- /* -->
|
||||
<!-- * Runners-up grid: -->
|
||||
<!-- * - 1 column on small screens (<480px) -->
|
||||
<!-- * - 2 columns on medium (480–699px) -->
|
||||
<!-- * - 4 columns on large (≥700px), max 5 -->
|
||||
<!-- * --runner-count drives the actual column count on large screens -->
|
||||
<!-- * so fewer than 5 teams still fill the whole row. -->
|
||||
<!-- */ -->
|
||||
<!-- .runners-grid { -->
|
||||
<!-- display: grid; -->
|
||||
<!-- gap: 10px; -->
|
||||
<!-- grid-template-columns: 1fr; -->
|
||||
<!-- } -->
|
||||
<!-- @media (min-width: 480px) { -->
|
||||
<!-- .runners-grid { -->
|
||||
<!-- grid-template-columns: repeat(2, 1fr); -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- .winner { -->
|
||||
<!-- aspect-ratio: 2 / 1; -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- .runner { -->
|
||||
<!-- aspect-ratio: 2 / 1; -->
|
||||
<!-- } -->
|
||||
<!-- } -->
|
||||
<!-- @media (min-width: 700px) { -->
|
||||
<!-- .runners-grid { -->
|
||||
<!-- /* clamp actual count to 4 on large, but use --runner-count -->
|
||||
<!-- so e.g. 2 teams still fill 2 equal columns not 2 of 4 */ -->
|
||||
<!-- grid-template-columns: repeat(min(var(--runner-count), 4), 1fr); -->
|
||||
<!-- } -->
|
||||
<!-- .winner { -->
|
||||
<!-- aspect-ratio: 3 / 1; -->
|
||||
<!-- } -->
|
||||
<!-- .runner { -->
|
||||
<!-- aspect-ratio: 3 / 2; -->
|
||||
<!-- } -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- /* ── Section label ── */ -->
|
||||
<!-- .section-label { -->
|
||||
<!-- font-size: 10px; -->
|
||||
<!-- letter-spacing: 2.5px; -->
|
||||
<!-- text-transform: uppercase; -->
|
||||
<!-- opacity: 0.4; -->
|
||||
<!-- padding: 12px 16px 4px; -->
|
||||
<!-- margin: 0; -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- /* ── Events scrollable container ── */ -->
|
||||
<!-- .events-scroll { -->
|
||||
<!-- flex: 1; -->
|
||||
<!-- overflow-y: auto; -->
|
||||
<!-- /* max-height: 900px; */ -->
|
||||
<!-- min-height: 0; -->
|
||||
<!-- padding: 0 14px 24px; -->
|
||||
<!-- /* Thin custom scrollbar */ -->
|
||||
<!-- scrollbar-width: thin; -->
|
||||
<!-- scrollbar-color: color-mix(in srgb, currentColor 30%, transparent) transparent; -->
|
||||
<!-- } -->
|
||||
<!-- .events { -->
|
||||
<!-- display: flex; -->
|
||||
<!-- flex-direction: column; -->
|
||||
<!-- gap: 10px; -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- /* ── Event card ── */ -->
|
||||
<!-- .event-card { -->
|
||||
<!-- border-radius: 12px; -->
|
||||
<!-- border: 1px solid color-mix(in srgb, currentColor 18%, transparent); -->
|
||||
<!-- overflow: hidden; -->
|
||||
<!-- transition: box-shadow 0.3s ease; -->
|
||||
<!-- } -->
|
||||
<!-- /* Focus highlight pulse — added/removed by $effect */ -->
|
||||
<!-- .event-card.highlight-pulse { -->
|
||||
<!-- animation: card-pulse 1.2s ease-out forwards; -->
|
||||
<!-- } -->
|
||||
<!-- @keyframes card-pulse { -->
|
||||
<!-- 0% { -->
|
||||
<!-- box-shadow: 0 0 0 3px currentColor; -->
|
||||
<!-- } -->
|
||||
<!-- 100% { -->
|
||||
<!-- box-shadow: 0 0 0 0px currentColor; -->
|
||||
<!-- } -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- .event-header { -->
|
||||
<!-- display: flex; -->
|
||||
<!-- align-items: baseline; -->
|
||||
<!-- gap: 10px; -->
|
||||
<!-- padding: 9px 13px 7px; -->
|
||||
<!-- border-bottom: 1px solid color-mix(in srgb, currentColor 10%, transparent); -->
|
||||
<!-- flex-wrap: wrap; -->
|
||||
<!-- } -->
|
||||
<!-- .event-name { -->
|
||||
<!-- font-size: 15px; -->
|
||||
<!-- text-decoration: none; -->
|
||||
<!-- color: inherit; -->
|
||||
<!-- } -->
|
||||
<!-- .event-name:hover { -->
|
||||
<!-- text-decoration: underline; -->
|
||||
<!-- } -->
|
||||
<!-- .event-division { -->
|
||||
<!-- font-size: 10px; -->
|
||||
<!-- letter-spacing: 1.2px; -->
|
||||
<!-- text-transform: uppercase; -->
|
||||
<!-- opacity: 0.4; -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- /* ── Brackets ── */ -->
|
||||
<!-- .brackets { -->
|
||||
<!-- display: flex; -->
|
||||
<!-- flex-direction: column; -->
|
||||
<!-- } -->
|
||||
<!-- .brackets-name { -->
|
||||
<!-- font-size: 20px; -->
|
||||
<!-- letter-spacing: 1.2px; -->
|
||||
<!-- text-transform: uppercase; -->
|
||||
<!-- opacity: 0.4; -->
|
||||
<!-- margin-left: 1px; -->
|
||||
<!-- } -->
|
||||
<!-- .brackets-name-text { -->
|
||||
<!-- display: table-cell; -->
|
||||
<!-- vertical-align: middle; -->
|
||||
<!-- } -->
|
||||
<!-- .bracket-vertical-sep { -->
|
||||
<!-- width: 1px; -->
|
||||
<!-- height: 100%; -->
|
||||
<!-- background: var(--ctp-mocha-surface2); -->
|
||||
<!-- margin: 10px 5px; -->
|
||||
<!-- } -->
|
||||
<!-- .bracket-sep { -->
|
||||
<!-- height: 1px; -->
|
||||
<!-- background: color-mix(in srgb, currentColor 10%, transparent); -->
|
||||
<!-- margin: 0 10px; -->
|
||||
<!-- } -->
|
||||
<!-- .bracket-row { -->
|
||||
<!-- display: flex; -->
|
||||
<!-- gap: 6px; -->
|
||||
<!-- padding: 7px 9px; -->
|
||||
<!-- flex-wrap: wrap; -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- /* ── Player boxes ── */ -->
|
||||
<!-- .player-box { -->
|
||||
<!-- flex: 1 1 0; /* equal widths, no min-content bias */ -->
|
||||
<!-- max-width: 160px; -->
|
||||
<!-- position: relative; -->
|
||||
<!-- overflow: hidden; -->
|
||||
<!-- border-radius: 8px; -->
|
||||
<!-- border: 1.5px solid var(--c); -->
|
||||
<!-- color: var(--c); -->
|
||||
<!-- background: color-mix(in srgb, var(--c) 10%, transparent); -->
|
||||
<!-- padding: 5px 7px 5px; -->
|
||||
<!-- display: flex; -->
|
||||
<!-- flex-direction: column; -->
|
||||
<!-- min-height: 52px; -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- /* 1 col on small screens, 4 across on large */ -->
|
||||
<!-- @media (max-width: 479px) { -->
|
||||
<!-- .bracket-row { -->
|
||||
<!-- flex-direction: column; -->
|
||||
<!-- } -->
|
||||
<!-- .player-box { -->
|
||||
<!-- max-width: 100%; -->
|
||||
<!-- } -->
|
||||
<!-- } -->
|
||||
<!-- @media (min-width: 700px) { -->
|
||||
<!-- .player-box { -->
|
||||
<!-- max-width: calc(25% - 6px); -->
|
||||
<!-- } /* 4 per row */ -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- .player-ghost { -->
|
||||
<!-- position: absolute; -->
|
||||
<!-- inset: 0; -->
|
||||
<!-- opacity: 0.15; -->
|
||||
<!-- fill: currentColor; -->
|
||||
<!-- pointer-events: none; -->
|
||||
<!-- } -->
|
||||
<!-- .ghost-svg { -->
|
||||
<!-- width: 100%; -->
|
||||
<!-- height: 100%; -->
|
||||
<!-- display: block; -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- .player-name-wrap { -->
|
||||
<!-- position: relative; -->
|
||||
<!-- z-index: 1; -->
|
||||
<!-- overflow: hidden; -->
|
||||
<!-- white-space: nowrap; -->
|
||||
<!-- } -->
|
||||
<!-- .marquee-inner { -->
|
||||
<!-- display: inline-block; -->
|
||||
<!-- font-size: 11px; -->
|
||||
<!-- font-weight: 600; -->
|
||||
<!-- white-space: nowrap; -->
|
||||
<!-- } -->
|
||||
<!-- .marquee-inner.scrolling { -->
|
||||
<!-- animation: marquee-scroll 7s ease-in-out infinite; -->
|
||||
<!-- } -->
|
||||
<!-- @keyframes marquee-scroll { -->
|
||||
<!-- 0%, -->
|
||||
<!-- 20% { -->
|
||||
<!-- transform: translateX(0); -->
|
||||
<!-- } -->
|
||||
<!-- 70%, -->
|
||||
<!-- 90% { -->
|
||||
<!-- transform: translateX(var(--scroll-dist, 0px)); -->
|
||||
<!-- } -->
|
||||
<!-- 100% { -->
|
||||
<!-- transform: translateX(0); -->
|
||||
<!-- } -->
|
||||
<!-- } -->
|
||||
<!---->
|
||||
<!-- .player-placement { -->
|
||||
<!-- position: relative; -->
|
||||
<!-- z-index: 1; -->
|
||||
<!-- font-size: 17px; -->
|
||||
<!-- line-height: 1.1; -->
|
||||
<!-- margin-top: 2px; -->
|
||||
<!-- } -->
|
||||
<!-- .player-placement-gap { -->
|
||||
<!-- height: 20px; -->
|
||||
<!-- } -->
|
||||
<!-- </style> -->
|
||||
|
||||
@@ -179,6 +179,8 @@
|
||||
/* ── Events scrollable container ── */
|
||||
.events-scroll {
|
||||
flex: 1;
|
||||
box-shadow: inset 0px 48px 20px -26px rgba(0, 0, 0, 0.35);
|
||||
border-radius: 25px;
|
||||
overflow-y: auto;
|
||||
/* max-height: 900px; */
|
||||
min-height: 0;
|
||||
@@ -193,6 +195,17 @@
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.event-status {
|
||||
align-self: center;
|
||||
justify-self: end;
|
||||
text-align: end;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.event-winner {
|
||||
color: var(--winner-color);
|
||||
}
|
||||
|
||||
/* ── Event card ── */
|
||||
.event-card {
|
||||
border-radius: 12px;
|
||||
@@ -200,6 +213,11 @@
|
||||
overflow: hidden;
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.ongoing-event {
|
||||
background-color: color-mix(in srgb, currentColor 18%, transparent);
|
||||
color: var(--ctp-latte-peach);
|
||||
}
|
||||
/* Focus highlight pulse — added/removed by $effect */
|
||||
.event-card.highlight-pulse {
|
||||
animation: card-pulse 1.2s ease-out forwards;
|
||||
@@ -271,13 +289,40 @@
|
||||
|
||||
/* 1 col on small screens, 4 across on large */
|
||||
@media (max-width: 479px) {
|
||||
.brackets {
|
||||
flex-direction: row;
|
||||
align-items: stretch; /* was flex-start — lets columns fill full height */
|
||||
}
|
||||
.bracket-sep {
|
||||
width: 1px;
|
||||
height: auto;
|
||||
margin: 10px 0;
|
||||
align-self: stretch;
|
||||
}
|
||||
.bracket-row {
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
.player-box {
|
||||
max-width: 100%;
|
||||
flex: 1; /* equal height across all player boxes in the column */
|
||||
}
|
||||
.bracket-row {
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
align-items: stretch; /* player boxes fill the full column width */
|
||||
}
|
||||
.brackets-name {
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.brackets-name-text {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 700px) {
|
||||
.player-box {
|
||||
max-width: calc(25% - 6px);
|
||||
|
||||
Reference in New Issue
Block a user