feat(ui): add ScopeTrail component for scope-based breadcrumbs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-28 13:52:49 +01:00
parent facf7fb6ef
commit 0eb377b515
2 changed files with 78 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
.trail {
display: flex;
align-items: center;
gap: 0;
font-size: 0.8125rem;
color: var(--text-muted);
min-height: 1.5rem;
}
.segment {
display: inline-flex;
align-items: center;
}
.link {
color: var(--text-secondary);
text-decoration: none;
cursor: pointer;
background: none;
border: none;
padding: 0;
font: inherit;
font-size: 0.8125rem;
}
.link:hover {
color: var(--amber);
text-decoration: underline;
}
.separator {
margin: 0 0.375rem;
color: var(--text-muted);
user-select: none;
}
.current {
color: var(--text-primary);
font-weight: 500;
}

View File

@@ -0,0 +1,38 @@
import type { Scope } from '../hooks/useScope';
import styles from './ScopeTrail.module.css';
interface ScopeTrailProps {
scope: Scope;
onNavigate: (path: string) => void;
}
export function ScopeTrail({ scope, onNavigate }: ScopeTrailProps) {
const segments: { label: string; path: string }[] = [
{ label: 'All Applications', path: `/${scope.tab}` },
];
if (scope.appId) {
segments.push({ label: scope.appId, path: `/${scope.tab}/${scope.appId}` });
}
if (scope.routeId) {
segments.push({ label: scope.routeId, path: `/${scope.tab}/${scope.appId}/${scope.routeId}` });
}
return (
<nav className={styles.trail}>
{segments.map((seg, i) => (
<span key={seg.path} className={styles.segment}>
{i > 0 && <span className={styles.separator}>&gt;</span>}
{i < segments.length - 1 ? (
<button className={styles.link} onClick={() => onNavigate(seg.path)}>
{seg.label}
</button>
) : (
<span className={styles.current}>{seg.label}</span>
)}
</span>
))}
</nav>
);
}