Skip to content

Commit 4efcd9c

Browse files
authoredJul 21, 2023
[docs][joy] Revise the Joy UI Link page (#37829)
1 parent 2b43b04 commit 4efcd9c

17 files changed

+511
-43
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import * as React from 'react';
2+
import Link from '@mui/joy/Link';
3+
import Box from '@mui/joy/Box';
4+
5+
export default function BasicsLink() {
6+
return (
7+
<Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap' }}>
8+
<Link href="#basics">Link</Link>
9+
<Link href="#basics" disabled>
10+
Disabled
11+
</Link>
12+
</Box>
13+
);
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import * as React from 'react';
2+
import Link from '@mui/joy/Link';
3+
import Box from '@mui/joy/Box';
4+
5+
export default function BasicsLink() {
6+
return (
7+
<Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap' }}>
8+
<Link href="#basics">Link</Link>
9+
<Link href="#basics" disabled>
10+
Disabled
11+
</Link>
12+
</Box>
13+
);
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<Link href="#basics">Link</Link>
2+
<Link href="#basics" disabled>
3+
Disabled
4+
</Link>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import * as React from 'react';
2+
import Box from '@mui/joy/Box';
3+
import Sheet from '@mui/joy/Sheet';
4+
import Link from '@mui/joy/Link';
5+
import RadioGroup from '@mui/joy/RadioGroup';
6+
import Radio from '@mui/joy/Radio';
7+
import Typography from '@mui/joy/Typography';
8+
9+
export default function LinkColors() {
10+
const [variant, setVariant] = React.useState('solid');
11+
return (
12+
<Box
13+
sx={{
14+
display: 'flex',
15+
alignItems: 'center',
16+
gap: 3,
17+
}}
18+
>
19+
<Box
20+
sx={{
21+
display: 'grid',
22+
gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
23+
gap: 2,
24+
}}
25+
>
26+
<Link href="#colors" variant={variant} color="primary">
27+
Primary
28+
</Link>
29+
<Link href="#colors" variant={variant} color="neutral">
30+
Neutral
31+
</Link>
32+
<Link href="#colors" variant={variant} color="danger">
33+
Danger
34+
</Link>
35+
<Link href="#colors" variant={variant} color="info">
36+
Info
37+
</Link>
38+
<Link href="#colors" variant={variant} color="success">
39+
Success
40+
</Link>
41+
<Link href="#colors" variant={variant} color="warning">
42+
Warning
43+
</Link>
44+
</Box>
45+
<Sheet
46+
sx={{
47+
background: 'transparent',
48+
pl: 4,
49+
borderLeft: '1px solid',
50+
borderColor: 'divider',
51+
}}
52+
>
53+
<Typography
54+
level="body2"
55+
fontWeight="xl"
56+
id="variant-label"
57+
textColor="text.primary"
58+
mb={1}
59+
>
60+
Variant:
61+
</Typography>
62+
<RadioGroup
63+
size="sm"
64+
aria-labelledby="variant-label"
65+
name="variant"
66+
value={variant}
67+
onChange={(event) => setVariant(event.target.value)}
68+
>
69+
<Radio label="Solid" value="solid" />
70+
<Radio label="Soft" value="soft" />
71+
<Radio label="Outlined" value="outlined" />
72+
<Radio label="Plain" value="plain" />
73+
</RadioGroup>
74+
</Sheet>
75+
</Box>
76+
);
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import * as React from 'react';
2+
import Box from '@mui/joy/Box';
3+
import Sheet from '@mui/joy/Sheet';
4+
import Link from '@mui/joy/Link';
5+
import RadioGroup from '@mui/joy/RadioGroup';
6+
import Radio from '@mui/joy/Radio';
7+
import Typography from '@mui/joy/Typography';
8+
import { VariantProp } from '@mui/joy/styles';
9+
10+
export default function LinkColors() {
11+
const [variant, setVariant] = React.useState<VariantProp>('solid');
12+
return (
13+
<Box
14+
sx={{
15+
display: 'flex',
16+
alignItems: 'center',
17+
gap: 3,
18+
}}
19+
>
20+
<Box
21+
sx={{
22+
display: 'grid',
23+
gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
24+
gap: 2,
25+
}}
26+
>
27+
<Link href="#colors" variant={variant} color="primary">
28+
Primary
29+
</Link>
30+
<Link href="#colors" variant={variant} color="neutral">
31+
Neutral
32+
</Link>
33+
<Link href="#colors" variant={variant} color="danger">
34+
Danger
35+
</Link>
36+
<Link href="#colors" variant={variant} color="info">
37+
Info
38+
</Link>
39+
<Link href="#colors" variant={variant} color="success">
40+
Success
41+
</Link>
42+
<Link href="#colors" variant={variant} color="warning">
43+
Warning
44+
</Link>
45+
</Box>
46+
<Sheet
47+
sx={{
48+
background: 'transparent',
49+
pl: 4,
50+
borderLeft: '1px solid',
51+
borderColor: 'divider',
52+
}}
53+
>
54+
<Typography
55+
level="body2"
56+
fontWeight="xl"
57+
id="variant-label"
58+
textColor="text.primary"
59+
mb={1}
60+
>
61+
Variant:
62+
</Typography>
63+
<RadioGroup
64+
size="sm"
65+
aria-labelledby="variant-label"
66+
name="variant"
67+
value={variant}
68+
onChange={(event) => setVariant(event.target.value as VariantProp)}
69+
>
70+
<Radio label="Solid" value="solid" />
71+
<Radio label="Soft" value="soft" />
72+
<Radio label="Outlined" value="outlined" />
73+
<Radio label="Plain" value="plain" />
74+
</RadioGroup>
75+
</Sheet>
76+
</Box>
77+
);
78+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import * as React from 'react';
2+
import Box from '@mui/joy/Box';
3+
import Link from '@mui/joy/Link';
4+
5+
export default function LinkDisabled() {
6+
return (
7+
<Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap' }}>
8+
<Link href="#disabled" disabled variant="solid">
9+
Solid
10+
</Link>
11+
<Link href="#disabled" disabled variant="soft">
12+
Soft
13+
</Link>
14+
<Link href="#disabled" disabled variant="outlined">
15+
Outlined
16+
</Link>
17+
<Link href="#disabled" disabled variant="plain">
18+
Plain
19+
</Link>
20+
</Box>
21+
);
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import * as React from 'react';
2+
import Box from '@mui/joy/Box';
3+
import Link from '@mui/joy/Link';
4+
5+
export default function LinkDisabled() {
6+
return (
7+
<Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap' }}>
8+
<Link href="#disabled" disabled variant="solid">
9+
Solid
10+
</Link>
11+
<Link href="#disabled" disabled variant="soft">
12+
Soft
13+
</Link>
14+
<Link href="#disabled" disabled variant="outlined">
15+
Outlined
16+
</Link>
17+
<Link href="#disabled" disabled variant="plain">
18+
Plain
19+
</Link>
20+
</Box>
21+
);
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Link href="#disabled" disabled variant="solid">
2+
Solid
3+
</Link>
4+
<Link href="#disabled" disabled variant="soft">
5+
Soft
6+
</Link>
7+
<Link href="#disabled" disabled variant="outlined">
8+
Outlined
9+
</Link>
10+
<Link href="#disabled" disabled variant="plain">
11+
Plain
12+
</Link>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import * as React from 'react';
2+
import Box from '@mui/joy/Box';
3+
import Link from '@mui/joy/Link';
4+
5+
export default function LinkLevels() {
6+
return (
7+
<Box sx={{ display: 'flex', gap: 2, alignItems: 'center', flexWrap: 'wrap' }}>
8+
<Link href="#levels" level="h1">
9+
H1
10+
</Link>
11+
<Link href="#levels" level="h2">
12+
H2
13+
</Link>
14+
<Link href="#levels" level="h3">
15+
H3
16+
</Link>
17+
<Link href="#levels" level="h4">
18+
H4
19+
</Link>
20+
<Link href="#levels" level="h5">
21+
H5
22+
</Link>
23+
<Link href="#levels" level="h6">
24+
H6
25+
</Link>
26+
<Link href="#levels" level="body1">
27+
Body 1
28+
</Link>
29+
<Link href="#levels" level="body2">
30+
Body 2
31+
</Link>
32+
<Link href="#levels" level="body3">
33+
Body 3
34+
</Link>
35+
</Box>
36+
);
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import * as React from 'react';
2+
import Box from '@mui/joy/Box';
3+
import Link from '@mui/joy/Link';
4+
5+
export default function LinkLevels() {
6+
return (
7+
<Box sx={{ display: 'flex', gap: 2, alignItems: 'center', flexWrap: 'wrap' }}>
8+
<Link href="#levels" level="h1">
9+
H1
10+
</Link>
11+
<Link href="#levels" level="h2">
12+
H2
13+
</Link>
14+
<Link href="#levels" level="h3">
15+
H3
16+
</Link>
17+
<Link href="#levels" level="h4">
18+
H4
19+
</Link>
20+
<Link href="#levels" level="h5">
21+
H5
22+
</Link>
23+
<Link href="#levels" level="h6">
24+
H6
25+
</Link>
26+
<Link href="#levels" level="body1">
27+
Body 1
28+
</Link>
29+
<Link href="#levels" level="body2">
30+
Body 2
31+
</Link>
32+
<Link href="#levels" level="body3">
33+
Body 3
34+
</Link>
35+
</Box>
36+
);
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import * as React from 'react';
2+
import Box from '@mui/joy/Box';
3+
import Link from '@mui/joy/Link';
4+
5+
export default function LinkUnderline() {
6+
return (
7+
<Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap' }}>
8+
<Link href="#underline" underline="always">
9+
Always
10+
</Link>
11+
<Link href="#underline" underline="hover">
12+
Hover
13+
</Link>
14+
<Link href="#underline" underline="none">
15+
None
16+
</Link>
17+
</Box>
18+
);
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import * as React from 'react';
2+
import Box from '@mui/joy/Box';
3+
import Link from '@mui/joy/Link';
4+
5+
export default function LinkUnderline() {
6+
return (
7+
<Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap' }}>
8+
<Link href="#underline" underline="always">
9+
Always
10+
</Link>
11+
<Link href="#underline" underline="hover">
12+
Hover
13+
</Link>
14+
<Link href="#underline" underline="none">
15+
None
16+
</Link>
17+
</Box>
18+
);
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Link href="#underline" underline="always">
2+
Always
3+
</Link>
4+
<Link href="#underline" underline="hover">
5+
Hover
6+
</Link>
7+
<Link href="#underline" underline="none">
8+
None
9+
</Link>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import * as React from 'react';
2+
import Link from '@mui/joy/Link';
3+
import Box from '@mui/joy/Box';
4+
5+
export default function LinkVariants() {
6+
return (
7+
<Box sx={{ display: 'flex', gap: 3, flexWrap: 'wrap' }}>
8+
<Link href="#variants">Link</Link>
9+
<Link href="#variants" variant="plain">
10+
Link
11+
</Link>
12+
<Link href="#variants" variant="soft">
13+
Link
14+
</Link>
15+
<Link href="#variants" variant="outlined">
16+
Link
17+
</Link>
18+
<Link href="#variants" variant="solid">
19+
Link
20+
</Link>
21+
</Box>
22+
);
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import * as React from 'react';
2+
import Link from '@mui/joy/Link';
3+
import Box from '@mui/joy/Box';
4+
5+
export default function LinkVariants() {
6+
return (
7+
<Box sx={{ display: 'flex', gap: 3, flexWrap: 'wrap' }}>
8+
<Link href="#variants">Link</Link>
9+
<Link href="#variants" variant="plain">
10+
Link
11+
</Link>
12+
<Link href="#variants" variant="soft">
13+
Link
14+
</Link>
15+
<Link href="#variants" variant="outlined">
16+
Link
17+
</Link>
18+
<Link href="#variants" variant="solid">
19+
Link
20+
</Link>
21+
</Box>
22+
);
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Link href="#variants">Link</Link>
2+
<Link href="#variants" variant="plain">
3+
Link
4+
</Link>
5+
<Link href="#variants" variant="soft">
6+
Link
7+
</Link>
8+
<Link href="#variants" variant="outlined">
9+
Link
10+
</Link>
11+
<Link href="#variants" variant="solid">
12+
Link
13+
</Link>

‎docs/data/joy/components/link/link.md

+88-43
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,87 @@ waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/link/
88

99
# Link
1010

11-
<p class="description">The <code>Link</code> component allows you to customize anchor tags with theme colors and typography styles.</p>
11+
<p class="description">The Link component lets you customize anchor tags with theme colors and typography styles.</p>
1212

1313
{{"component": "modules/components/ComponentLinkHeader.js", "design": false}}
1414

1515
## Introduction
1616

17-
The `Link` component represents the HTML `<a>` element.
18-
It accepts the same props as the [`Typography`](/joy-ui/react-typography/) component, as well as the system props.
17+
The Joy UI Link component replaces the native HTML `<a>` element, and accepts the same props as the [Typography](/joy-ui/react-typography/) component, as well as MUI System props.
1918

2019
{{"demo": "LinkUsage.js", "hideToolbar": true, "bg": "gradient"}}
2120

22-
## Component
23-
24-
After [installation](/joy-ui/getting-started/installation/), you can start building with this component using the following basic elements:
21+
## Basics
2522

2623
```jsx
2724
import Link from '@mui/joy/Link';
28-
29-
export default function MyApp() {
30-
return <Link>Hello world!</Link>;
31-
}
3225
```
3326

27+
The Joy UI Link behaves similar to the native HTML `<a>`, so it renders with an underline by default and has no background color on hover.
28+
29+
The demo below shows the two basic states available to the Link: default and disabled.
30+
Don't forget to always assign an `href` value:
31+
32+
{{"demo": "BasicsLink.js"}}
33+
34+
## Customization
35+
36+
### Variants
37+
38+
The Link component supports Joy UI's four global variants: `plain` (default), `soft`, `outlined`, and `solid`.
39+
40+
:::warning
41+
Although the component is technically set to `plain` by default, it will actually render without any variant if you don't customize it.
42+
This is so that it adheres to the standard visual design of links on the web (no background color on hover).
43+
:::
44+
45+
{{"demo": "LinkVariants.js"}}
46+
47+
:::info
48+
To learn how to add your own variants, check out [Themed components—Extend variants](/joy-ui/customization/themed-components/#extend-variants).
49+
Note that you lose the global variants when you add custom variants.
50+
:::
51+
52+
### Levels
53+
54+
The Link component comes with all the Typography levels to choose from.
55+
56+
{{"demo": "LinkLevels.js"}}
57+
58+
### Colors
59+
60+
Every palette included in the theme is available via the `color` prop.
61+
Play around combining different colors with different variants.
62+
63+
{{"demo": "LinkColors.js"}}
64+
65+
### Underline
66+
67+
Use the `underline` prop to control how the underline behaves on the Link component.
68+
It comes with three values: `hover`, `always`, and `none`.
69+
70+
{{"demo": "LinkUnderline.js"}}
71+
72+
### Disabled
73+
74+
Use the `disabled` prop to disable interaction and focus:
75+
76+
{{"demo": "LinkDisabled.js"}}
77+
78+
### Overlay prop
79+
80+
Use the `overlay` prop to make an entire component clickable as a link.
81+
The demo below shows how to use that with the Card component, ensuring proper accessibility.
82+
83+
{{"demo": "LinkCard.js"}}
84+
3485
### As a button
3586

36-
To use the `Link` as a button, assign the `button` value to the `component` prop.
37-
It's useful doing it in two main situations:
87+
To use the Link component as a button, assign the `button` value to the `component` prop.
88+
This can be useful in two situations:
3889

3990
1. The link doesn't have a meaningful href.
40-
2. The design looks more a link rather than a button.
91+
2. The design looks more like a button than a link.
4192

4293
```js
4394
<Link
@@ -50,41 +101,16 @@ It's useful doing it in two main situations:
50101
</Link>
51102
```
52103

53-
### With a typography
104+
### Usage with Typography
54105

55-
`Link` can be used as a child of the [`Typography`](/joy-ui/react-typography/) component.
56-
In that case, the link component will inherit the typographic level scale from its typography parent, unless a value for the `level` prop is specified.
106+
The Link component can be used as a child of the [Typography](/joy-ui/react-typography/) component.
107+
In this situation, the Link will inherit the typographic level scale from its Typography parent, unless you specify a value for the `level` prop on the Link itself.
57108

58109
{{"demo": "LinkAndTypography.js"}}
59110

60-
### With a card
61-
62-
Using the `Link` component as a card title, with the `overlay` prop, ensures proper accessibility when the whole card is clickable.
63-
64-
{{"demo": "LinkCard.js"}}
65-
66-
## Security
67-
68-
When using `target="_blank"` with links, it's [recommended](https://developers.google.com/web/tools/lighthouse/audits/noopener) to always set `rel="noopener"` or `rel="noreferrer"` when linking to a third-party content.
69-
70-
- `rel="noopener"` prevents the new page from being able to access the `window.opener` property and ensures it runs in a separate process.
71-
Without this, the target page can potentially redirect your page to a malicious URL.
72-
- `rel="noreferrer"` has the same effect, but also prevents the _Referer_ header from being sent to a new page.
73-
⚠️ Removing the referrer header will affect analytics.
74-
75-
## Accessibility
76-
77-
Here are a few tips for ensuring an accessible link component, based on [WAI-ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/link/).
78-
79-
- **Copywriting**: Avoid generic words as call to action, such as "click here" or "go to".
80-
Instead, use [descriptive texts](https://developers.google.com/web/tools/lighthouse/audits/descriptive-link-text).
81-
- **Design:** For a good user experience, links should stand out from the text on the page.
82-
Keeping the default `underline="always"` behavior is a safe bet.
83-
- **Href:** If a link doesn't have a meaningful href, [it should be rendered using a `<button>` element](#as-button).
84-
85111
## Third-party routing library
86112

87-
Here's how you can use the link component with libraries that also provide their version of it.
113+
The sections below explain how to integrate the Link component with third-party tools that have their own comparable component.
88114

89115
### Next.js
90116

@@ -112,8 +138,27 @@ import Link from '@mui/joy/Link';
112138
</Link>;
113139
```
114140

141+
## Security
142+
143+
When using `target="_blank"` with links to pages on another site, the [Google Chrome Developers documentation](https://developers.google.com/web/tools/lighthouse/audits/noopener) recommends adding `rel="noopener"` or `rel="noreferrer"` to avoid potential security issues.
144+
145+
- `rel="noopener"` prevents the new page from being able to access the `window.opener` property and ensures it runs in a separate process.
146+
Without this, the target page can potentially redirect your page to a malicious URL.
147+
- `rel="noreferrer"` has the same effect, but also prevents the _Referer_ header from being sent to a new page.
148+
Note that removing the referrer header will affect analytics.
149+
150+
## Accessibility
151+
152+
Here are a few tips for ensuring an accessible link component, based on [WAI-ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/link/).
153+
154+
- **Copywriting:** Avoid generic words as calls to action, such as "click here" or "go to".
155+
Instead, use [descriptive text](https://developers.google.com/web/tools/lighthouse/audits/descriptive-link-text) to inform the user about what they'll find when they click the link.
156+
- **Design:** For a good user experience, links should stand out from the text on the page.
157+
Keeping the default `underline="always"` behavior is a safe bet.
158+
- **Href:** If a link doesn't have a meaningful href, [it should be rendered using a `<button>` element](#as-button).
159+
115160
## Common examples
116161

117-
Examples showcasing how to compose designs with the `Link` component and others as decorators.
162+
Examples showcasing how to compose designs with the Link component and others as decorators.
118163

119164
{{"demo": "DecoratorExamples.js"}}

0 commit comments

Comments
 (0)
Please sign in to comment.