Let menu entries appear as buttons with icon, colours and phone placement
The menu editor gets "Als Button darstellen" per entry: shape, appearance and size from the button design, fill and ink with hover and palette, icon colour, icon from the dialog, motion, icon-only and where the button sits on the phone (in the opened menu, beside the burger, or there as an icon only). Colours go into the page stylesheet under a stable per-button id because the CSP forbids inline styles. ADR 110. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
48ae2443cd
commit
13f6759df8
22 files changed
+623
-14
No files matched your search
@@ -17,6 +17,27 @@
|
||||
{% endif %}
|
||||
<label class="check-label" for="menu-newTab-{{ n }}"><input id="menu-newTab-{{ n }}" type="checkbox" data-key="newTab" name="items[{{ n }}][newTab]" value="1"{{ row.newTab|default(false) ? ' checked' : '' }}> In neuem Tab öffnen</label>
|
||||
<div class="menu-icon-fields"><div><label for="menu-icon-{{ n }}">Icon</label><select id="menu-icon-{{ n }}" data-key="icon" name="items[{{ n }}][icon]"><option value="">Kein Icon</option>{% for icon in menuIcons %}<option value="{{ icon }}"{{ row.icon|default('') == icon ? ' selected' : '' }}>{{ icon }}</option>{% endfor %}</select></div><div><label for="menu-iconPosition-{{ n }}">Icon-Position</label><select id="menu-iconPosition-{{ n }}" data-key="iconPosition" name="items[{{ n }}][iconPosition]"><option value="before"{{ row.iconPosition|default('before') == 'before' ? ' selected' : '' }}>Vor dem Text</option><option value="after"{{ row.iconPosition|default('before') == 'after' ? ' selected' : '' }}>Nach dem Text</option></select></div></div>
|
||||
{# Als Button (ADR 110). Ohne Skript sind es gewöhnliche Felder; mit Skript kommen
|
||||
Vorschau, Symbolfenster und Palettenfarben dazu. Leer heißt Website-Standard. #}
|
||||
{% set btn = row.button|default({}) %}
|
||||
<fieldset class="menu-button-fields" data-button-fields>
|
||||
<legend>Button</legend>
|
||||
<label class="check-label" for="menu-button-{{ n }}"><input id="menu-button-{{ n }}" type="checkbox" data-key="button" name="items[{{ n }}][button]" value="1"{{ row.button ? ' checked' : '' }}> Als Button darstellen</label>
|
||||
<input type="hidden" data-key="buttonId" name="items[{{ n }}][buttonId]" value="{{ btn.id|default('') }}">
|
||||
<div class="menu-button-options" data-button-options{{ row.button ? '' : ' hidden' }}>
|
||||
{% for key, caption in {shape: 'Form', appearance: 'Darstellung', size: 'Größe'} %}
|
||||
{% set field = 'button' ~ key|capitalize %}
|
||||
<div><label for="menu-{{ field }}-{{ n }}">{{ caption }}</label><select id="menu-{{ field }}-{{ n }}" data-key="{{ field }}" name="items[{{ n }}][{{ field }}]"><option value="">Website-Standard</option>{% for value, name in buttonSchema.buttonOptions[key] %}<option value="{{ value }}"{{ btn[key]|default('') == value ? ' selected' : '' }}>{{ name }}</option>{% endfor %}</select></div>
|
||||
{% endfor %}
|
||||
{% for field, caption in {buttonFill: 'Fläche', buttonInk: 'Schrift', buttonHoverFill: 'Fläche beim Überfahren', buttonHoverInk: 'Schrift beim Überfahren', buttonIconColor: 'Symbolfarbe'} %}
|
||||
{% set stored = {buttonFill: 'fill', buttonInk: 'ink', buttonHoverFill: 'hoverFill', buttonHoverInk: 'hoverInk', buttonIconColor: 'iconColor'}[field] %}
|
||||
<div data-color-field><label for="menu-{{ field }}-{{ n }}">{{ caption }}</label><input id="menu-{{ field }}-{{ n }}" data-key="{{ field }}" name="items[{{ n }}][{{ field }}]" value="{{ btn[stored]|default('') }}" placeholder="Website-Standard" pattern="(#[0-9a-fA-F]{6}([0-9a-fA-F]{2})?|@[a-z][a-z0-9-]{0,31})" maxlength="33"></div>
|
||||
{% endfor %}
|
||||
<div><label for="menu-iconMotion-{{ n }}">Symbol beim Überfahren</label><select id="menu-iconMotion-{{ n }}" data-key="iconMotion" name="items[{{ n }}][iconMotion]">{% for value, name in {none: 'Ruhig', slide: 'Rückt', reveal: 'Erscheint'} %}<option value="{{ value }}"{{ btn.iconMotion|default('none') == value ? ' selected' : '' }}>{{ name }}</option>{% endfor %}</select></div>
|
||||
<label class="check-label" for="menu-iconOnly-{{ n }}"><input id="menu-iconOnly-{{ n }}" type="checkbox" data-key="iconOnly" name="items[{{ n }}][iconOnly]" value="1"{{ btn.iconOnly|default(false) ? ' checked' : '' }}> Nur das Symbol zeigen</label>
|
||||
<div><label for="menu-buttonMobile-{{ n }}">Auf dem Telefon</label><select id="menu-buttonMobile-{{ n }}" data-key="buttonMobile" name="items[{{ n }}][buttonMobile]">{% for value, name in buttonSchema.mobile %}<option value="{{ value }}"{{ btn.mobile|default('menu') == value ? ' selected' : '' }}>{{ name }}</option>{% endfor %}</select></div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</details>
|
||||
<div class="menu-entry-actions" role="group" aria-label="{{ row.label }} verschieben oder entfernen">
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
{% block title %}Menüs{% endblock %}
|
||||
{% block heading %}Menüs{% endblock %}
|
||||
{% block lead %}Inhalte suchen und hinzufügen. Rechts bestimmst du Beschriftung, Reihenfolge und Unterpunkte.{% endblock %}
|
||||
{% block styles %}<link rel="stylesheet" href="/assets/media-dialog.css?v={{ kant_version() }}">{% endblock %}
|
||||
{% block styles %}<link rel="stylesheet" href="/assets/media-dialog.css?v={{ kant_version() }}"><link rel="stylesheet" href="/assets/buttons.css?v={{ kant_version() }}"><link rel="stylesheet" href="/assets/button-controls.css?v={{ kant_version() }}"><link rel="stylesheet" href="/assets/color-control.css?v={{ kant_version() }}">{% endblock %}
|
||||
{% block scripts %}<script type="module" src="/assets/menu-editor.js?v={{ kant_version() }}"></script>{% endblock %}
|
||||
{% block content %}
|
||||
{% include 'admin/menu-icons.html.twig' %}
|
||||
<nav class="menu-slots" aria-label="Menü auswählen">{% for key, label in slots %}<a href="{{ path('admin_menus', {slot: key}) }}"{{ key == slot ? ' aria-current="page"' : '' }}>{{ label }}</a>{% endfor %}</nav>
|
||||
<form action="{{ path('admin_menu_save', {slot: slot}) }}" method="post" id="menu-editor" class="menu-workspace menu-form" data-icons="{{ menuIcons|json_encode|e('html_attr') }}">
|
||||
<form action="{{ path('admin_menu_save', {slot: slot}) }}" method="post" id="menu-editor" class="menu-workspace menu-form" data-icons="{{ menuIcons|json_encode|e('html_attr') }}" data-button-schema="{{ buttonSchema|json_encode|e('html_attr') }}">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('menus') }}"><input type="hidden" name="expectedVersion" value="{{ menu ? menu.version : 0 }}">
|
||||
<aside class="menu-add" aria-label="Menüeinträge hinzufügen">
|
||||
<section class="card card-body"><h2>Seiten und Beiträge</h2>
|
||||
|
||||
@@ -114,6 +114,10 @@
|
||||
<nav id="{{ block.id }}" class="block-menu menu-{{ menuLayout }} menu-collapse-{{ collapse }}{{ designClasses }}"
|
||||
aria-label="{{ {header: 'Hauptnavigation', secondary: 'Zweite Navigation', footer: 'Fußzeile', legal: 'Rechtliches'}[props.slot]|default('Navigation') }}">
|
||||
{% if menuLayout == 'burger' or collapse != 'never' %}
|
||||
{# Buttons, die auf dem Telefon neben dem Menü-Knopf stehen bleiben (ADR 110). Sichtbar nur,
|
||||
solange das Menü zusammengeklappt ist; im aufgeklappten Menü fehlen sie dann. #}
|
||||
{% set barLinks = links|filter(link => link.button is defined and link.button.mobile|default('menu') in ['bar', 'bar-icon']) %}
|
||||
{% if barLinks is not empty %}<ul class="menu-actions">{% for link in barLinks %}<li>{% include 'menu-button.html.twig' with {link: link, forceIconOnly: link.button.mobile == 'bar-icon'} only %}</li>{% endfor %}</ul>{% endif %}
|
||||
<details class="menu-burger">
|
||||
{# Nur Symbol behält den Namen für Vorlesesoftware; sichtbar ist dann nur der Strich. #}
|
||||
{% set burger = props.burgerLabel|default('both') %}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{# Ein Menüeintrag als Button (ADR 110): dieselben Klassen wie der Button-Baustein, also dieselben
|
||||
Website-Standards, Varianten, Symbole und Bewegungen. Eigene Farben stehen als Regel für
|
||||
.menu-button-<id> im Stylesheet der Seite. Die Beschriftung bleibt auch bei "nur Symbol" im
|
||||
Link - als zugänglicher Name. #}
|
||||
{% set b = link.button %}
|
||||
{% set iconFirst = link.iconPosition|default('before') == 'before' %}
|
||||
{% set hasIcon = link.icon|default('') != '' %}
|
||||
{# forceIconOnly: neben dem Menü-Knopf auf dem Telefon, wenn dort nur das Symbol stehen soll. #}
|
||||
{% set iconOnly = hasIcon and (b.iconOnly|default(false) or forceIconOnly|default(false)) %}
|
||||
{% set classes = 'button cms-button menu-button menu-button-' ~ b.id %}
|
||||
{% for key in ['shape', 'appearance', 'size'] %}{% if b[key] is defined %}{% set classes = classes ~ ' b-desktop-' ~ key ~ '-' ~ b[key] %}{% endif %}{% endfor %}
|
||||
{% if hasIcon %}{% set classes = classes ~ (iconFirst ? ' icon-start' : '') ~ (b.iconMotion|default('none') != 'none' ? ' icon-motion-' ~ b.iconMotion : '') ~ (iconOnly ? ' icon-only' : '') %}{% endif %}
|
||||
{% set iconMarkup = '' %}
|
||||
{% if hasIcon %}{% set iconMarkup %}<span class="button-icon" aria-hidden="true">{% include 'blocks/icon.html.twig' with {name: link.icon} only %}</span>{% endset %}{% endif %}
|
||||
<a class="{{ classes }}" href="{{ link.href }}"{% include 'blocks/link-attributes.html.twig' with {newTab: link.newTab|default(false)} only %}{% if link.current %} aria-current="page"{% endif %}>{% if iconMarkup and iconFirst %}{{ iconMarkup }} {% endif %}<span class="button-label">{{ link.label }}</span>{% if iconMarkup and not iconFirst %} {{ iconMarkup }}{% endif %}</a>
|
||||
@@ -1,8 +1,10 @@
|
||||
{# One level of a resolved menu. Dropdowns use details/summary so submenus work without JavaScript. #}
|
||||
<ul class="menu-list menu-level-{{ level|default(1) }}">
|
||||
{% for link in links %}
|
||||
<li>
|
||||
{% if link.children is not empty %}
|
||||
<li{% if link.button is defined %} class="menu-item-button{{ link.button.mobile|default('menu') in ['bar', 'bar-icon'] ? ' menu-keep-visible' }}"{% endif %}>
|
||||
{% if link.button is defined %}
|
||||
{% include 'menu-button.html.twig' with {link: link} only %}
|
||||
{% elseif link.children is not empty %}
|
||||
<details class="menu-branch">
|
||||
<summary>{% include 'nav-label.html.twig' with {link: link} only %}</summary>
|
||||
<div class="menu-branch-body">
|
||||
|
||||
Reference in new issue
Block a user