feat(a11y): add semantic markup to interface settings (#2809)

Co-authored-by: TAKAHASHI Shuuji <shuuji3@gmail.com>
zio/stable
Joaquín Sánchez 2024-04-14 20:06:25 +02:00 committed by GitHub
parent f78ce97f05
commit c504e14ff5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 143 additions and 143 deletions

View File

@ -67,61 +67,69 @@ function save() {
</script> </script>
<template> <template>
<form aria-labelledby="interface-bn" aria-describedby="interface-bn-desc" @submit.prevent="save"> <section space-y-2>
<!-- preview --> <h2 id="interface-bn" font-medium>
<div aria-hidden="true" flex="~ gap4 wrap" items-center select-settings h-14 p0> {{ $t('settings.interface.bottom_nav') }}
<nav </h2>
v-for="availableNavButton in selectedNavButtons" :key="availableNavButton.name" <form aria-labelledby="interface-bn" aria-describedby="interface-bn-desc" @submit.prevent="save">
flex="~ 1" items-center justify-center text-xl <p id="interface-bn-desc" pb-2>
scrollbar-hide overscroll-none {{ $t('settings.interface.bottom_nav_instructions') }}
> </p>
<button btn-base :class="availableNavButton.icon" mx-4 tabindex="-1" /> <!-- preview -->
</nav> <div aria-hidden="true" flex="~ gap4 wrap" items-center select-settings h-14 p0>
</div> <nav
v-for="availableNavButton in selectedNavButtons" :key="availableNavButton.name"
flex="~ 1" items-center justify-center text-xl
scrollbar-hide overscroll-none
>
<button btn-base :class="availableNavButton.icon" mx-4 tabindex="-1" />
</nav>
</div>
<!-- button selection --> <!-- button selection -->
<div flex="~ gap4 wrap" py4> <div flex="~ gap4 wrap" py4>
<button <button
v-for="{ name, label, icon } in availableNavButtons" v-for="{ name, label, icon } in availableNavButtons"
:key="name" :key="name"
btn-text flex="~ gap-2" items-center p2 border="~ base rounded" bg-base ws-nowrap btn-text flex="~ gap-2" items-center p2 border="~ base rounded" bg-base ws-nowrap
:class="isAdded(name) ? 'text-secondary hover:text-second bg-auto' : ''" :class="isAdded(name) ? 'text-secondary hover:text-second bg-auto' : ''"
type="button" type="button"
role="switch" role="switch"
:aria-checked="isAdded(name)" :aria-checked="isAdded(name)"
@click="isAdded(name) ? remove(name) : append(name)" @click="isAdded(name) ? remove(name) : append(name)"
> >
<span :class="icon" /> <span :class="icon" />
{{ label ? $t(label) : 'More menu' }} {{ label ? $t(label) : 'More menu' }}
</button> </button>
</div> </div>
<div flex="~ col" gap-y-4 gap-x-2 py-1 sm="~ justify-end flex-row"> <div flex="~ col" gap-y-4 gap-x-2 py-1 sm="~ justify-end flex-row">
<button <button
btn-outline font-bold py2 full-w sm-wa flex="~ gap2 center" btn-outline font-bold py2 full-w sm-wa flex="~ gap2 center"
type="button" type="button"
:disabled="selectedNavButtonNames.length === 0" :disabled="selectedNavButtonNames.length === 0"
:class="selectedNavButtonNames.length === 0 ? 'border-none' : undefined" :class="selectedNavButtonNames.length === 0 ? 'border-none' : undefined"
@click="clear" @click="clear"
> >
<span aria-hidden="true" class="block i-ri:delete-bin-line" /> <span aria-hidden="true" class="block i-ri:delete-bin-line" />
{{ $t('action.clear') }} {{ $t('action.clear') }}
</button> </button>
<button <button
btn-outline font-bold py2 full-w sm-wa flex="~ gap2 center" btn-outline font-bold py2 full-w sm-wa flex="~ gap2 center"
type="reset" type="reset"
@click="reset" @click="reset"
> >
<span aria-hidden="true" class="block i-ri:repeat-line" /> <span aria-hidden="true" class="block i-ri:repeat-line" />
{{ $t('action.reset') }} {{ $t('action.reset') }}
</button> </button>
<button <button
btn-solid font-bold py2 full-w sm-wa flex="~ gap2 center" btn-solid font-bold py2 full-w sm-wa flex="~ gap2 center"
:disabled="!canSave" :disabled="!canSave"
> >
<span aria-hidden="true" i-ri:save-2-fill /> <span aria-hidden="true" i-ri:save-2-fill />
{{ $t('action.save') }} {{ $t('action.save') }}
</button> </button>
</div> </div>
</form> </form>
</section>
</template> </template>

View File

@ -27,18 +27,23 @@ const modes = [
</script> </script>
<template> <template>
<div flex="~ gap4 wrap" w-full role="group" aria-labelledby="interface-cm"> <section space-y-2>
<button <h2 id="interface-cm" font-medium>
v-for="{ icon, label, mode } in modes" {{ $t('settings.interface.color_mode') }}
:key="mode" </h2>
type="button" <div flex="~ gap4 wrap" w-full role="group" aria-labelledby="interface-cm">
btn-text flex-1 flex="~ gap-1 center" p4 border="~ base rounded" bg-base ws-nowrap <button
:aria-pressed="colorMode.preference === mode ? 'true' : 'false'" v-for="{ icon, label, mode } in modes"
:class="colorMode.preference === mode ? 'pointer-events-none' : 'filter-saturate-0'" :key="mode"
@click="setColorMode(mode)" type="button"
> btn-text flex-1 flex="~ gap-1 center" p4 border="~ base rounded" bg-base ws-nowrap
<span :class="`${icon}`" /> :aria-pressed="colorMode.preference === mode ? 'true' : 'false'"
{{ $t(label) }} :class="colorMode.preference === mode ? 'pointer-events-none' : 'filter-saturate-0'"
</button> @click="setColorMode(mode)"
</div> >
<span :class="`${icon}`" />
{{ $t(label) }}
</button>
</div>
</section>
</template> </template>

View File

@ -13,40 +13,45 @@ function setFontSize(e: Event) {
</script> </script>
<template> <template>
<div flex items-center space-x-4> <section space-y-2>
<span text-xs text-secondary>Aa</span> <h2 id="interface-fs" font-medium>
<div flex-1 relative flex items-center> {{ $t('settings.interface.font_size') }}
<input </h2>
aria-labelledby="interface-fs" <div flex items-center space-x-4 select-settings>
:value="sizes.indexOf(userSettings.fontSize)" <span text-xs text-secondary>Aa</span>
:aria-valuetext="`${userSettings.fontSize}${userSettings.fontSize === DEFAULT_FONT_SIZE ? ` ${$t('settings.interface.default')}` : ''}`" <div flex-1 relative flex items-center>
:min="0" <input
:max="sizes.length - 1" aria-labelledby="interface-fs"
:step="1" :value="sizes.indexOf(userSettings.fontSize)"
type="range" :aria-valuetext="`${userSettings.fontSize}${userSettings.fontSize === DEFAULT_FONT_SIZE ? ` ${$t('settings.interface.default')}` : ''}`"
focus:outline-none :min="0"
appearance-none bg-transparent :max="sizes.length - 1"
w-full cursor-pointer :step="1"
@change="setFontSize" type="range"
> focus:outline-none
<div flex items-center justify-between absolute w-full pointer-events-none> appearance-none bg-transparent
<div w-full cursor-pointer
v-for="i in sizes.length" :key="i" @change="setFontSize"
class="container-marker"
h-3 w-3
rounded-full bg-secondary-light
relative
> >
<div flex items-center justify-between absolute w-full pointer-events-none>
<div <div
v-if="(sizes.indexOf(userSettings.fontSize)) === i - 1" v-for="i in sizes.length" :key="i"
absolute rounded-full class="-top-1 -left-1" class="container-marker"
bg-primary h-5 w-5 h-3 w-3
/> rounded-full bg-secondary-light
relative
>
<div
v-if="(sizes.indexOf(userSettings.fontSize)) === i - 1"
absolute rounded-full class="-top-1 -left-1"
bg-primary h-5 w-5
/>
</div>
</div> </div>
</div> </div>
<span text-xl text-secondary>Aa</span>
</div> </div>
<span text-xl text-secondary>Aa</span> </section>
</div>
</template> </template>
<style> <style>
@ -64,7 +69,7 @@ function setFontSize(e: Event) {
input[type=range]::-webkit-slider-runnable-track { input[type=range]::-webkit-slider-runnable-track {
--at-apply: bg-secondary-light rounded-full h1 op60; --at-apply: bg-secondary-light rounded-full h1 op60;
} }
input[type=range]:focus:-webkit-slider-runnable-track { input[type=range]:focus::-webkit-slider-runnable-track {
--at-apply: outline-2 outline-red; --at-apply: outline-2 outline-red;
} }
input[type=range]::-webkit-slider-thumb { input[type=range]::-webkit-slider-thumb {

View File

@ -12,20 +12,25 @@ function updateTheme(theme: ThemeColors) {
</script> </script>
<template> <template>
<div flex="~ gap4 wrap" p2 role="group" aria-labelledby="interface-tc"> <section space-y-2>
<button <h2 id="interface-tc" font-medium>
v-for="[key, theme] in themes" :key="key" {{ $t('settings.interface.theme_color') }}
:style="{ </h2>
'background': key, <div flex="~ gap4 wrap" p2 role="group" aria-labelledby="interface-tc">
'--local-ring-color': key, <button
}" v-for="[key, theme] in themes" :key="key"
type="button" :style="{
:class="currentTheme === theme['--theme-color-name'] ? 'ring-2' : 'scale-90'" 'background': key,
:aria-pressed="currentTheme === theme['--theme-color-name'] ? 'true' : 'false'" '--local-ring-color': key,
:title="theme['--theme-color-name']" }"
w-8 h-8 rounded-full transition-all type="button"
ring="$local-ring-color offset-3 offset-$c-bg-base" :class="currentTheme === theme['--theme-color-name'] ? 'ring-2' : 'scale-90'"
@click="updateTheme(theme)" :aria-pressed="currentTheme === theme['--theme-color-name'] ? 'true' : 'false'"
/> :title="theme['--theme-color-name']"
</div> w-8 h-8 rounded-full transition-all
ring="$local-ring-color offset-3 offset-$c-bg-base"
@click="updateTheme(theme)"
/>
</div>
</section>
</template> </template>

View File

@ -13,34 +13,11 @@ useHydratedHead({
<span>{{ $t('settings.interface.label') }}</span> <span>{{ $t('settings.interface.label') }}</span>
</div> </div>
</template> </template>
<div p6 flex="~ col gap6"> <div px-6 pt-3 pb-6 flex="~ col gap6">
<div space-y-2> <SettingsFontSize />
<p id="interface-fs" font-medium> <SettingsColorMode />
{{ $t('settings.interface.font_size') }} <SettingsThemeColors />
</p> <SettingsBottomNav />
<SettingsFontSize select-settings />
</div>
<div space-y-2>
<p id="interface-cm" font-medium>
{{ $t('settings.interface.color_mode') }}
</p>
<SettingsColorMode />
</div>
<div space-y-2>
<p id="interface-tc" font-medium>
{{ $t('settings.interface.theme_color') }}
</p>
<SettingsThemeColors />
</div>
<div space-y-2>
<p id="interface-bn" font-medium>
{{ $t('settings.interface.bottom_nav') }}
</p>
<p id="interface-bn-desc">
{{ $t('settings.interface.bottom_nav_instructions') }}
</p>
<SettingsBottomNav />
</div>
</div> </div>
</MainContent> </MainContent>
</template> </template>