mirror of
https://github.com/ipnet-mesh/meshcore-hub.git
synced 2026-07-28 20:42:36 +02:00
ui(routes): split from/to header into aligned icon grid
The route card header wrapped onto two lines when from/to labels were long. Replace the inline "from -> to" title with a two-row CSS grid (auto | 1fr) so labels align vertically, each preceded by a dedicated SVG icon (iconRouteFrom/iconRouteTo: arrow departing/arriving at a dot). Long labels now ellipsize with a title tooltip. Move the reversibility indicator (reversible <-> vs one-way ->) out of the title into a ghost badge beside the quality badge, where it no longer fights the grid layout. Also nudge spacing between "Recent Packets" and its path rows (mt-1 -> mt-2) for a little breathing room.
This commit is contained in:
@@ -181,3 +181,11 @@ export function iconClock(cls = 'h-5 w-5') {
|
||||
export function iconFilter(cls = 'h-5 w-5') {
|
||||
return html`<svg xmlns="http://www.w3.org/2000/svg" class=${cls} fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3c2.755 0 5.455.232 8.083.678.533.09.917.556.917 1.096v1.044a2.25 2.25 0 01-.659 1.591l-5.432 5.432a2.25 2.25 0 00-.659 1.591v2.927a2.25 2.25 0 01-1.244 2.013L9.75 21v-6.568a2.25 2.25 0 00-.659-1.591L3.659 7.409A2.25 2.25 0 013 5.818V4.774c0-.54.384-1.006.917-1.096A48.32 48.32 0 0112 3z" /></svg>`;
|
||||
}
|
||||
|
||||
export function iconRouteFrom(cls = 'h-5 w-5') {
|
||||
return html`<svg xmlns="http://www.w3.org/2000/svg" class=${cls} fill="none" viewBox="0 0 24 24" stroke="currentColor"><circle cx="5" cy="12" r="2.5" stroke-width="2" /><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7.5 12H21m0 0l-4-4m4 4l-4 4" /></svg>`;
|
||||
}
|
||||
|
||||
export function iconRouteTo(cls = 'h-5 w-5') {
|
||||
return html`<svg xmlns="http://www.w3.org/2000/svg" class=${cls} fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12h13.5m0 0l-4-4m4 4l-4 4" /><circle cx="19" cy="12" r="2.5" stroke-width="2" /></svg>`;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { apiGet, apiPost, apiPut, apiDelete, isAbortError } from '../api.js';
|
||||
import { html, litRender, nothing, t, errorAlert, getConfig, hasRole } from '../components.js';
|
||||
import { iconPath, iconPlus, iconEdit, iconTrash, iconPackets, iconClock, iconRuler, iconNodes, iconSatelliteDish } from '../icons.js';
|
||||
import { iconPath, iconPlus, iconEdit, iconTrash, iconPackets, iconClock, iconRuler, iconNodes, iconSatelliteDish, iconRouteFrom, iconRouteTo } from '../icons.js';
|
||||
|
||||
const VISIBILITY_ORDER = ['community', 'member', 'operator', 'admin'];
|
||||
|
||||
@@ -147,14 +147,18 @@ function renderRouteCard(route, { isAdmin, onDelete, onEdit, detail, navigate, p
|
||||
<div class="card-body">
|
||||
<div class="flex items-start justify-between gap-2">
|
||||
<div class="flex-1 min-w-0">
|
||||
<h2 class="card-title flex items-center gap-2 flex-wrap">
|
||||
<span>${route.from_label}</span>
|
||||
<span class="opacity-50">${arrow}</span>
|
||||
<span>${route.to_label}</span>
|
||||
<h2 class="card-title">
|
||||
<div class="grid grid-cols-[auto_1fr] gap-x-2 items-center min-w-0">
|
||||
<span class="flex items-center text-base-content/60">${iconRouteFrom('h-5 w-5')}</span>
|
||||
<span class="truncate" title=${route.from_label || ''}>${route.from_label}</span>
|
||||
<span class="flex items-center text-base-content/60">${iconRouteTo('h-5 w-5')}</span>
|
||||
<span class="truncate" title=${route.to_label || ''}>${route.to_label}</span>
|
||||
</div>
|
||||
</h2>
|
||||
${route.description ? html`<p class="text-sm opacity-70 mt-1">${route.description}</p>` : nothing}
|
||||
</div>
|
||||
<div class="flex items-center gap-2 flex-shrink-0">
|
||||
<span class="badge badge-ghost badge-sm opacity-60 font-mono text-xl leading-none px-2 inline-flex items-center" title=${route.reversible !== false ? t('routes.reversible_label') : ''}>${arrow}</span>
|
||||
${badge}
|
||||
</div>
|
||||
</div>
|
||||
@@ -186,7 +190,7 @@ function renderDetailContent(route, detail, { navigate, packetsEnabled, history
|
||||
${historySection}
|
||||
${matches.length > 0 ? html`<div>
|
||||
<strong class="opacity-70">${t('routes.recent_packets')}</strong>
|
||||
<div class="mt-1 space-y-2">
|
||||
<div class="mt-2 space-y-2">
|
||||
${matches.map(m => {
|
||||
const prefixLen = 2 * (route.match_width || 1);
|
||||
const pathLookup = new Map(
|
||||
|
||||
Reference in New Issue
Block a user