This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

web/components: polish the repo index for small screens

Signed-off-by: dawn <dawn@tangled.org>

author
dawn
date (Aug 1, 2026, 2:21 AM +0300) commit 20dd700c parent e78b3d5f change-id zxmsxwqt
+59 -53
-3
web/src/lib/api/repo.ts
··· 126 126 return [message.slice(0, separator).trim(), message.slice(separator + 2).trim()]; 127 127 }; 128 128 129 - /** the subject is the first paragraph, not the first line */ 130 - export const subjectOf = (message: string): string => splitMessage(message)[0]; 131 - 132 129 const coAuthorPattern = /^Co-authored-by:\s*(.+?)\s*<([^>]+)>/gim; 133 130 134 131 // trailers carry no date of their own, like types/commit.go every
+4 -3
web/src/lib/components/repo/FileTree.svelte
··· 4 4 import FileSymlink from "$icon/file-symlink"; 5 5 import Folder from "$icon/folder"; 6 6 import FolderInput from "$icon/folder-input"; 7 - import { subjectOf } from "$lib/api/repo"; 7 + import { splitMessage } from "$lib/api/repo"; 8 8 import TimeAgo from "$lib/components/ui/TimeAgo.svelte"; 9 9 import type { TreeEntrySummary } from "./types"; 10 + import { encodePathSegments } from "./urls"; 10 11 11 12 interface Props { 12 13 ownerHandle: string; ··· 25 26 const linkFor = (entry: TreeEntrySummary) => { 26 27 const target = path ? `${path}/${entry.name}` : entry.name; 27 28 const kind = entry.kind === "directory" ? "tree" : "blob"; 28 - return `${base}/${kind}/${encodedRef}/${target}`; 29 + return `${base}/${kind}/${encodedRef}/${encodePathSegments(target)}`; 29 30 }; 30 31 31 32 // lucide puts fill="none" on the path itself, which beats anything inherited ··· 71 72 href={resolve(`${base}/commit/${entry.lastCommitHash}` as "/")} 72 73 class="block truncate text-foreground-subtle no-underline hover:underline" 73 74 > 74 - {subjectOf(entry.lastCommitMessage)} 75 + {splitMessage(entry.lastCommitMessage)[0]} 75 76 </a> 76 77 {/if} 77 78 </div>
+4 -2
web/src/lib/components/repo/LastCommitPanel.svelte
··· 1 1 <script lang="ts"> 2 2 import { resolve } from "$app/paths"; 3 + import Avatar from "$lib/components/ui/Avatar.svelte"; 3 4 import TimeAgo from "$lib/components/ui/TimeAgo.svelte"; 4 5 import type { CommitSummary } from "./types"; 5 6 ··· 14 15 const href = $derived(resolve(`/${ownerHandle}/${repoName}/commit/${commit.hash}` as "/")); 15 16 </script> 16 17 17 - <!-- narrow screens get the per-entry times instead, there is no room for both --> 18 18 <div 19 19 class="mb-3 hidden flex-wrap items-center justify-between gap-2 border-b border-border-default pb-2 text-sm md:flex" 20 20 > 21 21 <div class="flex min-w-0 flex-wrap items-center gap-2"> 22 22 {#if commit.authorName} 23 - <span class="truncate text-foreground-muted">{commit.authorName}</span> 23 + <!-- no email→did mapping yet, always the placeholder --> 24 + <Avatar size="size-5" /> 25 + <span class="truncate text-foreground-default">{commit.authorName}</span> 24 26 <span class="text-foreground-subtle" aria-hidden="true">&middot;</span> 25 27 {/if} 26 28 <a {href} class="min-w-0 truncate text-foreground-default no-underline hover:underline">
+1 -1
web/src/lib/components/repo/Readme.svelte
··· 24 24 <div class="markup overflow-x-auto px-6 py-4">{@html html}</div> 25 25 {:else} 26 26 <div class="overflow-x-auto px-6 py-4"> 27 - <pre class="font-mono text-sm whitespace-pre-wrap text-foreground-default">{contents}</pre> 27 + <pre class="font-mono text-sm whitespace-pre text-foreground-default">{contents}</pre> 28 28 </div> 29 29 {/if} 30 30 </div>
+42 -36
web/src/lib/components/repo/RepoHeader.svelte
··· 25 25 const trimScheme = (url: string) => url.replace(/^https?:\/\//, "").replace(/\/$/, ""); 26 26 </script> 27 27 28 + {#snippet repoActions(className: string)} 29 + <div class={className}> 30 + {#if signedIn} 31 + <StarButton 32 + repoDid={repo.repoDid ?? ""} 33 + repoOwnerHandle={repo.ownerHandle} 34 + repoName={repo.name} 35 + initialCount={counts.stars} 36 + initialRkey={viewerStarRkey} 37 + /> 38 + {:else} 39 + <Button 40 + href={resolve(`${base}/stars` as "/")} 41 + variant="default" 42 + size="sm" 43 + icon={Star} 44 + title="Starred by" 45 + > 46 + {counts.stars} 47 + </Button> 48 + {/if} 49 + 50 + <ButtonGroup> 51 + <Button 52 + href={resolve(`${base}/fork` as "/")} 53 + variant="default" 54 + size="sm" 55 + insetShadow={true} 56 + icon={GitFork} 57 + > 58 + Fork 59 + </Button> 60 + <Button href={resolve(`${base}/forks` as "/")} variant="ghost" size="sm" title="Forked by"> 61 + {counts.forks} 62 + </Button> 63 + </ButtonGroup> 64 + </div> 65 + {/snippet} 66 + 28 67 <section class="mb-2 px-4 py-2"> 29 68 <div class="mb-2 flex flex-col items-start justify-between gap-4 sm:flex-row"> 30 69 <div class="flex min-w-0 flex-col gap-2"> ··· 59 98 {/if} 60 99 </div> 61 100 62 - <div class="flex shrink-0 items-start gap-2"> 63 - {#if signedIn} 64 - <StarButton 65 - repoDid={repo.repoDid ?? ""} 66 - repoOwnerHandle={repo.ownerHandle} 67 - repoName={repo.name} 68 - initialCount={counts.stars} 69 - initialRkey={viewerStarRkey} 70 - /> 71 - {:else} 72 - <Button 73 - href={resolve(`${base}/stars` as "/")} 74 - variant="default" 75 - size="sm" 76 - icon={Star} 77 - title="Starred by" 78 - > 79 - {counts.stars} 80 - </Button> 81 - {/if} 82 - 83 - <ButtonGroup> 84 - <Button 85 - href={resolve(`${base}/fork` as "/")} 86 - variant="default" 87 - size="sm" 88 - insetShadow={true} 89 - icon={GitFork} 90 - > 91 - Fork 92 - </Button> 93 - <Button href={resolve(`${base}/forks` as "/")} variant="ghost" size="sm" title="Forked by"> 94 - {counts.forks} 95 - </Button> 96 - </ButtonGroup> 97 - </div> 101 + {@render repoActions("flex shrink-0 items-start gap-2 hidden sm:flex")} 98 102 </div> 99 103 100 104 <div class="flex flex-wrap items-center gap-x-4 gap-y-2 typography-paragraph-small text-foreground-muted"> ··· 121 125 </div> 122 126 {/if} 123 127 </div> 128 + 129 + {@render repoActions("mt-2 grid grid-cols-2 items-center gap-2 sm:hidden")} 124 130 </section>
+5 -5
web/src/lib/components/repo/RepoIndexView.svelte
··· 72 72 /> 73 73 74 74 <div class="grid grid-cols-1 gap-2 md:grid-cols-2"> 75 - <div class="min-w-0 md:border-r md:border-border-default md:pr-2"> 75 + <div class="min-w-0 pr-2 md:border-r md:border-border-default"> 76 76 <FileTree 77 77 ownerHandle={repo.ownerHandle} 78 78 repoName={repo.name} ··· 81 81 /> 82 82 </div> 83 83 84 - <div class="hidden md:block"> 84 + <div> 85 85 {#if data.commits.length > 0} 86 - <div class="px-2 pb-4"> 86 + <div class="border-border-default pr-2 pb-4 max-md:border-t max-md:pt-4 md:px-2"> 87 87 <PanelHeader 88 88 title="Commits" 89 89 icon={Logs} ··· 100 100 {/if} 101 101 102 102 {#if data.branches.length > 0} 103 - <div class="border-t border-border-default px-2 py-4"> 103 + <div class="border-t border-border-default py-4 pr-2 md:px-2"> 104 104 <PanelHeader 105 105 title="Branches" 106 106 icon={GitBranch} ··· 118 118 {/if} 119 119 120 120 {#if data.tags.length > 0} 121 - <div class="border-t border-border-default px-2 py-4"> 121 + <div class="border-t border-border-default py-4 pr-2 md:px-2"> 122 122 <PanelHeader 123 123 title="Tags" 124 124 icon={Tags}
+3 -3
web/src/lib/components/repo/RepoToolbar.svelte
··· 52 52 <div class="flex items-center gap-3"> 53 53 <a 54 54 href={resolve(`${base}/commits/${encodedRef}` as "/")} 55 - class="inline-flex items-center gap-1 text-sm font-medium text-foreground-default no-underline hover:underline md:hidden" 55 + class="inline-flex items-center gap-1 text-sm font-bold text-foreground-default no-underline hover:underline md:hidden" 56 56 > 57 57 <GitCommitHorizontal class="size-4" aria-hidden="true" /> 58 58 {totalCommits} 59 59 </a> 60 60 <a 61 61 href={resolve(`${base}/branches` as "/")} 62 - class="inline-flex items-center gap-1 text-sm font-medium text-foreground-default no-underline hover:underline md:hidden" 62 + class="inline-flex items-center gap-1 text-sm font-bold text-foreground-default no-underline hover:underline md:hidden" 63 63 > 64 64 <GitBranch class="size-4" aria-hidden="true" /> 65 65 {totalBranches} 66 66 </a> 67 67 <a 68 68 href={resolve(`${base}/tags` as "/")} 69 - class="inline-flex items-center gap-1 text-sm font-medium text-foreground-default no-underline hover:underline md:hidden" 69 + class="inline-flex items-center gap-1 text-sm font-bold text-foreground-default no-underline hover:underline md:hidden" 70 70 > 71 71 <Tags class="size-4" aria-hidden="true" /> 72 72 {totalTags}