mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2025-12-30 03:03:06 -05:00
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:
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export interface LinkProps {
|
||||
export interface LinkProps
|
||||
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
||||
children: React.ReactNode;
|
||||
block?: boolean;
|
||||
to?: string;
|
||||
|
||||
Reference in New Issue
Block a user