mirror of
https://github.com/pupperpowell/bibdle.git
synced 2026-04-05 17:33:31 -04:00
feat: improve guesses collapse timing, win screen CTA, and progress page polish
- GuessesTable now accepts a `minimized` prop instead of deriving collapse from `isWon`, giving the parent control over timing - Delay collapsing guesses grid until win animations complete (1800ms), skipped for already-completed puzzles - Replace plain progress link on win screen with a styled green button matching other CTAs - Progress page: remove redundant subtitle and nav button from header, add book status legend, add axis labels to guess history chart Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,13 +5,17 @@
|
||||
let {
|
||||
guesses,
|
||||
correctBookId,
|
||||
isWon = false,
|
||||
}: { guesses: Guess[]; correctBookId: string; isWon?: boolean } = $props();
|
||||
minimized = false,
|
||||
}: { guesses: Guess[]; correctBookId: string; minimized?: boolean } = $props();
|
||||
|
||||
let hasGuesses = $derived(guesses.length > 0);
|
||||
let showMinimized = $derived(isWon && guesses.length > 3);
|
||||
let showMinimized = $derived(minimized);
|
||||
let expanded = $state(false);
|
||||
|
||||
$effect(() => {
|
||||
if (!minimized) expanded = false;
|
||||
});
|
||||
|
||||
function getBoxColor(isCorrect: boolean, isAdjacent?: boolean): string {
|
||||
if (isCorrect) return "bg-green-500 border-green-600";
|
||||
if (isAdjacent) return "bg-yellow-500 border-yellow-600";
|
||||
|
||||
@@ -330,12 +330,9 @@
|
||||
{/if}
|
||||
|
||||
{#if isLoggedIn}
|
||||
<a
|
||||
href="/progress"
|
||||
class="text-sm text-center text-gray-500 dark:text-gray-400 hover:text-emerald-600 dark:hover:text-emerald-400 transition-colors"
|
||||
>
|
||||
View your progress →
|
||||
</a>
|
||||
<div class="signin-prompt">
|
||||
<a href="/progress" class="progress-btn"> 📈 See your progress </a>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="signin-prompt">
|
||||
<p class="signin-text">
|
||||
@@ -712,4 +709,43 @@
|
||||
height: 1.1rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.progress-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.6rem 1rem;
|
||||
width: 100%;
|
||||
margin-bottom: 0.6rem;
|
||||
background: #059669;
|
||||
color: #fff;
|
||||
border-radius: 0.5rem;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
transition:
|
||||
background 150ms ease,
|
||||
transform 80ms ease;
|
||||
}
|
||||
.progress-btn:hover {
|
||||
background: #047857;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.progress-btn:active {
|
||||
background: #065f46;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.progress-btn {
|
||||
background: #10b981;
|
||||
color: #fff;
|
||||
}
|
||||
.progress-btn:hover {
|
||||
background: #059669;
|
||||
}
|
||||
.progress-btn:active {
|
||||
background: #047857;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
let statsData = $state<StatsData | null>(null);
|
||||
let streak = $state(0);
|
||||
let streakPercentile = $state<number | null>(null);
|
||||
let guessesMinimized = $state(false);
|
||||
|
||||
const persistence = createGamePersistence(
|
||||
() => dailyVerse.date,
|
||||
@@ -204,6 +205,23 @@
|
||||
}
|
||||
});
|
||||
|
||||
// Delay collapsing the guesses grid until animations complete (mirrors showWinScreen delay)
|
||||
$effect(() => {
|
||||
if (!isWon || persistence.guesses.length <= 3) {
|
||||
guessesMinimized = false;
|
||||
return;
|
||||
}
|
||||
if (persistence.isWinAlreadyTracked()) {
|
||||
guessesMinimized = true;
|
||||
} else {
|
||||
const animationDelay = 1800;
|
||||
const timeoutId = setTimeout(() => {
|
||||
guessesMinimized = true;
|
||||
}, animationDelay);
|
||||
return () => clearTimeout(timeoutId);
|
||||
}
|
||||
});
|
||||
|
||||
// Track win analytics
|
||||
$effect(() => {
|
||||
if (!browser || !isWon) return;
|
||||
@@ -333,7 +351,7 @@
|
||||
<GuessesTable
|
||||
guesses={persistence.guesses}
|
||||
{correctBookId}
|
||||
{isWon}
|
||||
minimized={guessesMinimized}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -186,16 +186,11 @@
|
||||
<div class="max-w-3xl mx-auto">
|
||||
<!-- Header -->
|
||||
<div class="text-center mb-6 md:mb-8">
|
||||
<h1 class="text-3xl md:text-4xl font-bold text-gray-100 mb-2">
|
||||
<h1 class="text-3xl md:text-4xl font-bold text-gray-100 mb-4">
|
||||
Your Progress
|
||||
</h1>
|
||||
<p class="text-sm md:text-base text-gray-300 mb-4">
|
||||
Your Bible knowledge journey
|
||||
</p>
|
||||
<a
|
||||
href="/"
|
||||
class="inline-flex items-center px-4 py-2 bg-amber-600 text-white rounded-lg hover:bg-amber-700 transition-colors text-sm font-medium shadow-md"
|
||||
>
|
||||
|
||||
<a href="/" class="p-2 px-20 w-full items-center text-gray-300">
|
||||
← Back to Game
|
||||
</a>
|
||||
</div>
|
||||
@@ -360,6 +355,16 @@
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 mt-3 leading-relaxed">
|
||||
<span class="text-blue-400 font-medium">Explored</span>
|
||||
— played at least once<br />
|
||||
<span class="text-emerald-400 font-medium"
|
||||
>Mastered</span
|
||||
>
|
||||
— avg ≤ 3 guesses over 2+ plays<br />
|
||||
<span class="text-amber-400 font-medium">Perfect</span> —
|
||||
mastered and guessed in 1 at least once
|
||||
</p>
|
||||
</Container>
|
||||
</div>
|
||||
|
||||
@@ -382,7 +387,7 @@
|
||||
</span>
|
||||
</div>
|
||||
<svg
|
||||
viewBox="0 0 400 120"
|
||||
viewBox="0 0 400 135"
|
||||
class="w-full"
|
||||
aria-hidden="true"
|
||||
>
|
||||
@@ -406,6 +411,13 @@
|
||||
/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<!-- Y-axis label -->
|
||||
<text
|
||||
transform="translate(8, 60) rotate(-90)"
|
||||
text-anchor="middle"
|
||||
font-size="8"
|
||||
fill="#9ca3af"
|
||||
>Guesses</text>
|
||||
<!-- Fill polygon -->
|
||||
<polygon
|
||||
points="{polylinePoints} {svgX(
|
||||
@@ -454,12 +466,27 @@
|
||||
>
|
||||
{chartPoints[chartPoints.length - 1].label}
|
||||
</text>
|
||||
<!-- X-axis title -->
|
||||
<text
|
||||
x="200"
|
||||
y="132"
|
||||
font-size="8"
|
||||
fill="#9ca3af"
|
||||
text-anchor="middle"
|
||||
>Date</text>
|
||||
</svg>
|
||||
{#if chartImproving}
|
||||
<p class="text-xs text-emerald-400 mt-1">
|
||||
You're getting better!
|
||||
</p>
|
||||
{/if}
|
||||
<p
|
||||
class="text-xs text-gray-500 mt-2 leading-relaxed"
|
||||
>
|
||||
Each point is your average guesses over a
|
||||
rolling window of games. A downward trend means
|
||||
you're improving.
|
||||
</p>
|
||||
</div>
|
||||
</Container>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user