Streamline UI: hide map filters on mobile, icon-only buttons, collapse multilingual country names

Reduces clutter on small screens and in the header/toolbar by trimming labels down to icons, and shows a single primary country name instead of full slash-separated translations.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Claudio Schaad 2026-07-22 14:48:45 +02:00
parent 8d4448b28c
commit 1cb9a2e133
5 changed files with 42 additions and 20 deletions

View file

@ -22,9 +22,23 @@ export function AppShell() {
{user?.isAdmin && <NavLink to="/admin/users">Users</NavLink>}
</nav>
<div className="app-user">
<span className="app-user-name">{user?.displayName || user?.username}</span>
<button type="button" className="btn btn-ghost" onClick={handleLogout}>
Log out
<button
type="button"
className="btn btn-ghost btn-icon"
onClick={handleLogout}
aria-label="Log out"
title="Log out"
>
<svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true">
<path
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
d="M15 17l5-5-5-5M20 12H9M12 19H6a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h6"
/>
</svg>
</button>
</div>
</header>

View file

@ -3,10 +3,9 @@ import type { City } from '@citytracker/shared';
export function cityMarkerIcon(city: City): L.DivIcon {
const color = city.status === 'visited' ? '#2f9e44' : '#1971c2';
const heart = city.liked ? '<span class="marker-heart">♥</span>' : '';
return L.divIcon({
className: 'city-marker',
html: `<span class="marker-pin" style="background:${color}"></span>${heart}`,
html: `<span class="marker-pin" style="background:${color}"></span>`,
iconSize: [22, 22],
iconAnchor: [11, 11],
popupAnchor: [0, -14],

View file

@ -3,6 +3,10 @@ import { useNavigate } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
import { useCities } from '../hooks/useCities';
function primaryCountryName(country: string): string {
return country.split('/')[0].trim();
}
export function CityListPage() {
const navigate = useNavigate();
const { user } = useAuth();
@ -62,7 +66,7 @@ export function CityListPage() {
{city.name}
{city.liked && <span className="cities-table-heart"> ♥</span>}
</td>
<td>{city.country}</td>
<td>{primaryCountryName(city.country)}</td>
<td>
<span className={`badge badge-${city.status}`}>
{city.status === 'visited' ? 'Visited' : 'Planned'}

View file

@ -42,8 +42,14 @@ export function MapDashboardPage() {
) : (
<CityMap cities={cities ?? []} focusCity={latestCity} />
)}
<button type="button" className="btn btn-primary fab" onClick={() => navigate('/cities/new')}>
+ Add city
<button
type="button"
className="btn btn-primary fab"
onClick={() => navigate('/cities/new')}
aria-label="Add city"
title="Add city"
>
+
</button>
</div>
</div>

View file

@ -107,6 +107,11 @@ a {
font-size: 0.85rem;
}
.btn-icon {
padding: var(--spacing-2);
line-height: 0;
}
/* App shell */
.app-shell {
@ -154,10 +159,6 @@ a {
gap: var(--spacing-3);
}
.app-user-name {
color: var(--color-text-muted);
}
.app-main {
flex: 1;
overflow: auto;
@ -256,6 +257,12 @@ a {
background: var(--color-bg);
}
@media (max-width: 640px) {
.map-filters {
display: none;
}
}
.chip {
padding: var(--spacing-1) var(--spacing-3);
border-radius: 999px;
@ -299,14 +306,6 @@ a {
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
}
.marker-heart {
position: absolute;
top: -8px;
right: -6px;
color: #e64980;
font-size: 0.8rem;
}
.map-popup {
display: flex;
flex-direction: column;