diff --git a/src/components.d.ts b/src/components.d.ts index c0cc00809..8359fc434 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -7,14 +7,6 @@ import { HTMLStencilElement, JSXBase } from "@stencil/core/internal"; export namespace Components { interface IonIcon { - /** - * Set the icon to hidden, respectively `true`, to remove it from the accessibility tree. - */ - "ariaHidden"?: string; - /** - * Specifies the label to use for accessibility. Defaults to the icon name. - */ - "ariaLabel"?: string; /** * The color to use for the background of the item. */ @@ -75,14 +67,6 @@ declare global { } declare namespace LocalJSX { interface IonIcon { - /** - * Set the icon to hidden, respectively `true`, to remove it from the accessibility tree. - */ - "ariaHidden"?: string; - /** - * Specifies the label to use for accessibility. Defaults to the icon name. - */ - "ariaLabel"?: string; /** * The color to use for the background of the item. */ diff --git a/src/components/icon/icon.tsx b/src/components/icon/icon.tsx index 1b61a0acc..11dfc12da 100755 --- a/src/components/icon/icon.tsx +++ b/src/components/icon/icon.tsx @@ -1,6 +1,6 @@ import { Build, Component, Element, Host, Prop, State, Watch, h } from '@stencil/core'; import { getSvgContent, ioniconContent } from './request'; -import { getName, getUrl } from './utils'; +import { getName, getUrl, inheritAttributes } from './utils'; @Component({ tag: 'ion-icon', @@ -11,11 +11,13 @@ import { getName, getUrl } from './utils'; export class Icon { private io?: IntersectionObserver; private iconName: string | null = null; + private inheritedAttributes: { [k: string]: any } = {}; @Element() el!: HTMLElement; @State() private svgContent?: string; @State() private isVisible = false; + @State() private ariaLabel?: string; /** * The mode determines which platform styles to use. @@ -27,16 +29,6 @@ export class Icon { */ @Prop() color?: string; - /** - * Specifies the label to use for accessibility. Defaults to the icon name. - */ - @Prop({ mutable: true, reflect: true }) ariaLabel?: string; - - /** - * Set the icon to hidden, respectively `true`, to remove it from the accessibility tree. - */ - @Prop({ reflect: true }) ariaHidden?: string; - /** * Specifies which icon to use on `ios` mode. */ @@ -88,6 +80,10 @@ export class Icon { * @default true */ @Prop() sanitize = true; + + componentWillLoad() { + this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']); + } connectedCallback() { // purposely do not return the promise here because loading @@ -126,6 +122,12 @@ export class Icon { cb(); } } + + private hasAriaHidden = () => { + const { el } = this; + + return el.hasAttribute('aria-hidden') && el.getAttribute('aria-hidden') === 'true'; + } @Watch('name') @Watch('src') @@ -146,17 +148,17 @@ export class Icon { const label = this.iconName = getName(this.name, this.icon, this.mode, this.ios, this.md); - if (!this.ariaLabel && this.ariaHidden !== 'true') { - // user did not provide a label - // come up with the label based on the icon name - if (label) { - this.ariaLabel = label.replace(/\-/g, ' '); - } + /** + * Come up with a default label + * in case user does not provide their own. + */ + if (label) { + this.ariaLabel = label.replace(/\-/g, ' '); } } render() { - const { iconName } = this; + const { iconName, ariaLabel, inheritedAttributes } = this; const mode = this.mode || 'md'; const flipRtl = this.flipRtl || @@ -164,8 +166,16 @@ export class Icon { (iconName.indexOf('arrow') > -1 || iconName.indexOf('chevron') > -1) && this.flipRtl !== false); + /** + * Only set the aria-label if a) we have generated + * one for the icon and if aria-hidden is not set to "true". + * If developer wants to set their own aria-label, then + * inheritedAttributes down below will override whatever + * default label we have set. + */ return ( {Build.isBrowser && this.svgContent ? (
diff --git a/src/components/icon/readme.md b/src/components/icon/readme.md index 3d1ae73fe..b4140b45b 100644 --- a/src/components/icon/readme.md +++ b/src/components/icon/readme.md @@ -7,21 +7,19 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| ------------ | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | -------------- | -| `ariaHidden` | `aria-hidden` | Set the icon to hidden, respectively `true`, to remove it from the accessibility tree. | `string \| undefined` | `undefined` | -| `ariaLabel` | `aria-label` | Specifies the label to use for accessibility. Defaults to the icon name. | `string \| undefined` | `undefined` | -| `color` | `color` | The color to use for the background of the item. | `string \| undefined` | `undefined` | -| `flipRtl` | `flip-rtl` | Specifies whether the icon should horizontally flip when `dir` is `"rtl"`. | `boolean \| undefined` | `undefined` | -| `icon` | `icon` | A combination of both `name` and `src`. If a `src` url is detected it will set the `src` property. Otherwise it assumes it's a built-in named SVG and set the `name` property. | `any` | `undefined` | -| `ios` | `ios` | Specifies which icon to use on `ios` mode. | `string \| undefined` | `undefined` | -| `lazy` | `lazy` | If enabled, ion-icon will be loaded lazily when it's visible in the viewport. Default, `false`. | `boolean` | `false` | -| `md` | `md` | Specifies which icon to use on `md` mode. | `string \| undefined` | `undefined` | -| `mode` | `mode` | The mode determines which platform styles to use. | `string` | `getIonMode()` | -| `name` | `name` | Specifies which icon to use from the built-in set of icons. | `string \| undefined` | `undefined` | -| `sanitize` | `sanitize` | When set to `false`, SVG content that is HTTP fetched will not be checked if the response SVG content has any `