feat: add camel logo and random desert-themed subtitles to login page
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 59s
CI / docker (push) Successful in 52s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 36s

25 rotating cameleer-themed login subtitles picked randomly on each
page load. Also adds the camel logo SVG next to the app name.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-29 11:10:27 +02:00
parent 7a84914866
commit 09a60c5a6c
2 changed files with 43 additions and 3 deletions

View File

@@ -21,12 +21,20 @@
}
.logo {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
font-size: 24px;
font-weight: 700;
color: var(--text-primary);
}
.logoImg {
width: 36px;
height: 36px;
}
.subtitle {
font-size: 13px;
color: var(--text-muted);

View File

@@ -1,4 +1,4 @@
import { type FormEvent, useEffect, useState } from 'react';
import { type FormEvent, useEffect, useMemo, useState } from 'react';
import { Navigate } from 'react-router';
import { useAuthStore } from './auth-store';
import { api } from '../api/client';
@@ -10,8 +10,37 @@ interface OidcInfo {
authorizationEndpoint: string;
}
const SUBTITLES = [
"Prove you're not a mirage",
"Only authorized cameleers beyond this dune",
"Halt, traveler — state your business",
"The caravan doesn't move without credentials",
"No hitchhikers on this caravan",
"This oasis requires a password",
"Camels remember faces. We use passwords.",
"You shall not pass... without logging in",
"The desert is vast. Your session has expired.",
"Another day, another dune to authenticate",
"Papers, please. The caravan master is watching.",
"Trust, but verify — ancient cameleer proverb",
"Even the Silk Road had checkpoints",
"Your camel is parked outside. Now identify yourself.",
"One does not simply walk into the dashboard",
"The sands shift, but your password shouldn't",
"Unauthorized access? In this economy?",
"Welcome back, weary traveler",
"The dashboard awaits on the other side of this dune",
"Keep calm and authenticate",
"Who goes there? Friend or rogue exchange?",
"Access denied looks the same in every desert",
"May your routes be green and your tokens valid",
"Forgot your password? That's between you and the dunes.",
"No ticket, no caravan",
];
export function LoginPage() {
const { isAuthenticated, login, loading, error } = useAuthStore();
const subtitle = useMemo(() => SUBTITLES[Math.floor(Math.random() * SUBTITLES.length)], []);
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [oidc, setOidc] = useState<OidcInfo | null>(null);
@@ -54,8 +83,11 @@ export function LoginPage() {
<div className={styles.page}>
<Card className={styles.card}>
<div className={styles.loginForm}>
<div className={styles.logo}>cameleer3</div>
<p className={styles.subtitle}>Sign in to access the observability dashboard</p>
<div className={styles.logo}>
<img src="/favicon.svg" alt="" className={styles.logoImg} />
cameleer3
</div>
<p className={styles.subtitle}>{subtitle}</p>
{error && (
<div className={styles.error}>