| 1 | | − | import { BookOpen, Check, ChevronDown, Code2, File, FileArchive, Folder, FolderGit2, GitBranch, History, Search, SquareTerminal, Tag as TagIcon } from "lucide-react"; |
| 1 | + | import { BookOpen, Check, ChevronDown, Code2, CornerLeftUp, File, FileArchive, Folder, FolderGit2, GitBranch, History, Search, SquareTerminal, Tag as TagIcon } from "lucide-react"; |
| 2 | 2 | | import { type ReactNode, Suspense } from "react"; |
| 3 | 3 | | import { Await, Form, Link } from "react-router"; |
| 4 | 4 | | |
| ⋯ |
| 274 | 274 | | last: FileCommits | null | undefined; |
| 275 | 275 | | }) { |
| 276 | 276 | | const byName = new Map((last?.entries ?? []).map((entry) => [entry.name, entry.commit])); |
| 277 | + | // Inside a directory, `..` leads one level up: to its parent, or the |
| 278 | + | // repository's top from a directory at the top. |
| 279 | + | const parent = prefix ? prefix.slice(0, -1).split("/").slice(0, -1).join("/") : null; |
| 277 | 280 | | return ( |
| 278 | 281 | | // Busy while each entry's last commit is on its way; its cells keep their size. |
| 279 | 282 | | <ul aria-busy={last === undefined || undefined} className="divide-y divide-line text-sm"> |
| 283 | + | {parent !== null && ( |
| 284 | + | <li className="px-4 transition-colors hover:bg-surface"> |
| 285 | + | <Link |
| 286 | + | to={parent ? `${base}/tree/${gitRef}/${parent}` : `${base}/tree/${gitRef}`} |
| 287 | + | aria-label="Parent directory" |
| 288 | + | className="flex min-h-11 min-w-0 items-center gap-3 py-2 hover:text-accent hover:underline sm:min-h-0" |
| 289 | + | > |
| 290 | + | <CornerLeftUp size={15} className="shrink-0 text-faint" /> |
| 291 | + | <span className="font-mono text-[0.8125rem]">..</span> |
| 292 | + | </Link> |
| 293 | + | </li> |
| 294 | + | )} |
| 280 | 295 | | {entries.map((entry) => { |
| 281 | 296 | | const isTree = entry.kind === "tree"; |
| 282 | 297 | | const Icon = isTree ? Folder : entry.kind === "gitlink" ? FolderGit2 : File; |