@khanacademy/wonder-blocks-link 4.1.0 → 4.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @khanacademy/wonder-blocks-link
2
2
 
3
+ ## 4.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 6a026e35: Fix link style
8
+
9
+ ## 4.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - ef08a547: Adds start and end icon props to link
14
+
15
+ ### Patch Changes
16
+
17
+ - 3686db61: Stop showing a focus outline on the first link when revisiting a tab
18
+
3
19
  ## 4.1.0
4
20
 
5
21
  ### Minor Changes
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
2
  import type { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
3
3
  import type { Typography } from "@khanacademy/wonder-blocks-typography";
4
+ import type { IconAsset } from "@khanacademy/wonder-blocks-icon";
4
5
  export type SharedProps = AriaProps & {
5
6
  /**
6
7
  * Text to appear on the link. It can be a plain text or a Typography element.
@@ -119,6 +120,16 @@ export type SharedProps = AriaProps & {
119
120
  * An optional title attribute.
120
121
  */
121
122
  title?: string;
123
+ /**
124
+ * An optional icon displayed before the link label.
125
+ */
126
+ startIcon?: IconAsset;
127
+ /**
128
+ * An optional icon displayed after the link label.
129
+ * If `target="_blank"` and `endIcon` is passed in, `endIcon` will override
130
+ * the default `externalIcon`.
131
+ */
132
+ endIcon?: IconAsset;
122
133
  };
123
134
  type DefaultProps = {
124
135
  inline: SharedProps["inline"];
@@ -7,6 +7,7 @@
7
7
  import * as React from "react";
8
8
  import type { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
9
9
  import type { Typography } from "@khanacademy/wonder-blocks-typography";
10
+ import type { IconAsset } from "@khanacademy/wonder-blocks-icon";
10
11
  export type SharedProps = {|
11
12
  ...AriaProps,
12
13
  ...{|
@@ -146,6 +147,18 @@ export type SharedProps = {|
146
147
  * An optional title attribute.
147
148
  */
148
149
  title?: string,
150
+
151
+ /**
152
+ * An optional icon displayed before the link label.
153
+ */
154
+ startIcon?: IconAsset,
155
+
156
+ /**
157
+ * An optional icon displayed after the link label.
158
+ * If `target="_blank"` and `endIcon` is passed in, `endIcon` will override
159
+ * the default `externalIcon`.
160
+ */
161
+ endIcon?: IconAsset,
149
162
  |},
150
163
  |};
151
164
  declare type DefaultProps = {|
package/dist/es/index.js CHANGED
@@ -40,9 +40,10 @@ function _objectWithoutPropertiesLoose(source, excluded) {
40
40
  return target;
41
41
  }
42
42
 
43
- const _excluded$1 = ["children", "skipClientNav", "focused", "hovered", "href", "inline", "kind", "light", "visitable", "pressed", "style", "testId", "waiting", "target"];
43
+ const _excluded$1 = ["children", "skipClientNav", "focused", "hovered", "href", "inline", "kind", "light", "visitable", "pressed", "style", "testId", "waiting", "target", "startIcon", "endIcon"];
44
44
  const StyledAnchor = addStyle("a");
45
45
  const StyledLink = addStyle(Link$1);
46
+ const StyledSpan = addStyle("span");
46
47
  class LinkCore extends React.Component {
47
48
  renderInner(router) {
48
49
  const _this$props = this.props,
@@ -59,12 +60,14 @@ class LinkCore extends React.Component {
59
60
  pressed,
60
61
  style,
61
62
  testId,
62
- target
63
+ target,
64
+ startIcon,
65
+ endIcon
63
66
  } = _this$props,
64
67
  restProps = _objectWithoutPropertiesLoose(_this$props, _excluded$1);
65
68
  const linkStyles = _generateStyles(inline, kind, light, visitable);
66
69
  const restingStyles = inline ? linkStyles.restingInline : linkStyles.resting;
67
- const defaultStyles = [sharedStyles.shared, !(hovered || focused || pressed) && restingStyles, pressed && linkStyles.active, !pressed && hovered && linkStyles.hover, !pressed && focused && linkStyles.focus];
70
+ const defaultStyles = [sharedStyles.shared, restingStyles, pressed && linkStyles.active, !pressed && hovered && linkStyles.hover, !pressed && focused && linkStyles.focus];
68
71
  const commonProps = _extends({
69
72
  "data-test-id": testId,
70
73
  style: [defaultStyles, style],
@@ -76,10 +79,24 @@ class LinkCore extends React.Component {
76
79
  const externalIcon = React.createElement(Icon, {
77
80
  icon: externalIconPath,
78
81
  size: "small",
79
- style: iconStyles.icon,
82
+ style: [linkContentStyles.endIcon, linkContentStyles.centered],
80
83
  testId: "external-icon"
81
84
  });
82
- const linkContent = React.createElement(React.Fragment, null, children, target === "_blank" && externalIcon);
85
+ const linkContent = React.createElement(React.Fragment, null, startIcon && React.createElement(Icon, {
86
+ icon: startIcon,
87
+ size: "small",
88
+ style: [linkContentStyles.startIcon, linkContentStyles.centered],
89
+ testId: "start-icon",
90
+ "aria-hidden": "true"
91
+ }), React.createElement(StyledSpan, {
92
+ style: linkContentStyles.centered
93
+ }, children), endIcon ? React.createElement(Icon, {
94
+ icon: endIcon,
95
+ size: "small",
96
+ style: [linkContentStyles.endIcon, linkContentStyles.centered],
97
+ testId: "end-icon",
98
+ "aria-hidden": "true"
99
+ }) : target === "_blank" && externalIcon);
83
100
  return router && !skipClientNav && isClientSideUrl(href) ? React.createElement(StyledLink, _extends({}, commonProps, {
84
101
  to: href
85
102
  }), linkContent) : React.createElement(StyledAnchor, _extends({}, commonProps, {
@@ -91,9 +108,15 @@ class LinkCore extends React.Component {
91
108
  }
92
109
  }
93
110
  const styles = {};
94
- const iconStyles = StyleSheet.create({
95
- icon: {
96
- marginLeft: Spacing.xxxSmall_4
111
+ const linkContentStyles = StyleSheet.create({
112
+ startIcon: {
113
+ marginInlineEnd: Spacing.xxxSmall_4
114
+ },
115
+ endIcon: {
116
+ marginInlineStart: Spacing.xxxSmall_4
117
+ },
118
+ centered: {
119
+ verticalAlign: "middle"
97
120
  }
98
121
  });
99
122
  const sharedStyles = StyleSheet.create({
@@ -101,7 +124,8 @@ const sharedStyles = StyleSheet.create({
101
124
  cursor: "pointer",
102
125
  textDecoration: "none",
103
126
  outline: "none",
104
- display: "inline-flex",
127
+ verticalAlign: "bottom",
128
+ textUnderlineOffset: "3px",
105
129
  alignItems: "center"
106
130
  }
107
131
  });
@@ -157,11 +181,13 @@ const _generateStyles = (inline, kind, light, visitable) => {
157
181
  textDecoration: "underline currentcolor solid",
158
182
  color: defaultTextColor
159
183
  }, defaultVisited),
160
- focus: _extends({
161
- color: defaultTextColor,
162
- outline: `1px solid ${light ? white : blue}`,
163
- borderRadius: 3
164
- }, defaultVisited),
184
+ focus: {
185
+ ":focus-visible": _extends({
186
+ color: defaultTextColor,
187
+ outline: `1px solid ${light ? white : blue}`,
188
+ borderRadius: 3
189
+ }, defaultVisited)
190
+ },
165
191
  active: _extends({
166
192
  color: activeColor,
167
193
  textDecoration: "underline currentcolor solid"
package/dist/index.js CHANGED
@@ -67,9 +67,10 @@ function _objectWithoutPropertiesLoose(source, excluded) {
67
67
  return target;
68
68
  }
69
69
 
70
- const _excluded$1 = ["children", "skipClientNav", "focused", "hovered", "href", "inline", "kind", "light", "visitable", "pressed", "style", "testId", "waiting", "target"];
70
+ const _excluded$1 = ["children", "skipClientNav", "focused", "hovered", "href", "inline", "kind", "light", "visitable", "pressed", "style", "testId", "waiting", "target", "startIcon", "endIcon"];
71
71
  const StyledAnchor = wonderBlocksCore.addStyle("a");
72
72
  const StyledLink = wonderBlocksCore.addStyle(reactRouterDom.Link);
73
+ const StyledSpan = wonderBlocksCore.addStyle("span");
73
74
  class LinkCore extends React__namespace.Component {
74
75
  renderInner(router) {
75
76
  const _this$props = this.props,
@@ -86,12 +87,14 @@ class LinkCore extends React__namespace.Component {
86
87
  pressed,
87
88
  style,
88
89
  testId,
89
- target
90
+ target,
91
+ startIcon,
92
+ endIcon
90
93
  } = _this$props,
91
94
  restProps = _objectWithoutPropertiesLoose(_this$props, _excluded$1);
92
95
  const linkStyles = _generateStyles(inline, kind, light, visitable);
93
96
  const restingStyles = inline ? linkStyles.restingInline : linkStyles.resting;
94
- const defaultStyles = [sharedStyles.shared, !(hovered || focused || pressed) && restingStyles, pressed && linkStyles.active, !pressed && hovered && linkStyles.hover, !pressed && focused && linkStyles.focus];
97
+ const defaultStyles = [sharedStyles.shared, restingStyles, pressed && linkStyles.active, !pressed && hovered && linkStyles.hover, !pressed && focused && linkStyles.focus];
95
98
  const commonProps = _extends({
96
99
  "data-test-id": testId,
97
100
  style: [defaultStyles, style],
@@ -103,10 +106,24 @@ class LinkCore extends React__namespace.Component {
103
106
  const externalIcon = React__namespace.createElement(Icon__default["default"], {
104
107
  icon: externalIconPath,
105
108
  size: "small",
106
- style: iconStyles.icon,
109
+ style: [linkContentStyles.endIcon, linkContentStyles.centered],
107
110
  testId: "external-icon"
108
111
  });
109
- const linkContent = React__namespace.createElement(React__namespace.Fragment, null, children, target === "_blank" && externalIcon);
112
+ const linkContent = React__namespace.createElement(React__namespace.Fragment, null, startIcon && React__namespace.createElement(Icon__default["default"], {
113
+ icon: startIcon,
114
+ size: "small",
115
+ style: [linkContentStyles.startIcon, linkContentStyles.centered],
116
+ testId: "start-icon",
117
+ "aria-hidden": "true"
118
+ }), React__namespace.createElement(StyledSpan, {
119
+ style: linkContentStyles.centered
120
+ }, children), endIcon ? React__namespace.createElement(Icon__default["default"], {
121
+ icon: endIcon,
122
+ size: "small",
123
+ style: [linkContentStyles.endIcon, linkContentStyles.centered],
124
+ testId: "end-icon",
125
+ "aria-hidden": "true"
126
+ }) : target === "_blank" && externalIcon);
110
127
  return router && !skipClientNav && wonderBlocksClickable.isClientSideUrl(href) ? React__namespace.createElement(StyledLink, _extends({}, commonProps, {
111
128
  to: href
112
129
  }), linkContent) : React__namespace.createElement(StyledAnchor, _extends({}, commonProps, {
@@ -118,9 +135,15 @@ class LinkCore extends React__namespace.Component {
118
135
  }
119
136
  }
120
137
  const styles = {};
121
- const iconStyles = aphrodite.StyleSheet.create({
122
- icon: {
123
- marginLeft: Spacing__default["default"].xxxSmall_4
138
+ const linkContentStyles = aphrodite.StyleSheet.create({
139
+ startIcon: {
140
+ marginInlineEnd: Spacing__default["default"].xxxSmall_4
141
+ },
142
+ endIcon: {
143
+ marginInlineStart: Spacing__default["default"].xxxSmall_4
144
+ },
145
+ centered: {
146
+ verticalAlign: "middle"
124
147
  }
125
148
  });
126
149
  const sharedStyles = aphrodite.StyleSheet.create({
@@ -128,7 +151,8 @@ const sharedStyles = aphrodite.StyleSheet.create({
128
151
  cursor: "pointer",
129
152
  textDecoration: "none",
130
153
  outline: "none",
131
- display: "inline-flex",
154
+ verticalAlign: "bottom",
155
+ textUnderlineOffset: "3px",
132
156
  alignItems: "center"
133
157
  }
134
158
  });
@@ -184,11 +208,13 @@ const _generateStyles = (inline, kind, light, visitable) => {
184
208
  textDecoration: "underline currentcolor solid",
185
209
  color: defaultTextColor
186
210
  }, defaultVisited),
187
- focus: _extends({
188
- color: defaultTextColor,
189
- outline: `1px solid ${light ? white : blue}`,
190
- borderRadius: 3
191
- }, defaultVisited),
211
+ focus: {
212
+ ":focus-visible": _extends({
213
+ color: defaultTextColor,
214
+ outline: `1px solid ${light ? white : blue}`,
215
+ borderRadius: 3
216
+ }, defaultVisited)
217
+ },
192
218
  active: _extends({
193
219
  color: activeColor,
194
220
  textDecoration: "underline currentcolor solid"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-link",
3
- "version": "4.1.0",
3
+ "version": "4.2.1",
4
4
  "design": "v1",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -19,8 +19,8 @@
19
19
  "@khanacademy/wonder-blocks-clickable": "^3.0.9",
20
20
  "@khanacademy/wonder-blocks-color": "^2.0.1",
21
21
  "@khanacademy/wonder-blocks-core": "^5.1.0",
22
- "@khanacademy/wonder-blocks-icon": "2.0.9",
23
- "@khanacademy/wonder-blocks-spacing": "4.0.1"
22
+ "@khanacademy/wonder-blocks-icon": "^2.0.9",
23
+ "@khanacademy/wonder-blocks-spacing": "^4.0.1"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "aphrodite": "^1.2.5",