Aggiunge skill /ux per frontend e UX design

Slash command che attiva il profilo senior frontend/UX designer.
Include checklist di revisione (touch, accessibilità, CSS, Vue 3)
e pattern di riferimento con le variabili CSS e componenti del progetto.
Formato SKILL.md conforme alla documentazione ufficiale Claude Code.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-25 00:10:09 +01:00
parent 14e89fee7c
commit 4413c8e7b6
3 changed files with 185 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
---
name: ux
description: Senior frontend developer e UX designer per app mobile-first. Usa quando si lavora su componenti Vue, layout, CSS, accessibilità o si vuole una revisione UX.
argument-hint: "[componente o area da rivedere]"
disable-model-invocation: true
---
Agisci come senior frontend developer e UX designer specializzato in app mobile-first (Vue 3, CSS nativo, accessibilità WCAG 2.1).
## Regole
- Proponi solo modifiche minime e mirate — niente over-engineering, niente librerie UI esterne salvo richiesta
- Per ogni scelta CSS o di layout, motiva la decisione UX in una riga
- Se esistono trade-off, mostra l'alternativa scartata e spiega perché
- Commenta nel codice solo le decisioni non ovvie
## Priorità di design
1. **Chiarezza** — l'utente capisce cosa fare senza istruzioni
2. **Feedback immediato** — ogni azione ha risposta visiva entro 100ms
3. **Touch-friendly** — target minimo 44×44px, spaziature generose
4. **Coerenza** — variabili CSS centralizzate, stessa logica visiva ovunque
5. **Accessibilità** — contrasto AA (4.5:1), label semantici, focus visibile
## Output atteso
Restituisci sempre il file Vue completo aggiornato (non solo il diff).
## Risorse di riferimento
- Per la checklist di revisione UX completa, consulta [checklist.md](checklist.md)
- Per i pattern Vue 3 + CSS approvati per questo progetto (variabili, componenti tipo), consulta [patterns.md](patterns.md)
$ARGUMENTS

View File

@@ -0,0 +1,38 @@
# UX Review Checklist
Usa questa checklist quando rivedi o scrivi un componente Vue mobile-first.
## Touch & interazione
- [ ] Ogni elemento interattivo ha `min-height: 44px` e `min-width: 44px`
- [ ] Spaziatura tra elementi adiacenti ≥ 8px (evita tap accidentali)
- [ ] Stati `:active` e `:focus-visible` definiti esplicitamente
- [ ] Nessun hover-only interaction (non funziona su touch)
## Feedback visivo
- [ ] Ogni azione utente ha risposta visiva immediata (cambio colore, spinner, messaggio)
- [ ] Stato vuoto gestito con messaggio utile, non schermata bianca
- [ ] Errori comunicati in linguaggio naturale, non codici tecnici
- [ ] Operazioni distruttive (elimina, svuota) richiedono conferma
## Accessibilità
- [ ] Rapporto di contrasto ≥ 4.5:1 per testo normale, ≥ 3:1 per testo grande
- [ ] `<input>` ha `<label>` associato (non solo placeholder)
- [ ] `<button>` ha testo leggibile o `aria-label`
- [ ] Ordine di navigazione con Tab è logico e visibile
## CSS & coerenza
- [ ] Colori e dimensioni usano variabili CSS (`:root { --color-* }`)
- [ ] Nessun valore hardcoded che duplica una variabile esistente
- [ ] Font-size base 16px, nessun testo sotto 14px
- [ ] `box-sizing: border-box` applicato globalmente
## Vue 3
- [ ] Props tipizzate con `defineProps`
- [ ] Eventi emessi con `defineEmits`
- [ ] Nessuna logica diretta nel template (estrai in computed o funzioni)
- [ ] `watch` con `{ deep: true }` solo dove necessario (ha costo)

View File

@@ -0,0 +1,113 @@
# Pattern di riferimento
Pattern Vue 3 + CSS nativo approvati per questo progetto.
## Variabili CSS del progetto
```css
:root {
--color-bg: #f5f5f5;
--color-surface: #ffffff;
--color-primary: #2d6a4f;
--color-primary-light: #52b788;
--color-text: #1a1a1a;
--color-muted: #6b7280;
--color-border: #e5e7eb;
--color-danger: #dc2626;
--radius: 8px;
--nav-height: 60px;
}
```
Usa sempre queste variabili. Non aggiungere colori hardcoded.
---
## Input con label accessibile
```vue
<label class="field">
<span class="field-label">Nome elemento</span>
<input v-model="value" type="text" placeholder="es. pollo 200g" />
</label>
```
```css
.field { display: flex; flex-direction: column; gap: 4px; }
.field-label { font-size: 0.85rem; color: var(--color-muted); font-weight: 600; }
input { border: 1px solid var(--color-border); border-radius: var(--radius);
padding: 10px 12px; min-height: 44px; font-size: 1rem; }
input:focus { outline: 2px solid var(--color-primary); outline-offset: 1px; }
```
---
## Riga con azione distruttiva
```vue
<div class="item-row">
<span class="item-text">{{ item.name }}</span>
<button class="btn-remove" @click="$emit('remove')" aria-label="Rimuovi {{ item.name }}"></button>
</div>
```
```css
.item-row { display: flex; align-items: center; justify-content: space-between;
background: var(--color-surface); border-radius: var(--radius);
padding: 12px 14px; border: 1px solid var(--color-border); }
.btn-remove { background: none; color: var(--color-muted); min-height: 44px;
min-width: 44px; font-size: 0.85rem; }
.btn-remove:active { color: var(--color-danger); }
```
---
## Bottone primario full-width (mobile)
```vue
<button class="btn-primary" @click="action">Conferma</button>
```
```css
.btn-primary { width: 100%; background: var(--color-primary); color: #fff;
border-radius: var(--radius); min-height: 48px; font-size: 1rem;
font-weight: 600; }
.btn-primary:active { background: var(--color-primary-light); }
```
---
## Stato vuoto
```vue
<template v-if="items.length">
<!-- lista -->
</template>
<div v-else class="empty-state">
<p>Nessun elemento.</p>
<p class="empty-hint">Aggiungi qualcosa con il campo qui sopra.</p>
</div>
```
```css
.empty-state { text-align: center; padding: 40px 16px; color: var(--color-muted); }
.empty-hint { font-size: 0.85rem; margin-top: 4px; }
```
---
## Toggle a due stati
```vue
<div class="toggle-group">
<button :class="['toggle-btn', { active: mode === 'a' }]" @click="mode = 'a'">Opzione A</button>
<button :class="['toggle-btn', { active: mode === 'b' }]" @click="mode = 'b'">Opzione B</button>
</div>
```
```css
.toggle-group { display: flex; gap: 8px; }
.toggle-btn { flex: 1; background: var(--color-bg); color: var(--color-muted);
border: 1px solid var(--color-border); min-height: 44px; font-size: 0.9rem; }
.toggle-btn.active { background: var(--color-primary); color: #fff; border-color: var(--color-primary); }
```