Go-Backend (chi, pgx, golang-migrate) + React/TS-Frontend als PWA. Enthalten: Auth inkl. OIDC, Dateien mit Versionen und Papierkorb, Freigaben (Links + intern), WebDAV, Gruppenordner, Admin/Theming, Volltextsuche mit OCR, eigener PDF-Betrachter und WOPI-Office (Collabora/OnlyOffice). Nicht im Repo: deploy/.env (Sitzungsschlüssel, DB- und Admin-Passwort) sowie alle Daten- und Build-Verzeichnisse – siehe .gitignore. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
88 lines
3.2 KiB
TypeScript
88 lines
3.2 KiB
TypeScript
import type { FolderItem } from '../api/client'
|
||
|
||
interface Props {
|
||
path: FolderItem[]
|
||
onNavigate: (folderId: string | undefined) => void
|
||
}
|
||
|
||
/**
|
||
* Der Pfad in der Kopfleiste.
|
||
*
|
||
* Schriftgröße und -stärke sind dieselben wie bei den Titeln der anderen
|
||
* Ansichten („Trash", „Shared links"): 15 px, 600 für den aktuellen Ort. Bis
|
||
* zum 23.08.2026 lief das über Tailwind-Klassen (`text-sm`, `font-medium`) und
|
||
* war damit 14 px bei Stärke 500 – nebeneinander sieht man den Unterschied
|
||
* sofort, auch ohne ihn benennen zu können.
|
||
*
|
||
* Auch das Symbol war kleiner (15 statt 18). Es ist jetzt Zeichen für Zeichen
|
||
* dasselbe wie in der Seitenleiste.
|
||
*/
|
||
const rootLabel = 'Home'
|
||
|
||
export default function Breadcrumb({ path, onNavigate }: Props) {
|
||
const atRoot = path.length === 0
|
||
|
||
const segment = (active: boolean) => ({
|
||
flexShrink: 0,
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
// 10 wie in PageHeader zwischen Symbol und Titel – bei 7 stand „Home"
|
||
// drei Pixel weiter links als „Trash". Gemessen: 265 statt 268.
|
||
gap: 10,
|
||
padding: '2px 6px',
|
||
borderRadius: 6,
|
||
border: 'none',
|
||
background: 'none',
|
||
cursor: 'pointer',
|
||
// Gleiche Schrift wie die Seitentitel – sonst wirkt die Dateiansicht wie
|
||
// eine andere Anwendung.
|
||
fontSize: 15,
|
||
fontWeight: 600,
|
||
lineHeight: 1.3,
|
||
color: active ? 'var(--color-text)' : 'var(--color-text-muted)',
|
||
})
|
||
|
||
return (
|
||
<nav style={{
|
||
display: 'flex', alignItems: 'center', gap: 2,
|
||
minWidth: 0, overflowX: 'auto',
|
||
// Der Wurzel-Knopf hat innen 6 px Rand, damit sein Hover-Feld nicht am
|
||
// Text klebt. Ohne diesen Ausgleich begänne das Haus-Symbol 6 px weiter
|
||
// rechts als das Symbol in Papierkorb und Co. – beim Umschalten sieht man
|
||
// genau diesen Sprung. Gemessen: 246 statt 240.
|
||
marginLeft: -6,
|
||
}}>
|
||
<button onClick={() => onNavigate(undefined)} style={segment(atRoot)} title={rootLabel}>
|
||
{/* Das Symbol bleibt gedämpft, auch wenn der Titel hell ist – genau so
|
||
steht es im Papierkorb und bei den Freigabe-Links. Vorher erbte es
|
||
die Textfarbe und leuchtete auf der Startebene heller als dort. */}
|
||
<span style={{ display: 'flex', color: 'var(--color-text-muted)' }}>
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||
strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||
<path d="M3 10.5L12 3l9 7.5" />
|
||
<path d="M5.5 9.5V20a1 1 0 001 1h11a1 1 0 001-1V9.5" />
|
||
</svg>
|
||
</span>
|
||
{rootLabel}
|
||
</button>
|
||
|
||
{path.map((folder, i) => (
|
||
<span key={folder.id} style={{ display: 'flex', alignItems: 'center', gap: 2, minWidth: 0 }}>
|
||
<span style={{ color: 'var(--color-text-muted)', fontSize: 15, opacity: 0.6 }}>/</span>
|
||
<button
|
||
onClick={() => onNavigate(folder.id)}
|
||
style={{
|
||
...segment(i === path.length - 1),
|
||
overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
|
||
display: 'block', maxWidth: 220,
|
||
}}
|
||
title={folder.name}
|
||
>
|
||
{folder.name}
|
||
</button>
|
||
</span>
|
||
))}
|
||
</nav>
|
||
)
|
||
}
|