mirror of
https://github.com/ant-design/ant-design.git
synced 2025-08-06 16:06:28 +08:00
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
This commit is contained in:
parent
6380fc7a95
commit
a03e2024d4
@ -155,4 +155,38 @@ describe('QRCode test', () => {
|
|||||||
).toBe('Scanned');
|
).toBe('Scanned');
|
||||||
expect(container).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should pass aria and data props to qrcode element', () => {
|
||||||
|
const { container } = render(<QRCode value="test" aria-label="Test QR Code" />);
|
||||||
|
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(
|
||||||
|
<QRCode
|
||||||
|
value="test"
|
||||||
|
aria-label="Test QR Code"
|
||||||
|
title="qr-title" // This prop should not be passed to canvas
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
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(
|
||||||
|
<QRCode value="test" type="canvas" aria-label={ariaLabel} />,
|
||||||
|
);
|
||||||
|
expect(canvasContainer.querySelector('canvas')).toHaveAttribute('aria-label', ariaLabel);
|
||||||
|
// test svg type
|
||||||
|
const { container: svgContainer } = render(
|
||||||
|
<QRCode value="test" type="svg" aria-label={ariaLabel} />,
|
||||||
|
);
|
||||||
|
expect(svgContainer.querySelector('svg')).toHaveAttribute('aria-label', ariaLabel);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import React, { useContext } from 'react';
|
import React, { useContext, type AriaAttributes } from 'react';
|
||||||
import { QRCodeCanvas, QRCodeSVG } from '@rc-component/qrcode';
|
import { QRCodeCanvas, QRCodeSVG } from '@rc-component/qrcode';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import omit from 'rc-util/lib/omit';
|
||||||
|
import pickAttrs from 'rc-util/lib/pickAttrs';
|
||||||
|
|
||||||
import { devUseWarning } from '../_util/warning';
|
import { devUseWarning } from '../_util/warning';
|
||||||
import type { ConfigConsumerProps } from '../config-provider';
|
import type { ConfigConsumerProps } from '../config-provider';
|
||||||
@ -8,8 +10,8 @@ import { ConfigContext } from '../config-provider';
|
|||||||
import { useLocale } from '../locale';
|
import { useLocale } from '../locale';
|
||||||
import { useToken } from '../theme/internal';
|
import { useToken } from '../theme/internal';
|
||||||
import type { QRCodeProps, QRProps } from './interface';
|
import type { QRCodeProps, QRProps } from './interface';
|
||||||
import useStyle from './style/index';
|
|
||||||
import QRcodeStatus from './QrcodeStatus';
|
import QRcodeStatus from './QrcodeStatus';
|
||||||
|
import useStyle from './style/index';
|
||||||
|
|
||||||
const QRCode: React.FC<QRCodeProps> = (props) => {
|
const QRCode: React.FC<QRCodeProps> = (props) => {
|
||||||
const [, token] = useToken();
|
const [, token] = useToken();
|
||||||
@ -41,12 +43,18 @@ const QRCode: React.FC<QRCodeProps> = (props) => {
|
|||||||
src: icon,
|
src: icon,
|
||||||
x: undefined,
|
x: undefined,
|
||||||
y: undefined,
|
y: undefined,
|
||||||
height: typeof iconSize === 'number' ? iconSize : iconSize?.height ?? 40,
|
height: typeof iconSize === 'number' ? iconSize : (iconSize?.height ?? 40),
|
||||||
width: typeof iconSize === 'number' ? iconSize : iconSize?.width ?? 40,
|
width: typeof iconSize === 'number' ? iconSize : (iconSize?.width ?? 40),
|
||||||
excavate: true,
|
excavate: true,
|
||||||
crossOrigin: 'anonymous',
|
crossOrigin: 'anonymous',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const a11yProps = pickAttrs(rest, true);
|
||||||
|
const restProps = omit<React.HTMLAttributes<HTMLDivElement>, keyof AriaAttributes>(
|
||||||
|
rest,
|
||||||
|
Object.keys(a11yProps) as Array<keyof AriaAttributes>,
|
||||||
|
);
|
||||||
|
|
||||||
const qrCodeProps = {
|
const qrCodeProps = {
|
||||||
value,
|
value,
|
||||||
size,
|
size,
|
||||||
@ -55,6 +63,7 @@ const QRCode: React.FC<QRCodeProps> = (props) => {
|
|||||||
fgColor: color,
|
fgColor: color,
|
||||||
style: { width: style?.width, height: style?.height },
|
style: { width: style?.width, height: style?.height },
|
||||||
imageSettings: icon ? imageSettings : undefined,
|
imageSettings: icon ? imageSettings : undefined,
|
||||||
|
...a11yProps,
|
||||||
};
|
};
|
||||||
|
|
||||||
const [locale] = useLocale('QRCode');
|
const [locale] = useLocale('QRCode');
|
||||||
@ -87,7 +96,7 @@ const QRCode: React.FC<QRCodeProps> = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return wrapCSSVar(
|
return wrapCSSVar(
|
||||||
<div {...rest} className={mergedCls} style={mergedStyle}>
|
<div {...restProps} className={mergedCls} style={mergedStyle}>
|
||||||
{status !== 'active' && (
|
{status !== 'active' && (
|
||||||
<div className={`${prefixCls}-mask`}>
|
<div className={`${prefixCls}-mask`}>
|
||||||
<QRcodeStatus
|
<QRcodeStatus
|
||||||
|
Loading…
Reference in New Issue
Block a user