enh(NcContent): Add skip content buttons

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
This commit is contained in:
Ferdinand Thiessen 2023-12-21 12:43:35 +01:00
Родитель 1ad3480fac
Коммит f482cf2ece
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 45FAE7268762B400
5 изменённых файлов: 104 добавлений и 3 удалений

Просмотреть файл

@ -313,6 +313,12 @@ msgstr ""
msgid "Show password"
msgstr ""
msgid "Skip to app navigation"
msgstr ""
msgid "Skip to main content"
msgstr ""
msgid "Smart Picker"
msgstr ""

12
package-lock.json сгенерированный
Просмотреть файл

@ -10,6 +10,7 @@
"license": "AGPL-3.0",
"dependencies": {
"@floating-ui/dom": "^1.1.0",
"@linusborg/vue-simple-portal": "^0.1.5",
"@nextcloud/auth": "^2.0.0",
"@nextcloud/axios": "^2.0.0",
"@nextcloud/browser-storage": "^0.3.0",
@ -3472,6 +3473,17 @@
"dev": true,
"peer": true
},
"node_modules/@linusborg/vue-simple-portal": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/@linusborg/vue-simple-portal/-/vue-simple-portal-0.1.5.tgz",
"integrity": "sha512-dq+oubEVW4UabBoQxmH97GiDa+F6sTomw4KcXFHnXEpw69rdkXFCxo1WzwuvWjoLiUVYJTyN1dtlUvTa50VcXg==",
"dependencies": {
"nanoid": "^3.1.20"
},
"peerDependencies": {
"vue": "^2.6.6"
}
},
"node_modules/@mapbox/hast-util-table-cell-style": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@mapbox/hast-util-table-cell-style/-/hast-util-table-cell-style-0.2.0.tgz",

Просмотреть файл

@ -65,6 +65,7 @@
],
"dependencies": {
"@floating-ui/dom": "^1.1.0",
"@linusborg/vue-simple-portal": "^0.1.5",
"@nextcloud/auth": "^2.0.0",
"@nextcloud/axios": "^2.0.0",
"@nextcloud/browser-storage": "^0.3.0",

Просмотреть файл

@ -78,14 +78,14 @@ emit('toggle-navigation', {
</template>
<script>
import NcAppNavigationToggle from '../NcAppNavigationToggle/index.js'
import { useIsMobile } from '../../composables/useIsMobile/index.js'
import { getTrapStack } from '../../utils/focusTrap.js'
import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus'
import { createFocusTrap } from 'focus-trap'
import NcAppNavigationToggle from '../NcAppNavigationToggle/index.js'
import Vue from 'vue'
export default {
name: 'NcAppNavigation',
@ -93,6 +93,14 @@ export default {
NcAppNavigationToggle,
},
// Injected from NcContent
inject: {
setHasAppNavigation: {
default: () => () => Vue.util.warn('NcAppNavigation is not mounted inside NcContent, this is probably an error.'),
from: 'NcContent:setHasAppNavigation',
},
},
props: {
/**
* The aria label to describe the navigation
@ -135,6 +143,7 @@ export default {
},
mounted() {
this.setHasAppNavigation(true)
subscribe('toggle-navigation', this.toggleNavigationByEventBus)
// Emit an event with the initial state of the navigation
emit('navigation-toggled', {
@ -150,6 +159,7 @@ export default {
this.toggleFocusTrap()
},
unmounted() {
this.setHasAppNavigation(false)
unsubscribe('toggle-navigation', this.toggleNavigationByEventBus)
this.focusTrap.deactivate()
},
@ -161,6 +171,14 @@ export default {
* @param {boolean} [state] set the state instead of inverting the current one
*/
toggleNavigation(state) {
// Early return if alreay in that state
if (this.open === state) {
emit('navigation-toggled', {
open: this.open,
})
return
}
this.open = (typeof state === 'undefined') ? !this.open : state
const bodyStyles = getComputedStyle(document.body)
const animationLength = parseInt(bodyStyles.getPropertyValue('--animation-quick')) || 100

Просмотреть файл

@ -28,6 +28,8 @@ This component provides the default container of all apps.
It _MUST_ be used as the main wrapper of your app.
It includes the Navigation, the App content and the Sidebar.
It also will set the skip content buttons needed for accessibility.
### Standard usage
```vue
@ -72,22 +74,84 @@ It includes the Navigation, the App content and the Sidebar.
<div id="content-vue"
:class="`app-${appName.toLowerCase()}`"
class="content">
<!-- TODO: with vue3 the `selector` attribute needs to be changed to `to="#skip-actions"` -->
<Teleport selector="#skip-actions">
<div class="skip-actions">
<NcButton type="primary" href="#app-content-vue">
{{ t('Skip to main content') }}
</NcButton>
<NcButton v-show="hasAppNavigation"
type="primary"
href="#app-navigation-vue"
@click.prevent="openAppNavigation">
{{ t('Skip to app navigation') }}
</NcButton>
</div>
</Teleport>
<slot />
</div>
</template>
<script>
import { emit } from '@nextcloud/event-bus'
import { t } from '../../l10n.js'
import NcButton from '../NcButton/NcButton.vue'
// TODO: This is built-in for vue3 just drop the import
import { Portal as Teleport } from '@linusborg/vue-simple-portal'
export default {
name: 'NcContent',
components: {
NcButton,
Teleport,
},
provide() {
return {
'NcContent:setHasAppNavigation': this.setAppNavigation,
}
},
props: {
appName: {
type: String,
required: true,
},
},
data() {
return {
hasAppNavigation: false,
}
},
beforeMount() {
const container = document.getElementById('skip-actions')
if (container) {
// clear default buttons
container.innerHTML = ''
}
},
methods: {
t,
openAppNavigation() {
emit('toggle-navigation', { open: true })
this.$nextTick(() => {
window.location.hash = 'app-navigation-vue'
// we need to manually focus if the window location is already set to the app-navigation then it will not focus again
document.getElementById('app-navigation-vue').focus()
})
},
setAppNavigation(value) {
this.hasAppNavigation = value
},
},
}
</script>
<style lang="scss" scoped>
.skip-actions {
display: flex;
gap: 12px;
}
.content {
box-sizing: border-box;
margin: var(--body-container-margin);