From 89dc19c79668615156e22d493710084da48fb947 Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Willms Date: Fri, 13 Mar 2026 16:53:43 +0100 Subject: make icons as button keyboard accesssible again, fixes #6333 Closes #6333 Merge request studip/studip!4804 --- lib/classes/HTMLAttributes.php | 2 +- lib/classes/Icon.php | 42 ++++++---------------- resources/assets/stylesheets/scss/buttons.scss | 12 ------- .../assets/stylesheets/scss/globalsearch.scss | 15 ++------ 4 files changed, 14 insertions(+), 57 deletions(-) diff --git a/lib/classes/HTMLAttributes.php b/lib/classes/HTMLAttributes.php index d9500d1..4bba3cc 100644 --- a/lib/classes/HTMLAttributes.php +++ b/lib/classes/HTMLAttributes.php @@ -189,7 +189,7 @@ class HTMLAttributes implements Stringable, ArrayAccess return implode(' ', $result); } - public function __toString() + public function __toString(): string { return $this->asString(); } diff --git a/lib/classes/Icon.php b/lib/classes/Icon.php index 8306181..459043b 100644 --- a/lib/classes/Icon.php +++ b/lib/classes/Icon.php @@ -246,9 +246,7 @@ class Icon implements JsonSerializable if ($force_img_tag || self::isStatic($this->shape)) { return sprintf( '', - arrayToHtmlAttributes( - $this->prepareHTMLAttributes($size, $view_attributes) - ) + $this->prepareHTMLAttributes($size, $view_attributes) ); } @@ -308,36 +306,17 @@ class Icon implements JsonSerializable * into the rendered output * @return String containing the html representation for the icon. */ - public function asInput($size = self::SIZE_DEFAULT, $view_attributes = [], $without_label = false) + public function asInput($size = self::SIZE_DEFAULT, $view_attributes = []) { if (is_array($size)) { [$view_attributes, $size] = [$size, self::SIZE_DEFAULT]; } - $view_attributes['tabindex'] ??= '0'; - $view_attributes['role'] ??= 'button'; + $attributes = $this->prepareHTMLAttributes(false, $view_attributes); + $attributes['class'] = 'as-link'; + unset($attributes['src']); - $text = isset($view_attributes['text']) ? htmlReady($view_attributes['text']) : ''; - - $svgContent = $this->asImg($size, $view_attributes); - - if ($without_label) { - return sprintf( - '%s', - arrayToHtmlAttributes($this->prepareHTMLAttributes($size, $view_attributes)), - $svgContent, - ); - } - - return sprintf( - '', - arrayToHtmlAttributes($this->prepareHTMLAttributes($size, $view_attributes)), - $svgContent, - $text - ); + return sprintf('', $attributes, $this->asImg($size)); } /** @@ -415,11 +394,10 @@ class Icon implements JsonSerializable * Prepares the html attributes for use assembling HTML attributes * from given shape, role, size, semantic and view attributes * - * @param int $size Size of the icon - * @param array $attributes Additional attributes - * @return Array containing the merged attributes + * @param int|false $size Size of the icon + * @param array $attributes Additional attributes */ - private function prepareHTMLAttributes($size, array $attributes) + private function prepareHTMLAttributes($size, array $attributes): HTMLAttributes { $html_attributes = HTMLAttributes::merge($this->attributes, $attributes); @@ -448,7 +426,7 @@ class Icon implements JsonSerializable $html_attributes['class'] = 'icon-shape-' . $this->shapeToPath($this->shape); } - return $html_attributes->getAttributes(); + return $html_attributes; } /** diff --git a/resources/assets/stylesheets/scss/buttons.scss b/resources/assets/stylesheets/scss/buttons.scss index 352d9b3..7510390 100644 --- a/resources/assets/stylesheets/scss/buttons.scss +++ b/resources/assets/stylesheets/scss/buttons.scss @@ -153,18 +153,6 @@ button, @include button-base; } -label { - &.undecorated.icon-button { - cursor: pointer; - .input-hidden { - display: none; - } - svg { - vertical-align: middle; - } - } -} - .btn-icon { all: unset; cursor: pointer; diff --git a/resources/assets/stylesheets/scss/globalsearch.scss b/resources/assets/stylesheets/scss/globalsearch.scss index 7671b3d..c9f6902 100644 --- a/resources/assets/stylesheets/scss/globalsearch.scss +++ b/resources/assets/stylesheets/scss/globalsearch.scss @@ -3,7 +3,6 @@ } #globalsearch-searchbar { display: flex; - align-items: center; border: thin solid var(--color--header-inverted); border-radius: var(--border-radius-search); background-color: var(--color--brand-primary); @@ -25,8 +24,9 @@ display: none; } - .icon-button { + > button.as-link { margin-left: 4px; + margin-top: 1px; // The box and input are 22px, the icon 20px = 1px top margin color: var(--color--font-inverted); } @@ -35,7 +35,6 @@ border: none; outline: none; margin-right: 5px; - vertical-align: middle; color: var(--color--font-inverted); background-color: var(--color--brand-primary); min-width: 0; @@ -45,14 +44,6 @@ } } - input[type=image] { - cursor: pointer; - border: none; - background: none; - padding: 0; - margin: 0 5px; - } - // Hint toggle text #globalsearch-togglehints { font-size: $font-size-small; @@ -89,7 +80,7 @@ color: var(--text-color); visibility: hidden; opacity: 0; - transition: opacity var(--transition-duration) ease; + transition: opacity var(--transition-duration) ease; max-height: 90vh; overflow: hidden; padding: 10px 5px; -- cgit v1.0