Skip to content

Commit 5fe228d

Browse files
committed
Profile picture
1 parent 3e28597 commit 5fe228d

File tree

8 files changed

+758
-595
lines changed

8 files changed

+758
-595
lines changed

auth-libs/web-component/dist/hanko-auth.esm.js

Lines changed: 528 additions & 487 deletions
Large diffs are not rendered by default.

auth-libs/web-component/dist/hanko-auth.iife.js

Lines changed: 66 additions & 38 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

auth-libs/web-component/dist/hanko-auth.umd.js

Lines changed: 65 additions & 37 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

auth-libs/web-component/src/hanko-auth.styles.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ export const styles = css`
146146
font-size: var(--hot-font-size-large);
147147
font-weight: var(--hot-font-weight-bold);
148148
color: var(--hot-color-gray-600);
149+
overflow: hidden;
149150
}
150151
151152
.profile-info {
@@ -238,6 +239,15 @@ export const styles = css`
238239
.osm-status-badge.required {
239240
background-color: var(--hot-color-warning-600);
240241
}
242+
/* Avatar image — fills the circle, hides the initial letter */
243+
.avatar-img {
244+
width: 100%;
245+
height: 100%;
246+
border-radius: 50%;
247+
object-fit: cover;
248+
display: block;
249+
}
250+
241251
.header-avatar {
242252
width: var(--hot-spacing-2x-large);
243253
height: var(--hot-spacing-2x-large);
@@ -247,6 +257,7 @@ export const styles = css`
247257
align-items: center;
248258
justify-content: center;
249259
font-size: var(--hot-font-size-small);
260+
overflow: hidden;
250261
font-weight: var(--hot-font-weight-semibold);
251262
color: white;
252263
}
@@ -267,8 +278,14 @@ export const styles = css`
267278
display: inline-block;
268279
cursor: pointer;
269280
transition: all 0.2s;
270-
font-weight: var(--login-btn-font-weight, var(--font-weight, var(--hot-font-weight-medium)));
271-
font-family: var(--login-btn-font-family, var(--font-family, var(--hot-font-sans)));
281+
font-weight: var(
282+
--login-btn-font-weight,
283+
var(--font-weight, var(--hot-font-weight-medium))
284+
);
285+
font-family: var(
286+
--login-btn-font-family,
287+
var(--font-family, var(--hot-font-sans))
288+
);
272289
}
273290
274291
/* Button variants - filled */
@@ -493,4 +510,9 @@ export const styles = css`
493510
box-sizing: border-box;
494511
text-decoration: none;
495512
}
513+
514+
/* Style Hanko's internal link button (e.g. "Create account") */
515+
hanko-auth::part(link) {
516+
font-weight: bold;
517+
}
496518
`;

auth-libs/web-component/src/hanko-auth.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ const sharedAuth = {
7272
initialized: false,
7373
instances: new Set<any>(),
7474
profileDisplayName: "", // Shared profile display name
75+
profilePictureUrl: "", // Shared profile picture URL
7576
hankoReady: false, // used for translations
7677
};
7778

@@ -144,6 +145,7 @@ export class HankoAuth extends LitElement {
144145
@state() private error: string | null = null;
145146
@state() private hankoReady = false; // Tracks when Hanko registration is complete
146147
@state() private profileDisplayName: string = "";
148+
@state() private profilePictureUrl: string = "";
147149
@state() private hasAppMapping = false; // True if user has mapping in the app
148150
@state() private userProfileLanguage: string | null = null; // Language from user profile
149151
// dropdown
@@ -321,6 +323,8 @@ export class HankoAuth extends LitElement {
321323
if (this._hanko !== sharedAuth.hanko) this._hanko = sharedAuth.hanko;
322324
if (this.profileDisplayName !== sharedAuth.profileDisplayName)
323325
this.profileDisplayName = sharedAuth.profileDisplayName;
326+
if (this.profilePictureUrl !== sharedAuth.profilePictureUrl)
327+
this.profilePictureUrl = sharedAuth.profilePictureUrl;
324328
if (this.hankoReady !== sharedAuth.hankoReady)
325329
this.hankoReady = sharedAuth.hankoReady;
326330
}
@@ -332,6 +336,7 @@ export class HankoAuth extends LitElement {
332336
sharedAuth.osmData = this.osmData;
333337
sharedAuth.loading = this.loading;
334338
sharedAuth.profileDisplayName = this.profileDisplayName;
339+
sharedAuth.profilePictureUrl = this.profilePictureUrl;
335340
sharedAuth.hankoReady = this.hankoReady;
336341

337342
// Sync to all other instances
@@ -886,6 +891,13 @@ export class HankoAuth extends LitElement {
886891
this.log("👤 Display name set to:", this.profileDisplayName);
887892
}
888893

894+
// picture_url is always set by the backend (Gravatar fallback); osm_avatar_url as secondary
895+
const picUrl = profile.picture_url || profile.osm_avatar_url;
896+
if (picUrl) {
897+
this.profilePictureUrl = picUrl;
898+
this.log("🖼️ Profile picture set to:", this.profilePictureUrl);
899+
}
900+
889901
// Set language from user profile if available
890902
if (profile.language) {
891903
this.userProfileLanguage = profile.language;
@@ -1254,6 +1266,7 @@ export class HankoAuth extends LitElement {
12541266
this.osmData = null;
12551267
this.hasAppMapping = false;
12561268
this.userProfileLanguage = null; // Clear user's language preference
1269+
this.profilePictureUrl = ""; // Clear profile picture
12571270

12581271
// Broadcast state changes to other instances
12591272
if (this._isPrimary) {
@@ -1453,7 +1466,11 @@ export class HankoAuth extends LitElement {
14531466
<div class="container">
14541467
<div class="profile">
14551468
<div class="profile-header">
1456-
<div class="profile-avatar">${initial}</div>
1469+
<div class="profile-avatar">
1470+
${this.profilePictureUrl
1471+
? html`<img class="avatar-img" src="${this.profilePictureUrl}" alt="${initial}" @error=${(e: Event) => { (e.target as HTMLImageElement).style.display = "none"; }} />`
1472+
: initial}
1473+
</div>
14571474
<div class="profile-info">
14581475
<div class="profile-email">
14591476
${this.user.email || this.user.id}
@@ -1538,7 +1555,11 @@ export class HankoAuth extends LitElement {
15381555
class="bar-trigger"
15391556
>
15401557
<div class="bar-info">
1541-
<span class="header-avatar">${initial}</span>
1558+
<span class="header-avatar">
1559+
${this.profilePictureUrl
1560+
? html`<img class="avatar-img" src="${this.profilePictureUrl}" alt="${initial}" @error=${(e: Event) => { (e.target as HTMLImageElement).style.display = "none"; }} />`
1561+
: initial}
1562+
</span>
15421563
<span class="bar-email"
15431564
>${this.user.email || this.user.id}</span
15441565
>
@@ -1563,7 +1584,11 @@ export class HankoAuth extends LitElement {
15631584
aria-haspopup="true"
15641585
class="dropdown-trigger"
15651586
>
1566-
<span class="header-avatar">${initial}</span>
1587+
<span class="header-avatar">
1588+
${this.profilePictureUrl
1589+
? html`<img class="avatar-img" src="${this.profilePictureUrl}" alt="${initial}" @error=${(e: Event) => { (e.target as HTMLImageElement).style.display = "none"; }} />`
1590+
: initial}
1591+
</span>
15671592
15681593
${this.osmConnected
15691594
? html`

frontend/src/pages/LoginPage.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,11 +278,12 @@ function LoginPage() {
278278

279279
{returnTo && !isOnboarding && (
280280
<div className="mt-6 pt-6 border-t border-hot-gray-200 text-center">
281+
<span></span>
281282
<a
282283
href={returnTo}
283-
className="text-sm text-hot-gray-600 hover:text-hot-gray-900 inline-flex items-center gap-2 transition-colors"
284+
className="font-bold text-hot-gray-900 hover:underline inline-flex items-center gap-2 transition-colors "
284285
>
285-
<span></span> {t("backToPreviousPage")}
286+
{t("backToPreviousPage")}
286287
</a>
287288
</div>
288289
)}

frontend/src/pages/ProfilePage.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ function ProfilePage() {
7070
setProfile(null);
7171

7272
// Show confirmation
73-
alert(t("accountDeleted") || "Your account has been deleted successfully.");
73+
alert(
74+
t("accountDeleted") || "Your account has been deleted successfully.",
75+
);
7476

7577
// Redirect to the return URL (previous app) or login page
7678
if (returnTo) {
@@ -198,7 +200,7 @@ function ProfilePage() {
198200
}}
199201
className="text-hot-gray-1000 hover:text-hot-gray-900 text-sm transition-colors"
200202
>
201-
{t("backTo")} {backInfo.label}
203+
{t("back")}
202204
</button>
203205
</div>
204206
</div>

frontend/src/translations.ts

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* Translations for the login frontend
3-
*
3+
*
44
* To add a new language, add a new key to the translations object
55
*/
66

@@ -20,10 +20,10 @@ export interface Translations {
2020
accessAllTools: string;
2121
backToPreviousPage: string;
2222
poweredBy: string;
23-
23+
2424
// ProfilePage
2525
myProfile: string;
26-
backTo: string;
26+
back: string;
2727
profileInformation: string;
2828
pictureUrl: string;
2929
firstName: string;
@@ -44,7 +44,7 @@ export interface Translations {
4444
accountCreated: string;
4545
accountDeleted: string;
4646
profileUpdated: string;
47-
47+
4848
// Common
4949
login: string;
5050
}
@@ -59,14 +59,15 @@ export const translations: Record<string, Translations> = {
5959
noImNew: "No, I'm new here",
6060
notSure: 'Not sure? Select "Yes" and we\'ll check for you.',
6161
connectOsmAccount: "Connect your OpenStreetMap account",
62-
connectSameOsm: "Connect with the same OSM account you used before to recover your",
62+
connectSameOsm:
63+
"Connect with the same OSM account you used before to recover your",
6364
goBack: "← Go back",
6465
settingUpAccount: "Setting up your account...",
6566
accessAllTools: "Access all HOT tools and services",
6667
backToPreviousPage: "Back to previous page",
6768
poweredBy: "Powered by",
6869
myProfile: "My Profile",
69-
backTo: "Back to",
70+
back: "Back",
7071
profileInformation: "Profile Information",
7172
pictureUrl: "Picture URL",
7273
firstName: "First Name",
@@ -78,11 +79,14 @@ export const translations: Record<string, Translations> = {
7879
saveChanges: "Save Changes",
7980
saving: "Saving...",
8081
security: "Security",
81-
managePasswordPasskeys: "Manage your password, passkeys, and active sessions.",
82+
managePasswordPasskeys:
83+
"Manage your password, passkeys, and active sessions.",
8284
dangerZone: "Danger Zone",
83-
deleteAccountWarning: "Permanently delete your account and all associated data.",
85+
deleteAccountWarning:
86+
"Permanently delete your account and all associated data.",
8487
deleteAccount: "Delete Account",
85-
deleteConfirm: "Are you sure you want to delete your account? This action cannot be undone.",
88+
deleteConfirm:
89+
"Are you sure you want to delete your account? This action cannot be undone.",
8690
deleteComingSoon: "Account deletion will be available soon.",
8791
accountCreated: "Account created",
8892
accountDeleted: "Your account has been deleted successfully.",
@@ -98,30 +102,35 @@ export const translations: Record<string, Translations> = {
98102
noImNew: "No, soy nuevo aquí",
99103
notSure: '¿No estás seguro? Selecciona "Sí" y lo verificaremos por ti.',
100104
connectOsmAccount: "Conecta tu cuenta de OpenStreetMap",
101-
connectSameOsm: "Conéctate con la misma cuenta OSM que usaste antes para recuperar tu",
105+
connectSameOsm:
106+
"Conéctate con la misma cuenta OSM que usaste antes para recuperar tu",
102107
goBack: "← Volver",
103108
settingUpAccount: "Configurando tu cuenta...",
104109
accessAllTools: "Accede a todas las herramientas y servicios de HOT",
105110
backToPreviousPage: "Volver a la página anterior",
106111
poweredBy: "Desarrollado por",
107112
myProfile: "Mi Perfil",
108-
backTo: "Volver a",
113+
back: "Volver",
109114
profileInformation: "Información del Perfil",
110115
pictureUrl: "URL de imagen",
111116
firstName: "Nombre",
112117
lastName: "Apellido",
113118
email: "Correo electrónico",
114-
emailManagedBy: "El correo es administrado por tu proveedor de inicio de sesión",
119+
emailManagedBy:
120+
"El correo es administrado por tu proveedor de inicio de sesión",
115121
language: "Idioma",
116122
connectedToOsm: "Conectado a OpenStreetMap",
117123
saveChanges: "Guardar Cambios",
118124
saving: "Guardando...",
119125
security: "Seguridad",
120-
managePasswordPasskeys: "Administra tu contraseña, passkeys y sesiones activas.",
126+
managePasswordPasskeys:
127+
"Administra tu contraseña, passkeys y sesiones activas.",
121128
dangerZone: "Zona de Peligro",
122-
deleteAccountWarning: "Elimina permanentemente tu cuenta y todos los datos asociados.",
129+
deleteAccountWarning:
130+
"Elimina permanentemente tu cuenta y todos los datos asociados.",
123131
deleteAccount: "Eliminar Cuenta",
124-
deleteConfirm: "¿Estás seguro de que quieres eliminar tu cuenta? Esta acción no se puede deshacer.",
132+
deleteConfirm:
133+
"¿Estás seguro de que quieres eliminar tu cuenta? Esta acción no se puede deshacer.",
125134
deleteComingSoon: "La eliminación de cuenta estará disponible pronto.",
126135
accountCreated: "Cuenta creada",
127136
accountDeleted: "Tu cuenta ha sido eliminada exitosamente.",
@@ -137,14 +146,15 @@ export const translations: Record<string, Translations> = {
137146
noImNew: "Non, je suis nouveau",
138147
notSure: 'Pas sûr ? Sélectionnez "Oui" et nous vérifierons pour vous.',
139148
connectOsmAccount: "Connectez votre compte OpenStreetMap",
140-
connectSameOsm: "Connectez-vous avec le même compte OSM que vous avez utilisé auparavant pour récupérer votre",
149+
connectSameOsm:
150+
"Connectez-vous avec le même compte OSM que vous avez utilisé auparavant pour récupérer votre",
141151
goBack: "← Retour",
142152
settingUpAccount: "Configuration de votre compte...",
143153
accessAllTools: "Accédez à tous les outils et services HOT",
144154
backToPreviousPage: "Retour à la page précédente",
145155
poweredBy: "Propulsé par",
146156
myProfile: "Mon Profil",
147-
backTo: "Retour à",
157+
back: "Retour",
148158
profileInformation: "Informations du Profil",
149159
pictureUrl: "URL de l'image",
150160
firstName: "Prénom",
@@ -156,11 +166,14 @@ export const translations: Record<string, Translations> = {
156166
saveChanges: "Enregistrer les Modifications",
157167
saving: "Enregistrement...",
158168
security: "Sécurité",
159-
managePasswordPasskeys: "Gérez votre mot de passe, passkeys et sessions actives.",
169+
managePasswordPasskeys:
170+
"Gérez votre mot de passe, passkeys et sessions actives.",
160171
dangerZone: "Zone Dangereuse",
161-
deleteAccountWarning: "Supprimer définitivement votre compte et toutes les données associées.",
172+
deleteAccountWarning:
173+
"Supprimer définitivement votre compte et toutes les données associées.",
162174
deleteAccount: "Supprimer le Compte",
163-
deleteConfirm: "Êtes-vous sûr de vouloir supprimer votre compte ? Cette action ne peut pas être annulée.",
175+
deleteConfirm:
176+
"Êtes-vous sûr de vouloir supprimer votre compte ? Cette action ne peut pas être annulée.",
164177
deleteComingSoon: "La suppression de compte sera bientôt disponible.",
165178
accountCreated: "Compte créé",
166179
accountDeleted: "Votre compte a été supprimé avec succès.",
@@ -176,14 +189,15 @@ export const translations: Record<string, Translations> = {
176189
noImNew: "Não, sou novo aqui",
177190
notSure: 'Não tem certeza? Selecione "Sim" e verificaremos para você.',
178191
connectOsmAccount: "Conecte sua conta OpenStreetMap",
179-
connectSameOsm: "Conecte-se com a mesma conta OSM que você usou antes para recuperar seu",
192+
connectSameOsm:
193+
"Conecte-se com a mesma conta OSM que você usou antes para recuperar seu",
180194
goBack: "← Voltar",
181195
settingUpAccount: "Configurando sua conta...",
182196
accessAllTools: "Acesse todas as ferramentas e serviços HOT",
183197
backToPreviousPage: "Voltar à página anterior",
184198
poweredBy: "Desenvolvido por",
185199
myProfile: "Meu Perfil",
186-
backTo: "Voltar para",
200+
back: "Voltar",
187201
profileInformation: "Informações do Perfil",
188202
pictureUrl: "URL da imagem",
189203
firstName: "Nome",
@@ -197,9 +211,11 @@ export const translations: Record<string, Translations> = {
197211
security: "Segurança",
198212
managePasswordPasskeys: "Gerencie sua senha, passkeys e sessões ativas.",
199213
dangerZone: "Zona de Perigo",
200-
deleteAccountWarning: "Excluir permanentemente sua conta e todos os dados associados.",
214+
deleteAccountWarning:
215+
"Excluir permanentemente sua conta e todos os dados associados.",
201216
deleteAccount: "Excluir Conta",
202-
deleteConfirm: "Tem certeza de que deseja excluir sua conta? Esta ação não pode ser desfeita.",
217+
deleteConfirm:
218+
"Tem certeza de que deseja excluir sua conta? Esta ação não pode ser desfeita.",
203219
deleteComingSoon: "A exclusão de conta estará disponível em breve.",
204220
accountCreated: "Conta criada",
205221
accountDeleted: "Sua conta foi excluída com sucesso.",

0 commit comments

Comments
 (0)