feat: various a11y fixes

This commit is contained in:
Björn Fromme
2025-05-14 16:08:11 +02:00
parent 69204656ae
commit 8f846c4401
22 changed files with 76 additions and 68 deletions
@@ -29,6 +29,7 @@ class IconViewHelper extends AbstractTagBasedViewHelper
$content = sprintf('<use href="%s#icon-%s"></use>', $imageUrl, $this->arguments['icon']);
$this->tag->setContent($content);
$this->tag->addAttributes(['aria-hidden' => 'true']);
return $this->tag->render();
}
@@ -41,6 +41,8 @@ class LazyLoadImageViewHelper extends ImageViewHelper
$classItems[] = 'lazyload';
$classes = implode(' ', array_unique($classItems));
$this->tag->addAttribute('class', $classes);
// ensure a11y compliance
$this->tag->removeAttribute('title');
return $this->tag->render();
}
@@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<!-- Symbols -->
<symbol id="icon-menu" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/></symbol>
<symbol id="icon-chevron-down" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></symbol>

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

@@ -4,14 +4,20 @@
<f:cObject typoscriptObjectPath="lib.searchBarCollapsed"/>
<f:alias map="{searchbarCollapsed: 1}">
<f:render partial="Topnav" arguments="{_all}"/>
<f:render partial="Mainnav" section="Main" arguments="{_all}"/>
</f:alias>
<f:render section="Content"/>
<f:render section="Teasers"/>
<f:render partial="Footer" arguments="{_all}"/>
<f:render partial="ContactBar" arguments="{_all}"/>
<f:render partial="Topnav" arguments="{_all}"/>
<f:render partial="Mobilenav" section="Main" arguments="{_all}"/>
<f:render partial="Search/MobileSearch" arguments="{_all}"/>
<main>
<f:render section="Content"/>
<f:render section="Teasers"/>
</main>
<footer>
<f:render partial="Footer" arguments="{_all}"/>
</footer>
<aside>
<f:render partial="ContactBar" arguments="{_all}"/>
<f:render partial="Mobilenav" section="Main" arguments="{_all}"/>
<f:render partial="Search/MobileSearch" arguments="{_all}"/>
</aside>
<f:render partial="Config" arguments="{_all}" />
</html>
@@ -2,6 +2,7 @@
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
<f:render partial="Topnav" arguments="{_all}"/>
<f:render partial="Mainnav" section="Main" arguments="{_all}"/>
<header>
<f:render partial="HeaderSlider" arguments="{_all}"/>
@@ -17,13 +18,14 @@
<footer>
<f:render partial="Footer" arguments="{_all}"/>
</footer>
<f:render partial="ContactBar" arguments="{_all}"/>
<f:render partial="Topnav" arguments="{_all}"/>
<f:render partial="Mobilenav" section="Main" arguments="{_all}"/>
<f:if condition="{data.tx_eptheme_hide_searchbar} || {settings.hideSearchbar}">
<f:else>
<f:render partial="Search/MobileSearch" arguments="{_all}"/>
</f:else>
</f:if>
<aside>
<f:render partial="ContactBar" arguments="{_all}"/>
<f:render partial="Mobilenav" section="Main" arguments="{_all}"/>
<f:if condition="{data.tx_eptheme_hide_searchbar} || {settings.hideSearchbar}">
<f:else>
<f:render partial="Search/MobileSearch" arguments="{_all}"/>
</f:else>
</f:if>
</aside>
<f:render partial="Config" arguments="{_all}" />
</html>
@@ -13,8 +13,10 @@
<footer>
<f:render partial="Footer" arguments="{_all}"/>
</footer>
<f:render partial="ContactBar" arguments="{_all}"/>
<f:render partial="Topnav" arguments="{_all}"/>
<f:render partial="Mobilenav" section="Main" arguments="{_all}"/>
<aside>
<f:render partial="ContactBar" arguments="{_all}"/>
<f:render partial="Topnav" arguments="{_all}"/>
<f:render partial="Mobilenav" section="Main" arguments="{_all}"/>
</aside>
<f:render partial="Config" arguments="{_all}" />
</html>
@@ -5,7 +5,7 @@
<f:section name="Teaser">
<f:if condition="{concept}">
<a href="{f:uri.typolink(parameter: concept.detailPage)}" class="flex flex-col">
<div class="relative flex flex-col">
<div class="relative">
<f:alias map="{teaserImage: concept.teaserImage, defaultImage: concept.headerImage}">
<f:if condition="{teaserImage}">
@@ -33,17 +33,19 @@
</f:else>
</f:if>
</f:alias>
<div class="absolute top-0 left-0 inset-0 bg-concept-{concept.code}/70">
<div class="flex h-full w-full p-4 items-end headline--3 text-white">
<div class="absolute z-10 inset-0 bg-concept-{concept.code}/70">
<f:link.typolink parameter="{concept.detailPage}"
class="flex h-full w-full p-4 items-end headline--3 text-white">
{concept.name}
</div>
<span class="absolute inset-0"></span>
</f:link.typolink>
</div>
</div>
<div class="p-4 flex-1">
{concept.teaser -> f:format.crop(maxCharacters: settings.teaserTextMaxChars) -> f:format.html()}
</div>
<div class="bg-concept-{concept.code} h-1 w-20"></div>
</a>
</div>
</f:if>
</f:section>
@@ -8,7 +8,7 @@
<div>{data.bodytext -> f:format.html()}</div>
<div>
{data.flexForm.buttons -> v:iterator.first() -> v:variable.set(name: 'button')}
<a href="{f:uri.typolink(parameter: button.container.link)}" class="btn btn-info" title="{button.container.label -> f:format.raw()}">{button.container.label -> f:format.raw()}</a>
<a href="{f:uri.typolink(parameter: button.container.link)}" class="btn btn-info">{button.container.label -> f:format.raw()}</a>
</div>
</div>
@@ -16,7 +16,7 @@
<picture class="w-full h-full">
<source srcset="{f:uri.image(image: image, width: '1370')}" media="(min-width: 768px)">
<source srcset="{f:uri.image(image: image, height: '640', cropVariant: 'mobile')}" media="(max-width: 767px)">
<f:image image="{image}" cropVariant="mobile" height="640" class="w-full h-auto" alt="{image.alternative}"/>
<img src="{f:uri.image(image: image, cropVariant: 'mobile', height: '640')}" class="w-full h-auto" alt="{image.alternative}">
</picture>
</div>
</f:if>
@@ -34,6 +34,7 @@
</f:if>
<f:if condition="{slide.button}">
<f:link.typolink parameter="{slide.page_uid}"
additionalAttributes="{'tabindex': '-1'}"
class="button bg-button inline-block">
{slide.button}
</f:link.typolink>
@@ -44,7 +45,8 @@
<f:if condition="{slide.skipass} || {badge}">
<div class="herounit__badge-wrapper">
<f:if condition="{slide.skipass}">
<f:link.typolink parameter="{settings.skipassPageUid}">
<f:link.typolink parameter="{settings.skipassPageUid}"
additionalAttributes="{'tabindex': '-1'}">
<div class="herounit__badge herounit__badge--skipass">
<div class="uppercase text-4xl font-bold leading-7 mb-2">Ski-<br>Pass</div>
<div class="uppercase">inklusive</div>
@@ -53,7 +55,8 @@
</f:if>
<f:if condition="{badge}">
<f:alias map="{badgeData: badge.0.data}">
<f:link.typolink parameter="{badgeData.link}">
<f:link.typolink parameter="{badgeData.link}"
additionalAttributes="{'tabindex': '-1'}">
<div class="herounit__badge herounit__badge--custom">
<svg viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg"
@@ -11,7 +11,7 @@
title="zur Startseite">
<f:image src="{settings.logoImage}"
class="block w-auto {ep:themeClasses(classes: '{ep: \'h-10 lg:h-12\', sbw: \'h-14 lg:h-24\', snz: \'h-14 lg:h-24\', suz: \'h-14 lg:h-24\', uch: \'h-12 lg:h-20\', ser: \'h-10 lg:h-12\'}', key: settings.themekey)}"
alt="Logo"/>
alt="Bildmarke"/>
</f:link.typolink>
<div class="hidden hover-hover:lg:block">
<f:render section="FirstLevel" arguments="{_all}"/>
@@ -43,10 +43,10 @@
</f:section>
<f:section name="FirstLevel">
<nav role="menu">
<ul class="m-0 p-0 list-none flex items-center justify-end space-x-4">
<nav role="navigation" aria-label="Hauptnavigation">
<ul class="m-0 p-0 list-none flex items-center justify-end space-x-4" role="menubar">
<f:for each="{mainnav}" as="topitem">
<li class="group pb-4">
<li class="group pb-4" role="none">
<f:if condition="{topitem.children}">
<f:then>
<a href="{f:uri.typolink(parameter: topitem.data.uid)}"
@@ -69,7 +69,7 @@
</f:for>
<f:if condition="{data.tx_eptheme_hide_searchbar} || {settings.hideSearchbar}">
<f:else>
<li class="pb-4">
<li class="pb-4" role="none">
<f:if condition="{searchbarCollapsed}">
<f:then>
<button type="button"
@@ -80,7 +80,7 @@
</button>
</f:then>
<f:else>
<f:link.typolink parameter="{settings.defaultSearchPageUid}" title="zur Suche">
<f:link.typolink parameter="{settings.defaultSearchPageUid}" title="zur Suche" additionalAttributes="{'role': 'menuitem'}">
{ep:icon(icon: 'search', class: 'w-6 h-6')}
</f:link.typolink>
</f:else>
@@ -96,11 +96,11 @@
<div class="absolute top-100 left-0 inset-x-0 pt-4 invisible opacity-0 group-hover:visible group-hover:opacity-100 transition-opacity duration-300 ease-in-out">
<div class="bg-white grid grid-cols-3 lg:grid-cols-4 gap-8 p-4 shadow-lg rounded">
<f:for each="{topitem.children}" as="subitem">
<ul class="m-0 p-0 list-none">
<li>
<ul class="m-0 p-0 list-none" role="menu">
<li role="none">
<f:if condition="{subitem.doktype} == 3">
<f:then>
<a href="{subitem.link}" target="_blank">
<a href="{subitem.link}" target="_blank" role="menuitem">
<f:if condition="{subitem.data.tx_eptheme_context_country_code}">
{ep:icon(icon: 'flag-{subitem.data.tx_eptheme_context_country_code -> f:format.case(mode: \'lower\')}', class: 'w-8 h-6')}
</f:if>
@@ -111,6 +111,7 @@
</f:then>
<f:else>
<a href="{f:uri.typolink(parameter: subitem.data.uid)}"
role="menuitem"
class="flex items-center space-x-2 underlined">
<f:if condition="{subitem.data.tx_eptheme_context_country_code}">
{ep:icon(icon: 'flag-{subitem.data.tx_eptheme_context_country_code -> f:format.case(mode: \'lower\')}', class: 'w-8 h-6')}
@@ -133,18 +134,20 @@
<f:for each="{subitem.children}" as="subsubitem">
<f:if condition="{subsubitem.doktype} == 3">
<f:then>
<li>
<li role="none">
<a href="{subsubitem.link}"
class="text-zinc-800 text-lg"
target="_blank">
target="_blank"
role="menuitem">
{subsubitem.title}
</a>
</li>
</f:then>
<f:else>
<li>
<li role="none">
<a href="{f:uri.typolink(parameter: subsubitem.data.uid)}"
class="text-zinc-800 text-lg">
class="text-zinc-800 text-lg"
role="menuitem">
{subsubitem.title}
</a>
</li>
@@ -14,7 +14,7 @@
<f:link.typolink parameter="{f:if(condition: settings.logoLink, then: settings.logoLink, else: settings.defaultHomeUid)}"
class="block hover-hover:lg:pb-4"
title="zur Startseite">
<f:image class="block h-10 lg:h-12 w-auto" src="{settings.logoImage}" alt="Logo"/>
<f:image class="block h-10 lg:h-12 w-auto" src="{settings.logoImage}" alt="Bildmarke"/>
</f:link.typolink>
<div class="flex hover-hover:lg:hidden items-center space-x-4">
<f:if condition="{data.tx_eptheme_hide_searchbar}">
@@ -6,7 +6,7 @@
<f:if condition="{images}">
<f:if condition="{images -> f:count()} == 1">
<f:then>
<f:link.typolink parameter="{images.0.originalResource.link}" title="{images.0.title}">
<f:link.typolink parameter="{images.0.originalResource.link}">
<img src="{f:uri.image(image: images.0, width: '770', height: '430c+100')}"
class="block w-full h-auto mb-4"
alt="{images.0.alternative}">
@@ -12,8 +12,7 @@
<f:alias map="{mediaElement: '{newsItem.mediaPreviews.0}'}">
<img class="block w-full h-auto lazyload"
data-src="{f:uri.image(image: mediaElement, width: '640', height: '360c+50')}"
alt="{mediaElement.originalResource.alternative}"
title="{mediaElement.originalResource.title}">
alt="{mediaElement.originalResource.alternative}">
</f:alias>
</f:if>
</f:then>
@@ -22,8 +21,7 @@
<f:alias map="{mediaElement: '{newsItem.media.0}'}">
<img class="block w-full h-auto lazyload"
data-src="{f:uri.image(image: mediaElement, width: '640', height: '360c+50')}"
alt="{mediaElement.originalResource.alternative}"
title="{mediaElement.originalResource.title}">
alt="{mediaElement.originalResource.alternative}">
</f:alias>
</f:if>
</f:else>
@@ -40,7 +38,7 @@
<time datetime="{f:format.date(date:newsItem.datetime, format:'Y-m-d')}"><f:format.date format="{f:translate(key:'dateFormat')}">{newsItem.datetime}</f:format.date></time>
<f:if condition="{newsItem.tags}"> in
<f:for each="{newsItem.tags}" as="tag" iteration="iteration">
<f:link.page title="{tag.title}" pageUid="{settings.tagListPageUid}" additionalParams="{tx_news_pi1:{overwriteDemand:{tags: tag}}}">
<f:link.page pageUid="{settings.tagListPageUid}" additionalParams="{tx_news_pi1:{overwriteDemand:{tags: tag}}}">
{tag.title}
</f:link.page>
{f:if(condition: iteration.isLast, else: ', ')}
@@ -59,7 +57,7 @@
</f:if>
</div>
</n:removeMediaTags>
<n:link newsItem="{newsItem}" settings="{settings}" class="button bg-button button--small" title="{newsItem.title}">
<n:link newsItem="{newsItem}" settings="{settings}" class="button bg-button button--small">
<f:translate key="more-link"/>
</n:link>
</div>
@@ -88,8 +88,7 @@
data-pricetable-type-param="options"
data-pricetable-uid-param="{row.roomUid}"
data-cooltipz-dir="top"
aria-label="Alle Zusatzleistungen anzeigen"
role="tooltip">
aria-label="Alle Zusatzleistungen anzeigen">
{ep:icon(icon: 'plus-circle', class: 'w-4 h-4 md:w-5 md:h-5')}
</button>
</f:if>
@@ -68,7 +68,6 @@
<f:if condition="{settings.showSkipassBadge} && {product.skipassIncluded}">
<div class="herounit__badge-wrapper">
<f:link.typolink parameter="{settings.skipassPageUid}"
title="Skipass inklusive"
class="herounit__badge herounit__badge--skipass">
<p class="uppercase text-4xl font-bold leading-7 mb-2">
Ski-<br>Pass
@@ -57,8 +57,7 @@
data-watchlist-toggle-target="ariaLabel"
data-action="watchlist-toggle#toggle"
data-cooltipz-dir="top-right"
aria-label="auf die Merkliste setzen"
role="tooltip">
aria-label="auf die Merkliste setzen">
<svg class="product-teaser__watchlist-icon" data-watchlist-toggle-target="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path></svg>
</button>
</div>
@@ -17,8 +17,7 @@
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="330"
alt="Webcam {region.name}"
title="Webcam {region.name}" />
alt="Webcam {region.name}" />
</a>
</div>
</f:if>
@@ -11,7 +11,7 @@
<a href="{f:uri.typolink(parameter: settings.defaultHomeUid)}"
class="block hover-hover:lg:pb-4"
title="zur Startseite">
<f:image class="block h-10 lg:h-12 w-auto" src="{settings.logoImage}" alt="Logo"/>
<f:image class="block h-10 lg:h-12 w-auto" src="{settings.logoImage}" alt="Bildmarke"/>
</a>
<button type="button"
aria-label="Suche schließen"
@@ -11,7 +11,6 @@
<div class="tiles__tile lg:col-span-2 lg:row-span-1"
style="background-image:url('{f:uri.image(image: images.0)}');">
<f:link.typolink parameter="{images.0.link}"
title="{images.0.title -> f:format.raw()}"
class="tiles__link">
<span class="tiles__label">
{images.0.title -> f:format.raw()}
@@ -23,7 +22,6 @@
<div class="tiles__tile lg:col-span-2 lg:row-span-1"
style="background-image:url('{f:uri.image(image: images.1)}');">
<f:link.typolink parameter="{images.1.link}"
title="{images.1.title -> f:format.raw()}"
class="tiles__link">
<span class="tiles__label">
{images.1.title -> f:format.raw()}
@@ -35,7 +33,6 @@
<div class="tiles__tile lg:col-span-12 lg:row-span-1"
style="background-image:url('{f:uri.image(image: images.4)}');">
<f:link.typolink parameter="{images.4.link}"
title="{images.4.title -> f:format.raw()}"
class="tiles__link">
<span class="tiles__label">
{images.4.title -> f:format.raw()}
@@ -47,7 +44,6 @@
<div class="tiles__tile lg:col-span-4 lg:row-span-2"
style="background-image:url('{f:uri.image(image: images.2)}');">
<f:link.typolink parameter="{images.2.link}"
title="{images.2.title -> f:format.raw()}"
class="tiles__link">
<span class="tiles__label">
{images.2.title -> f:format.raw()}
@@ -59,7 +55,6 @@
<div class="tiles__tile lg:col-span-6 lg:row-span-2"
style="background-image:url('{f:uri.image(image: images.3)}');">
<f:link.typolink parameter="{images.3.link}"
title="{images.3.title -> f:format.raw()}"
class="tiles__link">
<span class="tiles__label">
{images.3.title -> f:format.raw()}
@@ -7,7 +7,7 @@
<f:else>
<div class="topnav">
<div class="container">
<nav role="navigation" class="topnav__nav">
<nav role="navigation" aria-label="Bereichs-Navigation" class="topnav__nav">
<div class="flex items-center border-l border-white/50">
<f:if condition="{settings.mainSitePid}">
<f:link.typolink parameter="{settings.mainSitePid}"
@@ -15,7 +15,7 @@
title="zur Startseite">
<f:image src="EXT:ep_theme/Resources/Public/images/logo.svg"
class="h-5 w-auto"
alt="Logo"/>
alt=""/>
</f:link.typolink>
</f:if>
<f:link.typolink parameter="{settings.defaultHomeUid}" class="topnav__item" title="E&amp;P">
@@ -58,8 +58,7 @@
data-daytrip-type-param="services"
data-daytrip-uid-param="{iteration.cycle}"
data-cooltipz-dir="top"
aria-label="Alle Inklusivleistungen anzeigen"
role="tooltip">
aria-label="Alle Inklusivleistungen anzeigen">
<svg class="w-4 h-4">
<use href="{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/icons_sprite.svg')}#icon-info-circle"></use>
</svg>
@@ -246,8 +246,7 @@
data-pricetable-type-param="options"
data-pricetable-uid-param="{row.roomUid}"
data-cooltipz-dir="top"
aria-label="Alle Zusatzleistungen anzeigen"
role="tooltip">
aria-label="Alle Zusatzleistungen anzeigen">
Zusatz&shy;leistungen
</button>
</f:if>