1
1
import React from 'react' ;
2
2
import { Link } from 'react-router-dom' ;
3
- import PropTypes from 'prop-types' ;
4
3
5
4
/**
6
- * Helper for switching between <button>, <a>, and <Link>
5
+ * Accepts all the props of an HTML <a> or <button> tag.
7
6
*/
7
+ export type ButtonOrLinkProps = {
8
+ /**
9
+ * Can be internal or external ('http'- or 'https'-).
10
+ */
11
+ href ?: string ;
12
+ isDisabled ?: boolean ;
13
+ /**
14
+ * Content of the button/link.
15
+ * Can be either a string or a complex element.
16
+ */
17
+ children : React . ReactNode ;
18
+ onClick ?: (
19
+ e : React . MouseEvent < HTMLAnchorElement | HTMLButtonElement >
20
+ ) => void ;
21
+ } ;
22
+
23
+ export type Ref = HTMLAnchorElement | HTMLButtonElement ;
8
24
25
+ /**
26
+ * Helper for switching between `<button>`, `<a>`, and `<Link>`
27
+ * If providing an `href`, will render as a link instead of a button.
28
+ * - Internal links will use react-router.
29
+ * - External links should start with 'http' or 'https' and will open in a new window.
30
+ */
9
31
const ButtonOrLink = React . forwardRef (
10
- ( { href, children, isDisabled, onClick, ...props } , ref ) => {
11
- const handleClick = ( e ) => {
32
+ (
33
+ {
34
+ href,
35
+ children,
36
+ isDisabled = false ,
37
+ onClick,
38
+ ...props
39
+ } : ButtonOrLinkProps ,
40
+ ref : React . Ref < Ref >
41
+ ) => {
42
+ const handleClick = (
43
+ e : React . MouseEvent < HTMLAnchorElement | HTMLButtonElement >
44
+ ) => {
12
45
if ( isDisabled ) {
13
46
e . preventDefault ( ) ;
14
47
e . stopPropagation ( ) ;
@@ -23,7 +56,7 @@ const ButtonOrLink = React.forwardRef(
23
56
if ( href . startsWith ( 'http' ) ) {
24
57
return (
25
58
< a
26
- ref = { ref }
59
+ ref = { ref as React . Ref < HTMLAnchorElement > }
27
60
href = { href }
28
61
target = "_blank"
29
62
rel = "noopener noreferrer"
@@ -37,7 +70,7 @@ const ButtonOrLink = React.forwardRef(
37
70
}
38
71
return (
39
72
< Link
40
- ref = { ref }
73
+ ref = { ref as React . Ref < HTMLAnchorElement > }
41
74
to = { href }
42
75
aria-disabled = { isDisabled }
43
76
{ ...props }
@@ -49,7 +82,7 @@ const ButtonOrLink = React.forwardRef(
49
82
}
50
83
return (
51
84
< button
52
- ref = { ref }
85
+ ref = { ref as React . Ref < HTMLButtonElement > }
53
86
aria-disabled = { isDisabled }
54
87
{ ...props }
55
88
onClick = { handleClick }
@@ -60,30 +93,4 @@ const ButtonOrLink = React.forwardRef(
60
93
}
61
94
) ;
62
95
63
- /**
64
- * Accepts all the props of an HTML <a> or <button> tag.
65
- */
66
- ButtonOrLink . propTypes = {
67
- /**
68
- * If providing an href, will render as a link instead of a button.
69
- * Can be internal or external.
70
- * Internal links will use react-router.
71
- * External links should start with 'http' or 'https' and will open in a new window.
72
- */
73
- href : PropTypes . string ,
74
- isDisabled : PropTypes . bool ,
75
- /**
76
- * Content of the button/link.
77
- * Can be either a string or a complex element.
78
- */
79
- children : PropTypes . node . isRequired ,
80
- onClick : PropTypes . func
81
- } ;
82
-
83
- ButtonOrLink . defaultProps = {
84
- href : null ,
85
- isDisabled : false ,
86
- onClick : null
87
- } ;
88
-
89
96
export default ButtonOrLink ;
0 commit comments