Kundenansicht neu: Wasser-Leiste breiter mit Wörtern, Unterseiten im Vollbild

Wunsch vom 29.10. nach dem ersten Blick am iPhone:
- Die Leiste nutzt die Breite (12 px Rand, höchstens 480 px), Symbol über
  dem Wort, und steht ganz über dem Wisch-Balken des iPhones
  (Safe-Area plus 6 px statt minus 10 px).
- Unterseiten öffnen sich ganz und werden mit Unschärfe eingeblendet statt
  hochzufahren. Oben links die Überschrift, oben rechts „Zurück“ als
  Glasknopf, der beim Scrollen stehen bleibt (neuer Platz
  #kn-blatt-zurueck).
- Reiter einer Funktion stehen unten in derselben Wasser-Leiste (Art
  'reiter', Kurzwörter, kleinere Schrift wenn es eng wird), ohne Zurück.
  Ohne Reiter bleibt unten nichts. Die alte Leiste gibt beim Neuaufbau
  ihren WebGL-Kontext frei.

Glas und Unschärfe stehen weiter allein in wasser-leiste.css; huelle.css
bleibt ohne Glas. Desktop unverändert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-29 18:09:42 +00:00
1 parent c997703251
commit 1f350ca432
10 files changed
+147 -95

No files matched your search

+19 -15
View File
@@ -1,29 +1,32 @@
/* Kundenansicht neu: Etage 2. Eine Unterseite (Funktion, Detailseite, Passwort …) schiebt sich als Blatt über die Hauptseite.
Handy: Die Zeile unten fährt eine Etage hoch und zeigt „Zurück“ und, falls die Seite Reiter meldet, deren Kurzlabels als Balken.
Desktop: Brotkrume statt Zeile, Reiter als Unterstrich im Slot unter der Überschrift.
/* Kundenansicht neu: Etage 2. Eine Unterseite (Funktion, Detailseite, Passwort …) legt sich als Blatt über die Hauptseite.
Handy: Das Blatt deckt den ganzen Bildschirm, „Zurück“ steht oben rechts (zurueckSlot), und meldet die Seite Reiter, zeigt die Zeile unten
deren Kurzlabels als Wasser-Leiste (wasser-leiste.js, Art 'reiter') an Stelle der vier Bereiche; ohne Reiter bleibt unten nichts.
Desktop: Brotkrume statt Zurück, Reiter als Unterstrich im Slot unter der Überschrift.
Der Inhalt meldet Reiter und Titel ohne Import per CustomEvent (bubbles): kn:reiter { eintraege, aktiv, bei } (leere Liste = keine Reiter)
und kn:titel { text }. Alles Sichtbare wird mit h() und textContent gebaut. */
import { h, leeren, text } from './dom.js'
import { baueReiter } from './reiter.js'
import { baueWasserLeiste } from './wasser-leiste.js'
const gleicheEintraege = (a, b) => a.length === b.length && a.every((x, i) => x.key === b[i].key && x.label === b[i].label && (x.kurz ?? '') === (b[i].kurz ?? ''))
export function baueEtage({ blatt, haupt, zeile, titel, brot, reiterSlot, istHandy, onZurueck }) {
export function baueEtage({ blatt, haupt, zeile, zurueckSlot, titel, brot, reiterSlot, istHandy, onZurueck }) {
const stand = { offen: false, titel: '', eltern: null, seite: '', reiter: null, chatPunkt: false, reiterEl: null, zurueckEl: null }
const zurueckLabel = () => `Zurück zu ${stand.eltern.label}${stand.chatPunkt ? ', neue Nachricht im Chat' : ''}`
function baueZurueck(voll) {
return h('button', { class: voll ? 'kn-zurueck kn-zurueck--voll' : 'kn-zurueck', type: 'button', 'aria-label': zurueckLabel(), on: { click: () => onZurueck() } },
function baueZurueck() {
return h('button', { class: 'kn-zurueck', type: 'button', 'aria-label': zurueckLabel(), on: { click: () => onZurueck() } },
h('span', { class: 'kn-l' }, 'Zurück', stand.chatPunkt ? h('span', { class: 'kn-punkt' }) : null))
}
function neuerReiter(art) {
const { eintraege, aktiv } = stand.reiter
// Handy zeigt die Kurzlabels (der Balken hat wenig Platz), Desktop die vollen Beschriftungen
const zeigen = art === 'balken' ? eintraege : eintraege.map(({ kurz, ...rest }) => rest)
return baueReiter({ eintraege: zeigen, aktiv, art, ariaLabel: 'Reiter', bei: (key) => stand.reiter?.bei?.(key) })
const bei = (key) => stand.reiter?.bei?.(key)
// Handy: Wasser-Leiste mit den Kurzlabels (vorgelesen wird das volle Wort); Desktop: Unterstrich mit den vollen Beschriftungen
if (art === 'wasser') return baueWasserLeiste({ eintraege: eintraege.map(({ key, label, kurz }) => ({ key, label, kurz })), aktiv, art: 'reiter', ariaLabel: 'Reiter', bei })
return baueReiter({ eintraege: eintraege.map(({ kurz, ...rest }) => rest), aktiv, art, ariaLabel: 'Reiter', bei })
}
function zeichneBrot() {
@@ -37,18 +40,19 @@ export function baueEtage({ blatt, haupt, zeile, titel, brot, reiterSlot, istHan
brot.append(h('a', { href: stand.eltern.hash, on: { click: verlassen } }, stand.eltern.label), h('span', { class: 'kn-brot-trenner', 'aria-hidden': 'true' }, ' / '), h('span', { 'aria-current': 'page' }, stand.titel))
}
// Zeile (Handy) und Reiter-Slot (Desktop) aus dem Stand neu aufbauen
// Zurück und Zeile (Handy) bzw. Reiter-Slot (Desktop) aus dem Stand neu aufbauen
function zeichne() {
leeren(zeile); leeren(reiterSlot)
stand.reiterEl?.beende?.() // die alte Wasser-Leiste gibt ihren WebGL-Kontext frei
leeren(zeile); leeren(reiterSlot); if (zurueckSlot) leeren(zurueckSlot)
stand.zurueckEl = null; stand.reiterEl = null
zeichneBrot()
if (!stand.offen) return
if (istHandy()) {
stand.zurueckEl = baueZurueck(!stand.reiter)
zeile.append(stand.zurueckEl)
stand.zurueckEl = baueZurueck()
;(zurueckSlot ?? zeile).append(stand.zurueckEl)
if (stand.reiter) {
stand.reiterEl = neuerReiter('balken')
zeile.append(h('span', { class: 'kn-vl' }), stand.reiterEl)
stand.reiterEl = neuerReiter('wasser')
zeile.append(stand.reiterEl)
}
} else if (stand.reiter) {
stand.reiterEl = neuerReiter('unterstrich')