Skip to content

24 — Achievement Toast

Slide-in overlay. Fires when the player earns a medal, levels up, hits a coach-affinity tier, or unlocks a track. Not a route — appears over whatever screen is active.

Purpose

Verb: Celebrate. Acknowledge a win without yanking the player out of what they're doing.

Wireframe (slide-in from bottom-right)

┌────────────────────────────────────────────────────────────┐
│  (parent screen at 100 % opacity — no dim)                 │
│                                                            │
│                                                            │
│                                                            │
│                                                            │
│                                                            │
│                                                            │
│                                                            │
│                                                            │
│                                                            │
│                                                            │
│                                                            │
│                                                            │
│                                                            │
│                            ╔════════════════════════════╗  │
│                            ║ ★ MEDAL UNLOCKED            ║  │
│                            ║ ┌──┐ TRAIL BRAKE APPRENTICE ║  │
│                            ║ │★★│ See Quest Log ▶         ║  │
│                            ║ └──┘ ┌──┐ T-ROD              ║  │
│                            ║      │ proud │ "Distance."   ║  │
│                            ║      └──┘                    ║  │
│                            ╚════════════════════════════╝  │
└────────────────────────────────────────────────────────────┘

States

State Trigger Behaviour
pending Achievement event queued during apex window Wait for safe moment; do not interrupt mid-corner
slide-in Safe moment Slide-in from right (250 ms outBack) per 08-animation-spec.md
lingering Slide-in done Hold 2 500 ms
slide-out Linger ends OR tap Slide-out (200 ms inOutCubic)
dismissed Slide-out done Removed from DOM
tapped Tap on toast Dismiss + navigate to detail (Quest Log medal page, Trainer Card level row, etc.)

Sprite usage

Sprite Where Animation
Medal sprite (per tier) Left of toast, 32×32 Static; medal tier picked from event
Coach (save.preferredCoach) Right of toast, 48×48 Emotion = proud (medal), excited (level-up), encouraging (affinity tier), intense (track unlock)
frame-default 9-slice Toast background Static
flash-white overlay Spark behind medal during slide-in 100 ms one-shot

The coach emotion is the load-bearing detail — it says "this is the kind of win this is." See ../10-coach-emotions.md.

Vue component

<!-- pitwall-web/src/components/AchievementToast.vue -->
<template>
  <Teleport to="body">
    <TransitionGroup name="toast-slide">
      <div v-for="t in queue" :key="t.id"
           class="toast"
           @click="onTap(t)">
        <Sprite :sheet="'medals'" :animation="t.sprite" />
        <div class="text">
          <p class="font-title text-title">{{ t.title }}</p>
          <p class="font-ui text-body">{{ t.subtitle }}</p>
        </div>
        <Sprite :sheet="t.coachId" :animation="t.coachEmotion" :variant="'idle'" />
      </div>
    </TransitionGroup>
  </Teleport>
</template>

<script setup lang="ts">
import { useAchievementQueue } from '@/stores/achievement'
const { queue, onTap } = useAchievementQueue()
</script>

The useAchievementQueue store ensures only one toast shows at a time; events arriving during apex-windows of 08-on-track-hud.md are buffered and surfaced during the next safe moment.

Endpoints consumed

None directly. Events are emitted by: - useSaveStore mutations (medal awarded, level changed) - SSE /cues/stream from the bridge (when bridge detects a milestone)

Audio cues

Event type Sound
Medal medal_award (slot-machine ding)
Level up level_up (1.8 s rising chime)
Coach affinity tier goal_complete
Track unlock pb_unlock

Audio is suppressed during apex window of the on-track HUD per 06-audio-design.md § rule 5. SFX queues up with the visual.

Input map

Input Action
Tap on toast Dismiss instantly + navigate to detail
Any other input No-op (the toast is non-blocking)

Edge cases

  • Multiple achievements at once (rare) — queue them; show one at a time, 200 ms gap between
  • Network drop while toast pending — toast still shows; the underlying data is local
  • Player dismissed via tap mid-slide-in — finish slide-in, then immediately slide-out
  • prefers-reduced-motion: reduce — skip slide-in animation, appear for 1 500 ms then disappear