611 unmodified lines
Expand all
</Show>
</section>
<aside class="untangled-home-side flex flex-col gap-6 untangled-home-lower-right">
<section class="untangled-home-wide-section">
<HomeSectionHeader icon={<TrendingUp class="size-5" />} title="trending" />
<div class="flex flex-col gap-3">
<For each={SAMPLE_REPOS}>
{(repo) => (
<RepoCard
href={`/${repo.owner}/${repo.slug}`}
owner={repo.owner}
name={repo.slug}
description={repo.description}
language={repo.language}
stars={repo.stars}
forks={repo.forks}
openIssues={repo.openIssues}
compact
/>
)}
</For>
</div>
</section>
{/* Suggested (Vouches) Section */}
<div class="flex flex-col gap-3 w-full">
<header class="untangled-home-section-header flex justify-between items-center w-full">
<div class="flex items-center gap-3">
<ShieldPlus class="size-5" />
<h2>suggested</h2>
<div class="flex flex-col gap-6 w-full untangled-home-sticky-wrapper">
<section class="untangled-home-wide-section">
<HomeSectionHeader icon={<TrendingUp class="size-5" />} title="trending" />
<div class="flex flex-col gap-3">
<For each={SAMPLE_REPOS}>
{(repo) => (
<RepoCard
href={`/${repo.owner}/${repo.slug}`}
owner={repo.owner}
name={repo.slug}
description={repo.description}
language={repo.language}
stars={repo.stars}
forks={repo.forks}
openIssues={repo.openIssues}
compact
/>
)}
</For>
</div>
</section>
{/* Suggested (Vouches) Section */}
<div class="flex flex-col gap-3 w-full">
<header class="untangled-home-section-header flex justify-between items-center w-full">
<div class="flex items-center gap-3">
<ShieldPlus class="size-5" />
<h2>suggested</h2>
</div>
<Show when={auth.currentDid()}>
<A href={`/${ownReposQuery.data?.actor.handle || ownReposQuery.data?.actor.did || ''}?tab=vouches`} class="text-sm font-normal hover:underline text-gray-500 dark:text-gray-400">
view all →
</A>
</Show>
</header>
<div class="flex flex-col gap-4 bg-white dark:bg-gray-800 p-4 border border-gray-200 dark:border-gray-700 shadow-sm rounded-sm">
<Show when={!vouchSuggestionsQuery.isLoading} fallback={<LoadingState label="Loading suggestions..." />}>
<For each={vouchSuggestionsQuery.data ?? []}>
{(suggestion) => {
const isVouched = () => vouchedHandles().includes(suggestion.handle);
const toggleVouch = () => {
if (!auth.currentDid()) {
alert('Please sign in to vouch for users.');
return;
}
if (isVouched()) {
setVouchedHandles(prev => prev.filter(h => h !== suggestion.handle));
} else {
setVouchedHandles(prev => [...prev, suggestion.handle]);
}
};
return (
<div class="flex items-center gap-3">
<Avatar did={suggestion.did} size="size-10" />
<div class="flex flex-col min-w-0 flex-1">
<a href={`https://tangled.org/${suggestion.handle}`} target="_blank" rel="noopener noreferrer" class="text-sm font-medium dark:text-white hover:underline truncate">
{suggestion.handle}
</a>
<span class="text-xs text-gray-500 dark:text-gray-400 truncate">
</span>
<Show when={auth.currentDid()}>
<A href={`/${ownReposQuery.data?.actor.handle || ownReposQuery.data?.actor.did || ''}?tab=vouches`} class="text-sm font-normal hover:underline text-gray-500 dark:text-gray-400">
view all →
</A>
</Show>
</header>
<div class="flex flex-col gap-4 bg-white dark:bg-gray-800 p-4 border border-gray-200 dark:border-gray-700 shadow-sm rounded-sm">
<Show when={!vouchSuggestionsQuery.isLoading} fallback={<LoadingState label="Loading suggestions..." />}>
<For each={vouchSuggestionsQuery.data ?? []}>
{(suggestion) => {
const isVouched = () => vouchedHandles().includes(suggestion.handle);
const toggleVouch = () => {
if (!auth.currentDid()) {
alert('Please sign in to vouch for users.');
return;
}
if (isVouched()) {
setVouchedHandles(prev => prev.filter(h => h !== suggestion.handle));
} else {
setVouchedHandles(prev => [...prev, suggestion.handle]);
}
};
return (
<div class="flex items-center gap-3">
<Avatar did={suggestion.did} size="size-10" />
<div class="flex flex-col min-w-0 flex-1">
<a href={`https://tangled.org/${suggestion.handle}`} target="_blank" rel="noopener noreferrer" class="text-sm font-medium dark:text-white hover:underline truncate">
{suggestion.handle}
</a>
<span class="text-xs text-gray-500 dark:text-gray-400 truncate">
</span>
</div>
<div class="shrink-0">
<button
type="button"
onClick={toggleVouch}
class={isVouched() ? 'btn-create text-xs px-2.5 py-1.5' : 'btn text-xs px-2.5 py-1.5'}
>
<Show when={isVouched()} fallback={<><Shield class="size-3.5 mr-1 inline" /> vouch</>}>
<ShieldCheck class="size-3.5 mr-1 inline" /> vouched
</Show>
</button>
</div>
</div>
<div class="shrink-0">
<button
type="button"
onClick={toggleVouch}
class={isVouched() ? 'btn-create text-xs px-2.5 py-1.5' : 'btn text-xs px-2.5 py-1.5'}
>
<Show when={isVouched()} fallback={<><Shield class="size-3.5 mr-1 inline" /> vouch</>}>
<ShieldCheck class="size-3.5 mr-1 inline" /> vouched
</Show>
</button>
</div>
</div>
);
}}
</For>
</Show>
);
}}
</For>
</Show>
</div>
</div>
</div>
</aside>
</div>
<div class="absolute left-8 -top-4 w-px h-4 bg-gray-300 dark:bg-gray-600" />
</Show>
<div class="flex flex-col divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-sm">
{/* Header row */}
<div class="pl-6 py-2 bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 flex flex-wrap items-center gap-2 text-sm">
<div class="pl-6 py-2 bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 flex items-center gap-2 text-sm min-w-0 overflow-hidden">
<Show when={props.item.actorDid}>
<Avatar did={props.item.actorDid!} size="size-5" />
</Show>
<A href={actorUrl()} class="font-bold no-underline hover:underline text-black dark:text-white">
<A href={actorUrl()} class="font-bold no-underline hover:underline text-black dark:text-white truncate shrink-0 max-w-[8rem] sm:max-w-none">
{props.item.actorHandle || 'user'}
</A>
<span>{actionText()}</span>
<A href={repoUrl()} class="no-underline hover:underline font-bold text-black dark:text-white">
<span class="whitespace-nowrap shrink-0">{actionText()}</span>
<A href={repoUrl()} class="no-underline hover:underline font-bold text-black dark:text-white truncate min-w-0">
{props.item.repoLabel}
</A>
<span class="text-gray-400 dark:text-gray-500 text-xs ml-auto pr-6">
<span class="text-gray-400 dark:text-gray-500 text-xs ml-auto pr-6 shrink-0 whitespace-nowrap">
{formatRelativeTime(props.item.at)}
</span>
</div>