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:
Ilia Denisov
2026-06-03 13:20:56 +02:00
parent 03347c5a91
commit 38be7fea96
18 changed files with 871 additions and 244 deletions
+43 -20
View File
@@ -5,27 +5,38 @@
let { title, back, menu }: { title: string; back?: string; menu?: Snippet } = $props();
</script>
<header class="topbar">
{#if back}
<button class="icon" onclick={() => back && navigate(back)} aria-label="Back"></button>
{:else}
<span class="spacer"></span>
{/if}
<h1>{title}</h1>
<div class="end">{#if menu}{@render menu()}{/if}</div>
<header class="nav">
<div class="bar">
{#if back}
<button class="icon back" onclick={() => back && navigate(back)} aria-label="Back">
<span class="chev"></span>
</button>
{:else}
<span class="spacer"></span>
{/if}
<h1>{title}</h1>
<div class="end">{#if menu}{@render menu()}{/if}</div>
</div>
</header>
<style>
.topbar {
/* The nav bar grows to fill the spare vertical space (buttons stay at the top), so
the rest of the screen pins to the bottom — a mobile-app layout. */
.nav {
flex: 1 1 auto;
min-height: 52px;
background: var(--bg-elev);
border-bottom: 1px solid var(--border);
display: flex;
flex-direction: column;
user-select: none;
-webkit-user-select: none;
}
.bar {
display: flex;
align-items: center;
gap: var(--gap);
padding: 10px var(--pad);
background: var(--bg-elev);
border-bottom: 1px solid var(--border);
position: sticky;
top: 0;
z-index: 5;
}
h1 {
font-size: 1.05rem;
@@ -33,28 +44,40 @@
flex: 1;
text-align: center;
font-weight: 600;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.icon,
.spacer,
.end {
width: 40px;
height: 32px;
min-width: 40px;
height: 36px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.end {
width: auto;
min-width: 40px;
justify-content: flex-end;
}
.icon {
.back {
background: none;
border: none;
font-size: 1.1rem;
color: var(--text);
border-radius: var(--radius-sm);
padding: 0 8px;
}
.icon:hover {
.back:hover {
background: var(--surface-2);
}
/* A thin, compact "<" drawn from two borders — lighter than a glyph. */
.chev {
width: 11px;
height: 11px;
border-left: 2.5px solid currentColor;
border-bottom: 2.5px solid currentColor;
transform: rotate(45deg);
margin-left: 3px;
}
</style>