fix: resolve DIDs in breadcrumbs, hide irrelevant tabs for Tangled repos

Author: Aaron Steven White
Commit 20f35a721670f49d334a6bb5eaafd8ec5afb9a6d
Parent: b3b0fcb2c1
Structural diff unavailable

These commits were pushed via plain git push, so no pre-parsed schemas are available. Install git-remote-cospan and re-push via panproto:// to see scope-level changes, breaking change detection, and semantic diffs.

brew install panproto/tap/git-remote-cospan
3 files changed +54 -19
@@ -4,39 +4,51 @@
44 		activeTab = 'code',
55 		openIssueCount = 0,
66 		openMrCount = 0,
7-		isOwner = false
7+		isOwner = false,
8+		isTangled = false
89 	}: {
910 		basePath: string;
1011 		activeTab?: string;
1112 		openIssueCount?: number;
1213 		openMrCount?: number;
1314 		isOwner?: boolean;
15+		isTangled?: boolean;
1416 	} = $props();
1517 
16-	let tabs = $derived([
17-		{ id: 'code', label: 'Code', href: basePath, badge: 0 },
18-		{ id: 'issues', label: 'Issues', href: `${basePath}/issues`, badge: openIssueCount },
19-		{ id: 'pulls', label: 'Merge Requests', href: `${basePath}/pulls`, badge: openMrCount },
20-		{ id: 'branches', label: 'Branches', href: `${basePath}/branches`, badge: 0 },
21-		{ id: 'tags', label: 'Tags', href: `${basePath}/tags`, badge: 0 },
22-		{ id: 'releases', label: 'Releases', href: `${basePath}/releases`, badge: 0 },
23-		{ id: 'compare', label: 'Compare', href: `${basePath}/compare`, badge: 0 },
24-		...(isOwner ? [{ id: 'settings', label: 'Settings', href: `${basePath}/settings`, badge: 0 }] : []),
25-	]);
18+	let tabs = $derived(() => {
19+		if (isTangled) {
20+			// Tangled repos: only show tabs for data we actually have
21+			return [
22+				{ id: 'code', label: 'Overview', href: basePath, badge: 0 },
23+				{ id: 'issues', label: 'Issues', href: `${basePath}/issues`, badge: openIssueCount },
24+				{ id: 'pulls', label: 'Merge Requests', href: `${basePath}/pulls`, badge: openMrCount },
25+			];
26+		}
27+		return [
28+			{ id: 'code', label: 'Code', href: basePath, badge: 0 },
29+			{ id: 'issues', label: 'Issues', href: `${basePath}/issues`, badge: openIssueCount },
30+			{ id: 'pulls', label: 'Merge Requests', href: `${basePath}/pulls`, badge: openMrCount },
31+			{ id: 'branches', label: 'Branches', href: `${basePath}/branches`, badge: 0 },
32+			{ id: 'tags', label: 'Tags', href: `${basePath}/tags`, badge: 0 },
33+			{ id: 'releases', label: 'Releases', href: `${basePath}/releases`, badge: 0 },
34+			{ id: 'compare', label: 'Compare', href: `${basePath}/compare`, badge: 0 },
35+			...(isOwner ? [{ id: 'settings', label: 'Settings', href: `${basePath}/settings`, badge: 0 }] : []),
36+		];
37+	});
2638 </script>
2739 
28-<div class="mb-6 flex items-center gap-1 overflow-x-auto border-b border-border scrollbar-none">
29-	{#each tabs as tab (tab.id)}
40+<div class="mb-6 flex items-center gap-1 overflow-x-auto border-b border-line scrollbar-none">
41+	{#each tabs() as tab (tab.id)}
3042 		<a
3143 			href={tab.href}
3244 			class="whitespace-nowrap border-b-2 px-4 py-2 text-sm font-medium transition-colors
3345 				{activeTab === tab.id
34-					? 'border-accent text-text-primary'
35-					: 'border-transparent text-text-muted hover:text-text-primary'}"
46+					? 'border-focus text-ink'
47+					: 'border-transparent text-ghost hover:text-caption'}"
3648 		>
3749 			{tab.label}
3850 			{#if tab.badge > 0}
39-				<span class="ml-1 rounded-full bg-surface-2 px-1.5 py-0.5 text-xs">
51+				<span class="ml-1 text-xs text-ghost">
4052 					{tab.badge}
4153 				</span>
4254 			{/if}
@@ -1,21 +1,43 @@
11 <script lang="ts">
2+	import { onMount } from 'svelte';
3+	import { resolveHandle } from '$lib/api/handle.js';
4+
25 	let { crumbs }: { crumbs: { label: string; href?: string }[] } = $props();
6+
7+	// Auto-resolve any crumb label that looks like a DID
8+	let resolvedLabels = $state<Record<number, string>>({});
9+
10+	onMount(async () => {
11+		const resolved: Record<number, string> = {};
12+		await Promise.allSettled(
13+			crumbs.map(async (crumb, i) => {
14+				if (crumb.label.startsWith('did:')) {
15+					resolved[i] = await resolveHandle(crumb.label);
16+				}
17+			})
18+		);
19+		resolvedLabels = resolved;
20+	});
21+
22+	function getLabel(index: number): string {
23+		return resolvedLabels[index] || crumbs[index].label;
24+	}
325 </script>
426 
527 <nav class="flex items-center gap-1.5 text-sm">
628 	{#each crumbs as crumb, i}
729 		{#if i > 0}
8-			<span class="text-text-muted">/</span>
30+			<span class="text-ghost">/</span>
931 		{/if}
1032 		{#if crumb.href && i < crumbs.length - 1}
1133 			<a
1234 				href={crumb.href}
1335 				class="text-accent transition-colors hover:text-accent-hover"
1436 			>
15-				{crumb.label}
37+				{getLabel(i)}
1638 			</a>
1739 		{:else}
18-			<span class="text-text-muted">{crumb.label}</span>
40+			<span class="text-ghost">{getLabel(i)}</span>
1941 		{/if}
2042 	{/each}
2143 </nav>
@@ -162,6 +162,7 @@
162162 			openIssueCount={data.repo.openIssueCount}
163163 			openMrCount={data.repo.openMrCount}
164164 			{isOwner}
165+			{isTangled}
165166 		/>
166167 
167168 		{#if isTangled}
cospan · schematic version control on atproto built on AT Protocol