mirror of
https://github.com/Bubka/2FAuth.git
synced 2025-08-17 00:51:04 +02:00
Enhance accessibility with correct keyboard navigation and focus style
This commit is contained in:
@ -15,7 +15,7 @@
|
|||||||
<div v-else class="content has-text-centered">
|
<div v-else class="content has-text-centered">
|
||||||
<router-link id="lnkSettings" :to="{ name: 'settings.options' }" class="has-text-grey">{{ $t('settings.settings') }}</router-link>
|
<router-link id="lnkSettings" :to="{ name: 'settings.options' }" class="has-text-grey">{{ $t('settings.settings') }}</router-link>
|
||||||
<span v-if="!this.$root.appConfig.proxyAuth || (this.$root.appConfig.proxyAuth && this.$root.appConfig.proxyLogoutUrl)">
|
<span v-if="!this.$root.appConfig.proxyAuth || (this.$root.appConfig.proxyAuth && this.$root.appConfig.proxyLogoutUrl)">
|
||||||
- <a id="lnkSignOut" class="has-text-grey" @click="logout">{{ $t('auth.sign_out') }}</a>
|
- <button id="lnkSignOut" class="button is-text is-like-text has-text-grey" @click="logout">{{ $t('auth.sign_out') }}</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<input :id="fieldName" type="checkbox" :name="fieldName" class="is-checkradio is-info" v-model="form[fieldName]" v-on:change="$emit(fieldName, form[fieldName])" v-bind="$attrs">
|
<input :id="fieldName" type="checkbox" :name="fieldName" class="is-checkradio is-info" v-model="form[fieldName]" v-on:change="$emit(fieldName, form[fieldName])" v-bind="$attrs">
|
||||||
<label :for="fieldName" class="label" v-html="label"></label>
|
<label tabindex="0" :for="fieldName" class="label" :class="labelClass" v-html="label" v-on:keypress.space.prevent="setCheckbox"></label>
|
||||||
<p class="help" v-html="help" v-if="help"></p>
|
<p class="help" v-html="help" v-if="help"></p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -38,6 +38,15 @@
|
|||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
setCheckbox(event) {
|
||||||
|
if (this.$attrs.disabled == false) {
|
||||||
|
this.form[this.fieldName] = !this.form[this.fieldName]
|
||||||
|
this.$emit(this.fieldName, this.form[this.fieldName])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -13,10 +13,10 @@
|
|||||||
v-on:change="$emit('field-changed', form[fieldName])"
|
v-on:change="$emit('field-changed', form[fieldName])"
|
||||||
v-on:keyup="checkCapsLock"
|
v-on:keyup="checkCapsLock"
|
||||||
/>
|
/>
|
||||||
<span v-if="currentType == 'password'" class="icon is-small is-right is-clickable" @click="currentType = 'text'" :title="$t('auth.forms.reveal_password')">
|
<span v-if="currentType == 'password'" role="button" 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']" />
|
<font-awesome-icon :icon="['fas', 'eye-slash']" />
|
||||||
</span>
|
</span>
|
||||||
<span v-else class="icon is-small is-right is-clickable" @click="currentType = 'password'" :title="$t('auth.forms.hide_password')">
|
<span v-else role="button" tabindex="0" class="icon is-small is-right is-clickable" @keyup.enter="setFieldType('password')" @click="setFieldType('password')" :title="$t('auth.forms.hide_password')">
|
||||||
<font-awesome-icon :icon="['fas', 'eye']" />
|
<font-awesome-icon :icon="['fas', 'eye']" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -121,6 +121,12 @@
|
|||||||
checkCapsLock(event) {
|
checkCapsLock(event) {
|
||||||
this.hasCapsLockOn = event.getModifierState('CapsLock') ? true : false
|
this.hasCapsLockOn = event.getModifierState('CapsLock') ? true : false
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setFieldType(event) {
|
||||||
|
if (this.currentType != event) {
|
||||||
|
this.currentType = event
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -1,11 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="field" :class="{ 'pt-3' : hasOffset }">
|
<div class="field" :class="{ 'pt-3' : hasOffset }" role="radiogroup" :aria-labelledby="inputId('label', fieldName)">
|
||||||
<label class="label" v-html="label"></label>
|
<label :id="inputId('label', fieldName)" class="label" v-html="label"></label>
|
||||||
<div class="is-toggle buttons">
|
<div class="is-toggle buttons">
|
||||||
<label class="button is-dark" :disabled="isDisabled" v-for="(choice, index) in choices" :key="index" :class="{ 'is-link' : form[fieldName] === choice.value }">
|
<button
|
||||||
<input type="radio" class="is-hidden" :checked="form[fieldName] === choice.value" :value="choice.value" v-model="form[fieldName]" v-on:change="$emit(fieldName, form[fieldName])" :disabled="isDisabled" />
|
role="radio"
|
||||||
|
type="button"
|
||||||
|
class="button is-dark"
|
||||||
|
:aria-checked="form[fieldName] === choice.value"
|
||||||
|
:disabled="isDisabled"
|
||||||
|
v-for="(choice, index) in choices"
|
||||||
|
:key="index"
|
||||||
|
:class="{ 'is-link' : form[fieldName] === choice.value }"
|
||||||
|
v-on:click.stop="setRadio(choice.value)"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
:id="inputId(inputType, choice.value)"
|
||||||
|
:type="inputType"
|
||||||
|
class="is-hidden"
|
||||||
|
:checked="form[fieldName] === choice.value"
|
||||||
|
:value="choice.value"
|
||||||
|
v-model="form[fieldName]"
|
||||||
|
:disabled="isDisabled"
|
||||||
|
/>
|
||||||
<font-awesome-icon :icon="['fas', choice.icon]" v-if="choice.icon" class="mr-3" /> {{ choice.text }}
|
<font-awesome-icon :icon="['fas', choice.icon]" v-if="choice.icon" class="mr-3" /> {{ choice.text }}
|
||||||
</label>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<field-error :form="form" :field="fieldName" />
|
<field-error :form="form" :field="fieldName" />
|
||||||
<p class="help" v-html="help" v-if="help"></p>
|
<p class="help" v-html="help" v-if="help"></p>
|
||||||
@ -18,7 +36,7 @@
|
|||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
inputType: 'radio'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -58,6 +76,13 @@
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
setRadio(event) {
|
||||||
|
this.form[this.fieldName] = event
|
||||||
|
this.$emit(this.fieldName, this.form[this.fieldName])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -14,9 +14,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="this.showcloseButton" class="fullscreen-footer">
|
<div v-if="this.showcloseButton" class="fullscreen-footer">
|
||||||
<!-- Close button -->
|
<!-- Close button -->
|
||||||
<label class="button is-dark is-rounded" @click.stop="closeModal">
|
<button class="button is-dark is-rounded" @click.stop="closeModal">
|
||||||
{{ $t('commons.close') }}
|
{{ $t('commons.close') }}
|
||||||
</label>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
</figure>
|
</figure>
|
||||||
<p class="is-size-4 has-text-grey-light has-ellipsis">{{ internal_service }}</p>
|
<p class="is-size-4 has-text-grey-light has-ellipsis">{{ internal_service }}</p>
|
||||||
<p class="is-size-6 has-text-grey has-ellipsis">{{ internal_account }}</p>
|
<p class="is-size-6 has-text-grey has-ellipsis">{{ internal_account }}</p>
|
||||||
<p class="is-size-1 has-text-white is-clickable" :title="$t('commons.copy_to_clipboard')" v-clipboard="() => internal_password.replace(/ /g, '')" v-clipboard:success="clipboardSuccessHandler">{{ displayedOtp }}</p>
|
<p tabindex="0" class="is-size-1 has-text-white is-clickable" :title="$t('commons.copy_to_clipboard')" v-clipboard="() => internal_password.replace(/ /g, '')" v-clipboard:success="clipboardSuccessHandler">{{ displayedOtp }}</p>
|
||||||
<ul class="dots" v-show="isTimeBased(internal_otp_type)">
|
<ul class="dots" v-show="isTimeBased(internal_otp_type)">
|
||||||
<li v-for="n in 10" :key="n"></li>
|
<li v-for="n in 10" :key="n"></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<div class="tabs is-centered is-fullwidth">
|
<div class="tabs is-centered is-fullwidth">
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="tab in tabs" :key="tab.view" :class="{ 'is-active': tab.view === activeTab }">
|
<li v-for="tab in tabs" :key="tab.view" :class="{ 'is-active': tab.view === activeTab }">
|
||||||
<a :id="tab.id" @click="selectTab(tab.view)">{{ tab.name }}</a>
|
<a :id="tab.id" tabindex="0" @click="selectTab(tab.view)">{{ tab.name }}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
6
resources/js/mixins.js
vendored
6
resources/js/mixins.js
vendored
@ -177,6 +177,12 @@ Vue.mixin({
|
|||||||
case 'password':
|
case 'password':
|
||||||
prefix = 'pwd'
|
prefix = 'pwd'
|
||||||
break
|
break
|
||||||
|
case 'radio':
|
||||||
|
prefix = 'rdo'
|
||||||
|
break
|
||||||
|
case 'label':
|
||||||
|
prefix = 'lbl'
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
prefix = 'txt'
|
prefix = 'txt'
|
||||||
break
|
break
|
||||||
|
@ -50,9 +50,9 @@
|
|||||||
{{ $t('commons.environment') }}
|
{{ $t('commons.environment') }}
|
||||||
</h2>
|
</h2>
|
||||||
<div class="box has-background-black-bis is-family-monospace is-size-7">
|
<div class="box has-background-black-bis is-family-monospace is-size-7">
|
||||||
<span class="is-pulled-right is-clickable" v-clipboard="() => this.$refs.listInfos.innerText" v-clipboard:success="clipboardSuccessHandler">
|
<button class="button copy-text is-pulled-right is-small is-text" v-clipboard="() => this.$refs.listInfos.innerText" v-clipboard:success="clipboardSuccessHandler">
|
||||||
<font-awesome-icon :icon="['fas', 'copy']" />
|
<font-awesome-icon :icon="['fas', 'copy']" />
|
||||||
</span>
|
</button>
|
||||||
<ul ref="listInfos">
|
<ul ref="listInfos">
|
||||||
<li v-for="(value, key) in infos" :value="value" :key="key"><b>{{key}}</b>: {{value}}</li>
|
<li v-for="(value, key) in infos" :value="value" :key="key"><b>{{key}}</b>: {{value}}</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -62,9 +62,9 @@
|
|||||||
{{ $t('settings.user_options') }}
|
{{ $t('settings.user_options') }}
|
||||||
</h2>
|
</h2>
|
||||||
<div class="box has-background-black-bis is-family-monospace is-size-7">
|
<div class="box has-background-black-bis is-family-monospace is-size-7">
|
||||||
<span class="is-pulled-right is-clickable" v-clipboard="() => this.$refs.listUserOptions.innerText" v-clipboard:success="clipboardSuccessHandler">
|
<button class="button copy-text is-pulled-right is-small is-text" v-clipboard="() => this.$refs.listUserOptions.innerText" v-clipboard:success="clipboardSuccessHandler">
|
||||||
<font-awesome-icon :icon="['fas', 'copy']" />
|
<font-awesome-icon :icon="['fas', 'copy']" />
|
||||||
</span>
|
</button>
|
||||||
<ul ref="listUserOptions">
|
<ul ref="listUserOptions">
|
||||||
<li v-for="(value, option) in options" :value="value" :key="option"><b>{{option}}</b>: {{value}}</li>
|
<li v-for="(value, option) in options" :value="value" :key="option"><b>{{option}}</b>: {{value}}</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<vue-footer :showButtons="true">
|
<vue-footer :showButtons="true">
|
||||||
<!-- Close Group switch button -->
|
<!-- Close Group switch button -->
|
||||||
<p class="control">
|
<p class="control">
|
||||||
<a class="button is-dark is-rounded" @click="closeGroupSwitch()">{{ $t('commons.close') }}</a>
|
<button class="button is-dark is-rounded" @click="closeGroupSwitch()">{{ $t('commons.close') }}</button>
|
||||||
</p>
|
</p>
|
||||||
</vue-footer>
|
</vue-footer>
|
||||||
</div>
|
</div>
|
||||||
@ -81,7 +81,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
<div class="tfa-cell tfa-content is-size-3 is-size-4-mobile" @click.stop="showAccount(account)">
|
<div tabindex="0" class="tfa-cell tfa-content is-size-3 is-size-4-mobile" @click="showAccount(account)" @keyup.enter="showAccount(account)" role="button">
|
||||||
<div class="tfa-text has-ellipsis">
|
<div class="tfa-text has-ellipsis">
|
||||||
<img :src="'/storage/icons/' + account.icon" v-if="account.icon && $root.appSettings.showAccountsIcons" :alt="$t('twofaccounts.icon_for_account_x_at_service_y', {account: account.account, service: account.service})">
|
<img :src="'/storage/icons/' + account.icon" v-if="account.icon && $root.appSettings.showAccountsIcons" :alt="$t('twofaccounts.icon_for_account_x_at_service_y', {account: account.account, service: account.service})">
|
||||||
{{ displayService(account.service) }}<font-awesome-icon class="has-text-danger is-size-5 ml-2" v-if="$root.appSettings.useEncryption && account.account === $t('errors.indecipherable')" :icon="['fas', 'exclamation-circle']" />
|
{{ displayService(account.service) }}<font-awesome-icon class="has-text-danger is-size-5 ml-2" v-if="$root.appSettings.useEncryption && account.account === $t('errors.indecipherable')" :icon="['fas', 'exclamation-circle']" />
|
||||||
@ -148,7 +148,7 @@
|
|||||||
{{ selectedAccounts.length }} {{ $t('commons.selected') }}
|
{{ selectedAccounts.length }} {{ $t('commons.selected') }}
|
||||||
<button @click="clearSelected" :style="{visibility: selectedAccounts.length > 0 ? 'visible' : 'hidden'}" class="delete" :title="$t('commons.clear_selection')"></button>
|
<button @click="clearSelected" :style="{visibility: selectedAccounts.length > 0 ? 'visible' : 'hidden'}" class="delete" :title="$t('commons.clear_selection')"></button>
|
||||||
</span>
|
</span>
|
||||||
<span @click="selectAll" class="tag is-dark is-clickable has-background-black-ter has-text-grey" :title="$t('commons.select_all')">
|
<span role="button" @click="selectAll" class="tag is-dark is-clickable has-background-black-ter has-text-grey" :title="$t('commons.select_all')">
|
||||||
{{ $t('commons.all') }}
|
{{ $t('commons.all') }}
|
||||||
<font-awesome-icon class="ml-1" :icon="['fas', 'check-square']" />
|
<font-awesome-icon class="ml-1" :icon="['fas', 'check-square']" />
|
||||||
</span>
|
</span>
|
||||||
@ -156,10 +156,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<div class="tags has-addons are-medium">
|
<div class="tags has-addons are-medium">
|
||||||
<span @click="sortAsc" class="tag is-dark is-clickable has-background-black-ter has-text-grey" :title="$t('commons.sort_ascending')">
|
<span role="button" @click="sortAsc" class="tag is-dark is-clickable has-background-black-ter has-text-grey" :title="$t('commons.sort_ascending')">
|
||||||
<font-awesome-icon :icon="['fas', 'sort-alpha-down']" />
|
<font-awesome-icon :icon="['fas', 'sort-alpha-down']" />
|
||||||
</span>
|
</span>
|
||||||
<span @click="sortDesc" class="tag is-dark is-clickable has-background-black-ter has-text-grey" :title="$t('commons.sort_descending')">
|
<span role="button" @click="sortDesc" class="tag is-dark is-clickable has-background-black-ter has-text-grey" :title="$t('commons.sort_descending')">
|
||||||
<font-awesome-icon :icon="['fas', 'sort-alpha-up']" />
|
<font-awesome-icon :icon="['fas', 'sort-alpha-up']" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -167,7 +167,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="field is-grouped is-justify-content-center pt-1">
|
<div class="field is-grouped is-justify-content-center pt-1">
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<div class="tags are-medium has-addons is-clickable" v-if="selectedAccounts.length > 0" @click="showGroupSelector = true">
|
<div role="button" class="tags are-medium has-addons is-clickable" v-if="selectedAccounts.length > 0" @click="showGroupSelector = true">
|
||||||
<span class="tag is-dark">
|
<span class="tag is-dark">
|
||||||
{{ $t('groups.change_group') }}
|
{{ $t('groups.change_group') }}
|
||||||
</span>
|
</span>
|
||||||
@ -177,7 +177,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<div class="tags are-medium has-addons is-clickable" v-if="selectedAccounts.length > 0" @click="destroyAccounts">
|
<div role="button" class="tags are-medium has-addons is-clickable" v-if="selectedAccounts.length > 0" @click="destroyAccounts">
|
||||||
<span class="tag is-dark">
|
<span class="tag is-dark">
|
||||||
{{ $t('commons.delete') }}
|
{{ $t('commons.delete') }}
|
||||||
</span>
|
</span>
|
||||||
@ -193,7 +193,7 @@
|
|||||||
<!-- search -->
|
<!-- search -->
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="control has-icons-right">
|
<div class="control has-icons-right">
|
||||||
<input type="text" :title="$t('commons.search')" class="input is-rounded is-search" v-model="search">
|
<input id="txtSearch" type="search" tabindex="1" :aria-label="$t('commons.search')" :title="$t('commons.search')" class="input is-rounded is-search" v-model="search">
|
||||||
<span class="icon is-small is-right">
|
<span class="icon is-small is-right">
|
||||||
<font-awesome-icon :icon="['fas', 'search']" v-if="!search" />
|
<font-awesome-icon :icon="['fas', 'search']" v-if="!search" />
|
||||||
<a class="delete" v-if="search" @click="search = '' "></a>
|
<a class="delete" v-if="search" @click="search = '' "></a>
|
||||||
@ -201,14 +201,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- group switch toggle -->
|
<!-- group switch toggle -->
|
||||||
<div class="is-clickable has-text-centered">
|
<div class="has-text-centered">
|
||||||
<div class="columns" @click="toggleGroupSwitch">
|
<div class="columns">
|
||||||
<div class="column" v-if="!showGroupSwitch">
|
<div class="column" v-if="!showGroupSwitch">
|
||||||
{{ activeGroupName }} ({{ filteredAccounts.length }})
|
<button :title="$t('groups.show_group_selector')" tabindex="1" class="button is-text is-like-text" @click.stop="toggleGroupSwitch">
|
||||||
<font-awesome-icon :icon="['fas', 'caret-down']" />
|
{{ activeGroupName }} ({{ filteredAccounts.length }})
|
||||||
|
<font-awesome-icon :icon="['fas', 'caret-down']" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="column" v-else>
|
<div class="column" v-else>
|
||||||
{{ $t('groups.select_accounts_to_show') }}
|
<button :title="$t('groups.hide_group_selector')" tabindex="1" class="button is-text is-like-text" @click.stop="toggleGroupSwitch">
|
||||||
|
{{ $t('groups.select_accounts_to_show') }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="nav-links">
|
<div class="nav-links">
|
||||||
<p>{{ $t('auth.webauthn.lost_your_device') }} <router-link id="lnkRecoverAccount" :to="{ name: 'webauthn.lost' }" class="is-link">{{ $t('auth.webauthn.recover_your_account') }}</router-link></p>
|
<p>{{ $t('auth.webauthn.lost_your_device') }} <router-link id="lnkRecoverAccount" :to="{ name: 'webauthn.lost' }" class="is-link">{{ $t('auth.webauthn.recover_your_account') }}</router-link></p>
|
||||||
<p v-if="!this.$root.appSettings.useWebauthnOnly">{{ $t('auth.sign_in_using') }} <a id="lnkSignWithLegacy" class="is-link" @click="showWebauthn = false">{{ $t('auth.login_and_password') }}</a></p>
|
<p v-if="!this.$root.appSettings.useWebauthnOnly">{{ $t('auth.sign_in_using') }}
|
||||||
|
<a id="lnkSignWithLegacy" role="button" class="is-link" @keyup.enter="showWebauthn = false" @click="showWebauthn = false" tabindex="0">{{ $t('auth.login_and_password') }}</a>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</form-wrapper>
|
</form-wrapper>
|
||||||
<!-- login/password legacy form -->
|
<!-- login/password legacy form -->
|
||||||
@ -28,7 +30,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<p>{{ $t('auth.forms.forgot_your_password') }} <router-link id="lnkResetPwd" :to="{ name: 'password.request' }" class="is-link">{{ $t('auth.forms.request_password_reset') }}</router-link></p>
|
<p>{{ $t('auth.forms.forgot_your_password') }} <router-link id="lnkResetPwd" :to="{ name: 'password.request' }" class="is-link">{{ $t('auth.forms.request_password_reset') }}</router-link></p>
|
||||||
<p >{{ $t('auth.sign_in_using') }} <a id="lnkSignWithWebauthn" class="is-link" @click="showWebauthn = true">{{ $t('auth.webauthn.security_device') }}</a></p>
|
<p >{{ $t('auth.sign_in_using') }}
|
||||||
|
<a id="lnkSignWithWebauthn" role="button" class="is-link" @keyup.enter="showWebauthn = true" @click="showWebauthn = true" tabindex="0">{{ $t('auth.webauthn.security_device') }}</a>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form-wrapper>
|
</form-wrapper>
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
<vue-footer :showButtons="true">
|
<vue-footer :showButtons="true">
|
||||||
<!-- Cancel button -->
|
<!-- Cancel button -->
|
||||||
<p class="control">
|
<p class="control">
|
||||||
<a class="button is-dark is-rounded" @click.stop="exitSettings">
|
<a role="button" tabindex="0" class="button is-dark is-rounded" @click.stop="exitSettings">
|
||||||
{{ $t('commons.close') }}
|
{{ $t('commons.close') }}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
{{ $t('settings.token_legend')}}
|
{{ $t('settings.token_legend')}}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<a class="is-link" @click="createToken()">
|
<a role="button" tabindex="0" class="is-link" @click="createToken()">
|
||||||
<font-awesome-icon :icon="['fas', 'plus-circle']" /> {{ $t('settings.generate_new_token')}}
|
<font-awesome-icon :icon="['fas', 'plus-circle']" /> {{ $t('settings.generate_new_token')}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
{{ $t('auth.webauthn.security_devices_legend')}}
|
{{ $t('auth.webauthn.security_devices_legend')}}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<a class="is-link" @click="register()">
|
<a role="button" tabindex="0" @click="register()">
|
||||||
<font-awesome-icon :icon="['fas', 'plus-circle']" /> {{ $t('auth.webauthn.register_a_new_device')}}
|
<font-awesome-icon :icon="['fas', 'plus-circle']" /> {{ $t('auth.webauthn.register_a_new_device')}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<!-- credentials list -->
|
<!-- credentials list -->
|
||||||
|
@ -22,7 +22,7 @@ return [
|
|||||||
'Unable_to_decrypt_uri' => 'Unable to decrypt uri',
|
'Unable_to_decrypt_uri' => 'Unable to decrypt uri',
|
||||||
'not_a_supported_otp_type' => 'This OTP format is not currently supported',
|
'not_a_supported_otp_type' => 'This OTP format is not currently supported',
|
||||||
'cannot_create_otp_without_secret' => 'Cannot create an OTP without a secret',
|
'cannot_create_otp_without_secret' => 'Cannot create an OTP without a secret',
|
||||||
'data_of_qrcode_is_not_valid_URI' => 'The data of this QR code is not a valid OTP Auth URI:',
|
'data_of_qrcode_is_not_valid_URI' => 'The data of this QR code is not a valid OTP Auth URI. The QR code contains:',
|
||||||
'wrong_current_password' => 'Wrong current password, nothing has changed',
|
'wrong_current_password' => 'Wrong current password, nothing has changed',
|
||||||
'error_during_encryption' => 'Encryption failed, your database remains unprotected.',
|
'error_during_encryption' => 'Encryption failed, your database remains unprotected.',
|
||||||
'error_during_decryption' => 'Decryption failed, your database is still protected. This is mainly caused by an integrity issue of encrypted data for one or more accounts.',
|
'error_during_decryption' => 'Decryption failed, your database is still protected. This is mainly caused by an integrity issue of encrypted data for one or more accounts.',
|
||||||
|
@ -15,7 +15,9 @@ return [
|
|||||||
|
|
||||||
'groups' => 'Groups',
|
'groups' => 'Groups',
|
||||||
'create_group' => 'Create new group',
|
'create_group' => 'Create new group',
|
||||||
'select_accounts_to_show' => 'Select accounts to show',
|
'show_group_selector' => 'Show group selector',
|
||||||
|
'hide_group_selector' => 'Hide group selector',
|
||||||
|
'select_accounts_to_show' => 'Select accounts group to show',
|
||||||
'manage_groups' => 'Manage groups',
|
'manage_groups' => 'Manage groups',
|
||||||
'active_group' => 'Active group',
|
'active_group' => 'Active group',
|
||||||
'manage_groups_legend' => 'You can create groups to organize your accounts the way you want. All accounts remain visible in the pseudo group named \'All\', regardless of the group they belong to.',
|
'manage_groups_legend' => 'You can create groups to organize your accounts the way you want. All accounts remain visible in the pseudo group named \'All\', regardless of the group they belong to.',
|
||||||
|
65
resources/sass/app.scss
vendored
65
resources/sass/app.scss
vendored
@ -205,9 +205,13 @@ a:hover {
|
|||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
.tfa-content:focus, .tfa-content:focus-visible
|
||||||
// .tfa-grid .tfa-content {
|
{
|
||||||
// }
|
outline: 2px solid $grey;
|
||||||
|
border: none;
|
||||||
|
outline-offset: 7px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
.tfa-list .tfa-content {
|
.tfa-list .tfa-content {
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
@ -524,43 +528,24 @@ a.has-text-white-bis:focus, a.has-text-white-bis:focus-visible {
|
|||||||
box-shadow: $input-focus-box-shadow-size $input-focus-box-shadow-color;
|
box-shadow: $input-focus-box-shadow-size $input-focus-box-shadow-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
// .button.is-dark:focus:not(:active), .button.is-dark.is-focused:not(:active),
|
.is-checkradio[type="checkbox"] + label:focus,
|
||||||
// .button.is-link:focus:not(:active), .button.is-link.is-focused:not(:active) {
|
.is-checkradio[type="checkbox"] + label:focus-visible
|
||||||
// box-shadow: 0 0 0 0.125em hsla(0, 0%, 96%, 0.25);
|
{
|
||||||
// }
|
outline: none;
|
||||||
// .button.copy-text:focus:not(:active), .button.copy-text.is-focused:not(:active) {
|
border: none;
|
||||||
// box-shadow: none;
|
}
|
||||||
// color: hsl(0, 0%, 86%);
|
.is-checkradio[type="checkbox"] + label:focus::before,
|
||||||
// }
|
.is-checkradio[type="checkbox"] + label:focus-visible::before
|
||||||
|
{
|
||||||
// a:focus,
|
outline: none;
|
||||||
// .button:focus,
|
border: 1px solid $input-focus-border-color;
|
||||||
// .control.has-icons-right > span.icon:focus {
|
box-shadow: $input-focus-box-shadow-size $input-focus-box-shadow-color;
|
||||||
// outline: none !important;
|
}
|
||||||
// }
|
.is-checkradio[type="checkbox"] + label::before,
|
||||||
// .button:focus {
|
.is-checkradio[type="checkbox"] + label::before
|
||||||
// box-shadow: none;
|
{
|
||||||
// }
|
border-color: $grey;
|
||||||
// a:focus-visible,
|
}
|
||||||
// .control.has-icons-right > span.icon:focus {
|
|
||||||
// outline: 2px solid hsl(217, 71%, 53%) !important;
|
|
||||||
// outline-offset: 3px !important;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .button:focus-visible {
|
|
||||||
// box-shadow: none;
|
|
||||||
// outline: 2px solid hsl(217, 71%, 53%) !important;
|
|
||||||
// outline-offset: 3px !important;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @supports not selector(:focus-visible) {
|
|
||||||
// a:focus,
|
|
||||||
// button:focus,
|
|
||||||
// .control.has-icons-right > span.icon:focus {
|
|
||||||
// outline: 2px solid hsl(217, 71%, 53%);
|
|
||||||
// outline-offset: 3px;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
|
Reference in New Issue
Block a user