fix(ui): eine Breite fuer Seitenleiste und Kopfleiste

Kopfleiste blendete den Menue-Knopf ab 720px aus, die Seitenleiste stand
aber erst ab 768px fest im Bild. Dazwischen lag ein Band von 48 Pixeln
ohne Menue und ohne Knopf dorthin -- ein aufgeklapptes Fold landet mit
rund 757px genau darin.

Die Grenze steht jetzt einmal in src/breakpoints.ts.

Dazu zwei Folgefehler derselben Sache:

* Der abdunkelnde Grund lag mit z-index 40 ueber der fest stehenden
  Leiste (die hat dort keinen). Per Randwisch aufgeschoben, war die
  Leiste danach sichtbar, aber taub. Er blendet sich ab 720px aus.
* Der Randwisch loest breit gar nicht mehr aus, und Aufklappen bei
  aufgeschobener Leiste setzt sie zurueck -- sonst schluckte die
  Zurueck-Geste einmal ins Leere.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
marcandClaude Opus 5 committed 2026-09-08 21:33:08 +02:00
1 parent fbaf24bdbd
commit 8e27c703d2
6 files changed
+66 -4

No files matched your search

+6 -1
View File
@@ -1,5 +1,6 @@
import type { ReactNode } from 'react'
import UserMenu, { useSidebarToggle } from './UserMenu'
import { wideEnough } from '../breakpoints'
/**
* Die Kopfleiste jeder Ansicht.
@@ -23,8 +24,12 @@ export const headerHeight = 57
* Ansichts-Umschalter war ganz verschwunden und der Nutzerbereich am rechten
* Rand abgeschnitten. Eine Zeile, die nicht umbrechen kann, quetscht – und
* ausgerechnet auf dem Gerät, mit dem man unterwegs einen Beleg sucht.
*
* Dieselbe Grenze schaltet die Seitenleiste um; sie steht deshalb in
* `breakpoints.ts` und nicht mehr hier. Re-exportiert, weil sie hier gesucht
* wird.
*/
export const wideEnough = '(min-width: 720px)'
export { wideEnough }
interface Props {
/** Strichsymbol, 18 × 18 – dasselbe wie in der Seitenleiste. */
+20 -2
View File
@@ -1,4 +1,4 @@
import { useCallback, useState } from 'react'
import { useCallback, useEffect, useState } from 'react'
import { filesApi } from '../api/client'
import type { FolderItem, User } from '../api/client'
import { useNavHistory, type View } from '../hooks/useNavHistory'
@@ -14,6 +14,7 @@ import ProfilePage from '../pages/ProfilePage'
import TagsPage from '../pages/TagsPage'
import CalendarPage from '../pages/CalendarPage'
import { UserMenuProvider } from './UserMenu'
import { wideEnough } from '../breakpoints'
export type { View }
@@ -44,6 +45,19 @@ export default function Shell({ user, onLogout, onUserChanged }: Props) {
onClose: useCallback(() => { setSidebarOpen(false) }, []),
})
// Wird das Gerät aufgeklappt, während die Leiste aufgeschoben war, steht sie
// ab da ohnehin fest im Bild. Bliebe „aufgeschoben" dabei stehen, schluckte
// die Zurück-Geste einmal ins Leere – sie zielte auf etwas, das nichts mehr
// verdeckt.
useEffect(() => {
if (typeof matchMedia !== 'function') return
const mq = matchMedia(wideEnough)
const auf = () => { if (mq.matches) setSidebarOpen(false) }
auf()
mq.addEventListener('change', auf)
return () => mq.removeEventListener('change', auf)
}, [])
// Hochgezählt, wenn etwas auf den Papierkorb gezogen wurde – die Dateiliste
// hängt daran und holt sich daraufhin neu.
const [trashBump, setTrashBump] = useState(0)
@@ -81,9 +95,13 @@ export default function Shell({ user, onLogout, onUserChanged }: Props) {
onOpenSidebar: () => setSidebarOpen(true),
}}>
<div className="aether-vh" style={{ display: 'flex', overflow: 'hidden' }}>
{/* Mobile overlay */}
{/* Der abdunkelnde Grund hinter der aufgeschobenen Leiste.
Die Klasse blendet ihn aus, sobald die Leiste fest im Bild steht:
Dort liegt sie im Fluss und **ohne** z-index, ein Grund darüber
machte sie unanklickbar – sichtbar, aber taub. */}
{sidebarOpen && (
<div
className="aether-scrim"
style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)', zIndex: 40 }}
onClick={() => setSidebarOpen(false)}
/>
+6 -1
View File
@@ -8,6 +8,7 @@ import { RenameIcon, TrashIcon } from './icons'
import type { User } from '../api/client'
import type { View } from './Shell'
import { useAppSettings } from '../hooks/useAppSettings'
import { wideEnough } from '../breakpoints'
interface Props {
user: User
@@ -775,7 +776,11 @@ export default function Sidebar({ user, view, activeTagId, onOpenTag, onTrashDro
overflow-y: auto;
overflow-x: hidden;
}
@media (max-width: 767px) {
/* Schmal: Die Leiste liegt über dem Inhalt statt neben ihm.
Die Grenze ist dieselbe, die in der Kopfleiste den Knopf zum
Aufschieben zeigt – hätte sie eine eigene, gäbe es dazwischen einen
Streifen ohne Menü und ohne Knopf dorthin. */
@media not all and ${wideEnough} {
.aether-sidebar {
position: fixed;
top: var(--honeybar-h); left: 0;