feat: add the ability to create a download button (#48697)

* feat: add the ability to create a download button

* Allow the creating of download button

* update test, and stories props
This commit is contained in:
Muhammed Mustafa
2022-12-16 18:57:39 +02:00
committed by GitHub
parent 4291e153f7
commit 35c3a93a72
5 changed files with 40 additions and 16 deletions

View File

@@ -14,7 +14,8 @@ const story = {
'size',
'disabled',
'block',
'to',
'href',
'download',
'target',
'onClick'
]
@@ -41,7 +42,10 @@ const story = {
onClick: {
action: 'clicked'
},
to: {
href: {
control: { type: 'text' }
},
download: {
control: { type: 'text' }
}
}
@@ -95,7 +99,14 @@ FullWidth.args = {
export const AsALink = Template.bind({});
AsALink.args = {
children: "I'm a link that looks like a button",
to: 'https://www.freecodecamp.org'
href: 'https://www.freecodecamp.org'
};
export const AsADownloadLink = Template.bind({});
AsALink.args = {
children: "I'm a link that looks like a button",
href: 'https://www.freecodecamp.org',
download: 'download.txt'
};
export default story;

View File

@@ -72,8 +72,8 @@ describe('Button', () => {
expect(onClick).not.toBeCalled();
});
it('should render an anchor element if the `to` prop is defined', () => {
render(<Button to='https://www.freecodecamp.org'>freeCodeCamp</Button>);
it('should render an anchor element if the `href` prop is defined', () => {
render(<Button href='https://www.freecodecamp.org'>freeCodeCamp</Button>);
const link = screen.getByRole('link', { name: /freeCodeCamp/i });
const button = screen.queryByRole('button', { name: /freeCodeCamp/i });
@@ -84,9 +84,9 @@ describe('Button', () => {
expect(button).not.toBeInTheDocument();
});
it('should render a button element if the `to` and `disabled` props are both defined', () => {
it('should render a button element if the `href` and `disabled` props are both defined', () => {
render(
<Button to='https://www.freecodecamp.org' disabled>
<Button href='https://www.freecodecamp.org' disabled>
freeCodeCamp
</Button>
);

View File

@@ -116,7 +116,8 @@ export const Button = React.forwardRef<
children,
disabled,
block,
to,
href,
download,
target
},
ref
@@ -140,7 +141,7 @@ export const Button = React.forwardRef<
[onClick]
);
const renderButton = useCallback(() => {
const renderButton: () => JSX.Element = useCallback(() => {
return (
<button
ref={ref as React.ForwardedRef<HTMLButtonElement>}
@@ -154,7 +155,7 @@ export const Button = React.forwardRef<
);
}, [children, classes, ref, type, handleClick, disabled]);
const renderLink = useCallback(() => {
const renderLink: () => JSX.Element = useCallback(() => {
// Render a `button` tag if `disabled` is defined to keep the component semantically correct
// as a link cannot be disabled.
if (disabled) {
@@ -165,15 +166,25 @@ export const Button = React.forwardRef<
<a
ref={ref as React.ForwardedRef<HTMLAnchorElement>}
className={classes}
href={to}
href={href}
download={download}
target={target}
>
{children}
</a>
);
}, [children, classes, ref, disabled, to, target, renderButton]);
}, [
children,
classes,
ref,
disabled,
href,
target,
renderButton,
download
]);
if (to) {
if (href) {
return renderLink();
} else {
return renderButton();

View File

@@ -5,7 +5,7 @@ export type ButtonVariant = 'primary' | 'danger' | 'info';
export type ButtonSize = 'small' | 'medium' | 'large';
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
extends React.ButtonHTMLAttributes<HTMLButtonElement | HTMLAnchorElement> {
children: React.ReactNode;
variant?: ButtonVariant;
size?: ButtonSize;
@@ -13,6 +13,7 @@ export interface ButtonProps
type?: 'submit' | 'button';
disabled?: boolean;
block?: boolean;
to?: string;
href?: string;
download?: string;
target?: React.HTMLAttributeAnchorTarget;
}

View File

@@ -1,4 +1,5 @@
export interface LinkProps {
export interface LinkProps
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
children: React.ReactNode;
block?: boolean;
to?: string;