From a03e2024d4253fd4932935ef63a2a16e8789d1ab Mon Sep 17 00:00:00 2001 From: Jony J <1844749591@qq.com> Date: Mon, 4 Nov 2024 14:50:00 +0800 Subject: [PATCH] refactor(qr-code): improve a11y attributes handling in QRCode component (#51421) * refactor(qr-code): improve a11y attributes handling in QRCode component * test: update snapshot * feat(qr-code): improve a11y attributes handling in QRCode component * chore: remove useless code * test: add test case * chore: remove data attr and update test cases * chore: omit a11yProps from props --- components/qr-code/__tests__/index.test.tsx | 34 +++++++++++++++++++++ components/qr-code/index.tsx | 19 +++++++++--- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/components/qr-code/__tests__/index.test.tsx b/components/qr-code/__tests__/index.test.tsx index 0a537b1e27..b55f76f77d 100644 --- a/components/qr-code/__tests__/index.test.tsx +++ b/components/qr-code/__tests__/index.test.tsx @@ -155,4 +155,38 @@ describe('QRCode test', () => { ).toBe('Scanned'); expect(container).toMatchSnapshot(); }); + + it('should pass aria and data props to qrcode element', () => { + const { container } = render(); + const qrcodeElement = container.querySelector('.ant-qrcode canvas'); + expect(qrcodeElement).toHaveAttribute('aria-label', 'Test QR Code'); + }); + + it('should not pass other props to qrcode element', () => { + const { container } = render( + , + ); + + const qrcodeElement = container.querySelector('.ant-qrcode canvas'); + expect(qrcodeElement).toHaveAttribute('aria-label', 'Test QR Code'); + expect(qrcodeElement).not.toHaveAttribute('title', 'qr-title'); + }); + + it('should work with both canvas and svg type', () => { + const ariaLabel = 'Test QR Code'; + // test canvas type + const { container: canvasContainer } = render( + , + ); + expect(canvasContainer.querySelector('canvas')).toHaveAttribute('aria-label', ariaLabel); + // test svg type + const { container: svgContainer } = render( + , + ); + expect(svgContainer.querySelector('svg')).toHaveAttribute('aria-label', ariaLabel); + }); }); diff --git a/components/qr-code/index.tsx b/components/qr-code/index.tsx index 9cc88ffaeb..bcc9e2d160 100644 --- a/components/qr-code/index.tsx +++ b/components/qr-code/index.tsx @@ -1,6 +1,8 @@ -import React, { useContext } from 'react'; +import React, { useContext, type AriaAttributes } from 'react'; import { QRCodeCanvas, QRCodeSVG } from '@rc-component/qrcode'; import classNames from 'classnames'; +import omit from 'rc-util/lib/omit'; +import pickAttrs from 'rc-util/lib/pickAttrs'; import { devUseWarning } from '../_util/warning'; import type { ConfigConsumerProps } from '../config-provider'; @@ -8,8 +10,8 @@ import { ConfigContext } from '../config-provider'; import { useLocale } from '../locale'; import { useToken } from '../theme/internal'; import type { QRCodeProps, QRProps } from './interface'; -import useStyle from './style/index'; import QRcodeStatus from './QrcodeStatus'; +import useStyle from './style/index'; const QRCode: React.FC = (props) => { const [, token] = useToken(); @@ -41,12 +43,18 @@ const QRCode: React.FC = (props) => { src: icon, x: undefined, y: undefined, - height: typeof iconSize === 'number' ? iconSize : iconSize?.height ?? 40, - width: typeof iconSize === 'number' ? iconSize : iconSize?.width ?? 40, + height: typeof iconSize === 'number' ? iconSize : (iconSize?.height ?? 40), + width: typeof iconSize === 'number' ? iconSize : (iconSize?.width ?? 40), excavate: true, crossOrigin: 'anonymous', }; + const a11yProps = pickAttrs(rest, true); + const restProps = omit, keyof AriaAttributes>( + rest, + Object.keys(a11yProps) as Array, + ); + const qrCodeProps = { value, size, @@ -55,6 +63,7 @@ const QRCode: React.FC = (props) => { fgColor: color, style: { width: style?.width, height: style?.height }, imageSettings: icon ? imageSettings : undefined, + ...a11yProps, }; const [locale] = useLocale('QRCode'); @@ -87,7 +96,7 @@ const QRCode: React.FC = (props) => { }; return wrapCSSVar( - + {status !== 'active' && (