Stage 7 polish: app shell + nav + lobby + settings (Parts A/B/C)
- Screen.svelte shell: nav bar grows, ad+content+tabbar pinned bottom (mobile feel) - AdBanner.svelte + banner.ts rotator (params, mock long/short, linkify); Header CSS chevron + grow; Menu (bigger CSS hamburger); TabBar + HoldConfirm shared components; user-select:none - Lobby: hide-empty sections, tab order New/Tournaments/Stats, place-based result badges (result.ts) - Settings: Board style > Labels (beginner/classic/none) + prefs plumbing (boardlabels.ts); i18n keys + ru mirror
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
<script lang="ts">
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
import {
|
||||
createBannerRotator,
|
||||
defaultBannerConfig,
|
||||
linkify,
|
||||
mockBanners,
|
||||
type BannerConfig,
|
||||
type BannerItem,
|
||||
} from '../lib/banner';
|
||||
|
||||
let { items = mockBanners(), config = defaultBannerConfig }: { items?: BannerItem[]; config?: BannerConfig } =
|
||||
$props();
|
||||
|
||||
let current = $state(0);
|
||||
let tx = $state(0);
|
||||
let txDur = $state(0);
|
||||
let track = $state<HTMLElement>();
|
||||
let viewport = $state<HTMLElement>();
|
||||
|
||||
let rotator: ReturnType<typeof createBannerRotator> | null = null;
|
||||
|
||||
onMount(() => {
|
||||
rotator = createBannerRotator(items, {
|
||||
overflowPx: () => Math.max(0, (track?.scrollWidth ?? 0) - (viewport?.clientWidth ?? 0)),
|
||||
show: (i) => {
|
||||
current = i;
|
||||
tx = 0;
|
||||
txDur = 0;
|
||||
},
|
||||
scrollTo: (toPx, durationMs) => {
|
||||
txDur = durationMs;
|
||||
tx = -toPx;
|
||||
},
|
||||
}, config);
|
||||
rotator.start();
|
||||
});
|
||||
onDestroy(() => rotator?.stop());
|
||||
</script>
|
||||
|
||||
<div class="ad" bind:this={viewport}>
|
||||
{#key current}
|
||||
<div
|
||||
class="track"
|
||||
bind:this={track}
|
||||
in:fade={{ duration: config.fadeMs }}
|
||||
style="transform:translateX({tx}px); transition:transform {txDur}ms linear"
|
||||
>
|
||||
{@html linkify(items[current]?.md ?? '')}
|
||||
</div>
|
||||
{/key}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.ad {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
padding: 6px var(--pad);
|
||||
background: var(--surface-2);
|
||||
color: var(--text-muted);
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.2;
|
||||
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.18);
|
||||
border-top: 1px solid var(--border);
|
||||
border-bottom: 1px solid var(--border);
|
||||
user-select: none;
|
||||
}
|
||||
.track {
|
||||
display: inline-block;
|
||||
will-change: transform;
|
||||
}
|
||||
.track :global(a) {
|
||||
color: var(--accent);
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user