From 312b5d76764011bd8f856eabbdac847b5cd3df9e Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Fri, 10 Apr 2026 15:41:16 +0200 Subject: [PATCH 1/3] `SearchSuggestions`: Support rich labels Allow `ValidHtml` to be passed via the `label-html` key which is then rendered inside a `button` element. css selectors are adjusted to have increased specificity because otherwise the button elements are styled by icingaweb2. --- asset/css/search-base.less | 4 ++-- src/FormElement/SearchSuggestions.php | 25 ++++++++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/asset/css/search-base.less b/asset/css/search-base.less index 50e7fc75..a454dfe8 100644 --- a/asset/css/search-base.less +++ b/asset/css/search-base.less @@ -84,7 +84,7 @@ fieldset:disabled .term-input-area [data-drag-initiator] { } } -.search-suggestions { +.search-suggestions.search-suggestions { background: var(--suggestions-bg, @suggestions-bg); color: var(--suggestions-color, @suggestions-color); border: 1px solid var(--suggestions-border-color, @suggestions-border-color); @@ -355,7 +355,7 @@ fieldset:disabled .term-input-area [data-drag-initiator] { } } -.search-suggestions { +.search-suggestions.search-suggestions { z-index: 2; // Required so that nothing else can overlap it (such as opaque elements and the impact overlay) position: absolute; overflow: auto; diff --git a/src/FormElement/SearchSuggestions.php b/src/FormElement/SearchSuggestions.php index 8f2351eb..8f471a16 100644 --- a/src/FormElement/SearchSuggestions.php +++ b/src/FormElement/SearchSuggestions.php @@ -6,6 +6,7 @@ use ipl\Html\BaseHtmlElement; use ipl\Html\HtmlElement; use ipl\Html\Text; +use ipl\Html\ValidHtml; use ipl\I18n\Translation; use Psr\Http\Message\ServerRequestInterface; use Traversable; @@ -42,6 +43,7 @@ class SearchSuggestions extends BaseHtmlElement * The provider must deliver terms in form of arrays with the following keys: * * (required) search: The search value * * label: A human-readable label + * * label-html: A {@see ValidHtml} label to render inside a button element instead of an input * * class: A CSS class * * title: A message shown upon hover on the term * @@ -234,7 +236,7 @@ protected function assemble(): void $provider = ['' => $this->provider]; } - /** @var iterable>> $provider */ + /** @var iterable>> $provider */ foreach ($provider as $group => $suggestions) { if ($group) { $this->addHtml( @@ -251,18 +253,31 @@ protected function assemble(): void 'type' => 'button', 'value' => $data['label'] ?? $data['search'] ]; + $labelHtml = $data['label-html'] ?? null; + unset($data['label-html']); foreach ($data as $name => $value) { $attributes["data-$name"] = $value; } + if ($labelHtml instanceof ValidHtml) { + $attributes['class'] = 'has-details'; + $content = new HtmlElement( + 'button', + Attributes::create($attributes), + $labelHtml + ); + } else { + $content = new HtmlElement( + 'input', + Attributes::create($attributes) + ); + } + $this->addHtml( new HtmlElement( 'li', null, - new HtmlElement( - 'input', - Attributes::create($attributes) - ) + $content ) ); } From 8cdc2decc9df4197dd0e0b380549df749dfc3c93 Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Tue, 14 Apr 2026 14:12:53 +0200 Subject: [PATCH 2/3] `SearchSuggestions`: use `details` as key instead of `label-html` --- src/FormElement/SearchSuggestions.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/FormElement/SearchSuggestions.php b/src/FormElement/SearchSuggestions.php index 8f471a16..a53d5365 100644 --- a/src/FormElement/SearchSuggestions.php +++ b/src/FormElement/SearchSuggestions.php @@ -43,7 +43,7 @@ class SearchSuggestions extends BaseHtmlElement * The provider must deliver terms in form of arrays with the following keys: * * (required) search: The search value * * label: A human-readable label - * * label-html: A {@see ValidHtml} label to render inside a button element instead of an input + * * details: {@see ValidHtml} to render inside a button element instead of an input * * class: A CSS class * * title: A message shown upon hover on the term * @@ -253,18 +253,18 @@ protected function assemble(): void 'type' => 'button', 'value' => $data['label'] ?? $data['search'] ]; - $labelHtml = $data['label-html'] ?? null; - unset($data['label-html']); + $details = $data['details'] ?? null; + unset($data['details']); foreach ($data as $name => $value) { $attributes["data-$name"] = $value; } - if ($labelHtml instanceof ValidHtml) { + if ($details instanceof ValidHtml) { $attributes['class'] = 'has-details'; $content = new HtmlElement( 'button', Attributes::create($attributes), - $labelHtml + $details ); } else { $content = new HtmlElement( From d97fb15b7172fcb2a40dd7588198983b30f4335b Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Tue, 14 Apr 2026 14:14:09 +0200 Subject: [PATCH 3/3] `TermInput`: Move Suggestions outside the form to fix css problems --- asset/css/search-base.less | 4 ++-- src/FormElement/TermInput.php | 16 ++++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/asset/css/search-base.less b/asset/css/search-base.less index a454dfe8..50e7fc75 100644 --- a/asset/css/search-base.less +++ b/asset/css/search-base.less @@ -84,7 +84,7 @@ fieldset:disabled .term-input-area [data-drag-initiator] { } } -.search-suggestions.search-suggestions { +.search-suggestions { background: var(--suggestions-bg, @suggestions-bg); color: var(--suggestions-color, @suggestions-color); border: 1px solid var(--suggestions-border-color, @suggestions-border-color); @@ -355,7 +355,7 @@ fieldset:disabled .term-input-area [data-drag-initiator] { } } -.search-suggestions.search-suggestions { +.search-suggestions { z-index: 2; // Required so that nothing else can overlap it (such as opaque elements and the impact overlay) position: absolute; overflow: auto; diff --git a/src/FormElement/TermInput.php b/src/FormElement/TermInput.php index c10604bc..cb93ea53 100644 --- a/src/FormElement/TermInput.php +++ b/src/FormElement/TermInput.php @@ -7,6 +7,7 @@ use ipl\Html\Form; use ipl\Html\FormElement\FieldsetElement; use ipl\Html\FormElement\HiddenElement; +use ipl\Html\HtmlDocument; use ipl\Html\HtmlElement; use ipl\Html\HtmlString; use ipl\Stdlib\Events; @@ -328,6 +329,15 @@ public function onRegistered(Form $form) $this->hasBeenAutoSubmitted = in_array($mainInputId, $autoSubmittedBy, true) || in_array($termContainerId, $autoSubmittedBy, true); + $suggestions = (new HtmlElement('div')) + ->setAttribute('id', Attribute::sanitizeId($this->getValueOfNameAttribute()) . '-suggestions') + ->setAttribute('class', 'search-suggestions'); + + $form->prependWrapper( + (new HtmlDocument()) + ->addHtml($form, $suggestions) + ); + parent::onRegistered($form); } @@ -408,10 +418,6 @@ protected function assemble() $termContainer = $this->termContainer(); - $suggestions = (new HtmlElement('div')) - ->setAttribute('id', $suggestionsId) - ->setAttribute('class', 'search-suggestions'); - $termInput = $this->createElement('hidden', 'value', [ 'id' => $termInputId, 'disabled' => true @@ -508,8 +514,6 @@ public function getValueAttribute() new HtmlElement('label', null, $mainInput) ))); - $this->addHtml($suggestions); - if (! $this->hasBeenAutoSubmitted()) { $this->emit(self::ON_ENRICH, [$this->getTerms()]); }