snipe/web/src/composables/useTheme.ts
pyr0ball af51de4cec
Some checks are pending
CI / Python tests (push) Waiting to run
CI / Frontend typecheck + tests (push) Waiting to run
Mirror / mirror (push) Waiting to run
feat: landing hero copy polish + frontend test suite
- Rewrite landing hero subtitle with narrative opener ("Seen a listing
  that looks almost too good to pass up?") — more universal than the
  feature-list version, avoids category assumptions
- Update eBay cancellation callout CTA to "Search above to score
  listings before you commit" — direct action vs. passive reminder
- Tile descriptions rewritten with concrete examples: "does this seller
  actually know what they're selling?", "40% below median", quoted
  "scratch and dent" pattern for instant recognition
- Sign-in strip: add specific page count ("up to 5 pages") and
  "community-maintained" attribution for blocklist credibility
- Fix useTheme restore() to re-read from localStorage instead of using
  cached module-level ref — fixes test isolation failure where previous
  test's setMode('dark') leaked into the restore() system test
- Add 32-test Vitest suite: useTheme (7), searchStore (7),
  ListingView component (18) — all green
2026-04-16 12:39:54 -07:00

35 lines
878 B
TypeScript

import { ref, watchEffect } from 'vue'
const LS_KEY = 'snipe:theme'
type ThemeMode = 'system' | 'dark' | 'light'
// Module-level — shared across all callers
const mode = ref<ThemeMode>((localStorage.getItem(LS_KEY) as ThemeMode) ?? 'system')
function _apply(m: ThemeMode) {
const el = document.documentElement
if (m === 'dark') {
el.dataset.theme = 'dark'
} else if (m === 'light') {
el.dataset.theme = 'light'
} else {
delete el.dataset.theme
}
}
export function useTheme() {
function setMode(m: ThemeMode) {
mode.value = m
localStorage.setItem(LS_KEY, m)
_apply(m)
}
/** Re-apply from localStorage on hard reload (call from App.vue onMounted). */
function restore() {
const saved = (localStorage.getItem(LS_KEY) as ThemeMode) ?? 'system'
mode.value = saved
_apply(saved)
}
return { mode, setMode, restore }
}