Fixed #2895 - Improve Accordion implementation for Accessibility
parent
67320fb0d8
commit
3bdaf4a2b9
|
@ -28,6 +28,18 @@ const AccordionProps = [
|
|||
type: "string",
|
||||
default: "pi-chevron-down",
|
||||
description: "Icon of a expanded tab."
|
||||
},
|
||||
{
|
||||
name: "tabindex",
|
||||
type: "number",
|
||||
default: "0",
|
||||
description: "Index of the element in tabbing order."
|
||||
},
|
||||
{
|
||||
name: "selectOnFocus",
|
||||
type: "boolean",
|
||||
default: "false",
|
||||
description: "When enabled, the focused tab is activated."
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -63,6 +75,22 @@ const AccordionEvents = [
|
|||
description: "Closed tab index"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "tab-click",
|
||||
description: "Callback to invoke when an active tab is clicked.",
|
||||
arguments: [
|
||||
{
|
||||
name: "originalEvent",
|
||||
type: "object",
|
||||
description: "Original event"
|
||||
},
|
||||
{
|
||||
name: "index",
|
||||
type: "number",
|
||||
description: "Index of the clicked tab"
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
@ -5,6 +5,48 @@ const AccordionTabProps = [
|
|||
default: "null",
|
||||
description: "Orientation of tab headers."
|
||||
},
|
||||
{
|
||||
name: "headerStyle",
|
||||
type: "any",
|
||||
default: "null",
|
||||
description: "Inline style of the tab header."
|
||||
},
|
||||
{
|
||||
name: "headerClass",
|
||||
type: "any",
|
||||
default: "null",
|
||||
description: "Style class of the tab header."
|
||||
},
|
||||
{
|
||||
name: "headerProps",
|
||||
type: "any",
|
||||
default: "null",
|
||||
description: "Uses to pass all properties of the HTMLDivElement to the tab header."
|
||||
},
|
||||
{
|
||||
name: "headerActionProps",
|
||||
type: "any",
|
||||
default: "null",
|
||||
description: "Uses to pass all properties of the HTMLAnchorElement to the focusable anchor element inside the tab header."
|
||||
},
|
||||
{
|
||||
name: "contentStyle",
|
||||
type: "any",
|
||||
default: "null",
|
||||
description: "Inline style of the tab content."
|
||||
},
|
||||
{
|
||||
name: "contentClass",
|
||||
type: "any",
|
||||
default: "null",
|
||||
description: "Style class of the tab content."
|
||||
},
|
||||
{
|
||||
name: "contentProps",
|
||||
type: "any",
|
||||
default: "null",
|
||||
description: "Uses to pass all properties of the HTMLDivElement to the tab content."
|
||||
},
|
||||
{
|
||||
name: "disabled",
|
||||
type: "boolean",
|
||||
|
|
|
@ -18,6 +18,11 @@ export interface AccordionTabOpenEvent {
|
|||
*/
|
||||
export interface AccordionTabCloseEvent extends AccordionTabOpenEvent { }
|
||||
|
||||
/**
|
||||
* @extends AccordionTabOpenEvent
|
||||
*/
|
||||
export interface AccordionClickEvent extends AccordionTabOpenEvent { }
|
||||
|
||||
export interface AccordionProps {
|
||||
/**
|
||||
* When enabled, multiple tabs can be activated at the same time.
|
||||
|
@ -39,6 +44,14 @@ export interface AccordionProps {
|
|||
* Icon of an expanded tab.
|
||||
*/
|
||||
collapseIcon?: string | undefined;
|
||||
/**
|
||||
* Index of the element in tabbing order.
|
||||
*/
|
||||
tabindex?: number | undefined;
|
||||
/**
|
||||
* When enabled, the focused tab is activated.
|
||||
*/
|
||||
selectOnFocus?: boolean | undefined;
|
||||
}
|
||||
|
||||
export interface AccordionSlots {
|
||||
|
@ -64,6 +77,11 @@ export declare type AccordionEmits = {
|
|||
* @param {AccordionTabCloseEvent} event - Custom tab close event.
|
||||
*/
|
||||
'tab-close': (event: AccordionTabCloseEvent) => void;
|
||||
/**
|
||||
* Callback to invoke when an active tab is clicked.
|
||||
* @param {AccordionClickEvent} event - Custom tab click event.
|
||||
*/
|
||||
'tab-click': (event: AccordionClickEvent) => void;
|
||||
}
|
||||
|
||||
declare class Accordion extends ClassComponent<AccordionProps, AccordionSlots, AccordionEmits> { }
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
<template>
|
||||
<div class="p-accordion p-component">
|
||||
<div v-for="(tab,i) of tabs" :key="getKey(tab,i)" :class="getTabClass(i)">
|
||||
<div :class="getTabHeaderClass(tab, i)">
|
||||
<a role="tab" class="p-accordion-header-link" @click="onTabClick($event, tab, i)" @keydown="onTabKeydown($event, tab, i)" :tabindex="isTabDisabled(tab) ? null : '0'"
|
||||
:aria-expanded="isTabActive(i)" :id="getTabAriaId(i) + '_header'" :aria-controls="getTabAriaId(i) + '_content'">
|
||||
<span :class="isTabActive(i) ? getHeaderCollapseIcon() : getHeaderExpandIcon()"></span>
|
||||
<div v-for="(tab,i) of tabs" :key="getKey(tab,i)" :class="getTabClass(i)" :data-index="i">
|
||||
<div :style="getTabProp(tab, 'headerStyle')" :class="getTabHeaderClass(tab, i)" v-bind="getTabProp(tab, 'headerProps')">
|
||||
<a :id="getTabHeaderActionId(i)" class="p-accordion-header-link p-accordion-header-action" :tabindex="getTabProp(tab, 'disabled') ? -1 : tabindex"
|
||||
role="button" :aria-disabled="getTabProp(tab, 'disabled')" :aria-expanded="isTabActive(i)" :aria-controls="getTabContentId(i)"
|
||||
@click="onTabClick($event, tab, i)" @keydown="onTabKeyDown($event, tab, i)" v-bind="getTabProp(tab, 'headerActionProps')">
|
||||
<span :class="getTabHeaderIconClass(i)" aria-hidden="true"></span>
|
||||
<span class="p-accordion-header-text" v-if="tab.props && tab.props.header">{{tab.props.header}}</span>
|
||||
<component :is="tab.children.header" v-if="tab.children && tab.children.header"></component>
|
||||
</a>
|
||||
</div>
|
||||
<transition name="p-toggleable-content">
|
||||
<div class="p-toggleable-content" v-if="lazy ? isTabActive(i) : true" v-show="lazy ? true: isTabActive(i)"
|
||||
role="region" :id="getTabAriaId(i) + '_content'" :aria-labelledby="getTabAriaId(i) + '_header'">
|
||||
<div v-if="lazy ? isTabActive(i) : true" v-show="lazy ? true: isTabActive(i)" :id="getTabContentId(i)" :style="getTabProp(tab, 'contentStyle')" :class="getTabContentClass(tab)"
|
||||
role="region" :aria-labelledby="getTabHeaderActionId(i)" v-bind="getTabProp(tab, 'contentProps')">
|
||||
<div class="p-accordion-content">
|
||||
<component :is="tab"></component>
|
||||
</div>
|
||||
|
@ -22,11 +23,12 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {UniqueComponentId} from 'primevue/utils';
|
||||
import {UniqueComponentId,DomHandler} from 'primevue/utils';
|
||||
import Ripple from 'primevue/ripple';
|
||||
|
||||
export default {
|
||||
name: 'Accordion',
|
||||
emits: ['tab-close', 'tab-open', 'update:activeIndex'],
|
||||
emits: ['update:activeIndex', 'tab-open', 'tab-close', 'tab-click'],
|
||||
props: {
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
|
@ -47,10 +49,19 @@ export default {
|
|||
collapseIcon: {
|
||||
type: String,
|
||||
default: 'pi-chevron-down'
|
||||
},
|
||||
tabindex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
selectOnFocus: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
id: UniqueComponentId(),
|
||||
d_activeIndex: this.activeIndex
|
||||
}
|
||||
},
|
||||
|
@ -59,98 +70,186 @@ export default {
|
|||
this.d_activeIndex = newValue;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.id = this.$attrs.id || this.id;
|
||||
},
|
||||
methods: {
|
||||
onTabClick(event, tab, i) {
|
||||
if (!this.isTabDisabled(tab)) {
|
||||
const active = this.isTabActive(i);
|
||||
isAccordionTab(child) {
|
||||
return child.type.name === 'AccordionTab';
|
||||
},
|
||||
isTabActive(index) {
|
||||
return this.multiple ? (this.d_activeIndex && this.d_activeIndex.includes(index)) : this.d_activeIndex === index;
|
||||
},
|
||||
getTabProp(tab, name) {
|
||||
return tab.props ? tab.props[name] : undefined;
|
||||
},
|
||||
getKey(tab, index) {
|
||||
return this.getTabProp(tab, 'header') || index;
|
||||
},
|
||||
getTabHeaderActionId(index) {
|
||||
return `${this.id}_${index}_header_action`;
|
||||
},
|
||||
getTabContentId(index) {
|
||||
return `${this.id}_${index}_content`;
|
||||
},
|
||||
onTabClick(event, tab, index) {
|
||||
this.changeActiveIndex(event, tab, index);
|
||||
this.$emit('tab-click', { originalEvent: event, index });
|
||||
},
|
||||
onTabKeyDown(event, tab, index) {
|
||||
switch (event.code) {
|
||||
case 'ArrowDown':
|
||||
this.onTabArrowDownKey(event);
|
||||
break;
|
||||
|
||||
case 'ArrowUp':
|
||||
this.onTabArrowUpKey(event);
|
||||
break;
|
||||
|
||||
case 'Home':
|
||||
this.onTabHomeKey(event);
|
||||
break;
|
||||
|
||||
case 'End':
|
||||
this.onTabEndKey(event);
|
||||
break;
|
||||
|
||||
case 'Enter':
|
||||
case 'Space':
|
||||
this.onTabEnterKey(event, tab, index);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
onTabArrowDownKey(event) {
|
||||
const nextHeaderAction = this.findNextHeaderAction(event.target.parentElement.parentElement);
|
||||
|
||||
nextHeaderAction ? this.changeFocusedTab(event, nextHeaderAction) : this.onTabHomeKey(event);
|
||||
event.preventDefault();
|
||||
},
|
||||
onTabArrowUpKey(event) {
|
||||
const prevHeaderAction = this.findPrevHeaderAction(event.target.parentElement.parentElement);
|
||||
|
||||
prevHeaderAction ? this.changeFocusedTab(event, prevHeaderAction) : this.onTabEndKey(event);
|
||||
event.preventDefault();
|
||||
},
|
||||
onTabHomeKey(event) {
|
||||
const firstHeaderAction = this.findFirstHeaderAction();
|
||||
|
||||
this.changeFocusedTab(event, firstHeaderAction);
|
||||
event.preventDefault();
|
||||
},
|
||||
onTabEndKey(event) {
|
||||
const lastHeaderAction = this.findLastHeaderAction();
|
||||
|
||||
this.changeFocusedTab(event, lastHeaderAction);
|
||||
event.preventDefault();
|
||||
},
|
||||
onTabEnterKey(event, tab, index) {
|
||||
this.changeActiveIndex(event, tab, index);
|
||||
|
||||
event.preventDefault();
|
||||
},
|
||||
findNextHeaderAction(tabElement, selfCheck = false) {
|
||||
const nextTabElement = selfCheck ? tabElement : tabElement.nextElementSibling;
|
||||
const headerElement = DomHandler.findSingle(nextTabElement, '.p-accordion-header');
|
||||
|
||||
return headerElement ? (DomHandler.hasClass(headerElement, 'p-disabled') ? this.findNextHeaderAction(headerElement.parentElement) : DomHandler.findSingle(headerElement, '.p-accordion-header-action')) : null;
|
||||
},
|
||||
findPrevHeaderAction(tabElement, selfCheck = false) {
|
||||
const prevTabElement = selfCheck ? tabElement : tabElement.previousElementSibling;
|
||||
const headerElement = DomHandler.findSingle(prevTabElement, '.p-accordion-header');
|
||||
|
||||
return headerElement ? (DomHandler.hasClass(headerElement, 'p-disabled') ? this.findPrevHeaderAction(headerElement.parentElement) : DomHandler.findSingle(headerElement, '.p-accordion-header-action')) : null;
|
||||
},
|
||||
findFirstHeaderAction() {
|
||||
return this.findNextHeaderAction(this.$el.firstElementChild, true);
|
||||
},
|
||||
findLastHeaderAction() {
|
||||
return this.findPrevHeaderAction(this.$el.lastElementChild, true);
|
||||
},
|
||||
changeActiveIndex(event, tab, index) {
|
||||
if (!this.getTabProp(tab, 'disabled')) {
|
||||
const active = this.isTabActive(index);
|
||||
const eventName = active ? 'tab-close' : 'tab-open';
|
||||
|
||||
if (this.multiple) {
|
||||
if (active) {
|
||||
this.d_activeIndex = this.d_activeIndex.filter(index => index !== i);
|
||||
this.d_activeIndex = this.d_activeIndex.filter(i => i !== index);
|
||||
}
|
||||
else {
|
||||
if (this.d_activeIndex)
|
||||
this.d_activeIndex.push(i);
|
||||
this.d_activeIndex.push(index);
|
||||
else
|
||||
this.d_activeIndex = [i];
|
||||
this.d_activeIndex = [index];
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.d_activeIndex = this.d_activeIndex === i ? null : i;
|
||||
this.d_activeIndex = this.d_activeIndex === index ? null : index;
|
||||
}
|
||||
|
||||
this.$emit('update:activeIndex', this.d_activeIndex);
|
||||
this.$emit(eventName, { originalEvent: event, index });
|
||||
}
|
||||
},
|
||||
changeFocusedTab(event, element) {
|
||||
if (element) {
|
||||
element.focus();
|
||||
|
||||
this.$emit(eventName, {
|
||||
originalEvent: event,
|
||||
index: i
|
||||
});
|
||||
if (this.selectOnFocus) {
|
||||
const index = parseInt(element.parentElement.parentElement.dataset.index, 10);
|
||||
const tab = this.tabs[index];
|
||||
|
||||
this.changeActiveIndex(event, tab, index);
|
||||
}
|
||||
},
|
||||
onTabKeydown(event, tab, i) {
|
||||
if (event.which === 13) {
|
||||
this.onTabClick(event, tab, i);
|
||||
}
|
||||
},
|
||||
isTabActive(index) {
|
||||
if (this.multiple)
|
||||
return this.d_activeIndex && this.d_activeIndex.includes(index);
|
||||
else
|
||||
return index === this.d_activeIndex;
|
||||
},
|
||||
getKey(tab, i) {
|
||||
return (tab.props && tab.props.header) ? tab.props.header : i;
|
||||
},
|
||||
isTabDisabled(tab) {
|
||||
return tab.props && tab.props.disabled;
|
||||
},
|
||||
getTabClass(i) {
|
||||
return ['p-accordion-tab', {'p-accordion-tab-active': this.isTabActive(i)}];
|
||||
return ['p-accordion-tab', {
|
||||
'p-accordion-tab-active': this.isTabActive(i)
|
||||
}];
|
||||
},
|
||||
getTabHeaderClass(tab, i) {
|
||||
return ['p-accordion-header', {'p-highlight': this.isTabActive(i), 'p-disabled': this.isTabDisabled(tab)}];
|
||||
return ['p-accordion-header', this.getTabProp(tab, 'headerClass'), {
|
||||
'p-highlight': this.isTabActive(i),
|
||||
'p-disabled': this.getTabProp(tab, 'disabled')
|
||||
}];
|
||||
},
|
||||
getTabAriaId(i) {
|
||||
return this.ariaId + '_' + i;
|
||||
getTabHeaderIconClass(i) {
|
||||
return ['p-accordion-toggle-icon pi', this.isTabActive(i) ? this.collapseIcon : this.expandIcon];
|
||||
},
|
||||
getHeaderCollapseIcon() {
|
||||
return ['p-accordion-toggle-icon pi', this.collapseIcon];
|
||||
},
|
||||
getHeaderExpandIcon() {
|
||||
return ['p-accordion-toggle-icon pi', this.expandIcon];
|
||||
},
|
||||
isAccordionTab(child) {
|
||||
return child.type.name === 'AccordionTab';
|
||||
getTabContentClass(tab) {
|
||||
return ['p-toggleable-content', this.getTabProp(tab, 'contentClass')];
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
tabs() {
|
||||
const tabs = []
|
||||
this.$slots.default().forEach(child => {
|
||||
return this.$slots.default().reduce((tabs, child) => {
|
||||
if (this.isAccordionTab(child)) {
|
||||
tabs.push(child);
|
||||
}
|
||||
else if (child.children && child.children instanceof Array) {
|
||||
child.children.forEach(nestedChild => {
|
||||
if (this.isAccordionTab(nestedChild)) {
|
||||
tabs.push(nestedChild)
|
||||
tabs.push(nestedChild);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return tabs;
|
||||
},
|
||||
ariaId() {
|
||||
return UniqueComponentId();
|
||||
}, []);
|
||||
}
|
||||
},
|
||||
directives: {
|
||||
'ripple': Ripple
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.p-accordion-header-link {
|
||||
.p-accordion-header-action {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -159,7 +258,7 @@ export default {
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
.p-accordion-header-link:focus {
|
||||
.p-accordion-header-action:focus {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { VNode } from 'vue';
|
||||
import { AnchorHTMLAttributes, HTMLAttributes, VNode } from 'vue';
|
||||
import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers';
|
||||
|
||||
export interface AccordionTabProps {
|
||||
|
@ -6,6 +6,34 @@ export interface AccordionTabProps {
|
|||
* Orientation of tab headers.
|
||||
*/
|
||||
header?: string | undefined;
|
||||
/**
|
||||
* Inline style of the tab header.
|
||||
*/
|
||||
headerStyle?: any;
|
||||
/**
|
||||
* Style class of the tab header.
|
||||
*/
|
||||
headerClass?: any;
|
||||
/**
|
||||
* Uses to pass all properties of the HTMLDivElement to the tab header.
|
||||
*/
|
||||
headerProps?: HTMLAttributes | undefined;
|
||||
/**
|
||||
* Uses to pass all properties of the HTMLAnchorElement to the focusable anchor element inside the tab header.
|
||||
*/
|
||||
headerActionProps?: AnchorHTMLAttributes | undefined;
|
||||
/**
|
||||
* Inline style of the tab content.
|
||||
*/
|
||||
contentStyle?: any;
|
||||
/**
|
||||
* Style class of the tab content.
|
||||
*/
|
||||
contentClass?: any;
|
||||
/**
|
||||
* Uses to pass all properties of the HTMLDivElement to the tab content.
|
||||
*/
|
||||
contentProps?: HTMLAttributes | undefined;
|
||||
/**
|
||||
* Whether the tab is disabled.
|
||||
*/
|
||||
|
|
|
@ -7,6 +7,13 @@ export default {
|
|||
name: 'AccordionTab',
|
||||
props: {
|
||||
header: null,
|
||||
headerStyle: null,
|
||||
headerClass: null,
|
||||
headerProps: null,
|
||||
headerActionProps: null,
|
||||
contentStyle: null,
|
||||
contentClass: null,
|
||||
contentProps: null,
|
||||
disabled: Boolean
|
||||
}
|
||||
}
|
||||
|
|
|
@ -224,6 +224,48 @@ export default {
|
|||
<td>null</td>
|
||||
<td>Orientation of tab headers.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>headerStyle</td>
|
||||
<td>string</td>
|
||||
<td>null</td>
|
||||
<td>Inline style of the tab header.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>headerClass</td>
|
||||
<td>string</td>
|
||||
<td>null</td>
|
||||
<td>Style class of the tab header.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>headerProps</td>
|
||||
<td>object</td>
|
||||
<td>null</td>
|
||||
<td>Uses to pass all properties of the HTMLDivElement to the tab header.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>headerActionProps</td>
|
||||
<td>object</td>
|
||||
<td>null</td>
|
||||
<td>Uses to pass all properties of the HTMLAnchorElement to the focusable anchor element inside the tab header.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>contentStyle</td>
|
||||
<td>string</td>
|
||||
<td>null</td>
|
||||
<td>Inline style of the tab content.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>contentClass</td>
|
||||
<td>string</td>
|
||||
<td>null</td>
|
||||
<td>Style class of the tab content.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>contentProps</td>
|
||||
<td>object</td>
|
||||
<td>null</td>
|
||||
<td>Uses to pass all properties of the HTMLDivElement to the tab content.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>disabled</td>
|
||||
<td>boolean</td>
|
||||
|
@ -276,6 +318,18 @@ export default {
|
|||
<td>string</td>
|
||||
<td>pi-chevron-down</td>
|
||||
<td>Icon of an expanded tab.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>tabindex</td>
|
||||
<td>number</td>
|
||||
<td>0</td>
|
||||
<td>Index of the element in tabbing order.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>selectOnFocus</td>
|
||||
<td>boolean</td>
|
||||
<td>false</td>
|
||||
<td>When enabled, the focused tab is activated.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -305,6 +359,13 @@ export default {
|
|||
event.index: Closed tab index
|
||||
</td>
|
||||
<td>Callback to invoke when an active tab is collapsed by clicking on the header.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>tab-click</td>
|
||||
<td>event.originalEvent: Browser event <br/>
|
||||
event.index: Index of the clicked tab
|
||||
</td>
|
||||
<td>Callback to invoke when an active tab is clicked.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -337,6 +398,78 @@ export default {
|
|||
</table>
|
||||
</div>
|
||||
|
||||
<h5>Accessibility</h5>
|
||||
<h6>Screen Reader</h6>
|
||||
<p>
|
||||
Accordion header elements have a <i>button</i> role and use <i>aria-controls</i> to define the id of the content section along with <i>aria-expanded</i> for the visibility state. The value to read a header element defaults
|
||||
to the value of the <i>header</i> property and can be customized by defining an <i>aria-label</i> or <i>aria-labelledby</i> via the <i>headerActionProps</i> property.
|
||||
</p>
|
||||
<p>
|
||||
The content uses <i>region</i> role, defines an id that matches the <i>aria-controls</i> of the header and <i>aria-labelledby</i> referring to the id of the header.
|
||||
</p>
|
||||
|
||||
<h6>Header Keyboard Support</h6>
|
||||
<div className="doc-tablewrapper">
|
||||
<table className="doc-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Function</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<i>tab</i>
|
||||
</td>
|
||||
<td>Moves focus to the next the focusable element in the page tab sequence.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<i>shift</i> + <i>tab</i>
|
||||
</td>
|
||||
<td>Moves focus to the previous the focusable element in the page tab sequence.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<i>enter</i>
|
||||
</td>
|
||||
<td>Toggles the visibility of the content.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<i>space</i>
|
||||
</td>
|
||||
<td>Toggles the visibility of the content.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<i>down arrow</i>
|
||||
</td>
|
||||
<td>Moves focus to the next header. If focus is on the last header, moves focus to the first header.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<i>up arrow</i>
|
||||
</td>
|
||||
<td>Moves focus to the previous header. If focus is on the first header, moves focus to the last header.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<i>home</i>
|
||||
</td>
|
||||
<td>Moves focus to the first header.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<i>end</i>
|
||||
</td>
|
||||
<td>Moves focus to the last header.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h5>Dependencies</h5>
|
||||
<p>None.</p>
|
||||
</AppDoc>
|
||||
|
|
Loading…
Reference in New Issue