Skip to content

Commit 8690580

Browse files
mannycarrera4manuel.carrera
and
manuel.carrera
authored
feat!: Refactor External Hyperlink to use new styling utilities (#3101)
Fixes: #2955 [category:Components] Release Note: We've updated `ExternalHyperlink` to use our new styling utilities and tokens. ### BREAKING CHANGES `iconLabel` is now a *required* prop. We've removed the default `aria-label` of `Opens link in new window` to better support internationalization. You must provide a value to `iconLabel`. Co-authored-by: manuel.carrera <[email protected]>
1 parent b5251e8 commit 8690580

11 files changed

+119
-51
lines changed

modules/docs/lib/StylePropsTable.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export const StylePropsTable = ({styleProps = []}: StylePropsTableProps) => {
3838
const mdnUrl = `https://developer.mozilla.org/en-US/docs/Web/CSS/${formattedName}`;
3939
return (
4040
<Box display="inline-block" marginInlineEnd="xxxs">
41-
<ExternalHyperlink href={mdnUrl} key={i}>
41+
<ExternalHyperlink href={mdnUrl} key={i} iconLabel="Open link in new window">
4242
{formattedName}
4343
</ExternalHyperlink>
4444
</Box>

modules/docs/lib/widgets/external.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import {registerWidget} from '../Value';
88

99
registerWidget<ExternalSymbolValue>('external', ({value}) => (
1010
<>
11-
<ExternalHyperlink href={value.url}>{value.name}</ExternalHyperlink>
11+
<ExternalHyperlink href={value.url} iconLabel="Open link in new window">
12+
{value.name}
13+
</ExternalHyperlink>
1214
{renderTypeParameters(value.typeParameters)}
1315
</>
1416
));

modules/docs/mdx/13.0-UPGRADE-GUIDE.mdx

+30-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ any questions.
2020
- [Instructions](#instructions)
2121
- [Component Updates](#component-updates)
2222
- [Styling API and CSS Tokens](#styling-api-and-css-tokens)
23+
- [External Hyperlink](#external-hyperlink)
2324
- [Troubleshooting](#troubleshooting)
2425
- [Glossary](#glossary)
2526
- [Main](#main)
@@ -87,18 +88,45 @@ yarn remove @workday/canvas-kit-codemod
8788
> after executing the codemod, as its resulting formatting (spacing, quotes, etc.) may not match
8889
> your project conventions.
8990
91+
## Component Updates
9092

9193
### Styling API and CSS Tokens
9294

93-
Some components have been refactored to use our new
95+
**PRs:** [#3101](https://github.com/Workday/canvas-kit/pull/3101), [#3088](https://github.com/Workday/canvas-kit/pull/3088)
96+
97+
Several components have been refactored to use our
9498
[Canvas Tokens](https://workday.github.io/canvas-tokens/?path=/docs/docs-getting-started--docs) and
9599
[styling API](https://workday.github.io/canvas-kit/?path=/docs/styling-basics--create-modifiers#createstyles-api).
96100
The React interface **has not changed**, but CSS variables are now used for dynamic properties.
97101

98-
> **Note:** These components also support our new `cs` prop for styling. Learn more about styling
102+
> **Note:** These components also support our `cs` prop for styling. Learn more about styling
99103
> with `cs` in our
100104
> [documentation](https://workday.github.io/canvas-kit/?path=/docs/styling-basics--cs-prop).
101105
106+
The following components are affected:
107+
108+
- `ExternalHyperlink`
109+
- `Skeleton`
110+
111+
## External Hyperlink
112+
113+
**PR:** [#3101](https://github.com/Workday/canvas-kit/pull/3101)
114+
115+
`iconLabel` is now a *required* prop. We've removed the default `aria-label` of `Opens link in new window` to better support internationalization. You must provide a value to `iconLabel`.
116+
117+
```tsx
118+
//v12
119+
<ExternalHyperlink href="https://workday.com">
120+
External Hyperlink
121+
</ExternalHyperlink>
122+
123+
//v13
124+
<ExternalHyperlink href="https://workday.com" iconLabel='Open link in new window'>
125+
External Hyperlink
126+
</ExternalHyperlink>
127+
```
128+
129+
102130
## Troubleshooting
103131

104132
## Glossary

modules/docs/mdx/welcomePage.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ export const WelcomePage = () => {
4040
{' '}
4141
This project provides a set of components for the Workday Canvas Design System that can be
4242
used to implement user experiences consistent with{' '}
43-
<ExternalHyperlink href="https://canvas.workdaydesign.com/">
43+
<ExternalHyperlink
44+
href="https://canvas.workdaydesign.com/"
45+
iconLabel="Open docs in new window"
46+
>
4447
Workday Design Principles.
4548
</ExternalHyperlink>
4649
</Text>
+37-32
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
11
import React from 'react';
2-
import {styled, createComponent, StyledType} from '@workday/canvas-kit-react/common';
2+
import {createComponent} from '@workday/canvas-kit-react/common';
33
import {extLinkIcon} from '@workday/canvas-system-icons-web';
4-
import {SystemIcon, systemIconStyles} from '@workday/canvas-kit-react/icon';
5-
import {Hyperlink, HyperlinkProps} from './Hyperlink';
4+
import {SystemIcon, systemIconStencil} from '@workday/canvas-kit-react/icon';
5+
import {HyperlinkProps, hyperlinkStencil} from './Hyperlink';
6+
import {calc, createStencil, px2rem, handleCsProp} from '@workday/canvas-kit-styling';
7+
import {system} from '@workday/canvas-tokens-web';
68

79
export interface ExternalHyperlinkProps extends HyperlinkProps {
810
/**
911
* Informs a screen reader user the link will open in a new window. It is read after the link text.
1012
* This value will need to be translated.
11-
* @default 'Opens link in new window'
1213
*/
13-
iconLabel?: string;
14+
iconLabel: string;
1415
}
1516

16-
const iconStyles = {
17-
...systemIconStyles({fill: 'currentColor', fillHover: 'currentColor'}),
18-
};
19-
20-
const Anchor = styled(Hyperlink)<ExternalHyperlinkProps & StyledType>({
21-
...iconStyles,
22-
display: 'inline-flex',
23-
flexDirection: 'row',
24-
alignItems: 'center',
25-
});
26-
27-
const iconSize = '1em';
28-
const minIconSize = '16px';
29-
30-
const StyledSystemIcon = styled(SystemIcon)<StyledType>({
31-
...iconStyles,
32-
width: `calc(${iconSize} - 1px)`,
33-
minWidth: `calc(${minIconSize} - 1px)`,
34-
marginLeft: '2px',
17+
export const externalHyperlinkStencil = createStencil({
18+
extends: hyperlinkStencil,
19+
base: {
20+
display: 'inline-flex',
21+
flexDirection: 'row',
22+
alignItems: 'center',
23+
'& [data-part="external-hyperlink-icon"]': {
24+
[systemIconStencil.vars.color]: 'currentColor',
25+
[systemIconStencil.vars.size]: '1em',
26+
width: calc.subtract('1em', px2rem(1)),
27+
minWidth: calc.subtract(system.space.x4, px2rem(1)),
28+
marginInlineStart: calc.subtract(system.space.x1, px2rem(2)),
29+
'& > svg': {
30+
minWidth: system.space.x4,
31+
minHeight: system.space.x4,
32+
},
33+
},
34+
},
3535
});
3636

3737
/**
@@ -41,18 +41,23 @@ const StyledSystemIcon = styled(SystemIcon)<StyledType>({
4141
export const ExternalHyperlink = createComponent('a')({
4242
displayName: 'ExternalHyperlink',
4343
Component: (
44-
{children, iconLabel = 'Opens link in new window', ...elemProps}: ExternalHyperlinkProps,
45-
ref
44+
{children, iconLabel, variant, ...elemProps}: ExternalHyperlinkProps,
45+
ref,
46+
Element
4647
) => (
47-
<Anchor ref={ref} target="_blank" rel="noreferrer" {...elemProps}>
48-
<span>{children}</span>
49-
<StyledSystemIcon
48+
<Element
49+
ref={ref}
50+
target="_blank"
51+
rel="noreferrer"
52+
{...handleCsProp(elemProps, externalHyperlinkStencil({variant}))}
53+
>
54+
<span data-part="external-hyperlink-children">{children}</span>
55+
<SystemIcon
5056
icon={extLinkIcon}
5157
role="img"
5258
aria-label={iconLabel}
53-
size={iconSize}
54-
cs={{'& svg': {minWidth: minIconSize, minHeight: minIconSize}}}
59+
data-part="external-hyperlink-icon"
5560
/>
56-
</Anchor>
61+
</Element>
5762
),
5863
});

modules/react/button/lib/Hyperlink.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export interface HyperlinkProps extends CSProps {
1616
children?: React.ReactNode;
1717
}
1818

19-
const hyperlinkStencil = createStencil({
19+
export const hyperlinkStencil = createStencil({
2020
base: {
2121
fontFamily: system.fontFamily.default,
2222
textDecoration: 'underline',

modules/react/button/stories/button/examples/ExternalHyperlink.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@ import React from 'react';
33
import {ExternalHyperlink} from '@workday/canvas-kit-react/button';
44

55
export const ExternalLink = () => (
6-
<ExternalHyperlink href="https://workday.com">External Hyperlink</ExternalHyperlink>
6+
<ExternalHyperlink href="https://workday.com" iconLabel="Opens link in new window">
7+
External Hyperlink
8+
</ExternalHyperlink>
79
);

modules/react/button/stories/button/examples/ExternalHyperlinkInverse.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ const parentContainerStyles = createStyles({
1212

1313
export const ExternalLinkInverse = () => (
1414
<Box cs={parentContainerStyles}>
15-
<ExternalHyperlink href="https://workday.com" variant="inverse">
15+
<ExternalHyperlink
16+
href="https://workday.com"
17+
variant="inverse"
18+
iconLabel="Opens link in new window"
19+
>
1620
Hyperlink
1721
</ExternalHyperlink>
1822
</Box>

modules/react/button/stories/visual-testing/ExternalHyperlink.stories.tsx

+30-10
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
} from '@workday/canvas-kit-react/testing';
1111
import {ExternalHyperlink} from '@workday/canvas-kit-react/button';
1212
import {Container} from './utils';
13-
import {Box, Flex} from '@workday/canvas-kit-react/layout';
13+
import {Flex} from '@workday/canvas-kit-react/layout';
1414
import {BodyText, Subtext} from '@workday/canvas-kit-react/text';
1515

1616
export default {
@@ -49,7 +49,11 @@ export const ExternalHyperlinkStates = {
4949
{(props: any) => (
5050
<Container blue={props.variant === 'inverse'}>
5151
<Subtext as="span" size="large" variant={props.variant}>
52-
Here's a <ExternalHyperlink {...props}>Link</ExternalHyperlink> to something
52+
Here's a{' '}
53+
<ExternalHyperlink {...props} iconLabel="Opens link in new window">
54+
Link
55+
</ExternalHyperlink>{' '}
56+
to something
5357
</Subtext>
5458
</Container>
5559
)}
@@ -58,31 +62,47 @@ export const ExternalHyperlinkStates = {
5862
<Flex flexDirection="column" gap="xxs">
5963
<h3>Typography</h3>
6064
<Subtext size="large">
61-
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
65+
The quick{' '}
66+
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
67+
jumps over the lazy dog
6268
</Subtext>
6369
<BodyText size="small">
64-
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
70+
The quick{' '}
71+
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
72+
jumps over the lazy dog
6573
</BodyText>
6674
<BodyText size="medium">
67-
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
75+
The quick{' '}
76+
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
77+
jumps over the lazy dog
6878
</BodyText>
6979
<BodyText size="large">
70-
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
80+
The quick{' '}
81+
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
82+
jumps over the lazy dog
7183
</BodyText>
7284
</Flex>
7385
<CanvasProvider theme={{canvas: {direction: ContentDirection.RTL}}}>
7486
<Flex flexDirection="column" gap="xxs">
7587
<Subtext size="large">
76-
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
88+
The quick{' '}
89+
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
90+
jumps over the lazy dog
7791
</Subtext>
7892
<BodyText size="small">
79-
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
93+
The quick{' '}
94+
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
95+
jumps over the lazy dog
8096
</BodyText>
8197
<BodyText size="medium">
82-
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
98+
The quick{' '}
99+
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
100+
jumps over the lazy dog
83101
</BodyText>
84102
<BodyText size="large">
85-
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
103+
The quick{' '}
104+
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
105+
jumps over the lazy dog
86106
</BodyText>
87107
</Flex>
88108
</CanvasProvider>

modules/react/combobox/lib/hooks/useComboboxInputConstrained.ts

+1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ export const useComboboxInputConstrained = createElemPropsHook(useComboboxModel)
141141
model.onFilterChange?.(event);
142142
return null; // Prevent further `onChange` callbacks from firing
143143
},
144+
144145
name: null,
145146
disabled,
146147
/**

modules/react/skeleton/index.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
export {Skeleton} from './lib/Skeleton';
1+
export * from './lib/Skeleton';
2+
export {skeletonTextStencil} from './lib/parts/SkeletonText';
3+
export {skeletonShapeStencil} from './lib/parts/SkeletonShape';
4+
export {skeletonHeaderStencil} from './lib/parts/SkeletonHeader';

0 commit comments

Comments
 (0)