From b43700e64545b8cc0cd71b8f826f9362bc69eebf Mon Sep 17 00:00:00 2001 From: Behrokh Satarnejad Date: Wed, 23 Oct 2024 15:09:17 +0200 Subject: [PATCH] revert changes for react component and make tabindex optional --- lib/octicons_angular/README.md | 18 ++++++++++++++++++ .../src/octicon-component-base.ts | 4 ++++ lib/octicons_react/README.md | 18 ++++++++++++++++++ .../__tests__/__snapshots__/octicon.js.snap | 1 + lib/octicons_react/src/__tests__/octicon.js | 17 +++++++++++++++++ lib/octicons_react/src/createIconComponent.js | 3 +++ lib/octicons_react/src/index.d.ts | 1 + 7 files changed, 62 insertions(+) diff --git a/lib/octicons_angular/README.md b/lib/octicons_angular/README.md index 3fe71628e..aa9e7e60c 100644 --- a/lib/octicons_angular/README.md +++ b/lib/octicons_angular/README.md @@ -91,6 +91,24 @@ You have the option of adding information to the icon with the > ``` +#### `tabIndex` + +You can add the `tabindex` attribute to an SVG element via the `tabIndex` input if the SVG element is intended to be interactive. +`tabIndex` input also controls the `focusable` attribute of the SVG element which is defined by SVG Tiny 1.2 and only implemented in +Internet Explorer and Microsoft Edge. + +If there is no `tabIndex` input is present (default behavior), it will set the `focusable` attribute to `false`. This is helpful +for preventing the decorative SVG from being announced by some specialized assistive technology browsing modes which can get delayed +while trying to parse the SVG markup. + +```html + +``` + #### Sizes The `size` input takes `small`, `medium`, and `large` values that can be used to render octicons at standard sizes: diff --git a/lib/octicons_angular/src/octicon-component-base.ts b/lib/octicons_angular/src/octicon-component-base.ts index fb3f1c32c..b51e15635 100644 --- a/lib/octicons_angular/src/octicon-component-base.ts +++ b/lib/octicons_angular/src/octicon-component-base.ts @@ -15,6 +15,7 @@ export class OpOcticonComponentBase { @HostBinding('attr.role') role = 'img'; @HostBinding('attr.fill') @Input() fill = 'currentColor'; @HostBinding('attr.id') @Input() id = ''; + @HostBinding('attr.tabindex') @Input() tabIndex?:number; @HostBinding('attr.aria-label') @Input('aria-label') ariaLabel = ''; @HostBinding('attr.aria-labelledby') @Input('aria-labelledby') arialabelledby = ''; @@ -22,6 +23,9 @@ export class OpOcticonComponentBase { @HostBinding('attr.aria-hidden') get ariaHidden() { return !this.ariaLabel; } + @HostBinding('attr.focusable') get focusable() { + return (this.tabIndex && this.tabIndex >= 0); + } @HostBinding('style') get style () { return { display: 'inline-block', diff --git a/lib/octicons_react/README.md b/lib/octicons_react/README.md index b5e2b27a6..234c55f6f 100644 --- a/lib/octicons_react/README.md +++ b/lib/octicons_react/README.md @@ -99,6 +99,24 @@ export default () => ( ) ``` +### `tabIndex` + +You can add the `tabindex` attribute to an SVG element via the `tabIndex` prop if the SVG element is intended to be interactive. +`tabIndex` prop also controls the `focusable` attribute of the SVG element which is defined by SVG Tiny 1.2 and only implemented in +Internet Explorer and Microsoft Edge. + +If there is no `tabIndex` prop is present (default behavior), it will set the `focusable` attribute to `false`. This is helpful +for preventing the decorative SVG from being announced by some specialized assistive technology browsing modes which can get delayed +while trying to parse the SVG markup. + +```js +// Example usage +import {PlusIcon} from '@primer/octicons-react' +export default () => ( + New Item +) +``` + ### Sizes The `size` prop takes `small`, `medium`, and `large` values that can be used to diff --git a/lib/octicons_react/src/__tests__/__snapshots__/octicon.js.snap b/lib/octicons_react/src/__tests__/__snapshots__/octicon.js.snap index edcdf8f39..2c1947a65 100644 --- a/lib/octicons_react/src/__tests__/__snapshots__/octicon.js.snap +++ b/lib/octicons_react/src/__tests__/__snapshots__/octicon.js.snap @@ -5,6 +5,7 @@ exports[`An icon component matches snapshot 1`] = ` aria-hidden="true" class="octicon octicon-alert" fill="currentColor" + focusable="false" height="16" style="display: inline-block; user-select: none; vertical-align: text-bottom; overflow: visible;" viewBox="0 0 16 16" diff --git a/lib/octicons_react/src/__tests__/octicon.js b/lib/octicons_react/src/__tests__/octicon.js index 165a6d951..c4a9493a7 100644 --- a/lib/octicons_react/src/__tests__/octicon.js +++ b/lib/octicons_react/src/__tests__/octicon.js @@ -35,6 +35,23 @@ describe('An icon component', () => { expect(container.querySelector('svg')).toHaveAttribute('aria-label', 'icon') }) + it('set the focusable prop to false if tabIndex prop is not present', () => { + const {container} = render() + expect(container.querySelector('svg')).toHaveAttribute('focusable', 'false') + }) + + it('sets focusable prop to true if tabIndex prop is present and greater than 0', () => { + const {container} = render() + expect(container.querySelector('svg')).toHaveAttribute('tabindex', '0') + expect(container.querySelector('svg')).toHaveAttribute('focusable', 'true') + }) + + it('sets focusable prop to false if tabIndex prop is -1', () => { + const {container} = render() + expect(container.querySelector('svg')).toHaveAttribute('tabindex', '-1') + expect(container.querySelector('svg')).toHaveAttribute('focusable', 'false') + }) + it('respects the className prop', () => { const {container} = render() expect(container.querySelector('svg')).toHaveAttribute('class', 'foo') diff --git a/lib/octicons_react/src/createIconComponent.js b/lib/octicons_react/src/createIconComponent.js index 89e41e858..f895c43ec 100644 --- a/lib/octicons_react/src/createIconComponent.js +++ b/lib/octicons_react/src/createIconComponent.js @@ -15,6 +15,7 @@ export function createIconComponent(name, defaultClassName, getSVGData) { { 'aria-label': ariaLabel, 'aria-labelledby': arialabelledby, + tabIndex, className = defaultClassName, fill = 'currentColor', size = 16, @@ -36,6 +37,8 @@ export function createIconComponent(name, defaultClassName, getSVGData) { = 0 ? 'true' : 'false'} aria-label={ariaLabel} aria-labelledby={arialabelledby} className={className} diff --git a/lib/octicons_react/src/index.d.ts b/lib/octicons_react/src/index.d.ts index 92a40ab8f..3b7302c5b 100644 --- a/lib/octicons_react/src/index.d.ts +++ b/lib/octicons_react/src/index.d.ts @@ -9,6 +9,7 @@ type Size = 'small' | 'medium' | 'large' export interface OcticonProps { 'aria-label'?: string 'aria-labelledby'?: string + tabIndex?: number children?: React.ReactElement className?: string title?: string | React.ReactElement