Skip to content

Commit 308bb2f

Browse files
committed
feat(ui-link): add variants to <Link>
INSTUI-4506
1 parent e481373 commit 308bb2f

File tree

17 files changed

+170
-31
lines changed

17 files changed

+170
-31
lines changed

packages/shared-types/src/BaseTheme.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,35 @@ type Spacing = {
7777
large: string | 0
7878
xLarge: string | 0
7979
xxLarge: string | 0
80+
81+
space0: string | 0
82+
space2: string | 0
83+
space4: string | 0
84+
space8: string | 0
85+
space12: string | 0
86+
space16: string | 0
87+
space24: string | 0
88+
space36: string | 0
89+
space48: string | 0
90+
space60: string | 0
91+
sections: string | 0
92+
sectionElements: string | 0
93+
trayElements: string | 0
94+
modalElements: string | 0
95+
moduleElements: string | 0
96+
paddingCardLarge: string | 0
97+
paddingCardMedium: string | 0
98+
paddingCardSmall: string | 0
99+
selects: string | 0
100+
textareas: string | 0
101+
inputFields: string | 0
102+
checkboxes: string | 0
103+
radios: string | 0
104+
toggles: string | 0
105+
buttons: string | 0
106+
tags: string | 0
107+
statusIndicators: string | 0
108+
dataPoints: string | 0
80109
}
81110

82111
type Stacking = {

packages/shared-types/src/ComponentThemeVariables.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,9 @@ export type ImgTheme = {
670670
export type LinkTheme = {
671671
fontFamily: Typography['fontFamily']
672672
fontWeight: Typography['fontWeightNormal']
673+
fontSize: string | 0
674+
fontSizeSmall: string | 0
675+
lineHeight: number
673676
color: Colors['contrasts']['blue4570']
674677
textDecorationWithinText: string
675678
hoverTextDecorationWithinText: string
@@ -684,7 +687,8 @@ export type LinkTheme = {
684687
focusInverseOutlineColor: Colors['contrasts']['white1010']
685688
focusInverseIconOutlineColor: Colors['contrasts']['white1010']
686689
iconSize: string
687-
iconPlusTextMargin: Spacing['xxSmall']
690+
iconPlusTextMargin: string | 0
691+
iconPlusTextMarginSmall: string | 0
688692
textUnderlineOffset: string
689693
}
690694

packages/ui-link/src/Link/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,37 @@ type: example
2222
</View>
2323
```
2424

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+
2556
### Adding margin
2657

2758
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
76107
icon _after_ the link text, change the `iconPlacement` property to `end`. You can also
77108
render a Link with just an icon. Don't forget to add text for screen readers, though.
78109

110+
NOTE: if you want the icon to have the same `font-size` as the link, do not specify its `size`!
111+
79112
```js
80113
---
81114
type: example

packages/ui-link/src/Link/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,9 @@ class Link extends Component<LinkProps, LinkState> {
252252
tabIndex={tabIndex}
253253
css={this.props.styles?.link}
254254
>
255-
{renderIcon && iconPlacement === 'start' && this.renderIcon()}
255+
{renderIcon && iconPlacement === 'start' ? this.renderIcon() : null}
256256
{children}
257-
{renderIcon && iconPlacement === 'end' && this.renderIcon()}
257+
{renderIcon && iconPlacement === 'end' ? this.renderIcon() : null}
258258
</View>
259259
)
260260
}

packages/ui-link/src/Link/props.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ type LinkOwnProps = {
129129
* Fires when the Link is hovered
130130
*/
131131
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'
132137
}
133138

134139
export type LinkStyleProps = {
@@ -174,7 +179,13 @@ const propTypes: PropValidators<PropKeys> = {
174179
onBlur: PropTypes.func,
175180
onClick: PropTypes.func,
176181
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+
])
178189
}
179190

180191
const allowedProps: AllowedPropKeys = [
@@ -194,7 +205,8 @@ const allowedProps: AllowedPropKeys = [
194205
'onBlur',
195206
'onClick',
196207
'onFocus',
197-
'onMouseEnter'
208+
'onMouseEnter',
209+
'variant'
198210
]
199211

200212
export type { LinkProps, LinkState, LinkStyle }

packages/ui-link/src/Link/styles.ts

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,33 @@ const generateStyle = (
4040
props: LinkProps,
4141
state: LinkStyleProps
4242
): LinkStyle => {
43-
const { isWithinText, renderIcon, iconPlacement, color } = props
43+
const { isWithinText, renderIcon, iconPlacement, color, variant } = props
4444
const { containsTruncateText, hasVisibleChildren } = state
4545
const inverseStyle = color === 'link-inverse'
4646

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+
4770
const baseStyles = {
4871
boxSizing: 'border-box',
4972
fontFamily: componentTheme.fontFamily,
@@ -84,9 +107,6 @@ const generateStyle = (
84107
...baseStyles,
85108
cursor: 'pointer',
86109
color: componentTheme.color,
87-
textDecoration: isWithinText
88-
? componentTheme.textDecorationWithinText
89-
: componentTheme.textDecorationOutsideText,
90110
'&:focus': {
91111
color: componentTheme.color,
92112
outlineColor: componentTheme.focusOutlineColor
@@ -96,7 +116,14 @@ const generateStyle = (
96116
textDecoration: isWithinText
97117
? componentTheme.hoverTextDecorationWithinText
98118
: componentTheme.hoverTextDecorationOutsideText
99-
}
119+
},
120+
...(variant
121+
? variantStyles[variant]
122+
: {
123+
textDecoration: isWithinText
124+
? componentTheme.textDecorationWithinText
125+
: componentTheme.textDecorationOutsideText
126+
})
100127
}
101128

102129
const buttonStyle = {
@@ -105,10 +132,10 @@ const generateStyle = (
105132
background: 'none',
106133
border: 'none',
107134
cursor: 'pointer',
108-
fontSize: '1em',
109135
margin: 0,
110136
padding: 0,
111-
textAlign: 'inherit'
137+
textAlign: 'inherit',
138+
...(variant ? variantStyles[variant] : { fontSize: '1em' })
112139
}
113140

114141
const inverseStyles = {
@@ -120,7 +147,32 @@ const generateStyle = (
120147
color: componentTheme.colorInverse
121148
}
122149
}
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+
}
124176
return {
125177
link: {
126178
label: 'link',
@@ -145,10 +197,18 @@ const generateStyle = (
145197
...(renderIcon && {
146198
fontSize: componentTheme.iconSize,
147199
boxSizing: 'border-box',
148-
paddingInlineStart:
149-
iconPlacement === 'start' ? 0 : componentTheme.iconPlusTextMargin,
150-
paddingInlineEnd:
151-
iconPlacement === 'start' ? componentTheme.iconPlusTextMargin : 0
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+
})
152212
})
153213
}
154214
}

packages/ui-link/src/Link/theme.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ const generateComponentTheme = (theme: Theme): LinkTheme => {
5252
const componentVariables: LinkTheme = {
5353
fontFamily: typography?.fontFamily,
5454
fontWeight: typography?.fontWeightNormal,
55+
fontSize: typography?.content,
56+
lineHeight: typography?.lineHeight150,
57+
fontSizeSmall: typography?.contentSmall,
5558
color: colors?.contrasts?.blue5782,
5659

5760
textDecorationWithinText: 'underline',
@@ -71,7 +74,8 @@ const generateComponentTheme = (theme: Theme): LinkTheme => {
7174
focusInverseIconOutlineColor: colors?.contrasts?.white1010,
7275

7376
iconSize: '1.125em', // make icon slightly larger than inherited font-size,
74-
iconPlusTextMargin: spacing?.xxSmall,
77+
iconPlusTextMargin: spacing.space4,
78+
iconPlusTextMarginSmall: spacing.space2,
7579
textUnderlineOffset: 'auto'
7680
}
7781

packages/ui-text/src/Text/index.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,8 @@ class Text extends Component<TextProps> {
5454
} as const
5555

5656
checkProps() {
57-
const { variant, size, lineHeight, weight, fontStyle } = this.props
57+
const { variant, lineHeight, weight, fontStyle } = this.props
5858
if (variant) {
59-
if (size) {
60-
console.warn("[Text]: Don't use 'size' with 'variant' ")
61-
}
6259
if (lineHeight) {
6360
console.warn("[Text]: Don't use 'lineHeight' with 'variant' ")
6461
}

packages/ui-themes/src/sharedThemeTokens/borders.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { Border } from '@instructure/shared-types'
2626

2727
// use for consistency between buttons, text inputs, etc.
2828

29-
const borders: Border = Object.freeze({
29+
const borders: Border = Object.freeze<Border>({
3030
radiusSmall: '0.125rem', // 2px
3131
radiusMedium: '0.25rem', // 4px
3232
radiusLarge: '0.5rem', // 8px

packages/ui-themes/src/sharedThemeTokens/breakpoints.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const values = {
3838
xLarge: 75 // 1200px
3939
}
4040

41-
const breakpoints: Breakpoints = Object.freeze({
41+
const breakpoints: Breakpoints = Object.freeze<Breakpoints>({
4242
xxSmall: `${values.xxSmall}em`,
4343
xSmall: `${values.xSmall}em`,
4444
small: `${values.small}em`,

0 commit comments

Comments
 (0)