diff --git a/asset/css/compat.less b/asset/css/compat.less index 9f5482a55..f29dc67b8 100644 --- a/asset/css/compat.less +++ b/asset/css/compat.less @@ -92,6 +92,15 @@ form.icinga-form .control-group { } } +// suggestion-element style +form.icinga-form .suggestion-element-group { + flex: 1 1 auto; + + .suggestion-element { + border-radius: 0 0.25em 0.25em 0; + } +} + .module-icingadb { // Icinga DB Web (legacy) table header layout (e.g. in group details) > .controls { diff --git a/asset/css/suggestion-element.less b/asset/css/suggestion-element.less new file mode 100644 index 000000000..db6b89fc4 --- /dev/null +++ b/asset/css/suggestion-element.less @@ -0,0 +1,29 @@ +.suggestion-element-group { + display: inline-flex; + + .suggestion-element, + .suggestion-element-icon { + line-height: normal; + height: 2.25em; + padding: 0.5em; + background-color: var(--default-input-bg, @default-input-bg); + color: var(--default-text-color, @default-text-color); + } + + .suggestion-element { + border: none; + outline: none; + border-radius: 0 0.25em 0.25em 0; + } + + .suggestion-element-icon { + padding-right: 0; + border-radius: 0.25em 0 0 0.25em; + } + + &:focus-within { + border-radius: 0.25em; + outline: 3px solid var(--default-input-outline-color, @default-input-outline-color); + outline-offset: 1px; + } +} diff --git a/asset/css/variables.less b/asset/css/variables.less index b5d0e773f..01c2e68f6 100644 --- a/asset/css/variables.less +++ b/asset/css/variables.less @@ -42,6 +42,7 @@ @default-text-color-inverted: @default-bg; @default-input-bg: #404d72; @default-input-hover-bg: #434374; +@default-input-outline-color: @base-primary-light; @default-remove-bg: @state-critical; @default-remove-color: @default-text-color-inverted; @default-delete-bg: @state-critical; @@ -123,7 +124,7 @@ @schedule-element-fields-selected-bg: @primary-button-bg; @schedule-element-fields-selected-color: @default-text-color-inverted; @schedule-element-fields-hover-bg: @base-primary-light; -@schedule-element-fields-outline-color: fade(@base-primary-bg, 50%); +@schedule-element-fields-outline-color: @default-input-outline-color; @schedule-element-fields-selected-outline-color: fade(#fff, 50%); @schedule-element-fields-selected-hover-bg: @primary-button-hover-bg; @schedule-element-fields-disabled-color: @base-gray; @@ -152,6 +153,7 @@ --default-text-color-inverted: #F5F9FA; --default-input-bg: #DEECF1; --default-input-hover-bg: #C0CCCD; + --default-input-outline-color: @base-primary-light; --default-remove-bg: var(--base-remove-bg); --default-remove-color: var(--default-text-color-inverted); --default-delete-bg: var(--base-remove-bg); @@ -219,7 +221,7 @@ --schedule-element-fields-selected-bg: var(--primary-button-bg); --schedule-element-fields-selected-color: var(--default-text-color-inverted); --schedule-element-fields-hover-bg: @base-primary-light; - --schedule-element-fields-outline-color: fade(@base-primary-bg, 50%); + --schedule-element-fields-outline-color: @default-input-outline-color; --schedule-element-fields-selected-outline-color: fade(#fff, 50%); --schedule-element-fields-selected-hover-bg: var(--primary-button-hover-bg); --schedule-element-fields-disabled-color: var(--base-gray); diff --git a/src/FormElement/SuggestionElement.php b/src/FormElement/SuggestionElement.php new file mode 100644 index 000000000..83f3d45cc --- /dev/null +++ b/src/FormElement/SuggestionElement.php @@ -0,0 +1,87 @@ + 'off', + 'class' => 'suggestion-element', + 'data-enrichment-type' => 'completion' + ]; + + /** @var Url URL to fetch suggestions from */ + protected Url $suggestionsUrl; + + /** + * Create a new SuggestionElement + * + * @param string $name Name of the form element + * @param Url $suggestionsUrl URL to fetch suggestions from + * @param ?(array|Attributes) $attributes Attributes of the form element + */ + public function __construct(string $name, Url $suggestionsUrl, array|Attributes $attributes = null) + { + parent::__construct($name, $attributes); + + $this->setSuggestionsUrl($suggestionsUrl); + } + + /** + * Get the URL to fetch suggestions from + * + * @return Url + */ + public function getSuggestionsUrl(): Url + { + return $this->suggestionsUrl; + } + + /** + * Set the URL to fetch suggestions from + * + * @param Url $suggestionsUrl + * + * @return $this + */ + public function setSuggestionsUrl(Url $suggestionsUrl): static + { + $this->suggestionsUrl = $suggestionsUrl; + + return $this; + } + + /** + * @return string If not set, returns a default placeholder + */ + public function getPlaceholder(): string + { + return $this->placeholder ?? $this->translate('Start typing to see suggestions…'); + } + + protected function assemble(): void + { + $suggestionsId = uniqid('search-suggestions-'); + + $this->prependWrapper( + new HtmlElement( + 'div', + new Attributes(['class' => 'suggestion-element-group']), + new HtmlElement('div', new Attributes(['id' => $suggestionsId, 'class' => 'search-suggestions'])), + new HtmlElement('span', new Attributes(['class' => 'suggestion-element-icon']), new Icon('search')) + ) + ); + + $this->getAttributes()->add([ + 'data-term-suggestions' => '#' . $suggestionsId, + 'data-suggest-url' => $this->getSuggestionsUrl() + ]); + } +}