Fassung 1.4.3: Update ohne Git, Verwaltung auf dem Telefon, eigene Symbole
Vier Wuensche und ein Fund beim Nachmessen. - Farbwaehler im Designbereich. Das Textfeld bleibt massgeblich, damit "@akzent" ein Verweis auf die Palette bleibt und nicht beim ersten Klick zu einem festen Hexwert erstarrt (ADR 066). - Die Verwaltung auf dem Telefon: das Menue klappt unter 760 px zu und nennt den Bereich, in dem man steht; Ziele 44 px, kein Skript. - Eigene SVG-Symbole statt Unicode-Zeichen - ein Telefon ersetzt die sonst durch Emoji in fremdem Stil. Zwei Eintraege trugen dabei denselben Pfad; ein Test findet beides (ADR 067). - Update aus dem Releasearchiv: der Weg fuer Installationen ohne Git. Zwei Schritte, weil ein Prozess, der sich selbst ausgetauscht hat, mit dem alten Code weiterarbeitet. var/, .env, hochgeladene Schriften und das erzeugte Buendel bleiben unberuehrt; public/ wird dazu Datei fuer Datei zusammengefuehrt. Geprueft ohne Netz gegen eine Releaseseite im Speicher (ADR 068). Beim Nachmessen der echten Startseite statt einer Testseite: das groesste Element ueber der Falz ist dort kein <img>, sondern der Hintergrund des ersten Abschnitts - und der steht nur im Stylesheet. Drei Vorabverweise mit denselben Geraetegrenzen wie der Compiler holen genau die Variante, die die Regel auch nimmt. LCP 1,3 s -> 1,1 s. Dabei gefunden: dasselbe Bild wurde je Geraeteregel neu abgefragt - Startseite 19 -> 15 Abfragen (ADR 069). Geprueft: 428 Tests auf PHP 8.2 und 8.4, Editor-, Browser- und Linkpruefung, Lighthouse auf drei echten Seiten (alles ausser der Leistung der Startseite 100). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ea3dd4ddf2
commit
d6d476177a
26 files changed
+1740
-26
No files matched your search
+35
-1
@@ -144,7 +144,7 @@ label { display: block; margin: 18px 0 7px; font-size: 13px; font-weight: 600 }
|
||||
.nav-item:hover { background: #21362d }
|
||||
.nav-item[aria-current=page] { background: #2b4a3b; color: #fff; font-weight: 650 }
|
||||
.nav-item[aria-current=page] .nav-icon { color: var(--mint) }
|
||||
.nav-icon { width: 19px; text-align: center; font-size: 14px; color: var(--shell-muted); flex-shrink: 0 }
|
||||
.nav-icon { width: 18px; height: 18px; color: var(--shell-muted); flex-shrink: 0 }
|
||||
.nav-out::after { content: '↗'; margin-left: auto; color: var(--shell-muted); font-size: 11px }
|
||||
|
||||
.shell-foot { margin-top: auto; padding-top: 20px; border-top: 1px solid #2a3d35; display: grid; gap: 6px }
|
||||
@@ -654,3 +654,37 @@ details.card > summary:hover { background: #fafbf8 }
|
||||
.favicon-field{display:flex;align-items:center;gap:12px}
|
||||
.favicon-field select{flex:1}
|
||||
.favicon-preview{border-radius:6px;background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.12)}
|
||||
|
||||
.color-field { display: flex; gap: 8px; align-items: center }
|
||||
.color-field input[type="text"], .color-field > input:not([type="color"]) { flex: 1; min-width: 0 }
|
||||
.color-field-swatch { width: 46px; min-height: 38px; padding: 2px; flex: 0 0 auto; cursor: pointer }
|
||||
.color-field-palette { flex: 0 0 auto; max-width: 40% }
|
||||
/* Die Verwaltung auf dem Telefon.
|
||||
|
||||
Bis 1000px stand die Navigation als waagerechte Wischleiste da - zwei Listen untereinander,
|
||||
also zwei Zeilen, und der letzte Eintrag ausserhalb des Bildes. Auf einem Telefon ist ein
|
||||
Klappmenue ehrlicher: eine Zeile im Ruhezustand, aufgeklappt die vollstaendige Liste mit
|
||||
Flaechen, die ein Daumen trifft. Das details-Element macht das ohne Skript. */
|
||||
.shell-menu > summary { display: none }
|
||||
@media (max-width: 760px) {
|
||||
.shell-nav { flex-wrap: wrap; padding: 10px 14px; gap: 10px; overflow: visible }
|
||||
.shell-menu { flex: 1 1 100%; order: 3 }
|
||||
.shell-menu > summary {
|
||||
display: flex; align-items: center; gap: 10px; list-style: none; cursor: pointer;
|
||||
min-height: 44px; padding: 0 14px; border-radius: 10px;
|
||||
background: #ffffff14; color: #fff; font-weight: 600; font-size: 15px;
|
||||
}
|
||||
.shell-menu > summary::-webkit-details-marker { display: none }
|
||||
.shell-menu > summary:focus-visible { outline: 3px solid var(--mint); outline-offset: 2px }
|
||||
.shell-menu-icon { font-size: 17px }
|
||||
.shell-menu[open] > summary { margin-bottom: 8px }
|
||||
.shell-menu nav { display: block }
|
||||
.shell-menu:not([open]) nav { display: none }
|
||||
.nav-label { display: block; margin: 12px 4px 6px; font-size: 11px; letter-spacing: 1.4px; color: #9db3a8 }
|
||||
.nav-list { display: grid; gap: 2px }
|
||||
/* Vierundvierzig Pixel: die Flaeche, die ein Daumen zuverlaessig trifft. */
|
||||
.nav-item { min-height: 44px; display: flex; align-items: center; gap: 12px; padding: 10px 14px; white-space: normal }
|
||||
.shell-foot { margin-left: auto; border-left: 0; padding-left: 0; gap: 10px }
|
||||
.shell-version { display: none }
|
||||
.shell-user strong { display: none }
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Farbfelder in den Verwaltungsformularen.
|
||||
*
|
||||
* Eine Farbe tippt man nicht, man wählt sie. Im Editor gibt es dafür längst ein Bedienelement aus
|
||||
* Farbwähler, Textfeld und Palettenliste - in den Formularen unter „Design" und „Einstellungen"
|
||||
* stand bisher nur ein nacktes Textfeld.
|
||||
*
|
||||
* Das Textfeld bleibt die Wahrheit: Es nimmt einen Wert wie `#1a2b3c` **oder** einen Schlüssel aus
|
||||
* der Palette (`@accent`), und das kann ein Farbwähler nicht. Deshalb wird es nicht ersetzt,
|
||||
* sondern ergänzt. Ohne JavaScript bleibt das Feld genau das, was es vorher war.
|
||||
*/
|
||||
(() => {
|
||||
const felder = [...document.querySelectorAll('input[data-color]')];
|
||||
if (0 === felder.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const feld of felder) {
|
||||
const palette = JSON.parse(feld.dataset.palette || '[]');
|
||||
const reihe = document.createElement('div');
|
||||
reihe.className = 'color-field';
|
||||
feld.parentNode.insertBefore(reihe, feld);
|
||||
|
||||
const waehler = document.createElement('input');
|
||||
waehler.type = 'color';
|
||||
waehler.className = 'color-field-swatch';
|
||||
waehler.setAttribute('aria-label', 'Farbwähler für ' + (feld.labels?.[0]?.textContent.trim() || 'diese Farbe'));
|
||||
// Der Wähler kennt nur Hexwerte. Steht im Feld ein Palettenschlüssel, zeigt er die Farbe,
|
||||
// für die der Schlüssel steht - sonst bliebe er auf Schwarz stehen und sähe falsch aus.
|
||||
const alsHex = wert => {
|
||||
if (/^#[0-9a-f]{6}$/i.test(wert)) {
|
||||
return wert;
|
||||
}
|
||||
const treffer = palette.find(eintrag => '@' + eintrag.key === wert);
|
||||
|
||||
return treffer ? treffer.value : '#000000';
|
||||
};
|
||||
waehler.value = alsHex(feld.value || feld.placeholder || '#000000');
|
||||
waehler.addEventListener('input', () => {
|
||||
feld.value = waehler.value;
|
||||
feld.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
});
|
||||
|
||||
reihe.append(waehler, feld);
|
||||
|
||||
if (palette.length > 0) {
|
||||
const auswahl = document.createElement('select');
|
||||
auswahl.className = 'color-field-palette';
|
||||
auswahl.setAttribute('aria-label', 'Farbe aus der Palette');
|
||||
auswahl.append(new Option('Aus der Palette …', ''));
|
||||
for (const eintrag of palette) {
|
||||
auswahl.append(new Option(`${eintrag.name} (${eintrag.value})`, '@' + eintrag.key));
|
||||
}
|
||||
auswahl.value = palette.some(eintrag => '@' + eintrag.key === feld.value) ? feld.value : '';
|
||||
auswahl.addEventListener('change', () => {
|
||||
if ('' === auswahl.value) {
|
||||
return;
|
||||
}
|
||||
feld.value = auswahl.value;
|
||||
waehler.value = alsHex(auswahl.value);
|
||||
feld.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
});
|
||||
reihe.append(auswahl);
|
||||
}
|
||||
|
||||
// Tippt jemand von Hand, folgt der Wähler mit - solange der Wert einer ist, den er kennt.
|
||||
feld.addEventListener('input', () => {
|
||||
const hex = alsHex(feld.value);
|
||||
if (waehler.value !== hex) {
|
||||
waehler.value = hex;
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
Reference in new issue
Block a user