feat(aether): initial commit – self-hosted Cloud, Phasen 1–7
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>
This commit is contained in:
commit
31a027c93a
225 files changed
+38042
No files matched your search
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Die Reiterleiste – eine Definition für Admin-Bereich und Einstellungen.
|
||||
*
|
||||
* Beide hatten sie zunächst eigen im Code stehen. Zwei Kopien derselben Leiste
|
||||
* laufen mit der Zeit auseinander: Die eine bekommt eine andere Schriftstärke,
|
||||
* die andere einen anderen Abstand, und beim Umschalten merkt man den
|
||||
* Unterschied, ohne ihn benennen zu können. Genau das ist bei den Kopfleisten
|
||||
* schon einmal passiert (siehe components/PageHeader.tsx).
|
||||
*/
|
||||
interface Props<T extends string> {
|
||||
tabs: { id: T; label: string }[]
|
||||
active: T
|
||||
onChange: (id: T) => void
|
||||
}
|
||||
|
||||
export default function Tabs<T extends string>({ tabs, active, onChange }: Props<T>) {
|
||||
return (
|
||||
<div style={{
|
||||
display: 'flex', gap: 4, marginBottom: 24,
|
||||
borderBottom: '1px solid var(--color-border)',
|
||||
// Ein Pixel Innenrand, damit die Unterstreichung des aktiven Reiters
|
||||
// genau auf der Trennlinie sitzt statt darunter.
|
||||
paddingBottom: 1,
|
||||
overflowX: 'auto',
|
||||
}}>
|
||||
{tabs.map(t => (
|
||||
<button
|
||||
key={t.id}
|
||||
onClick={() => onChange(t.id)}
|
||||
style={{
|
||||
padding: '8px 18px', border: 'none', cursor: 'pointer', fontSize: 14,
|
||||
background: 'transparent', whiteSpace: 'nowrap', flexShrink: 0,
|
||||
color: active === t.id ? 'var(--color-primary)' : 'var(--color-text-muted)',
|
||||
fontWeight: active === t.id ? 700 : 400,
|
||||
borderBottom: active === t.id ? '2px solid var(--color-primary)' : '2px solid transparent',
|
||||
marginBottom: -1,
|
||||
transition: 'color 0.15s',
|
||||
}}
|
||||
>
|
||||
{t.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user