mirror of
https://github.com/Bubka/2FAuth.git
synced 2025-08-09 05:54:34 +02:00
Fix & Enhance accessibility
This commit is contained in:
@ -1,4 +1,6 @@
|
||||
<script setup>
|
||||
import { useValidationErrorIdGenerator } from '@/composables/helpers'
|
||||
|
||||
const props = defineProps({
|
||||
error: {
|
||||
type: String,
|
||||
@ -13,11 +15,13 @@
|
||||
default: 'is-danger'
|
||||
}
|
||||
})
|
||||
|
||||
const { valErrorId } = useValidationErrorIdGenerator(props.field)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div role="alert">
|
||||
<p :id="'valError' + field[0].toUpperCase() + field.toLowerCase().slice(1)"
|
||||
<p :id="valErrorId"
|
||||
class="help"
|
||||
:class="alertType"
|
||||
v-html="error" />
|
||||
|
@ -1,4 +1,6 @@
|
||||
<script setup>
|
||||
import { useIdGenerator } from '@/composables/helpers'
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false
|
||||
})
|
||||
@ -27,6 +29,7 @@
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const legendId = useIdGenerator('legend', props.fieldName).inputId
|
||||
const attrs = useAttrs()
|
||||
const model = computed({
|
||||
get() {
|
||||
@ -50,9 +53,9 @@
|
||||
<FontAwesomeIcon class="has-text-grey" :icon="['fas', 'chevron-right']" transform="rotate-135"/>
|
||||
</div>
|
||||
<div>
|
||||
<input :id="fieldName" type="checkbox" :name="fieldName" class="is-checkradio is-info" v-model="model" :disabled="isDisabled" />
|
||||
<input :id="fieldName" type="checkbox" :name="fieldName" class="is-checkradio is-info" v-model="model" :disabled="isDisabled" :aria-describedby="help ? legendId : undefined" />
|
||||
<label tabindex="0" :for="fieldName" class="label" :class="labelClass" v-html="$t(label)" v-on:keypress.space.prevent="toggleModel" />
|
||||
<p class="help" v-html="$t(help)" v-if="help" />
|
||||
<p :id="legendId" class="help" v-html="$t(help)" v-if="help" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { useIdGenerator } from '@/composables/helpers'
|
||||
import { useIdGenerator, useValidationErrorIdGenerator } from '@/composables/helpers'
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false
|
||||
@ -44,9 +44,15 @@
|
||||
isIndented: Boolean,
|
||||
leftIcon: '',
|
||||
rightIcon: '',
|
||||
idSuffix: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
})
|
||||
|
||||
const { inputId } = useIdGenerator(props.inputType, props.fieldName)
|
||||
const { inputId } = useIdGenerator(props.inputType, props.fieldName + props.idSuffix)
|
||||
const { valErrorId } = useValidationErrorIdGenerator(props.fieldName)
|
||||
const legendId = useIdGenerator('legend', props.fieldName).inputId
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -68,6 +74,9 @@
|
||||
v-on:input="$emit('update:modelValue', $event.target.value)"
|
||||
v-on:change="$emit('change:modelValue', $event.target.value)"
|
||||
:maxlength="maxLength"
|
||||
:aria-describedby="help ? legendId : undefined"
|
||||
:aria-invalid="fieldError != undefined"
|
||||
:aria-errormessage="fieldError != undefined ? valErrorId : undefined"
|
||||
/>
|
||||
<span v-if="leftIcon" class="icon is-small is-left">
|
||||
<FontAwesomeIcon :icon="['fas', leftIcon]" transform="rotate-75" size="xs" />
|
||||
@ -77,7 +86,7 @@
|
||||
</span>
|
||||
</div>
|
||||
<FieldError v-if="fieldError != undefined" :error="fieldError" :field="fieldName" />
|
||||
<p class="help" v-html="$t(help)" v-if="help"></p>
|
||||
<p :id="legendId" class="help" v-html="$t(help)" v-if="help"></p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { useIdGenerator } from '@/composables/helpers'
|
||||
import { useIdGenerator, useValidationErrorIdGenerator } from '@/composables/helpers'
|
||||
import { UseColorMode } from '@vueuse/components'
|
||||
|
||||
defineOptions({
|
||||
@ -50,10 +50,16 @@
|
||||
maxLength: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
idSuffix: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const { inputId } = useIdGenerator(props.inputType, props.fieldName)
|
||||
const { inputId } = useIdGenerator(props.inputType, props.fieldName + props.idSuffix)
|
||||
const { valErrorId } = useValidationErrorIdGenerator(props.fieldName)
|
||||
const legendId = useIdGenerator('legend', props.fieldName).inputId
|
||||
|
||||
const fieldIsLocked = ref(props.isDisabled || props.isEditMode)
|
||||
const hasBeenTrimmed = ref(false)
|
||||
@ -106,6 +112,9 @@
|
||||
v-on:change="emitValue"
|
||||
v-on:blur="forceRefresh"
|
||||
:maxlength="maxLength"
|
||||
:aria-describedby="help ? legendId : undefined"
|
||||
:aria-invalid="fieldError != undefined"
|
||||
:aria-errormessage="fieldError != undefined ? valErrorId : undefined"
|
||||
/>
|
||||
</div>
|
||||
<UseColorMode v-slot="{ mode }" v-if="isEditMode">
|
||||
@ -127,5 +136,5 @@
|
||||
</div>
|
||||
<FieldError v-if="hasBeenTrimmed" :error="$t('twofaccounts.forms.spaces_are_ignored')" :field="'spaces'" :alertType="'is-warning'" />
|
||||
<FieldError v-if="fieldError != undefined" :error="fieldError" :field="fieldName" />
|
||||
<p class="help" v-html="$t(help)" v-if="help"></p>
|
||||
<p :id="legendId" class="help" v-html="$t(help)" v-if="help"></p>
|
||||
</template>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { useIdGenerator } from '@/composables/helpers'
|
||||
import { useIdGenerator, useValidationErrorIdGenerator } from '@/composables/helpers'
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: true
|
||||
@ -41,9 +41,15 @@
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
idSuffix: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
})
|
||||
|
||||
const { inputId } = useIdGenerator(props.inputType, props.fieldName)
|
||||
const { inputId } = useIdGenerator(props.inputType, props.fieldName + props.idSuffix)
|
||||
const { valErrorId } = useValidationErrorIdGenerator(props.fieldName)
|
||||
const legendId = useIdGenerator('legend', props.fieldName).inputId
|
||||
const currentType = ref(props.inputType)
|
||||
const hasCapsLockOn = ref(false)
|
||||
|
||||
@ -90,6 +96,9 @@
|
||||
v-bind="$attrs"
|
||||
v-on:input="$emit('update:modelValue', $event.target.value)"
|
||||
v-on:keyup="checkCapsLock"
|
||||
:aria-describedby="help ? legendId : undefined"
|
||||
:aria-invalid="fieldError != undefined"
|
||||
:aria-errormessage="fieldError != undefined ? valErrorId : undefined"
|
||||
/>
|
||||
<span v-if="currentType == 'password'" role="button" id="btnTogglePassword" tabindex="0" class="icon is-small is-right is-clickable" @keyup.enter="setFieldType('text')" @click="setFieldType('text')" :title="$t('auth.forms.reveal_password')">
|
||||
<font-awesome-icon :icon="['fas', 'eye-slash']" />
|
||||
@ -101,7 +110,7 @@
|
||||
<p class="help is-warning" v-if="hasCapsLockOn" v-html="$t('auth.forms.caps_lock_is_on')" />
|
||||
<FieldError v-if="fieldError != undefined" :error="fieldError" :field="fieldName" />
|
||||
<p class="help" v-html="$t(help)" v-if="help" />
|
||||
<div v-if="showRules" class="columns is-mobile is-size-7 mt-0">
|
||||
<div v-if="showRules" :id="legendId" class="columns is-mobile is-size-7 mt-0">
|
||||
<div class="column is-one-third">
|
||||
<span class="has-text-weight-semibold">{{ $t("auth.forms.mandatory_rules") }}</span><br />
|
||||
<span class="is-underscored" id="valPwdIsLongEnough" :class="{'is-dot' : IsLongEnough}"></span>{{ $t('auth.forms.is_long_enough') }}<br/>
|
||||
|
@ -1,4 +1,6 @@
|
||||
<script setup>
|
||||
import { useIdGenerator, useValidationErrorIdGenerator } from '@/composables/helpers'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: [String, Number, Boolean],
|
||||
label: {
|
||||
@ -21,9 +23,16 @@
|
||||
},
|
||||
isIndented: Boolean,
|
||||
isDisabled: Boolean,
|
||||
idSuffix: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
})
|
||||
|
||||
const selected = ref(props.modelValue)
|
||||
const { inputId } = useIdGenerator('select', props.fieldName + props.idSuffix)
|
||||
const { valErrorId } = useValidationErrorIdGenerator(props.fieldName)
|
||||
const legendId = useIdGenerator('legend', props.fieldName + props.idSuffix).inputId
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -32,16 +41,24 @@
|
||||
<FontAwesomeIcon class="has-text-grey" :icon="['fas', 'chevron-right']" transform="rotate-135"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label" v-html="$t(label)" :style="{ 'opacity': isDisabled ? '0.5' : '1' }"></label>
|
||||
<label :for="inputId" class="label" v-html="$t(label)" :style="{ 'opacity': isDisabled ? '0.5' : '1' }"></label>
|
||||
<div class="control">
|
||||
<div class="select">
|
||||
<select v-model="selected" v-on:change="$emit('update:modelValue', $event.target.value)" :disabled="isDisabled">
|
||||
<select
|
||||
:id="inputId"
|
||||
v-model="selected"
|
||||
v-on:change="$emit('update:modelValue', $event.target.value)"
|
||||
:disabled="isDisabled"
|
||||
:aria-describedby="help ? legendId : undefined"
|
||||
:aria-invalid="fieldError != undefined"
|
||||
:aria-errormessage="fieldError != undefined ? valErrorId : undefined"
|
||||
>
|
||||
<option v-for="option in options" :value="option.value">{{ $t(option.text) }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<FieldError v-if="fieldError != undefined" :error="fieldError" :field="fieldName" />
|
||||
<p class="help" v-html="$t(help)" v-if="help"></p>
|
||||
<p :id="legendId" class="help" v-html="$t(help)" v-if="help"></p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { useIdGenerator } from '@/composables/helpers'
|
||||
import { useIdGenerator, useValidationErrorIdGenerator } from '@/composables/helpers'
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false
|
||||
@ -42,9 +42,17 @@
|
||||
default: null
|
||||
},
|
||||
isIndented: Boolean,
|
||||
leftIcon: '',
|
||||
rightIcon: '',
|
||||
idSuffix: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const { inputId } = useIdGenerator(props.inputType, props.fieldName)
|
||||
const { inputId } = useIdGenerator(props.inputType, props.fieldName + props.idSuffix)
|
||||
const { valErrorId } = useValidationErrorIdGenerator(props.fieldName)
|
||||
const legendId = useIdGenerator('legend', props.fieldName).inputId
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -53,7 +61,7 @@
|
||||
<FontAwesomeIcon class="has-text-grey" :icon="['fas', 'chevron-right']" transform="rotate-135"/>
|
||||
</div>
|
||||
<div class="field" :class="{ 'is-flex-grow-5' : isIndented }">
|
||||
<label :for="inputId" class="label" v-html="$t(label)"></label>
|
||||
<label v-if="label" :for="inputId" class="label" v-html="$t(label)"></label>
|
||||
<div class="control" :class="{ 'has-icons-left' : leftIcon, 'has-icons-right': rightIcon }">
|
||||
<textarea
|
||||
:disabled="isDisabled"
|
||||
@ -66,10 +74,13 @@
|
||||
v-on:input="$emit('update:modelValue', $event.target.value)"
|
||||
v-on:change="$emit('change:modelValue', $event.target.value)"
|
||||
:maxlength="maxLength"
|
||||
:aria-describedby="help ? legendId : undefined"
|
||||
:aria-invalid="fieldError != undefined"
|
||||
:aria-errormessage="fieldError != undefined ? valErrorId : undefined"
|
||||
/>
|
||||
</div>
|
||||
<FieldError v-if="fieldError != undefined" :error="fieldError" :field="fieldName" />
|
||||
<p class="help" v-html="$t(help)" v-if="help"></p>
|
||||
<p :id="legendId" class="help" v-html="$t(help)" v-if="help"></p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { useIdGenerator } from '@/composables/helpers'
|
||||
import { useIdGenerator, useValidationErrorIdGenerator } from '@/composables/helpers'
|
||||
import { UseColorMode } from '@vueuse/components'
|
||||
|
||||
const props = defineProps({
|
||||
@ -27,6 +27,8 @@
|
||||
|
||||
// defines what events our component emits
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { valErrorId } = useValidationErrorIdGenerator(props.fieldName)
|
||||
const legendId = useIdGenerator('legend', props.fieldName).inputId
|
||||
|
||||
function setRadio(event) {
|
||||
emit('update:modelValue', event)
|
||||
@ -35,10 +37,16 @@
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="field" :class="{ 'pt-3': hasOffset }" role="radiogroup"
|
||||
:aria-labelledby="useIdGenerator('label',fieldName).inputId">
|
||||
<label v-if="label" :id="useIdGenerator('label',fieldName).inputId" class="label" v-html="$t(label)" />
|
||||
<div class="is-toggle buttons">
|
||||
<div class="field" :class="{ 'pt-3': hasOffset }">
|
||||
<span v-if="label" class="label" v-html="$t(label)" />
|
||||
<div
|
||||
id="rdoGroup"
|
||||
role="radiogroup"
|
||||
:aria-describedby="help ? legendId : undefined"
|
||||
:aria-invalid="fieldError != undefined"
|
||||
:aria-errormessage="fieldError != undefined ? valErrorId : undefined"
|
||||
class="is-toggle buttons"
|
||||
>
|
||||
<UseColorMode v-slot="{ mode }">
|
||||
<button
|
||||
v-for="choice in choices"
|
||||
@ -54,21 +62,24 @@
|
||||
'is-dark': mode==='dark',
|
||||
'is-multiline': choice.legend,
|
||||
}"
|
||||
v-on:click.stop="setRadio(choice.value)"
|
||||
:title="choice.title? choice.title:''">
|
||||
v-on:click.stop="setRadio(choice.value)">
|
||||
<input
|
||||
:id="useIdGenerator('radio',choice.value).inputId"
|
||||
type="radio"
|
||||
class="is-hidden"
|
||||
:checked="modelValue===choice.value"
|
||||
:value="choice.value"
|
||||
:disabled="isDisabled" />
|
||||
:disabled="isDisabled"
|
||||
/>
|
||||
<span v-if="choice.legend" v-html="$t(choice.legend)" class="is-block is-size-7" />
|
||||
<FontAwesomeIcon :icon="['fas',choice.icon]" v-if="choice.icon" class="mr-2" /> {{ $t(choice.text) }}
|
||||
<FontAwesomeIcon :icon="['fas',choice.icon]" v-if="choice.icon" class="mr-2" />
|
||||
<label :for="useIdGenerator('button',fieldName+choice.value).inputId" class="is-clickable">
|
||||
{{ $t(choice.text) }}
|
||||
</label>
|
||||
</button>
|
||||
</UseColorMode>
|
||||
</div>
|
||||
<FieldError v-if="fieldError != undefined" :error="fieldError" :field="fieldName" />
|
||||
<p class="help" v-html="$t(help)" v-if="help" />
|
||||
<p :id="legendId" class="help" v-html="$t(help)" v-if="help" />
|
||||
</div>
|
||||
</template>
|
Reference in New Issue
Block a user