Skip to content

Commit 71fb8ac

Browse files
aesteves60dpellier
authored andcommitted
fix(link): docs & cursor
1 parent 15f7bda commit 71fb8ac

File tree

8 files changed

+163
-46
lines changed

8 files changed

+163
-46
lines changed

packages/ods/src/components/link/documentation/migration.from.17.x.mdx

+42-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ Icons are now font, they will by default have the same color as the current text
1010

1111
Has been removed.
1212

13-
You can use the new `label` attribute to obtain the same behavior.
13+
You can no longer put any content inside the component. The ods-link now enforces the rendering of a label, and eventually an icon.
14+
You can use the new attributes `label` and `icon` to achieve that.
1415

1516
## Migration examples
1617

@@ -22,9 +23,48 @@ You can use the `color` attribute with the value `contrasted` to obtain the same
2223
<ods-link href="/page" color="contrasted"></ods-link>
2324
```
2425

25-
Slot link:
26+
Label link:
2627
```html
2728
<ods-link href="/page">Content</ods-link>
2829
<!-- is now -->
2930
<ods-link href="/page" label="Content"></ods-link>
3031
```
32+
33+
Icon link:
34+
```html
35+
<ods-link href="/page">
36+
<ods-icon name="warning" size="xs">
37+
</ods-link>
38+
<!-- is now -->
39+
<ods-link href="/page" icon="warning"></ods-link>
40+
```
41+
42+
Custom link css:
43+
```html
44+
<ods-link href="/page">
45+
<ods-icon name="warning" size="xl">
46+
</ods-link>
47+
<!-- is now -->
48+
<ods-link class="" href="/page" icon="warning"></ods-link>
49+
<style>
50+
.my-link-icon::part(link) {
51+
color: green;
52+
font-size: 32px;
53+
}
54+
</style>
55+
```
56+
57+
Custom icon css:
58+
```html
59+
<ods-link href="/page">
60+
<ods-icon name="warning" size="xl">
61+
</ods-link>
62+
<!-- is now -->
63+
<ods-link class="" href="/page" icon="warning"></ods-link>
64+
<style>
65+
.my-link-icon::part(icon) {
66+
width: 2rem;
67+
height: 2rem;
68+
}
69+
</style>
70+
```

packages/ods/src/components/link/src/components/ods-link/ods-link.scss

+17-14
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,34 @@
77
&__text {
88
display: inline-flex;
99
align-items: center;
10-
transition: background-size .2s ease-in, color ease-in-out .1s;
11-
background-image: linear-gradient(currentcolor, currentcolor);
12-
background-position: 0 100%;
13-
background-repeat: no-repeat;
14-
background-size: 0 0.1em;
15-
padding-bottom: 1px;
1610
}
1711

18-
/* stylelint-disable-next-line order/order */
19-
&:focus-visible, &:hover {
20-
.ods-link__link__text {
21-
transition: background-size .2s ease-out;
22-
background-size: 100% 0.1em;
23-
}
12+
&__icon {
13+
margin-left: var(--ods-spacing-8);
14+
background-color: currentcolor;
2415
}
2516

2617
&--disabled {
2718
opacity: .5;
2819
cursor: not-allowed;
29-
pointer-events: none;
30-
user-select: none;
20+
color: var(--ods-color-neutral-400) !important;
21+
22+
&:focus-visible, &:hover {
23+
transition: none;
24+
background-size: 0;
25+
}
3126
}
3227

3328
&--primary {
3429
color: var(--ods-color-primary-500);
30+
31+
&:hover {
32+
color: var(--ods-color-primary-700);
33+
}
34+
35+
&:visited {
36+
color: var(--ods-color-primary-800);
37+
}
3538
}
3639
}
3740
}

packages/ods/src/components/link/src/components/ods-link/ods-link.tsx

+23-16
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, type FunctionalComponent, Host, Prop, h } from '@stencil/core';
1+
import { Component, type FunctionalComponent, Host, Listen, Prop, h } from '@stencil/core';
22
import { type OdsIconName } from '../../../../icon/src/constants/icon-name';
33
import { ODS_LINK_COLOR, type OdsLinkColor } from '../../constant/link-color';
44

@@ -18,28 +18,35 @@ export class OdsLink {
1818
@Prop({ reflect: true }) public rel?: HTMLAnchorElement['rel'];
1919
@Prop({ reflect: true }) public target?: HTMLAnchorElement['target'];
2020

21+
@Listen('click')
22+
onClick(event: MouseEvent): void {
23+
if (this.disabled) {
24+
event.preventDefault();
25+
event.stopPropagation();
26+
}
27+
}
28+
2129
render(): FunctionalComponent {
2230
return (
23-
<Host class='ods-link'>
24-
<a
25-
class={{
26-
'ods-link__link': true,
27-
'ods-link__link--disabled': this.disabled ?? false,
28-
[`ods-link__link--${this.color}`]: true,
29-
}}
30-
download={ this.download }
31-
href={ this.href }
32-
part="link"
33-
referrerPolicy={ this.referrerpolicy }
34-
rel={ this.rel }
35-
tabindex={ this.disabled ? -1 : 0 }
36-
target={ this.target }>
31+
<Host class="ods-link">
32+
<a class={{
33+
'ods-link__link': true,
34+
'ods-link__link--disabled': this.disabled ?? false,
35+
[`ods-link__link--${this.color}`]: true,
36+
}}
37+
download={ this.download }
38+
href={ this.href }
39+
part="link"
40+
referrerPolicy={ this.referrerpolicy }
41+
rel={ this.rel }
42+
tabindex={ this.disabled ? -1 : 0 }
43+
target={ this.target }>
3744
<span class="ods-link__link__text">
3845
{ this.label }
3946
</span>
4047

4148
{
42-
!!this.icon && <ods-icon name={ this.icon }></ods-icon>
49+
!!this.icon && <ods-icon part="icon" name={ this.icon } class="ods-link__link__icon"></ods-icon>
4350
}
4451
</a>
4552
</Host>

packages/ods/src/components/link/src/index.html

+27-4
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,42 @@
1212

1313
<body>
1414
<p>Default</p>
15-
<ods-link href="test" label="link clickable">
15+
<ods-link href="test" label="link clickable" target="_blank">
1616
</ods-link>
1717

1818
<p>Disabled</p>
19-
<ods-link href="test" label="link clickable" disabled>
19+
<ods-link href="test" label="link disabled" disabled target="_blank">
2020
</ods-link>
2121

2222
<p>Icon</p>
23-
<ods-link href="test" label="link clickable" icon="warning">
23+
<ods-link href="test" label="link icon clickable" icon="warning">
2424
</ods-link>
2525

2626
<p>Icon Disabled</p>
27-
<ods-link href="test" label="link clickable" icon="warning" disabled>
27+
<ods-link href="test" label="link icon disabled" icon="warning" disabled>
2828
</ods-link>
29+
30+
<p>Custom CSS</p>
31+
<ods-link class="my-link" href="test" label="link custom css">
32+
</ods-link>
33+
34+
<p>Custom CSS with icon</p>
35+
<ods-link class="my-link-icon" href="test" label="link custom css icon" icon="warning">
36+
</ods-link>
37+
38+
<style>
39+
.my-link::part(link) {
40+
color: green;
41+
font-size: 32px;
42+
}
43+
44+
.my-link-icon::part(link) {
45+
font-size: 32px;
46+
}
47+
.my-link-icon::part(icon) {
48+
width: 2rem;
49+
height: 2rem;
50+
}
51+
</style>
2952
</body>
3053
</html>

packages/ods/src/components/link/tests/rendering/ods-link.e2e.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ describe('ods-link rendering', () => {
1515

1616
if (customStyle) {
1717
await page.addStyleTag({ content: customStyle });
18+
await page.waitForChanges();
1819
}
1920

2021
el = await page.find('ods-link');
@@ -24,7 +25,8 @@ describe('ods-link rendering', () => {
2425

2526
describe('part', () => {
2627
it('should render with custom style applied', async() => {
27-
await setup('<ods-link label="some link" href="https://www.ovhcloud.com/fr/"></ods-link>', 'ods-link::part(link) { color: #00ff00; }');
28+
await setup('<ods-link label="some link" href="https://www.ovhcloud.com/fr/"></ods-link>', 'ods-link::part(link) { color: #00FF00 }');
29+
await new Promise(resolve => setTimeout(resolve, 500));
2830
const partStyle = await part.getComputedStyle();
2931
expect(partStyle.getPropertyValue('color')).toBe('rgb(0, 255, 0)');
3032
});

packages/ods/src/style/_link.scss

+14-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
11
@mixin ods-link() {
22
display: inline-flex;
33
align-items: center;
4+
transition: background-size .2s ease-in, color ease-in-out .1s;
5+
background-image: linear-gradient(currentcolor, currentcolor);
6+
background-position: 0 100%;
7+
background-repeat: no-repeat;
8+
background-size: 0 1px;
49
cursor: pointer;
10+
padding-bottom: 3px;
511
text-decoration: none;
612
font-family: var(--ods-font-family-default);
713
font-weight: 600;
814

15+
/* stylelint-disable-next-line order/order */
16+
&:focus-visible, &:hover {
17+
transition: background-size .2s ease-out;
18+
background-size: 100% 1px;
19+
}
20+
921
&:focus-visible {
10-
outline-offset: 3px;
11-
outline-width: 3px;
12-
outline-style: dotted;
22+
outline: currentcolor var(--ods-outline-style) var(--ods-outline-width);
23+
outline-offset: var(--ods-outline-offset);
1324
}
1425
}

packages/storybook/stories/components/link/link.stories.ts

+30-6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export default meta;
1616
export const Demo: StoryObj = {
1717
render: (args) => html`
1818
<ods-link
19+
class="my-link"
1920
color="${args.color}"
2021
disabled="${args.disabled}"
2122
download="${args.download}"
@@ -26,6 +27,14 @@ export const Demo: StoryObj = {
2627
referrerpolicy="${args.referrerpolicy}"
2728
target="${args.target}">
2829
</ods-link>
30+
<style>
31+
.my-link::part(link) {
32+
${args.customCssLink}
33+
}
34+
.my-link::part(icon) {
35+
${args.customCssIcon}
36+
}
37+
</style>
2938
`,
3039
argTypes: orderControls({
3140
color: {
@@ -37,6 +46,24 @@ export const Demo: StoryObj = {
3746
control: 'select',
3847
options: ODS_LINK_COLORS,
3948
},
49+
customCssLink: {
50+
table: {
51+
category: CONTROL_CATEGORY.design,
52+
defaultValue: { summary: 'ø' },
53+
type: { summary: 'string' }
54+
},
55+
control: 'text',
56+
description: 'Set a custom style properties on the link. Example: "color: green; font-size: 32px;"',
57+
},
58+
customCssIcon: {
59+
table: {
60+
category: CONTROL_CATEGORY.design,
61+
defaultValue: { summary: 'ø' },
62+
type: { summary: 'string' }
63+
},
64+
control: 'text',
65+
description: 'Set a custom style properties on the icon. Example: "width: 2rem; height: 2rem;"',
66+
},
4067
disabled: {
4168
table: {
4269
category: CONTROL_CATEGORY.general,
@@ -85,26 +112,23 @@ export const Demo: StoryObj = {
85112
defaultValue: { summary: 'ø' },
86113
type: { summary: 'string' }
87114
},
88-
control: 'select',
89-
options: [],
115+
control: 'text',
90116
},
91117
rel: {
92118
table: {
93119
category: CONTROL_CATEGORY.accessibility,
94120
defaultValue: { summary: 'ø' },
95121
type: { summary: 'string' }
96122
},
97-
control: 'select',
98-
options: [],
123+
control: 'text',
99124
},
100125
target: {
101126
table: {
102127
category: CONTROL_CATEGORY.general,
103128
defaultValue: { summary: 'ø' },
104129
type: { summary: 'string' }
105130
},
106-
control: 'select',
107-
options: [],
131+
control: 'text',
108132
},
109133
}),
110134
args: {

packages/themes/src/default/index.scss

+7
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,12 @@ $ods-notifier-foreground-color-critical-focused: $ods-color-critical-800;
101101
--ods-color-primary-800: #{$ods-color-primary-800};
102102
--ods-font-family-code: 'Source Code Pro', arial;
103103
--ods-font-family-default: 'Source Sans Pro', 'Trebuchet MS', arial, 'Segoe UI', sans-serif;
104+
--ods-spacing-1: #{$ods-spacing-1};
105+
--ods-spacing-2: #{$ods-spacing-2};
106+
--ods-spacing-4: #{$ods-spacing-4};
104107
--ods-spacing-8: #{$ods-spacing-8};
108+
--ods-outline-color: #{$ods-outline-color};
109+
--ods-outline-width: #{$ods-outline-width};
110+
--ods-outline-offset: #{$ods-outline-offset};
111+
--ods-outline-style: #{$ods-outline-style};
105112
}

0 commit comments

Comments
 (0)