Drei Auswahlfelder liessen sich gleichzeitig aufklappen

Jedes merkte sich nur seine eigene Liste. Nebeneinander geöffnet lagen
sie übereinander, und keine wusste von den anderen. Ein Auswahlfeld ist
ein Menü, und von denen ist höchstens eines offen — jetzt modulweit
vermerkt, genau wie beim Kontextmenü. Escape schliesst zusätzlich von
überall, nicht nur mit dem Fokus in der Liste.

Dazu stand unter jeder Mediathek „0 Titel freigeben". Der Knopf wurde
über `hidden` versteckt — das Attribut wirkt über `display: none` mit der
Spezifität von Null, und `.btn` setzt `display: inline-flex`. Die Klasse
`.hidden` trägt ein `!important` und setzt sich durch.

Und das Favicon kommt jetzt aus `icon.png`, dem gerenderten App-Icon
selbst. Meine nachgezeichnete Fassung war falsch: die Grafik füllt die
Fläche, statt klein in der Mitte zu sitzen. Ein Icon, das dem echten nur
ähnelt, driftet beim nächsten Entwurf wieder auseinander.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-10-04 19:01:58 +02:00
co-authored by Claude Opus 5
parent 8809b9f46f
commit 4b0323f955
9 changed files with 41 additions and 38 deletions
+25 -1
View File
@@ -28,6 +28,20 @@ export type Auswahlfeld = {
setzen: (optionen: Option[]) => void;
};
/** Das eine offene Auswahlfeld — oder keines.
*
* **Modulweit, nicht je Feld.** Vorher merkte sich jedes Feld nur seine
* eigene Liste; drei Felder nebeneinander liessen sich alle drei aufklappen
* und überlagerten einander. Ein Auswahlfeld ist ein Menü, und von denen ist
* immer höchstens eines offen — genauso hält es das Kontextmenü.
*/
let offenesFeld: { schliessen: () => void } | null = null;
export function alleAuswahlenSchliessen(): void {
offenesFeld?.schliessen();
offenesFeld = null;
}
export function auswahl(optionen: Option[], vorgabe = ''): Auswahlfeld {
let liste = [...optionen];
let wert = vorgabe;
@@ -56,8 +70,11 @@ export function auswahl(optionen: Option[], vorgabe = ''): Auswahlfeld {
offen?.remove();
offen = null;
knopf.setAttribute('aria-expanded', 'false');
if (offenesFeld === steuerung) offenesFeld = null;
}
const steuerung = { schliessen };
function waehlen(neu: string): void {
const geaendert = neu !== wert;
wert = neu;
@@ -70,6 +87,10 @@ export function auswahl(optionen: Option[], vorgabe = ''): Auswahlfeld {
function oeffnen(): void {
if (offen) { schliessen(); return; }
// Erst das andere zu, dann dieses auf.
alleAuswahlenSchliessen();
offenesFeld = steuerung;
const box = document.createElement('div');
box.className = 'auswahl-liste';
box.setAttribute('role', 'listbox');
@@ -172,8 +193,11 @@ export function auswahl(optionen: Option[], vorgabe = ''): Auswahlfeld {
// Kontextmenü. Je Feld registriert und nicht global: es gibt wenige davon,
// und beim Entfernen des Feldes gehen sie mit.
document.addEventListener('click', e => {
if (offen && !offen.contains(e.target as Node) && e.target !== knopf) schliessen();
if (offen && !offen.contains(e.target as Node) && !knopf.contains(e.target as Node)) {
schliessen();
}
});
document.addEventListener('keydown', e => { if (e.key === 'Escape' && offen) schliessen(); });
window.addEventListener('scroll', () => schliessen(), { passive: true, capture: true });
return {