forked from flexport/__latitude
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTextLink.jsx
133 lines (124 loc) · 4.22 KB
/
TextLink.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
* TEAM: frontend_infra
* WATCHERS: notandrewkaye
* @flow strict
*/
/* eslint-disable react/forbid-elements */
import * as React from "react";
import {css, StyleSheet} from "aphrodite";
import {typeScale, fontWeights} from "./styles";
import linkStyles, {type LinkStyle} from "./styles/linkStyles";
import colors from "./colors";
import ThemeNameContext, {type Theme} from "./context/ThemeNameContext";
import TextLinkContext from "./TextLinkContext";
import RouterContext from "./context/RouterContext";
import Link from "./Link";
/* eslint-disable react/prefer-stateless-function */
type Props = {|
/** TextLink tags can only wrap strings. If you find this restrictive, contact @theseus. The thought is we want to avoid the temptation for folks to wrap entire apps or components in TextLink tags, since that usually means a different component should be built. */
+children: string,
/** The url that the link component will direct to. */
+href: string,
/** One of three standard link color schemes. */
+linkStyle: LinkStyle,
/** Should this link open in a new tab, i.e. target='_blank' */
+openInNewTab: boolean,
/** The size of the link which is is a subset of TypeScale's sizes. */
+scale?: "base" | "subtext" | "title",
/** The boldness of the link. */
+weight?: $Keys<typeof fontWeights>,
/** Select a custom display property depending on how you intend to use the link. */
+display:
| "inline"
| "inline-block"
| "flex"
| "block"
| "inline-flex"
| "none",
// determines if we download the target page content instead of navigation.
/** download attribute will override the target (new tab) behaviour if set to true */
+download: boolean,
/**
* our single page app routing (called spaMixin) hijacks all clicks on
* anchor tags. You might not want this, most often for switching between
* applications (you want a full page reload). Set this to true to disable that
* behavior.
*/
+disableSpaHijack: boolean,
|};
/**
* @short A TextLink which we can pass in a href for webpage navigation. TextLinks are more accessible (hovering over them shows the link preview in the browser), and don't require JavaScript.
* @brandStatus V2
* @status Stable
* @category Interaction
* @extends React.Component */
class TextLink extends React.PureComponent<Props> {
static defaultProps = {
linkStyle: "default",
openInNewTab: false,
display: "inline-block",
disableSpaHijack: false,
download: false,
};
static contextType = ThemeNameContext;
context: Theme;
render() {
const {
children,
href,
openInNewTab,
download,
display,
disableSpaHijack,
linkStyle,
} = this.props;
return (
<TextLinkContext.Consumer>
{parentStyles => (
<RouterContext.Consumer>
{router => {
let {scale, weight} = this.props;
// If we are not provided with a style prop and we will use the one from context
scale = scale || parentStyles.scale;
weight = weight || parentStyles.weight;
const isActive = router.isActive(href, true);
return (
<Link
download={download}
disableSpaHijack={disableSpaHijack}
openInNewTab={openInNewTab}
className={css(
styles.standardOverride,
linkStyles(this.context)[linkStyle],
isActive && styles.activeColor
)}
href={href}
style={{
display,
...typeScale[scale],
fontWeight: fontWeights[weight],
}}
>
{children}
</Link>
);
}}
</RouterContext.Consumer>
)}
</TextLinkContext.Consumer>
);
}
}
export default TextLink;
const styles = StyleSheet.create({
standardOverride: {
// override for our questionable OOCSS bottom margins on all semantic type tags
marginBottom: 0,
marginTop: 0,
cursor: "pointer",
},
// activeColor is only used in apps that support Found router
activeColor: {
color: colors.blue50,
},
});