Skip to content

Commit bf258e6

Browse files
committed
UI improvements: fingerprint inline right of password, delete cross in card header, centered generate button
1 parent 391d9d9 commit bf258e6

4 files changed

Lines changed: 151 additions & 21 deletions

File tree

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Plan : Améliorations UI (4 points)
2+
3+
## Avis sur les 4 propositions
4+
5+
| # | Proposition | Avis | Raison |
6+
|---|---|---|---|
7+
| 1 | "Ajouter un site" en modal | **Non recommandé** | Le formulaire n'est utilisé qu'occasionnellement. Un modal ajoute de la complexité JS (open/close, focus trap, ESC handler) pour un gain UX marginal. Le `.form-add` actuel est bien contenu. KISS : garder inline. |
8+
| 2 | Fingerprints à droite du input, visible sur `""` | **Oui** | Déjà validé par le user. Améliore la lisibilité. |
9+
| 3 | "Générer" centré, bouton unique par carte | **Oui** | Nettoie le footer des cartes. Un seul bouton centré = moins de charge cognitive. |
10+
| 4 | Supprimer = croix rouge à droite du site | **Oui** | Réduit le clutter visuel. Le site est déjà le titre de la carte → la croix est naturellement associée. |
11+
12+
## Implémentation
13+
14+
### Fichiers modifiés
15+
16+
- `index.html` — réorganiser layout generateur, cartes, supprimer section inline
17+
- `src/store.ts` — fingerprint toujours calculé (même sur `""`)
18+
- `src/style.css` — styles inline fingerprint, croix delete, bouton centré
19+
20+
### 1. Fingerprints inline à droite du mdp maître (`index.html` + `src/style.css`)
21+
22+
**HTML** : Remplacer la div fingerprint par un conteneur flex à côté de l'input :
23+
```html
24+
<div class="password-field">
25+
<input type="password" ... x-model="$store.app.masterPassword" />
26+
<div class="fingerprint-inline">
27+
<template x-for="(finger, i) in ($store.app.fingerprint ?? $store.app.defaultFingerprint)" :key="i">
28+
<span :style="{ color: finger.color }" x-text="iconToEmoji(finger.icon)"></span>
29+
</template>
30+
</div>
31+
</div>
32+
```
33+
34+
**Store** : Ajouter un `defaultFingerprint` (hash d'une chaîne vide ou constante) pour afficher 3 emojis par défaut même quand le champ est vide.
35+
36+
**CSS** :
37+
```css
38+
.password-field {
39+
display: flex;
40+
align-items: center;
41+
gap: 0.5rem;
42+
}
43+
.password-field input { flex: 1; }
44+
.fingerprint-inline { display: flex; gap: 0.35rem; font-size: 1.4rem; user-select: none; }
45+
```
46+
47+
### 2. Générer = bouton centré unique par carte (`index.html` + `src/style.css`)
48+
49+
**HTML** : Dans les cartes profil, remplacer le footer par un seul bouton centré :
50+
```html
51+
<article>
52+
<header>
53+
<strong x-text="profile.site"></strong>
54+
<button class="delete-btn" @click="$store.app.removeProfile(profile.id)" title="Supprimer">×</button>
55+
</header>
56+
<p>Login : <span class="login-copy" ...>...</span></p>
57+
<p><small>...</small></p>
58+
<footer>
59+
<button @click="$store.app.fillGenerator(profile); $store.app.generatePassword()">Générer</button>
60+
</footer>
61+
</article>
62+
```
63+
64+
**CSS** :
65+
```css
66+
article header { display: flex; justify-content: space-between; align-items: center; }
67+
.delete-btn { background: none; border: none; color: var(--pico-del-color); font-size: 1.2rem; cursor: pointer; padding: 0; line-height: 1; }
68+
.delete-btn:hover { opacity: 0.7; }
69+
article footer { display: flex; justify-content: center; }
70+
```
71+
72+
### 3. Supprimer = croix rouge dans le header (`index.html`)
73+
74+
Intégré au point 2 ci-dessus. La croix `×` est à droite du `<strong>` du site dans le header de l'article.
75+
76+
### 4. Fingerprint toujours calculé (`src/store.ts`)
77+
78+
Modifier `updateFingerprint()` pour calculer la fingerprint même sur chaîne vide (utiliser une constante comme fallback) :
79+
```ts
80+
updateFingerprint() {
81+
buildFingerprint(this.masterPassword || '').then(fp => { this.fingerprint = fp; });
82+
},
83+
```
84+
85+
Le watcher Alpine effect déclenche `updateFingerprint()` au montage → la fingerprint par défaut (chaîne vide) s'affiche immédiatement.
86+
87+
## Vérification
88+
89+
1. Au chargement de la page → 3 emojis colorés visibles à côté du champ mdp
90+
2. Taper un mdp → les emojis changent en temps réel
91+
3. Cartes profil → croix rouge à droite du site name
92+
4. Cliquer la croix → profil supprimé
93+
5. Bouton "Générer" centré dans chaque carte
94+
6. Cliquer "Générer" sur une carte → remplit le générateur ET génère directement
95+
7. `npm run build` passe
96+
8. Test mobile responsive

index.html

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,17 @@ <h1>LessPass Helper</h1>
3737
<section>
3838
<h2>Générer un mot de passe</h2>
3939
<form @submit.prevent="$store.app.generatePassword()">
40-
<input
41-
type="password"
42-
placeholder="Mot de passe maître"
43-
x-model="$store.app.masterPassword"
44-
/>
45-
<div class="fingerprint" x-show="$store.app.fingerprint">
46-
<template x-for="(finger, i) in $store.app.fingerprint" :key="i">
47-
<span :style="{ color: finger.color }" x-text="iconToEmoji(finger.icon)"></span>
48-
</template>
40+
<div class="password-field">
41+
<input
42+
type="password"
43+
placeholder="Mot de passe maître"
44+
x-model="$store.app.masterPassword"
45+
/>
46+
<div class="fingerprint-inline">
47+
<template x-for="(finger, i) in $store.app.fingerprint" :key="i">
48+
<span :style="{ color: finger.color }" x-text="iconToEmoji(finger.icon)"></span>
49+
</template>
50+
</div>
4951
</div>
5052
<input
5153
type="text"
@@ -111,6 +113,7 @@ <h2>
111113
<article>
112114
<header>
113115
<strong x-text="profile.site"></strong>
116+
<button class="delete" @click="$store.app.removeProfile(profile.id)" title="Supprimer">&times;</button>
114117
</header>
115118
<p>
116119
Login :
@@ -134,8 +137,7 @@ <h2>
134137
</small>
135138
</p>
136139
<footer>
137-
<button @click="$store.app.fillGenerator(profile)">Générer</button>
138-
<button class="secondary" @click="$store.app.removeProfile(profile.id)">Supprimer</button>
140+
<button @click="$store.app.fillGenerator(profile); $store.app.generatePassword()" style="margin: 0 auto;">Générer</button>
139141
</footer>
140142
</article>
141143
</template>

src/store.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -205,13 +205,8 @@ Alpine.store('app', {
205205
},
206206

207207
updateFingerprint() {
208-
const pwd = this.masterPassword;
209-
if (!pwd) {
210-
this.fingerprint = null;
211-
return;
212-
}
213-
buildFingerprint(pwd).then(fp => {
214-
this.fingerprint = fp;
208+
buildFingerprint(this.masterPassword || '').then(fp => {
209+
this.fingerprint = fp as Fingerprint;
215210
});
216211
},
217212
} satisfies AppStore);

src/style.css

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,47 @@ output {
9797
margin-bottom: 0;
9898
}
9999

100-
.fingerprint {
100+
.password-field {
101101
display: flex;
102+
align-items: center;
102103
gap: 0.5rem;
103-
font-size: 1.5rem;
104-
padding: 0.25rem 0;
104+
}
105+
106+
.password-field input {
107+
flex: 1;
108+
}
109+
110+
.fingerprint-inline {
111+
display: flex;
112+
gap: 0.35rem;
113+
font-size: 1.4rem;
105114
user-select: none;
106115
}
116+
117+
article header {
118+
display: flex;
119+
justify-content: space-between;
120+
align-items: center;
121+
}
122+
123+
.delete {
124+
background: none;
125+
border: none;
126+
color: var(--pico-del-color, #ef4444);
127+
font-size: 1.3rem;
128+
cursor: pointer;
129+
padding: 0;
130+
line-height: 1;
131+
opacity: 0.5;
132+
transition: opacity 0.15s;
133+
}
134+
135+
.delete:hover {
136+
opacity: 1;
137+
}
138+
139+
article footer {
140+
display: flex;
141+
justify-content: center;
142+
padding: 0.5rem 0.75rem;
143+
}

0 commit comments

Comments
 (0)