Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Refactor External Hyperlink to use new styling utilities #3101

Merged
2 changes: 1 addition & 1 deletion modules/docs/mdx/12.0-UPGRADE-GUIDE.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ not follow semver, so 5.0 doesn't mean a large breaking change from 4.9. TypeScr
### Styling API and CSS Tokens

**PRs:** [#2793](https://github.com/Workday/canvas-kit/pull/2793),
[#2865](https://github.com/Workday/canvas-kit/pull/2865),
[#2865](https://github.com/Workday/canv as-kit/pull/2865),
mannycarrera4 marked this conversation as resolved.
Show resolved Hide resolved
[#2881](https://github.com/Workday/canvas-kit/pull/2881),
[#2825](https://github.com/Workday/canvas-kit/pull/2825),
[#2795](https://github.com/Workday/canvas-kit/pull/2795),
Expand Down
19 changes: 19 additions & 0 deletions modules/docs/mdx/13.0-UPGRADE-GUIDE.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,25 @@ yarn remove @workday/canvas-kit-codemod
> after executing the codemod, as its resulting formatting (spacing, quotes, etc.) may not match
> your project conventions.

## Component Updates

### Styling API and CSS Tokens

**PRs:** [#3101](https://github.com/Workday/canvas-kit/pull/3101)
mannycarrera4 marked this conversation as resolved.
Show resolved Hide resolved

Several components have been refactored to use our new
[Canvas Tokens](https://workday.github.io/canvas-tokens/?path=/docs/docs-getting-started--docs) and
[styling API](https://workday.github.io/canvas-kit/?path=/docs/styling-basics--create-modifiers#createstyles-api).
The React interface **has not changed**, but CSS variables are now used for dynamic properties.
mannycarrera4 marked this conversation as resolved.
Show resolved Hide resolved

> **Note:** These components also support our new `cs` prop for styling. Learn more about styling
> with `cs` in our
> [documentation](https://workday.github.io/canvas-kit/?path=/docs/styling-basics--cs-prop).

The following components are affected:

- `ExternalHyperlink`


### Styling API and CSS Tokens

Expand Down
69 changes: 37 additions & 32 deletions modules/react/button/lib/ExternalHyperlink.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,36 @@
import React from 'react';
import {styled, createComponent, StyledType} from '@workday/canvas-kit-react/common';
import {createComponent} from '@workday/canvas-kit-react/common';
import {extLinkIcon} from '@workday/canvas-system-icons-web';
import {SystemIcon, systemIconStyles} from '@workday/canvas-kit-react/icon';
import {Hyperlink, HyperlinkProps} from './Hyperlink';
import {SystemIcon, systemIconStencil} from '@workday/canvas-kit-react/icon';
import {HyperlinkProps, hyperlinkStencil} from './Hyperlink';
mannycarrera4 marked this conversation as resolved.
Show resolved Hide resolved
import {calc, createStencil, px2rem, handleCsProp} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';

export interface ExternalHyperlinkProps extends HyperlinkProps {
/**
* Informs a screen reader user the link will open in a new window. It is read after the link text.
* This value will need to be translated.
* @default 'Opens link in new window'
*/
iconLabel?: string;
iconLabel: string;
}

const iconStyles = {
...systemIconStyles({fill: 'currentColor', fillHover: 'currentColor'}),
};

const Anchor = styled(Hyperlink)<ExternalHyperlinkProps & StyledType>({
...iconStyles,
display: 'inline-flex',
flexDirection: 'row',
alignItems: 'center',
});

const iconSize = '1em';
const minIconSize = '16px';

const StyledSystemIcon = styled(SystemIcon)<StyledType>({
...iconStyles,
width: `calc(${iconSize} - 1px)`,
minWidth: `calc(${minIconSize} - 1px)`,
marginLeft: '2px',
export const externalHyperlinkStencil = createStencil({
extends: hyperlinkStencil,
mannycarrera4 marked this conversation as resolved.
Show resolved Hide resolved
base: {
display: 'inline-flex',
flexDirection: 'row',
alignItems: 'center',
'& [data-part="external-hyperlink-icon"]': {
[systemIconStencil.vars.color]: 'currentColor',
width: calc.subtract('1em', px2rem(1)),
minWidth: calc.subtract(system.space.x4, px2rem(1)),
marginInlineStart: calc.subtract(system.space.x1, px2rem(2)),
'& > svg': {
minWidth: system.space.x4,
minHeight: system.space.x4,
mannycarrera4 marked this conversation as resolved.
Show resolved Hide resolved
},
},
},
});

/**
Expand All @@ -41,18 +40,24 @@ const StyledSystemIcon = styled(SystemIcon)<StyledType>({
export const ExternalHyperlink = createComponent('a')({
displayName: 'ExternalHyperlink',
Component: (
{children, iconLabel = 'Opens link in new window', ...elemProps}: ExternalHyperlinkProps,
ref
{children, iconLabel, variant, ...elemProps}: ExternalHyperlinkProps,
ref,
Element
) => (
<Anchor ref={ref} target="_blank" rel="noreferrer" {...elemProps}>
<span>{children}</span>
<StyledSystemIcon
<Element
ref={ref}
target="_blank"
rel="noreferrer"
{...handleCsProp(elemProps, externalHyperlinkStencil({variant}))}
>
<span data-part="external-hyperlink-children">{children}</span>
<SystemIcon
icon={extLinkIcon}
role="img"
aria-label={iconLabel}
size={iconSize}
cs={{'& svg': {minWidth: minIconSize, minHeight: minIconSize}}}
data-part="external-hyperlink-icon"
size="1em"
/>
</Anchor>
</Element>
),
});
2 changes: 1 addition & 1 deletion modules/react/button/lib/Hyperlink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface HyperlinkProps extends CSProps {
children?: React.ReactNode;
}

const hyperlinkStencil = createStencil({
export const hyperlinkStencil = createStencil({
base: {
fontFamily: system.fontFamily.default,
textDecoration: 'underline',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ import React from 'react';
import {ExternalHyperlink} from '@workday/canvas-kit-react/button';

export const ExternalLink = () => (
<ExternalHyperlink href="https://workday.com">External Hyperlink</ExternalHyperlink>
<ExternalHyperlink href="https://workday.com" iconLabel="Opens link in new window">
External Hyperlink
</ExternalHyperlink>
);
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ const parentContainerStyles = createStyles({

export const ExternalLinkInverse = () => (
<Box cs={parentContainerStyles}>
<ExternalHyperlink href="https://workday.com" variant="inverse">
<ExternalHyperlink
href="https://workday.com"
variant="inverse"
iconLabel="Opens link in new window"
>
Hyperlink
</ExternalHyperlink>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ export const ExternalHyperlinkStates = {
{(props: any) => (
<Container blue={props.variant === 'inverse'}>
<Subtext as="span" size="large" variant={props.variant}>
Here's a <ExternalHyperlink {...props}>Link</ExternalHyperlink> to something
Here's a{' '}
<ExternalHyperlink {...props} iconLabel="Opens link in new window">
Link
</ExternalHyperlink>{' '}
to something
</Subtext>
</Container>
)}
Expand All @@ -58,31 +62,47 @@ export const ExternalHyperlinkStates = {
<Flex flexDirection="column" gap="xxs">
<h3>Typography</h3>
<Subtext size="large">
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
The quick{' '}
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
jumps over the lazy dog
</Subtext>
<BodyText size="small">
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
The quick{' '}
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
jumps over the lazy dog
</BodyText>
<BodyText size="medium">
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
The quick{' '}
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
jumps over the lazy dog
</BodyText>
<BodyText size="large">
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
The quick{' '}
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
jumps over the lazy dog
</BodyText>
</Flex>
<CanvasProvider theme={{canvas: {direction: ContentDirection.RTL}}}>
<Flex flexDirection="column" gap="xxs">
<Subtext size="large">
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
The quick{' '}
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
jumps over the lazy dog
</Subtext>
<BodyText size="small">
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
The quick{' '}
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
jumps over the lazy dog
</BodyText>
<BodyText size="medium">
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
The quick{' '}
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
jumps over the lazy dog
</BodyText>
<BodyText size="large">
The quick <ExternalHyperlink>brown fox</ExternalHyperlink> jumps over the lazy dog
The quick{' '}
<ExternalHyperlink iconLabel="Opens link in new window">brown fox</ExternalHyperlink>{' '}
jumps over the lazy dog
</BodyText>
</Flex>
</CanvasProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ export const useComboboxInputConstrained = createElemPropsHook(useComboboxModel)
model.onFilterChange?.(event);
return null; // Prevent further `onChange` callbacks from firing
},

name: null,
disabled,
/**
Expand Down
Loading