Rework forms, statistics, design and the sidebar foot in 1.15.0
CMS quality / php (8.2) (push) Canceled after 0s
CMS quality / php (8.4) (push) Canceled after 0s
CMS quality / browser (push) Canceled after 0s
CMS quality / mysql (push) Canceled after 0s

Forms are an editor now: one card per field with add and remove, the
technical name derived from the label, options only for a choice, and a
new "Aussehen" section with a button label and four colours (field border
and background, button and button text) that travel to the page as one
rule per form inside the hashed style block. A live preview draws the
form with the site's default button and names the text contrast.

Statistics open with six figures (views against the same span before,
average per day, busiest day, pages, referred views, missing addresses),
a chart with grid lines and a title per bar, a weekday chart and ranked
lists with share bars. The design screen shows the palette as colour
cards with seven ready-made palettes, picks the base colours from the
palette, previews every font in itself and the typography as a sample.
The sidebar ends in an account card with role and a logout icon.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
kantarciandClaude Fable 5.1 committed 2026-09-15 07:59:30 +02:00
1 parent a4ee04533c
commit 160c394c3f
25 files changed
+1293 -278

No files matched your search

+62 -1
View File
@@ -21,6 +21,13 @@ final class FormRepository
'consent' => 'Einwilligung',
];
public const MAX_FIELDS = 25;
/** Die gestaltbaren Farben eines Formulars, mit ihrer Bezeichnung in der Verwaltung. */
public const COLORS = [
'fieldBorderColor' => 'den Rahmen der Felder',
'fieldBackgroundColor' => 'den Hintergrund der Felder',
'buttonColor' => 'den Button',
'buttonInk' => 'die Buttonschrift',
];
/** Submissions per sender per hour. Deliberately low: a contact form is not a chat. */
public const RATE_LIMIT = 5;
/** A human needs longer than this to fill in a form; anything faster is a script. */
@@ -165,12 +172,66 @@ final class FormRepository
}
}
return [
$clean = [
'recipient' => $recipient,
'subject' => mb_substr(trim((string) ($settings['subject'] ?? '')), 0, 160) ?: 'Neue Formularnachricht',
'success' => mb_substr(trim((string) ($settings['success'] ?? '')), 0, 300) ?: 'Vielen Dank. Deine Nachricht ist angekommen.',
'replyToField' => $replyTo,
'buttonLabel' => mb_substr(trim((string) ($settings['buttonLabel'] ?? '')), 0, 40) ?: 'Absenden',
];
// Das Aussehen: leer heisst "wie die Website", sonst ein Palettenschluessel oder ein
// Hexwert - dieselbe Regel wie fuer jede Farbe im Editor.
foreach (self::COLORS as $field => $label) {
$value = trim((string) ($settings[$field] ?? ''));
if ('' !== $value && 1 !== preg_match(StyleSchema::COLOR, $value)) {
throw new InvalidForm(sprintf('„%s“ ist kein Farbwert für %s.', $value, $label));
}
$clean[$field] = $value;
}
return $clean;
}
/**
* Die Gestaltung eines Formulars als Regel fuer die Seite, die es zeigt.
*
* Das Formular bekommt seine Farben als Variablen: Rahmen und Grund der Felder direkt, die
* Buttonfarben ueber dieselben Token, die auch der Standardbutton der Website benutzt - so
* behaelt der Absendeknopf Form und Darstellung aus dem Design und wechselt nur die Farbe.
* Nichts gesetzt, nichts geschrieben: dann gilt weiter die Website.
*/
public function css(array $form, array $theme): string
{
$values = [];
$button = false;
foreach (['fieldBorderColor' => '--form-border', 'fieldBackgroundColor' => '--form-bg', 'buttonColor' => '--kb-fill', 'buttonInk' => '--kb-ink'] as $field => $variable) {
$value = Theme::cssColor((string) ($form['settings'][$field] ?? ''), $theme);
if (null === $value) {
continue;
}
$values[] = $variable.':'.$value;
if ('buttonColor' === $field) {
$values[] = '--kb-hover-fill:color-mix(in srgb,'.$value.' 82%,#000)';
$button = true;
}
if ('buttonInk' === $field) {
$values[] = '--kb-hover-ink:'.$value;
$button = true;
}
}
if ($button) {
// Die Darstellung (gefuellt, Rahmen, dezent) leitet Flaeche und Schrift aus Fuellung
// und Tinte ab - am Wurzelelement, mit den Werten von dort. Hier noch einmal, damit
// die Ableitung die Farben dieses Formulars nimmt.
foreach (ButtonDesign::appearance($theme['buttons']['appearance'] ?? 'solid') as $key => $value) {
$values[] = '--kb-'.$key.':'.$value;
}
}
if ([] === $values) {
return '';
}
return sprintf('.block-form[data-form="%s"]{%s}', $form['slug'], implode(';', $values));
}
/**