@instructure/ui-link 10.15.3-snapshot-0 → 10.15.3-snapshot-2
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 +5 -2
- package/es/Link/index.js +1 -1
- package/es/Link/props.js +3 -2
- package/es/Link/styles.js +54 -7
- package/es/Link/theme.js +5 -1
- package/lib/Link/index.js +1 -1
- package/lib/Link/props.js +3 -2
- package/lib/Link/styles.js +54 -7
- package/lib/Link/theme.js +5 -1
- package/package.json +16 -16
- package/src/Link/README.md +33 -0
- package/src/Link/index.tsx +2 -2
- package/src/Link/props.ts +14 -2
- package/src/Link/styles.ts +72 -12
- package/src/Link/theme.ts +5 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/Link/index.d.ts +2 -0
- package/types/Link/index.d.ts.map +1 -1
- package/types/Link/props.d.ts +4 -0
- package/types/Link/props.d.ts.map +1 -1
- package/types/Link/styles.d.ts.map +1 -1
- package/types/Link/theme.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,9 +3,12 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
## [10.15.3-snapshot-
|
|
6
|
+
## [10.15.3-snapshot-2](https://github.com/instructure/instructure-ui/compare/v10.15.2...v10.15.3-snapshot-2) (2025-04-11)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **ui-link:** add variants to <Link> ([308bb2f](https://github.com/instructure/instructure-ui/commit/308bb2f0e58cff05fd2358e17f449d6eaadf7d4a))
|
|
9
12
|
|
|
10
13
|
|
|
11
14
|
|
package/es/Link/index.js
CHANGED
|
@@ -195,7 +195,7 @@ let Link = (_dec = withStyle(generateStyle, generateComponentTheme), _dec2 = tes
|
|
|
195
195
|
type: type,
|
|
196
196
|
tabIndex: tabIndex,
|
|
197
197
|
css: (_this$props$styles2 = this.props.styles) === null || _this$props$styles2 === void 0 ? void 0 : _this$props$styles2.link
|
|
198
|
-
}), renderIcon && iconPlacement === 'start'
|
|
198
|
+
}), renderIcon && iconPlacement === 'start' ? this.renderIcon() : null, children, renderIcon && iconPlacement === 'end' ? this.renderIcon() : null);
|
|
199
199
|
}
|
|
200
200
|
}, _Link.displayName = "Link", _Link.componentId = 'Link', _Link.propTypes = propTypes, _Link.allowedProps = allowedProps, _Link.defaultProps = {
|
|
201
201
|
// Leave interaction default undefined so that `disabled` can also be supplied
|
package/es/Link/props.js
CHANGED
|
@@ -40,7 +40,8 @@ const propTypes = {
|
|
|
40
40
|
onBlur: PropTypes.func,
|
|
41
41
|
onClick: PropTypes.func,
|
|
42
42
|
onFocus: PropTypes.func,
|
|
43
|
-
onMouseEnter: PropTypes.func
|
|
43
|
+
onMouseEnter: PropTypes.func,
|
|
44
|
+
variant: PropTypes.oneOf(['inline', 'inline-small', 'standalone', 'standalone-small'])
|
|
44
45
|
};
|
|
45
|
-
const allowedProps = ['children', 'href', 'color', 'elementRef', 'as', 'role', 'forceButtonRole', 'interaction', 'margin', 'renderIcon', 'iconPlacement', 'display', 'isWithinText', 'onBlur', 'onClick', 'onFocus', 'onMouseEnter'];
|
|
46
|
+
const allowedProps = ['children', 'href', 'color', 'elementRef', 'as', 'role', 'forceButtonRole', 'interaction', 'margin', 'renderIcon', 'iconPlacement', 'display', 'isWithinText', 'onBlur', 'onClick', 'onFocus', 'onMouseEnter', 'variant'];
|
|
46
47
|
export { propTypes, allowedProps };
|
package/es/Link/styles.js
CHANGED
|
@@ -36,10 +36,33 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
36
36
|
const isWithinText = props.isWithinText,
|
|
37
37
|
renderIcon = props.renderIcon,
|
|
38
38
|
iconPlacement = props.iconPlacement,
|
|
39
|
-
color = props.color
|
|
39
|
+
color = props.color,
|
|
40
|
+
variant = props.variant;
|
|
40
41
|
const containsTruncateText = state.containsTruncateText,
|
|
41
42
|
hasVisibleChildren = state.hasVisibleChildren;
|
|
42
43
|
const inverseStyle = color === 'link-inverse';
|
|
44
|
+
const variantStyles = {
|
|
45
|
+
inline: {
|
|
46
|
+
fontSize: componentTheme.fontSize,
|
|
47
|
+
lineHeight: componentTheme.lineHeight,
|
|
48
|
+
textDecoration: 'underline'
|
|
49
|
+
},
|
|
50
|
+
'inline-small': {
|
|
51
|
+
fontSize: componentTheme.fontSizeSmall,
|
|
52
|
+
lineHeight: '1.3125rem',
|
|
53
|
+
textDecoration: 'underline'
|
|
54
|
+
},
|
|
55
|
+
standalone: {
|
|
56
|
+
fontSize: componentTheme.fontSize,
|
|
57
|
+
lineHeight: componentTheme.lineHeight,
|
|
58
|
+
textDecoration: 'none'
|
|
59
|
+
},
|
|
60
|
+
'standalone-small': {
|
|
61
|
+
fontSize: componentTheme.fontSizeSmall,
|
|
62
|
+
lineHeight: componentTheme.lineHeight,
|
|
63
|
+
textDecoration: 'none'
|
|
64
|
+
}
|
|
65
|
+
};
|
|
43
66
|
const baseStyles = {
|
|
44
67
|
boxSizing: 'border-box',
|
|
45
68
|
fontFamily: componentTheme.fontFamily,
|
|
@@ -75,7 +98,6 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
75
98
|
...baseStyles,
|
|
76
99
|
cursor: 'pointer',
|
|
77
100
|
color: componentTheme.color,
|
|
78
|
-
textDecoration: isWithinText ? componentTheme.textDecorationWithinText : componentTheme.textDecorationOutsideText,
|
|
79
101
|
'&:focus': {
|
|
80
102
|
color: componentTheme.color,
|
|
81
103
|
outlineColor: componentTheme.focusOutlineColor
|
|
@@ -83,7 +105,10 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
83
105
|
'&:hover, &:active': {
|
|
84
106
|
color: componentTheme.hoverColor,
|
|
85
107
|
textDecoration: isWithinText ? componentTheme.hoverTextDecorationWithinText : componentTheme.hoverTextDecorationOutsideText
|
|
86
|
-
}
|
|
108
|
+
},
|
|
109
|
+
...(variant ? variantStyles[variant] : {
|
|
110
|
+
textDecoration: isWithinText ? componentTheme.textDecorationWithinText : componentTheme.textDecorationOutsideText
|
|
111
|
+
})
|
|
87
112
|
};
|
|
88
113
|
const buttonStyle = {
|
|
89
114
|
appearance: 'none',
|
|
@@ -91,10 +116,12 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
91
116
|
background: 'none',
|
|
92
117
|
border: 'none',
|
|
93
118
|
cursor: 'pointer',
|
|
94
|
-
fontSize: '1em',
|
|
95
119
|
margin: 0,
|
|
96
120
|
padding: 0,
|
|
97
|
-
textAlign: 'inherit'
|
|
121
|
+
textAlign: 'inherit',
|
|
122
|
+
...(variant ? variantStyles[variant] : {
|
|
123
|
+
fontSize: '1em'
|
|
124
|
+
})
|
|
98
125
|
};
|
|
99
126
|
const inverseStyles = {
|
|
100
127
|
color: componentTheme.colorInverse,
|
|
@@ -105,6 +132,24 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
105
132
|
color: componentTheme.colorInverse
|
|
106
133
|
}
|
|
107
134
|
};
|
|
135
|
+
const variantIconStyles = {
|
|
136
|
+
inline: {
|
|
137
|
+
paddingInlineStart: iconPlacement === 'start' ? 0 : componentTheme.iconPlusTextMargin,
|
|
138
|
+
paddingInlineEnd: iconPlacement === 'start' ? componentTheme.iconPlusTextMargin : 0
|
|
139
|
+
},
|
|
140
|
+
'inline-small': {
|
|
141
|
+
paddingInlineStart: iconPlacement === 'start' ? 0 : componentTheme.iconPlusTextMarginSmall,
|
|
142
|
+
paddingInlineEnd: iconPlacement === 'start' ? componentTheme.iconPlusTextMarginSmall : 0
|
|
143
|
+
},
|
|
144
|
+
standalone: {
|
|
145
|
+
paddingInlineStart: iconPlacement === 'start' ? 0 : componentTheme.iconPlusTextMargin,
|
|
146
|
+
paddingInlineEnd: iconPlacement === 'start' ? componentTheme.iconPlusTextMargin : 0
|
|
147
|
+
},
|
|
148
|
+
'standalone-small': {
|
|
149
|
+
paddingInlineStart: iconPlacement === 'start' ? 0 : componentTheme.iconPlusTextMarginSmall,
|
|
150
|
+
paddingInlineEnd: iconPlacement === 'start' ? componentTheme.iconPlusTextMarginSmall : 0
|
|
151
|
+
}
|
|
152
|
+
};
|
|
108
153
|
return {
|
|
109
154
|
link: {
|
|
110
155
|
label: 'link',
|
|
@@ -125,8 +170,10 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
125
170
|
...(renderIcon && {
|
|
126
171
|
fontSize: componentTheme.iconSize,
|
|
127
172
|
boxSizing: 'border-box',
|
|
128
|
-
|
|
129
|
-
|
|
173
|
+
...(variant ? variantIconStyles[variant] : {
|
|
174
|
+
paddingInlineStart: iconPlacement === 'start' ? 0 : componentTheme.iconPlusTextMargin,
|
|
175
|
+
paddingInlineEnd: iconPlacement === 'start' ? componentTheme.iconPlusTextMargin : 0
|
|
176
|
+
})
|
|
130
177
|
})
|
|
131
178
|
}
|
|
132
179
|
};
|
package/es/Link/theme.js
CHANGED
|
@@ -54,6 +54,9 @@ const generateComponentTheme = theme => {
|
|
|
54
54
|
const componentVariables = {
|
|
55
55
|
fontFamily: typography === null || typography === void 0 ? void 0 : typography.fontFamily,
|
|
56
56
|
fontWeight: typography === null || typography === void 0 ? void 0 : typography.fontWeightNormal,
|
|
57
|
+
fontSize: typography === null || typography === void 0 ? void 0 : typography.content,
|
|
58
|
+
lineHeight: typography === null || typography === void 0 ? void 0 : typography.lineHeight150,
|
|
59
|
+
fontSizeSmall: typography === null || typography === void 0 ? void 0 : typography.contentSmall,
|
|
57
60
|
color: colors === null || colors === void 0 ? void 0 : (_colors$contrasts = colors.contrasts) === null || _colors$contrasts === void 0 ? void 0 : _colors$contrasts.blue5782,
|
|
58
61
|
textDecorationWithinText: 'underline',
|
|
59
62
|
hoverTextDecorationWithinText: 'none',
|
|
@@ -69,7 +72,8 @@ const generateComponentTheme = theme => {
|
|
|
69
72
|
focusInverseIconOutlineColor: colors === null || colors === void 0 ? void 0 : (_colors$contrasts6 = colors.contrasts) === null || _colors$contrasts6 === void 0 ? void 0 : _colors$contrasts6.white1010,
|
|
70
73
|
iconSize: '1.125em',
|
|
71
74
|
// make icon slightly larger than inherited font-size,
|
|
72
|
-
iconPlusTextMargin: spacing
|
|
75
|
+
iconPlusTextMargin: spacing.space4,
|
|
76
|
+
iconPlusTextMarginSmall: spacing.space2,
|
|
73
77
|
textUnderlineOffset: 'auto'
|
|
74
78
|
};
|
|
75
79
|
return {
|
package/lib/Link/index.js
CHANGED
|
@@ -207,7 +207,7 @@ let Link = exports.Link = (_dec = (0, _emotion.withStyle)(_styles.default, _them
|
|
|
207
207
|
type: type,
|
|
208
208
|
tabIndex: tabIndex,
|
|
209
209
|
css: (_this$props$styles2 = this.props.styles) === null || _this$props$styles2 === void 0 ? void 0 : _this$props$styles2.link
|
|
210
|
-
}), renderIcon && iconPlacement === 'start'
|
|
210
|
+
}), renderIcon && iconPlacement === 'start' ? this.renderIcon() : null, children, renderIcon && iconPlacement === 'end' ? this.renderIcon() : null);
|
|
211
211
|
}
|
|
212
212
|
}, _Link.displayName = "Link", _Link.componentId = 'Link', _Link.propTypes = _props.propTypes, _Link.allowedProps = _props.allowedProps, _Link.defaultProps = {
|
|
213
213
|
// Leave interaction default undefined so that `disabled` can also be supplied
|
package/lib/Link/props.js
CHANGED
|
@@ -47,6 +47,7 @@ const propTypes = exports.propTypes = {
|
|
|
47
47
|
onBlur: _propTypes.default.func,
|
|
48
48
|
onClick: _propTypes.default.func,
|
|
49
49
|
onFocus: _propTypes.default.func,
|
|
50
|
-
onMouseEnter: _propTypes.default.func
|
|
50
|
+
onMouseEnter: _propTypes.default.func,
|
|
51
|
+
variant: _propTypes.default.oneOf(['inline', 'inline-small', 'standalone', 'standalone-small'])
|
|
51
52
|
};
|
|
52
|
-
const allowedProps = exports.allowedProps = ['children', 'href', 'color', 'elementRef', 'as', 'role', 'forceButtonRole', 'interaction', 'margin', 'renderIcon', 'iconPlacement', 'display', 'isWithinText', 'onBlur', 'onClick', 'onFocus', 'onMouseEnter'];
|
|
53
|
+
const allowedProps = exports.allowedProps = ['children', 'href', 'color', 'elementRef', 'as', 'role', 'forceButtonRole', 'interaction', 'margin', 'renderIcon', 'iconPlacement', 'display', 'isWithinText', 'onBlur', 'onClick', 'onFocus', 'onMouseEnter', 'variant'];
|
package/lib/Link/styles.js
CHANGED
|
@@ -42,10 +42,33 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
42
42
|
const isWithinText = props.isWithinText,
|
|
43
43
|
renderIcon = props.renderIcon,
|
|
44
44
|
iconPlacement = props.iconPlacement,
|
|
45
|
-
color = props.color
|
|
45
|
+
color = props.color,
|
|
46
|
+
variant = props.variant;
|
|
46
47
|
const containsTruncateText = state.containsTruncateText,
|
|
47
48
|
hasVisibleChildren = state.hasVisibleChildren;
|
|
48
49
|
const inverseStyle = color === 'link-inverse';
|
|
50
|
+
const variantStyles = {
|
|
51
|
+
inline: {
|
|
52
|
+
fontSize: componentTheme.fontSize,
|
|
53
|
+
lineHeight: componentTheme.lineHeight,
|
|
54
|
+
textDecoration: 'underline'
|
|
55
|
+
},
|
|
56
|
+
'inline-small': {
|
|
57
|
+
fontSize: componentTheme.fontSizeSmall,
|
|
58
|
+
lineHeight: '1.3125rem',
|
|
59
|
+
textDecoration: 'underline'
|
|
60
|
+
},
|
|
61
|
+
standalone: {
|
|
62
|
+
fontSize: componentTheme.fontSize,
|
|
63
|
+
lineHeight: componentTheme.lineHeight,
|
|
64
|
+
textDecoration: 'none'
|
|
65
|
+
},
|
|
66
|
+
'standalone-small': {
|
|
67
|
+
fontSize: componentTheme.fontSizeSmall,
|
|
68
|
+
lineHeight: componentTheme.lineHeight,
|
|
69
|
+
textDecoration: 'none'
|
|
70
|
+
}
|
|
71
|
+
};
|
|
49
72
|
const baseStyles = {
|
|
50
73
|
boxSizing: 'border-box',
|
|
51
74
|
fontFamily: componentTheme.fontFamily,
|
|
@@ -81,7 +104,6 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
81
104
|
...baseStyles,
|
|
82
105
|
cursor: 'pointer',
|
|
83
106
|
color: componentTheme.color,
|
|
84
|
-
textDecoration: isWithinText ? componentTheme.textDecorationWithinText : componentTheme.textDecorationOutsideText,
|
|
85
107
|
'&:focus': {
|
|
86
108
|
color: componentTheme.color,
|
|
87
109
|
outlineColor: componentTheme.focusOutlineColor
|
|
@@ -89,7 +111,10 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
89
111
|
'&:hover, &:active': {
|
|
90
112
|
color: componentTheme.hoverColor,
|
|
91
113
|
textDecoration: isWithinText ? componentTheme.hoverTextDecorationWithinText : componentTheme.hoverTextDecorationOutsideText
|
|
92
|
-
}
|
|
114
|
+
},
|
|
115
|
+
...(variant ? variantStyles[variant] : {
|
|
116
|
+
textDecoration: isWithinText ? componentTheme.textDecorationWithinText : componentTheme.textDecorationOutsideText
|
|
117
|
+
})
|
|
93
118
|
};
|
|
94
119
|
const buttonStyle = {
|
|
95
120
|
appearance: 'none',
|
|
@@ -97,10 +122,12 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
97
122
|
background: 'none',
|
|
98
123
|
border: 'none',
|
|
99
124
|
cursor: 'pointer',
|
|
100
|
-
fontSize: '1em',
|
|
101
125
|
margin: 0,
|
|
102
126
|
padding: 0,
|
|
103
|
-
textAlign: 'inherit'
|
|
127
|
+
textAlign: 'inherit',
|
|
128
|
+
...(variant ? variantStyles[variant] : {
|
|
129
|
+
fontSize: '1em'
|
|
130
|
+
})
|
|
104
131
|
};
|
|
105
132
|
const inverseStyles = {
|
|
106
133
|
color: componentTheme.colorInverse,
|
|
@@ -111,6 +138,24 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
111
138
|
color: componentTheme.colorInverse
|
|
112
139
|
}
|
|
113
140
|
};
|
|
141
|
+
const variantIconStyles = {
|
|
142
|
+
inline: {
|
|
143
|
+
paddingInlineStart: iconPlacement === 'start' ? 0 : componentTheme.iconPlusTextMargin,
|
|
144
|
+
paddingInlineEnd: iconPlacement === 'start' ? componentTheme.iconPlusTextMargin : 0
|
|
145
|
+
},
|
|
146
|
+
'inline-small': {
|
|
147
|
+
paddingInlineStart: iconPlacement === 'start' ? 0 : componentTheme.iconPlusTextMarginSmall,
|
|
148
|
+
paddingInlineEnd: iconPlacement === 'start' ? componentTheme.iconPlusTextMarginSmall : 0
|
|
149
|
+
},
|
|
150
|
+
standalone: {
|
|
151
|
+
paddingInlineStart: iconPlacement === 'start' ? 0 : componentTheme.iconPlusTextMargin,
|
|
152
|
+
paddingInlineEnd: iconPlacement === 'start' ? componentTheme.iconPlusTextMargin : 0
|
|
153
|
+
},
|
|
154
|
+
'standalone-small': {
|
|
155
|
+
paddingInlineStart: iconPlacement === 'start' ? 0 : componentTheme.iconPlusTextMarginSmall,
|
|
156
|
+
paddingInlineEnd: iconPlacement === 'start' ? componentTheme.iconPlusTextMarginSmall : 0
|
|
157
|
+
}
|
|
158
|
+
};
|
|
114
159
|
return {
|
|
115
160
|
link: {
|
|
116
161
|
label: 'link',
|
|
@@ -131,8 +176,10 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
131
176
|
...(renderIcon && {
|
|
132
177
|
fontSize: componentTheme.iconSize,
|
|
133
178
|
boxSizing: 'border-box',
|
|
134
|
-
|
|
135
|
-
|
|
179
|
+
...(variant ? variantIconStyles[variant] : {
|
|
180
|
+
paddingInlineStart: iconPlacement === 'start' ? 0 : componentTheme.iconPlusTextMargin,
|
|
181
|
+
paddingInlineEnd: iconPlacement === 'start' ? componentTheme.iconPlusTextMargin : 0
|
|
182
|
+
})
|
|
136
183
|
})
|
|
137
184
|
}
|
|
138
185
|
};
|
package/lib/Link/theme.js
CHANGED
|
@@ -60,6 +60,9 @@ const generateComponentTheme = theme => {
|
|
|
60
60
|
const componentVariables = {
|
|
61
61
|
fontFamily: typography === null || typography === void 0 ? void 0 : typography.fontFamily,
|
|
62
62
|
fontWeight: typography === null || typography === void 0 ? void 0 : typography.fontWeightNormal,
|
|
63
|
+
fontSize: typography === null || typography === void 0 ? void 0 : typography.content,
|
|
64
|
+
lineHeight: typography === null || typography === void 0 ? void 0 : typography.lineHeight150,
|
|
65
|
+
fontSizeSmall: typography === null || typography === void 0 ? void 0 : typography.contentSmall,
|
|
63
66
|
color: colors === null || colors === void 0 ? void 0 : (_colors$contrasts = colors.contrasts) === null || _colors$contrasts === void 0 ? void 0 : _colors$contrasts.blue5782,
|
|
64
67
|
textDecorationWithinText: 'underline',
|
|
65
68
|
hoverTextDecorationWithinText: 'none',
|
|
@@ -75,7 +78,8 @@ const generateComponentTheme = theme => {
|
|
|
75
78
|
focusInverseIconOutlineColor: colors === null || colors === void 0 ? void 0 : (_colors$contrasts6 = colors.contrasts) === null || _colors$contrasts6 === void 0 ? void 0 : _colors$contrasts6.white1010,
|
|
76
79
|
iconSize: '1.125em',
|
|
77
80
|
// make icon slightly larger than inherited font-size,
|
|
78
|
-
iconPlusTextMargin: spacing
|
|
81
|
+
iconPlusTextMargin: spacing.space4,
|
|
82
|
+
iconPlusTextMarginSmall: spacing.space2,
|
|
79
83
|
textUnderlineOffset: 'auto'
|
|
80
84
|
};
|
|
81
85
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instructure/ui-link",
|
|
3
|
-
"version": "10.15.3-snapshot-
|
|
3
|
+
"version": "10.15.3-snapshot-2",
|
|
4
4
|
"description": "A component for creating links",
|
|
5
5
|
"author": "Instructure, Inc. Engineering and Product Design",
|
|
6
6
|
"module": "./es/index.js",
|
|
@@ -24,24 +24,24 @@
|
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@babel/runtime": "^7.26.0",
|
|
27
|
-
"@instructure/console": "10.15.3-snapshot-
|
|
28
|
-
"@instructure/emotion": "10.15.3-snapshot-
|
|
29
|
-
"@instructure/shared-types": "10.15.3-snapshot-
|
|
30
|
-
"@instructure/ui-a11y-utils": "10.15.3-snapshot-
|
|
31
|
-
"@instructure/ui-color-utils": "10.15.3-snapshot-
|
|
32
|
-
"@instructure/ui-dom-utils": "10.15.3-snapshot-
|
|
33
|
-
"@instructure/ui-icons": "10.15.3-snapshot-
|
|
34
|
-
"@instructure/ui-prop-types": "10.15.3-snapshot-
|
|
35
|
-
"@instructure/ui-react-utils": "10.15.3-snapshot-
|
|
36
|
-
"@instructure/ui-testable": "10.15.3-snapshot-
|
|
37
|
-
"@instructure/ui-view": "10.15.3-snapshot-
|
|
27
|
+
"@instructure/console": "10.15.3-snapshot-2",
|
|
28
|
+
"@instructure/emotion": "10.15.3-snapshot-2",
|
|
29
|
+
"@instructure/shared-types": "10.15.3-snapshot-2",
|
|
30
|
+
"@instructure/ui-a11y-utils": "10.15.3-snapshot-2",
|
|
31
|
+
"@instructure/ui-color-utils": "10.15.3-snapshot-2",
|
|
32
|
+
"@instructure/ui-dom-utils": "10.15.3-snapshot-2",
|
|
33
|
+
"@instructure/ui-icons": "10.15.3-snapshot-2",
|
|
34
|
+
"@instructure/ui-prop-types": "10.15.3-snapshot-2",
|
|
35
|
+
"@instructure/ui-react-utils": "10.15.3-snapshot-2",
|
|
36
|
+
"@instructure/ui-testable": "10.15.3-snapshot-2",
|
|
37
|
+
"@instructure/ui-view": "10.15.3-snapshot-2",
|
|
38
38
|
"prop-types": "^15.8.1"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@instructure/ui-axe-check": "10.15.3-snapshot-
|
|
42
|
-
"@instructure/ui-babel-preset": "10.15.3-snapshot-
|
|
43
|
-
"@instructure/ui-test-utils": "10.15.3-snapshot-
|
|
44
|
-
"@instructure/ui-themes": "10.15.3-snapshot-
|
|
41
|
+
"@instructure/ui-axe-check": "10.15.3-snapshot-2",
|
|
42
|
+
"@instructure/ui-babel-preset": "10.15.3-snapshot-2",
|
|
43
|
+
"@instructure/ui-test-utils": "10.15.3-snapshot-2",
|
|
44
|
+
"@instructure/ui-themes": "10.15.3-snapshot-2",
|
|
45
45
|
"@testing-library/jest-dom": "^6.6.3",
|
|
46
46
|
"@testing-library/react": "^16.0.1",
|
|
47
47
|
"@testing-library/user-event": "^14.5.2",
|
package/src/Link/README.md
CHANGED
|
@@ -22,6 +22,37 @@ type: example
|
|
|
22
22
|
</View>
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
### Variant
|
|
26
|
+
|
|
27
|
+
In order to make it easy to get the most commonly used links, we have the variant prop. It will set all the necessary styles (fontSize, lineHeight, and textDecoration).
|
|
28
|
+
|
|
29
|
+
```js
|
|
30
|
+
---
|
|
31
|
+
type: example
|
|
32
|
+
---
|
|
33
|
+
<div>
|
|
34
|
+
<div>
|
|
35
|
+
In a line of text you should use the <Link variant="inline" renderIcon={<IconUserLine />} href="https://instructure.github.io/instructure-ui/">inline</Link> link variant.
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<br></br>
|
|
39
|
+
<div>
|
|
40
|
+
<Text variant="contentSmall">In a line of text, where the text is smaller, use the <Link variant="inline-small" renderIcon={<IconUserLine />} href="https://instructure.github.io/instructure-ui/">inline-small</Link> link variant
|
|
41
|
+
</Text>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<br></br>
|
|
45
|
+
<div>
|
|
46
|
+
If the link is standalone (not in a text), use the <code>standalone</code> <Link display="block" variant="standalone" renderIcon={<IconUserLine />} href="https://instructure.github.io/instructure-ui/">standalone</Link>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<br></br>
|
|
50
|
+
<div>
|
|
51
|
+
If the link is standalone (not in a text), but smaller, use the <code>standalone-small</code> <Link display="block" variant="standalone-small" renderIcon={<IconUserLine />} href="https://instructure.github.io/instructure-ui/">standalone-small</Link>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
```
|
|
55
|
+
|
|
25
56
|
### Adding margin
|
|
26
57
|
|
|
27
58
|
Use the `margin` prop to add space to the left or right of the Link. Because
|
|
@@ -76,6 +107,8 @@ Use the `renderIcon` property to put an [icon](#icons) inside a Link. To positio
|
|
|
76
107
|
icon _after_ the link text, change the `iconPlacement` property to `end`. You can also
|
|
77
108
|
render a Link with just an icon. Don't forget to add text for screen readers, though.
|
|
78
109
|
|
|
110
|
+
NOTE: if you want the icon to have the same `font-size` as the link, do not specify its `size`!
|
|
111
|
+
|
|
79
112
|
```js
|
|
80
113
|
---
|
|
81
114
|
type: example
|
package/src/Link/index.tsx
CHANGED
|
@@ -252,9 +252,9 @@ class Link extends Component<LinkProps, LinkState> {
|
|
|
252
252
|
tabIndex={tabIndex}
|
|
253
253
|
css={this.props.styles?.link}
|
|
254
254
|
>
|
|
255
|
-
{renderIcon && iconPlacement === 'start'
|
|
255
|
+
{renderIcon && iconPlacement === 'start' ? this.renderIcon() : null}
|
|
256
256
|
{children}
|
|
257
|
-
{renderIcon && iconPlacement === 'end'
|
|
257
|
+
{renderIcon && iconPlacement === 'end' ? this.renderIcon() : null}
|
|
258
258
|
</View>
|
|
259
259
|
)
|
|
260
260
|
}
|
package/src/Link/props.ts
CHANGED
|
@@ -129,6 +129,11 @@ type LinkOwnProps = {
|
|
|
129
129
|
* Fires when the Link is hovered
|
|
130
130
|
*/
|
|
131
131
|
onMouseEnter?: (event: React.MouseEvent<ViewOwnProps>) => void
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Sets pre-defined values for the component to achieve specific roles for the component
|
|
135
|
+
*/
|
|
136
|
+
variant?: 'inline' | 'inline-small' | 'standalone' | 'standalone-small'
|
|
132
137
|
}
|
|
133
138
|
|
|
134
139
|
export type LinkStyleProps = {
|
|
@@ -174,7 +179,13 @@ const propTypes: PropValidators<PropKeys> = {
|
|
|
174
179
|
onBlur: PropTypes.func,
|
|
175
180
|
onClick: PropTypes.func,
|
|
176
181
|
onFocus: PropTypes.func,
|
|
177
|
-
onMouseEnter: PropTypes.func
|
|
182
|
+
onMouseEnter: PropTypes.func,
|
|
183
|
+
variant: PropTypes.oneOf([
|
|
184
|
+
'inline',
|
|
185
|
+
'inline-small',
|
|
186
|
+
'standalone',
|
|
187
|
+
'standalone-small'
|
|
188
|
+
])
|
|
178
189
|
}
|
|
179
190
|
|
|
180
191
|
const allowedProps: AllowedPropKeys = [
|
|
@@ -194,7 +205,8 @@ const allowedProps: AllowedPropKeys = [
|
|
|
194
205
|
'onBlur',
|
|
195
206
|
'onClick',
|
|
196
207
|
'onFocus',
|
|
197
|
-
'onMouseEnter'
|
|
208
|
+
'onMouseEnter',
|
|
209
|
+
'variant'
|
|
198
210
|
]
|
|
199
211
|
|
|
200
212
|
export type { LinkProps, LinkState, LinkStyle }
|
package/src/Link/styles.ts
CHANGED
|
@@ -40,10 +40,33 @@ const generateStyle = (
|
|
|
40
40
|
props: LinkProps,
|
|
41
41
|
state: LinkStyleProps
|
|
42
42
|
): LinkStyle => {
|
|
43
|
-
const { isWithinText, renderIcon, iconPlacement, color } = props
|
|
43
|
+
const { isWithinText, renderIcon, iconPlacement, color, variant } = props
|
|
44
44
|
const { containsTruncateText, hasVisibleChildren } = state
|
|
45
45
|
const inverseStyle = color === 'link-inverse'
|
|
46
46
|
|
|
47
|
+
const variantStyles = {
|
|
48
|
+
inline: {
|
|
49
|
+
fontSize: componentTheme.fontSize,
|
|
50
|
+
lineHeight: componentTheme.lineHeight,
|
|
51
|
+
textDecoration: 'underline'
|
|
52
|
+
},
|
|
53
|
+
'inline-small': {
|
|
54
|
+
fontSize: componentTheme.fontSizeSmall,
|
|
55
|
+
lineHeight: '1.3125rem',
|
|
56
|
+
textDecoration: 'underline'
|
|
57
|
+
},
|
|
58
|
+
standalone: {
|
|
59
|
+
fontSize: componentTheme.fontSize,
|
|
60
|
+
lineHeight: componentTheme.lineHeight,
|
|
61
|
+
textDecoration: 'none'
|
|
62
|
+
},
|
|
63
|
+
'standalone-small': {
|
|
64
|
+
fontSize: componentTheme.fontSizeSmall,
|
|
65
|
+
lineHeight: componentTheme.lineHeight,
|
|
66
|
+
textDecoration: 'none'
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
47
70
|
const baseStyles = {
|
|
48
71
|
boxSizing: 'border-box',
|
|
49
72
|
fontFamily: componentTheme.fontFamily,
|
|
@@ -84,9 +107,6 @@ const generateStyle = (
|
|
|
84
107
|
...baseStyles,
|
|
85
108
|
cursor: 'pointer',
|
|
86
109
|
color: componentTheme.color,
|
|
87
|
-
textDecoration: isWithinText
|
|
88
|
-
? componentTheme.textDecorationWithinText
|
|
89
|
-
: componentTheme.textDecorationOutsideText,
|
|
90
110
|
'&:focus': {
|
|
91
111
|
color: componentTheme.color,
|
|
92
112
|
outlineColor: componentTheme.focusOutlineColor
|
|
@@ -96,7 +116,14 @@ const generateStyle = (
|
|
|
96
116
|
textDecoration: isWithinText
|
|
97
117
|
? componentTheme.hoverTextDecorationWithinText
|
|
98
118
|
: componentTheme.hoverTextDecorationOutsideText
|
|
99
|
-
}
|
|
119
|
+
},
|
|
120
|
+
...(variant
|
|
121
|
+
? variantStyles[variant]
|
|
122
|
+
: {
|
|
123
|
+
textDecoration: isWithinText
|
|
124
|
+
? componentTheme.textDecorationWithinText
|
|
125
|
+
: componentTheme.textDecorationOutsideText
|
|
126
|
+
})
|
|
100
127
|
}
|
|
101
128
|
|
|
102
129
|
const buttonStyle = {
|
|
@@ -105,10 +132,10 @@ const generateStyle = (
|
|
|
105
132
|
background: 'none',
|
|
106
133
|
border: 'none',
|
|
107
134
|
cursor: 'pointer',
|
|
108
|
-
fontSize: '1em',
|
|
109
135
|
margin: 0,
|
|
110
136
|
padding: 0,
|
|
111
|
-
textAlign: 'inherit'
|
|
137
|
+
textAlign: 'inherit',
|
|
138
|
+
...(variant ? variantStyles[variant] : { fontSize: '1em' })
|
|
112
139
|
}
|
|
113
140
|
|
|
114
141
|
const inverseStyles = {
|
|
@@ -120,7 +147,32 @@ const generateStyle = (
|
|
|
120
147
|
color: componentTheme.colorInverse
|
|
121
148
|
}
|
|
122
149
|
}
|
|
123
|
-
|
|
150
|
+
const variantIconStyles = {
|
|
151
|
+
inline: {
|
|
152
|
+
paddingInlineStart:
|
|
153
|
+
iconPlacement === 'start' ? 0 : componentTheme.iconPlusTextMargin,
|
|
154
|
+
paddingInlineEnd:
|
|
155
|
+
iconPlacement === 'start' ? componentTheme.iconPlusTextMargin : 0
|
|
156
|
+
},
|
|
157
|
+
'inline-small': {
|
|
158
|
+
paddingInlineStart:
|
|
159
|
+
iconPlacement === 'start' ? 0 : componentTheme.iconPlusTextMarginSmall,
|
|
160
|
+
paddingInlineEnd:
|
|
161
|
+
iconPlacement === 'start' ? componentTheme.iconPlusTextMarginSmall : 0
|
|
162
|
+
},
|
|
163
|
+
standalone: {
|
|
164
|
+
paddingInlineStart:
|
|
165
|
+
iconPlacement === 'start' ? 0 : componentTheme.iconPlusTextMargin,
|
|
166
|
+
paddingInlineEnd:
|
|
167
|
+
iconPlacement === 'start' ? componentTheme.iconPlusTextMargin : 0
|
|
168
|
+
},
|
|
169
|
+
'standalone-small': {
|
|
170
|
+
paddingInlineStart:
|
|
171
|
+
iconPlacement === 'start' ? 0 : componentTheme.iconPlusTextMarginSmall,
|
|
172
|
+
paddingInlineEnd:
|
|
173
|
+
iconPlacement === 'start' ? componentTheme.iconPlusTextMarginSmall : 0
|
|
174
|
+
}
|
|
175
|
+
}
|
|
124
176
|
return {
|
|
125
177
|
link: {
|
|
126
178
|
label: 'link',
|
|
@@ -145,10 +197,18 @@ const generateStyle = (
|
|
|
145
197
|
...(renderIcon && {
|
|
146
198
|
fontSize: componentTheme.iconSize,
|
|
147
199
|
boxSizing: 'border-box',
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
200
|
+
...(variant
|
|
201
|
+
? variantIconStyles[variant]
|
|
202
|
+
: {
|
|
203
|
+
paddingInlineStart:
|
|
204
|
+
iconPlacement === 'start'
|
|
205
|
+
? 0
|
|
206
|
+
: componentTheme.iconPlusTextMargin,
|
|
207
|
+
paddingInlineEnd:
|
|
208
|
+
iconPlacement === 'start'
|
|
209
|
+
? componentTheme.iconPlusTextMargin
|
|
210
|
+
: 0
|
|
211
|
+
})
|
|
152
212
|
})
|
|
153
213
|
}
|
|
154
214
|
}
|
package/src/Link/theme.ts
CHANGED
|
@@ -52,6 +52,9 @@ const generateComponentTheme = (theme: Theme): LinkTheme => {
|
|
|
52
52
|
const componentVariables: LinkTheme = {
|
|
53
53
|
fontFamily: typography?.fontFamily,
|
|
54
54
|
fontWeight: typography?.fontWeightNormal,
|
|
55
|
+
fontSize: typography?.content,
|
|
56
|
+
lineHeight: typography?.lineHeight150,
|
|
57
|
+
fontSizeSmall: typography?.contentSmall,
|
|
55
58
|
color: colors?.contrasts?.blue5782,
|
|
56
59
|
|
|
57
60
|
textDecorationWithinText: 'underline',
|
|
@@ -71,7 +74,8 @@ const generateComponentTheme = (theme: Theme): LinkTheme => {
|
|
|
71
74
|
focusInverseIconOutlineColor: colors?.contrasts?.white1010,
|
|
72
75
|
|
|
73
76
|
iconSize: '1.125em', // make icon slightly larger than inherited font-size,
|
|
74
|
-
iconPlusTextMargin: spacing
|
|
77
|
+
iconPlusTextMargin: spacing.space4,
|
|
78
|
+
iconPlusTextMarginSmall: spacing.space2,
|
|
75
79
|
textUnderlineOffset: 'auto'
|
|
76
80
|
}
|
|
77
81
|
|