Skip to content

feat(ui): home stile Apple Wallet + restyle Pocket#32

Open
juni93 wants to merge 1 commit into
savez:mainfrom
juni93:feat/home-apple-wallet
Open

feat(ui): home stile Apple Wallet + restyle Pocket#32
juni93 wants to merge 1 commit into
savez:mainfrom
juni93:feat/home-apple-wallet

Conversation

@juni93

@juni93 juni93 commented Jun 27, 2026

Copy link
Copy Markdown

Cosa cambia

Restyle della UI con due livelli:

Nuovo look "Apple Wallet" per la home

  • Da griglia 2 colonne a carte impilate/sovrapposte stile Wallet iOS (pinnate in cima).
  • Tap su una carta → si espande inline mostrando il barcode/QR + azioni Ingrandisci / Dettaglio. Una sola aperta alla volta, animazione fluida.
  • Ricerca con apertura automatica: quando i filtri lasciano un solo risultato, la carta si apre da sola (codice pronto, zero tap in più).

Fix e polish (direzione "Pocket" indigo mantenuta)

  • contrast.js: pick WCAG reale (max-contrast) → nomi leggibili su brand verdi/arancioni (es. Leroy Merlin passava da 2.29:1 a 7.92:1).
  • Bottom-bar a 3 slot con FAB circolare incastonato + safe-area iOS; spazio in fondo così l'ultima carta non resta sotto la barra.
  • Resi theme-aware (dark/light): pill versione (era invisibile in light), app-bar (hairline di separazione), fullscreen barcode (niente più "flashbang" bianco in dark), icon-picker.
  • Disabled "fantasma" del bottone primario neutralizzato; theme-color PWA allineato alla palette indigo; header/spaziature coerenti tra le viste.
  • Fix utility inesistenti gap-*ga-* (Vuetify 3).
  • Rimosso CardTile.vue (sostituito da WalletCard.vue).

Perché

Miglioria UX: la home aveva una griglia poco distintiva, alcuni difetti di leggibilità (pill invisibile in light, nomi tessera a basso contrasto su certi brand, fullscreen accecante in dark) e il FAB copriva il contenuto. Il Wallet rende il gesto "mostra il codice alla cassa" immediato.

Test plan

  • npm test verde (68/68)
  • npm run build verde
  • npm run lint verde (0 errori)
  • Provato manualmente in npm run dev
  • (se UI) provato anche in dark mode
  • (se PWA / Service Worker) provato con npm run preview

Tipo di cambiamento

  • Bug fix (non breaking)
  • Nuova feature (non breaking)
  • Breaking change
  • Refactor / chore (no funzionalità nuove)
  • Documentazione

Note per il review

  • Contrasto verificato su tutti i 30 brand: nessuno sotto 3:1; unico borderline Decathlon #0082C3 (dark 4.30 vs white 4.22), WCAG-max-correct, AA-large ok.
  • CardTile eliminato perché interamente sostituito da WalletCard (unico utilizzo era la home).
  • Tutte le scelte di colore passano per i token tema Vuetify; unica eccezione voluta: la card bianca del fullscreen barcode (serve la quiet-zone bianca per lo scanner).
  • Nota repo: npm ci installa una Prettier più recente di quella con cui erano committati alcuni file → format:check segnala file non toccati da questa PR (drift pre-esistente). La CI non esegue format:check, quindi non blocca; eventuale cleanup in un chore/ separato.

- Home: griglia -> carte impilate stile Apple Wallet; tap espande il barcode inline

- Ricerca: apre automaticamente l'unico risultato (zero tap per il codice)

- Contrasto tessere: pick WCAG reale, leggibile su brand verdi/arancioni (Leroy Merlin)

- FAB circolare incastonato + bottom-bar a 3 slot + safe-area iOS

- Spazio in fondo per non coprire l'ultima carta

- Pill versione, app-bar, fullscreen e icon-picker resi theme-aware (dark/light)

- theme-color PWA indigo; header e spaziature coerenti tra le viste

- Rimosso CardTile (sostituito da WalletCard); fix gap-* -> ga-*
@savez

savez commented Jun 27, 2026

Copy link
Copy Markdown
Owner

@juni93 carino!

ti segnalo un mini bug.
se selezioni dalla ricerca un nome di una card si apre, ma poi cancellando la ricerca non si chiude rimannedo aperta.

Registrazione.schermo.2026-06-27.alle.22.17.12.mov

Comment thread src/views/CardsView.vue
Comment on lines +10 to +22
const openId = ref(null)

// Quando i filtri lasciano un solo risultato (es. ricerca con un match),
// la apriamo automaticamente: il codice è pronto senza un tap in più.
// Legato all'id dell'unico match — non si riapre a ogni tasto se lo chiudi.
const soleMatchId = computed(() => (cards.filtered.length === 1 ? cards.filtered[0].id : null))
watch(soleMatchId, (id) => {
if (id) openId.value = id
})

function onToggle(id) {
openId.value = openId.value === id ? null : id
}

@savez savez Jun 27, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: con la ricerca che lascia un solo risultato la card si auto-apre, ma cancellando la ricerca non si richiude. Causa: il watch(soleMatchId) apre soltanto (if (id) openId.value = id) e non chiude mai quando il match unico finisce.

Suggerimento: tracciare l'id aperto automaticamente e richiuderlo quando il match unico finisce, senza toccare le aperture manuali.

Suggested change
const openId = ref(null)
// Quando i filtri lasciano un solo risultato (es. ricerca con un match),
// la apriamo automaticamente: il codice è pronto senza un tap in più.
// Legato all'id dell'unico match — non si riapre a ogni tasto se lo chiudi.
const soleMatchId = computed(() => (cards.filtered.length === 1 ? cards.filtered[0].id : null))
watch(soleMatchId, (id) => {
if (id) openId.value = id
})
function onToggle(id) {
openId.value = openId.value === id ? null : id
}
const openId = ref(null)
// Traccia la carta aperta automaticamente dal match unico, così possiamo
// richiuderla quando la ricerca viene cancellata/allargata.
const autoOpenedId = ref(null)
// Quando i filtri lasciano un solo risultato (es. ricerca con un match),
// la apriamo automaticamente: il codice è pronto senza un tap in più.
const soleMatchId = computed(() => (cards.filtered.length === 1 ? cards.filtered[0].id : null))
watch(soleMatchId, (id) => {
if (id) {
openId.value = id
autoOpenedId.value = id
} else if (autoOpenedId.value) {
// Match unico finito (ricerca cancellata/allargata): richiudi solo ciò
// che avevamo aperto noi, lasciando stare un'apertura manuale.
if (openId.value === autoOpenedId.value) openId.value = null
autoOpenedId.value = null
}
})
function onToggle(id) {
openId.value = openId.value === id ? null : id
autoOpenedId.value = null // interazione manuale: non più "automatica"
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants