mirror of
https://github.com/lucide-icons/lucide.git
synced 2026-08-29 12:08:25 +02:00
feat(packages): Added aria-hidden fallback for decorative icons to all packages (#3604)
* Add aria hidden to lucide package * Add aria-hidden to astro package * Add tests for shared package * Fix test for props * add aria prop to lucide-solid * Add aria-hidden to lucide-vue-next * Add aria-hidden prop to angular package * Fix builds * Add notice about aria-label in docs * Format code * Update packages/svelte/tests/Icon.spec.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/lucide-svelte/tests/Icon.spec.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/shared/src/utils/hasA11yProp.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Adjusted docs * Fix import * update tests * test(shared): fix hasA11yProp unit test * fix(packages/lucide-angular): fix hasA11yProp import path (non-relative import path will not get properly resolved by ng-packagr) * Format code * Adjust aria props to root element * Format code --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Karsa <contact@karsa.org>
This commit is contained in:
@@ -46,7 +46,7 @@
|
||||
"@lucide/rollup-plugins": "workspace:*",
|
||||
"@lucide/shared": "workspace:*",
|
||||
"@preact/preset-vite": "^2.10.2",
|
||||
"@testing-library/jest-dom": "^6.1.4",
|
||||
"@testing-library/jest-dom": "^6.8.0",
|
||||
"@testing-library/preact": "^3.2.3",
|
||||
"jest-serializer-html": "^7.1.0",
|
||||
"preact": "^10.27.3",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { h, toChildArray } from 'preact';
|
||||
import defaultAttributes from './defaultAttributes';
|
||||
import type { IconNode, LucideProps } from './types';
|
||||
import { hasA11yProp } from '@lucide/shared';
|
||||
|
||||
interface IconComponentProps extends LucideProps {
|
||||
iconNode: IconNode;
|
||||
@@ -42,6 +43,7 @@ const Icon = ({
|
||||
? (Number(strokeWidth) * 24) / Number(size)
|
||||
: strokeWidth,
|
||||
class: ['lucide', classes].join(' '),
|
||||
...(!children && !hasA11yProp(rest) && { 'aria-hidden': 'true' }),
|
||||
...rest,
|
||||
},
|
||||
[...iconNode.map(([tag, attrs]) => h(tag, attrs)), ...toChildArray(children)],
|
||||
|
||||
@@ -31,3 +31,62 @@ describe('Using Icon Component', () => {
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Icon Component Accessibility', () => {
|
||||
it('should not have aria-hidden prop when aria prop is present', async () => {
|
||||
const { container } = render(
|
||||
<Icon
|
||||
iconNode={airVent}
|
||||
size={48}
|
||||
stroke="red"
|
||||
absoluteStrokeWidth
|
||||
aria-label="Air conditioning"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(container.firstChild).not.toHaveAttribute('aria-hidden');
|
||||
});
|
||||
|
||||
it('should not have aria-hidden prop when title prop is present', async () => {
|
||||
const { container } = render(
|
||||
<Icon
|
||||
iconNode={airVent}
|
||||
size={48}
|
||||
stroke="red"
|
||||
absoluteStrokeWidth
|
||||
title="Air conditioning"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(container.firstChild).not.toHaveAttribute('aria-hidden');
|
||||
});
|
||||
|
||||
it('should not have aria-hidden prop when there are children that could be a <title> element', async () => {
|
||||
const { container } = render(
|
||||
<Icon
|
||||
iconNode={airVent}
|
||||
size={48}
|
||||
stroke="red"
|
||||
absoluteStrokeWidth
|
||||
>
|
||||
<title>Some title</title>
|
||||
</Icon>,
|
||||
);
|
||||
|
||||
expect(container.firstChild).not.toHaveAttribute('aria-hidden');
|
||||
});
|
||||
|
||||
it('should never override aria-hidden prop', async () => {
|
||||
const { container } = render(
|
||||
<Icon
|
||||
iconNode={airVent}
|
||||
size={48}
|
||||
stroke="red"
|
||||
absoluteStrokeWidth
|
||||
aria-hidden={false}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(container.firstChild).toHaveAttribute('aria-hidden', 'false');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
exports[`Using Icon Component > should render icon and match snapshot 1`] = `
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="lucide "
|
||||
fill="none"
|
||||
height="48"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
exports[`Using createLucideIcon > should create a component from an iconNode 1`] = `
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-air-vent"
|
||||
fill="none"
|
||||
height="24"
|
||||
@@ -30,6 +31,7 @@ exports[`Using createLucideIcon > should create a component from an iconNode 1`]
|
||||
|
||||
exports[`Using createLucideIcon > should create a component from an iconNode with iconName 1`] = `
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-air-vent"
|
||||
fill="none"
|
||||
height="24"
|
||||
@@ -58,6 +60,7 @@ exports[`Using createLucideIcon > should create a component from an iconNode wit
|
||||
|
||||
exports[`Using createLucideIcon > should include backwards compatible className 1`] = `
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-layout2 lucide-layout-2"
|
||||
fill="none"
|
||||
height="24"
|
||||
|
||||
@@ -11,6 +11,7 @@ exports[`Using lucide icon components > should adjust the size, stroke color and
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-grid3x3 lucide-grid-3x3"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<rect width="18"
|
||||
height="18"
|
||||
@@ -41,6 +42,7 @@ exports[`Using lucide icon components > should not scale the strokeWidth when ab
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-grid3x3 lucide-grid-3x3"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<rect width="18"
|
||||
height="18"
|
||||
@@ -71,6 +73,7 @@ exports[`Using lucide icon components > should render an component 1`] = `
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-grid3x3 lucide-grid-3x3"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<rect width="18"
|
||||
height="18"
|
||||
|
||||
Reference in New Issue
Block a user