mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 03:00:58 +08:00
@ -2,9 +2,9 @@ import { Component, ComponentInterface, Element, Host, Prop, h } from '@stencil/
|
|||||||
|
|
||||||
import { config } from '../../global/config';
|
import { config } from '../../global/config';
|
||||||
import { getIonMode } from '../../global/ionic-global';
|
import { getIonMode } from '../../global/ionic-global';
|
||||||
import { AnimationBuilder, Color } from '../../interface';
|
import type { AnimationBuilder, Color } from '../../interface';
|
||||||
import { ButtonInterface } from '../../utils/element-interface';
|
import type { ButtonInterface } from '../../utils/element-interface';
|
||||||
import { inheritAttributes } from '../../utils/helpers';
|
import { inheritAriaAttributes } from '../../utils/helpers';
|
||||||
import { createColorClasses, hostContext, openURL } from '../../utils/theme';
|
import { createColorClasses, hostContext, openURL } from '../../utils/theme';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,7 +67,7 @@ export class BackButton implements ComponentInterface, ButtonInterface {
|
|||||||
@Prop() routerAnimation: AnimationBuilder | undefined;
|
@Prop() routerAnimation: AnimationBuilder | undefined;
|
||||||
|
|
||||||
componentWillLoad() {
|
componentWillLoad() {
|
||||||
this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);
|
this.inheritedAttributes = inheritAriaAttributes(this.el);
|
||||||
|
|
||||||
if (this.defaultHref === undefined) {
|
if (this.defaultHref === undefined) {
|
||||||
this.defaultHref = config.get('backButtonDefaultHref');
|
this.defaultHref = config.get('backButtonDefaultHref');
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Prop, h } from '@stencil/core';
|
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Prop, h } from '@stencil/core';
|
||||||
|
|
||||||
import { getIonMode } from '../../global/ionic-global';
|
import { getIonMode } from '../../global/ionic-global';
|
||||||
import { AnimationBuilder, Color, RouterDirection } from '../../interface';
|
import type { AnimationBuilder, Color, RouterDirection } from '../../interface';
|
||||||
import { AnchorInterface, ButtonInterface } from '../../utils/element-interface';
|
import type { AnchorInterface, ButtonInterface } from '../../utils/element-interface';
|
||||||
import { hasShadowDom, inheritAttributes } from '../../utils/helpers';
|
import { hasShadowDom, inheritAriaAttributes } from '../../utils/helpers';
|
||||||
import { createColorClasses, hostContext, openURL } from '../../utils/theme';
|
import { createColorClasses, hostContext, openURL } from '../../utils/theme';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -135,7 +135,7 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
|
|||||||
this.inToolbar = !!this.el.closest('ion-buttons');
|
this.inToolbar = !!this.el.closest('ion-buttons');
|
||||||
this.inListHeader = !!this.el.closest('ion-list-header');
|
this.inListHeader = !!this.el.closest('ion-list-header');
|
||||||
this.inItem = !!this.el.closest('ion-item') || !!this.el.closest('ion-item-divider');
|
this.inItem = !!this.el.closest('ion-item') || !!this.el.closest('ion-item-divider');
|
||||||
this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);
|
this.inheritedAttributes = inheritAriaAttributes(this.el);
|
||||||
}
|
}
|
||||||
|
|
||||||
private get hasIconOnly() {
|
private get hasIconOnly() {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component, ComponentInterface, Element, Host, Prop, h, writeTask } from '@stencil/core';
|
import { Component, ComponentInterface, Element, Host, Prop, h, writeTask } from '@stencil/core';
|
||||||
|
|
||||||
import { getIonMode } from '../../global/ionic-global';
|
import { getIonMode } from '../../global/ionic-global';
|
||||||
import { inheritAttributes } from '../../utils/helpers';
|
import { inheritAriaAttributes } from '../../utils/helpers';
|
||||||
import { hostContext } from '../../utils/theme';
|
import { hostContext } from '../../utils/theme';
|
||||||
|
|
||||||
import { cloneElement, createHeaderIndex, handleContentScroll, handleToolbarIntersection, setHeaderActive, setToolbarBackgroundOpacity } from './header.utils';
|
import { cloneElement, createHeaderIndex, handleContentScroll, handleToolbarIntersection, setHeaderActive, setToolbarBackgroundOpacity } from './header.utils';
|
||||||
@ -46,7 +46,7 @@ export class Header implements ComponentInterface {
|
|||||||
@Prop() translucent = false;
|
@Prop() translucent = false;
|
||||||
|
|
||||||
componentWillLoad() {
|
componentWillLoad() {
|
||||||
this.inheritedAttributes = inheritAttributes(this.el, ['role']);
|
this.inheritedAttributes = inheritAriaAttributes(this.el);
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidLoad() {
|
async componentDidLoad() {
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
import { Build, Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, State, Watch, h } from '@stencil/core';
|
import { Build, Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, State, Watch, h } from '@stencil/core';
|
||||||
|
|
||||||
import { getIonMode } from '../../global/ionic-global';
|
import { getIonMode } from '../../global/ionic-global';
|
||||||
import { AutocompleteTypes, Color, InputChangeEventDetail, StyleEventDetail, TextFieldTypes } from '../../interface';
|
import type {
|
||||||
import { debounceEvent, findItemLabel, inheritAttributes } from '../../utils/helpers';
|
AutocompleteTypes,
|
||||||
|
Color,
|
||||||
|
InputChangeEventDetail,
|
||||||
|
StyleEventDetail,
|
||||||
|
TextFieldTypes,
|
||||||
|
} from '../../interface';
|
||||||
|
import { debounceEvent, findItemLabel, inheritAriaAttributes, inheritAttributes } from '../../utils/helpers';
|
||||||
import { createColorClasses } from '../../utils/theme';
|
import { createColorClasses } from '../../utils/theme';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -234,7 +240,10 @@ export class Input implements ComponentInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillLoad() {
|
componentWillLoad() {
|
||||||
this.inheritedAttributes = inheritAttributes(this.el, ['aria-label', 'tabindex', 'title']);
|
this.inheritedAttributes = {
|
||||||
|
...inheritAriaAttributes(this.el),
|
||||||
|
...inheritAttributes(this.el, ['tabindex', 'title']),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
|
@ -2,9 +2,9 @@ import { Component, ComponentInterface, Element, Host, Listen, Prop, State, h }
|
|||||||
|
|
||||||
import { config } from '../../global/config';
|
import { config } from '../../global/config';
|
||||||
import { getIonMode } from '../../global/ionic-global';
|
import { getIonMode } from '../../global/ionic-global';
|
||||||
import { Color } from '../../interface';
|
import type { Color } from '../../interface';
|
||||||
import { ButtonInterface } from '../../utils/element-interface';
|
import type { ButtonInterface } from '../../utils/element-interface';
|
||||||
import { inheritAttributes } from '../../utils/helpers';
|
import { inheritAriaAttributes } from '../../utils/helpers';
|
||||||
import { menuController } from '../../utils/menu-controller';
|
import { menuController } from '../../utils/menu-controller';
|
||||||
import { createColorClasses, hostContext } from '../../utils/theme';
|
import { createColorClasses, hostContext } from '../../utils/theme';
|
||||||
import { updateVisibility } from '../menu-toggle/menu-toggle-util';
|
import { updateVisibility } from '../menu-toggle/menu-toggle-util';
|
||||||
@ -58,7 +58,7 @@ export class MenuButton implements ComponentInterface, ButtonInterface {
|
|||||||
@Prop() type: 'submit' | 'reset' | 'button' = 'button';
|
@Prop() type: 'submit' | 'reset' | 'button' = 'button';
|
||||||
|
|
||||||
componentWillLoad() {
|
componentWillLoad() {
|
||||||
this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);
|
this.inheritedAttributes = inheritAriaAttributes(this.el);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidLoad() {
|
componentDidLoad() {
|
||||||
|
@ -5,7 +5,7 @@ import { getIonMode } from '../../global/ionic-global';
|
|||||||
import { Animation, Gesture, GestureDetail, MenuChangeEventDetail, MenuI, Side } from '../../interface';
|
import { Animation, Gesture, GestureDetail, MenuChangeEventDetail, MenuI, Side } from '../../interface';
|
||||||
import { getTimeGivenProgression } from '../../utils/animation/cubic-bezier';
|
import { getTimeGivenProgression } from '../../utils/animation/cubic-bezier';
|
||||||
import { GESTURE_CONTROLLER } from '../../utils/gesture';
|
import { GESTURE_CONTROLLER } from '../../utils/gesture';
|
||||||
import { assert, clamp, inheritAttributes, isEndSide as isEnd } from '../../utils/helpers';
|
import { assert, clamp, inheritAriaAttributes, isEndSide as isEnd } from '../../utils/helpers';
|
||||||
import { menuController } from '../../utils/menu-controller';
|
import { menuController } from '../../utils/menu-controller';
|
||||||
|
|
||||||
const iosEasing = 'cubic-bezier(0.32,0.72,0,1)';
|
const iosEasing = 'cubic-bezier(0.32,0.72,0,1)';
|
||||||
@ -213,7 +213,7 @@ AFTER:
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillLoad() {
|
componentWillLoad() {
|
||||||
this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);
|
this.inheritedAttributes = inheritAriaAttributes(this.el);
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidLoad() {
|
async componentDidLoad() {
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Prop, State, Watch, h } from '@stencil/core';
|
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Prop, State, Watch, h } from '@stencil/core';
|
||||||
|
|
||||||
import { getIonMode } from '../../global/ionic-global';
|
import { getIonMode } from '../../global/ionic-global';
|
||||||
import { Color, Gesture, GestureDetail, KnobName, RangeChangeEventDetail, RangeValue, StyleEventDetail } from '../../interface';
|
import type {
|
||||||
import { clamp, debounceEvent, getAriaLabel, inheritAttributes, renderHiddenInput } from '../../utils/helpers';
|
Color,
|
||||||
|
Gesture,
|
||||||
|
GestureDetail,
|
||||||
|
KnobName,
|
||||||
|
RangeChangeEventDetail,
|
||||||
|
RangeValue,
|
||||||
|
StyleEventDetail,
|
||||||
|
} from '../../interface';
|
||||||
|
import { clamp, debounceEvent, getAriaLabel, inheritAriaAttributes, renderHiddenInput } from '../../utils/helpers';
|
||||||
import { createColorClasses, hostContext } from '../../utils/theme';
|
import { createColorClasses, hostContext } from '../../utils/theme';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -205,7 +213,7 @@ export class Range implements ComponentInterface {
|
|||||||
*/
|
*/
|
||||||
this.rangeId = (this.el.hasAttribute('id')) ? this.el.getAttribute('id')! : `ion-r-${rangeIds++}`;
|
this.rangeId = (this.el.hasAttribute('id')) ? this.el.getAttribute('id')! : `ion-r-${rangeIds++}`;
|
||||||
|
|
||||||
this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);
|
this.inheritedAttributes = inheritAriaAttributes(this.el);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidLoad() {
|
componentDidLoad() {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Build, Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, State, Watch, h, readTask } from '@stencil/core';
|
import { Build, Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, State, Watch, h, readTask } from '@stencil/core';
|
||||||
|
|
||||||
import { getIonMode } from '../../global/ionic-global';
|
import { getIonMode } from '../../global/ionic-global';
|
||||||
import { Color, StyleEventDetail, TextareaChangeEventDetail } from '../../interface';
|
import type { Color, StyleEventDetail, TextareaChangeEventDetail } from '../../interface';
|
||||||
import { debounceEvent, findItemLabel, inheritAttributes, raf } from '../../utils/helpers';
|
import { debounceEvent, findItemLabel, inheritAriaAttributes, inheritAttributes, raf } from '../../utils/helpers';
|
||||||
import { createColorClasses } from '../../utils/theme';
|
import { createColorClasses } from '../../utils/theme';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -214,7 +214,10 @@ export class Textarea implements ComponentInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillLoad() {
|
componentWillLoad() {
|
||||||
this.inheritedAttributes = inheritAttributes(this.el, ['title']);
|
this.inheritedAttributes = {
|
||||||
|
...inheritAriaAttributes(this.el),
|
||||||
|
...inheritAttributes(this.el, ['title']),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidLoad() {
|
componentDidLoad() {
|
||||||
|
@ -51,6 +51,74 @@ export const inheritAttributes = (el: HTMLElement, attributes: string[] = []) =>
|
|||||||
return attributeObject;
|
return attributeObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of available ARIA attributes + `role`.
|
||||||
|
* Removed deprecated attributes.
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes
|
||||||
|
*/
|
||||||
|
const ariaAttributes = [
|
||||||
|
'role',
|
||||||
|
'aria-activedescendant',
|
||||||
|
'aria-atomic',
|
||||||
|
'aria-autocomplete',
|
||||||
|
'aria-braillelabel',
|
||||||
|
'aria-brailleroledescription',
|
||||||
|
'aria-busy',
|
||||||
|
'aria-checked',
|
||||||
|
'aria-colcount',
|
||||||
|
'aria-colindex',
|
||||||
|
'aria-colindextext',
|
||||||
|
'aria-colspan',
|
||||||
|
'aria-controls',
|
||||||
|
'aria-current',
|
||||||
|
'aria-describedby',
|
||||||
|
'aria-description',
|
||||||
|
'aria-details',
|
||||||
|
'aria-disabled',
|
||||||
|
'aria-errormessage',
|
||||||
|
'aria-expanded',
|
||||||
|
'aria-flowto',
|
||||||
|
'aria-haspopup',
|
||||||
|
'aria-hidden',
|
||||||
|
'aria-invalid',
|
||||||
|
'aria-keyshortcuts',
|
||||||
|
'aria-label',
|
||||||
|
'aria-labelledby',
|
||||||
|
'aria-level',
|
||||||
|
'aria-live',
|
||||||
|
'aria-multiline',
|
||||||
|
'aria-multiselectable',
|
||||||
|
'aria-orientation',
|
||||||
|
'aria-owns',
|
||||||
|
'aria-placeholder',
|
||||||
|
'aria-posinset',
|
||||||
|
'aria-pressed',
|
||||||
|
'aria-readonly',
|
||||||
|
'aria-relevant',
|
||||||
|
'aria-required',
|
||||||
|
'aria-roledescription',
|
||||||
|
'aria-rowcount',
|
||||||
|
'aria-rowindex',
|
||||||
|
'aria-rowindextext',
|
||||||
|
'aria-rowspan',
|
||||||
|
'aria-selected',
|
||||||
|
'aria-setsize',
|
||||||
|
'aria-sort',
|
||||||
|
'aria-valuemax',
|
||||||
|
'aria-valuemin',
|
||||||
|
'aria-valuenow',
|
||||||
|
'aria-valuetext',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of aria attributes that should be copied from
|
||||||
|
* the shadow host element to a target within the light DOM.
|
||||||
|
* @param el The element that the attributes should be copied from.
|
||||||
|
*/
|
||||||
|
export const inheritAriaAttributes = (el: HTMLElement) => {
|
||||||
|
return inheritAttributes(el, ariaAttributes);
|
||||||
|
};
|
||||||
|
|
||||||
export const addEventListener = (el: any, eventName: string, callback: any, opts?: any) => {
|
export const addEventListener = (el: any, eventName: string, callback: any, opts?: any) => {
|
||||||
if (typeof (window as any) !== 'undefined') {
|
if (typeof (window as any) !== 'undefined') {
|
||||||
const win = window as any;
|
const win = window as any;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { inheritAttributes } from '../helpers';
|
import { inheritAttributes, inheritAriaAttributes } from '../helpers';
|
||||||
|
|
||||||
describe('inheritAttributes()', () => {
|
describe('inheritAttributes()', () => {
|
||||||
it('should create an attribute inheritance object', () => {
|
it('should create an attribute inheritance object', () => {
|
||||||
@ -37,3 +37,29 @@ describe('inheritAttributes()', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('inheritAriaAttributes()', () => {
|
||||||
|
it('should inherit ARIA attributes defined on the HTML element', () => {
|
||||||
|
const el = document.createElement('div');
|
||||||
|
el.setAttribute('aria-label', 'myLabel');
|
||||||
|
el.setAttribute('aria-describedby', 'myDescription');
|
||||||
|
|
||||||
|
const attributeObject = inheritAriaAttributes(el);
|
||||||
|
|
||||||
|
expect(attributeObject).toEqual({
|
||||||
|
'aria-label': 'myLabel',
|
||||||
|
'aria-describedby': 'myDescription',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should inherit the role attribute defined on the HTML element', () => {
|
||||||
|
const el = document.createElement('div');
|
||||||
|
el.setAttribute('role', 'button');
|
||||||
|
|
||||||
|
const attributeObject = inheritAriaAttributes(el);
|
||||||
|
|
||||||
|
expect(attributeObject).toEqual({
|
||||||
|
role: 'button',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Reference in New Issue
Block a user