-
Notifications
You must be signed in to change notification settings - Fork 4
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(Link)!: introduce v2.0 component #1890
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
@import '../../design-tokens/mixins.css'; | ||
|
||
/*------------------------------------*\ | ||
# LINK | ||
\*------------------------------------*/ | ||
|
||
.link { | ||
color: var(--eds-theme-color-text-utility-neutral-primary); | ||
display: inline; | ||
|
||
/* TODO-AH: verify the way to sync type tokens and one-off treatments */ | ||
font-weight: 500; | ||
text-decoration-line: underline; | ||
} | ||
|
||
/** | ||
* Sub-components | ||
*/ | ||
.link__icon { | ||
padding-left: 0.25rem; | ||
|
||
/* Sub-component spacing */ | ||
&.link--size-xl, | ||
&.link--size-lg { padding-left: 0.5rem; } | ||
|
||
&.link--size-md, | ||
&.link--size-sm, | ||
&.link--size-xs { padding-left: 0.25rem; } | ||
} | ||
|
||
/** | ||
* Contexts | ||
*/ | ||
.link--context-standalone { | ||
display: block; | ||
|
||
/** | ||
* Sizes - using the presets for type ramp matching body-* | ||
*/ | ||
&.link--size-xl { | ||
font: var(--eds-theme-typography-body-xl); | ||
} | ||
|
||
&.link--size-lg { | ||
font: var(--eds-theme-typography-body-lg); | ||
} | ||
|
||
&.link--size-md { | ||
font: var(--eds-theme-typography-body-md); | ||
} | ||
|
||
&.link--size-sm { | ||
font: var(--eds-theme-typography-body-sm); | ||
} | ||
|
||
&.link--size-xs { | ||
font: var(--eds-theme-typography-body-xs); | ||
} | ||
} | ||
|
||
/** | ||
* Emphasis | ||
*/ | ||
.link--emphasis-high { | ||
color: var(--eds-theme-color-text-utility-interactive-secondary); | ||
} | ||
|
||
.link--emphasis-low { | ||
color: var(--eds-theme-color-text-utility-neutral-primary); | ||
text-decoration: none; | ||
} | ||
|
||
|
||
/** | ||
* States | ||
*/ | ||
|
||
.link:hover { | ||
color: var(--eds-theme-color-text-utility-interactive-secondary-hover); | ||
} | ||
|
||
.link:active { | ||
color: var(--eds-theme-color-text-utility-interactive-secondary-active); | ||
} | ||
|
||
.link:visited { | ||
color: var(--eds-theme-color-text-utility-interactive-visited); | ||
} | ||
|
||
.link:focus-visible { | ||
outline: 0.125rem solid var(--eds-theme-color-border-utility-focus); | ||
outline-offset: 0.125rem; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import type { StoryObj, Meta } from '@storybook/react'; | ||
import React from 'react'; | ||
import { Link, type LinkProps } from './Link-v2'; | ||
|
||
export default { | ||
title: 'Components/V2/Link', | ||
component: Link, | ||
parameters: { | ||
badges: ['intro-1.0', 'current-2.0'], | ||
}, | ||
args: { | ||
children: 'Link', | ||
size: 'lg', | ||
href: 'https://go.czi.team/eds', | ||
// stop link from navigating to another page so we can click the link for testing | ||
onClick: (event: any) => event.preventDefault(), | ||
}, | ||
} as Meta<Args>; | ||
|
||
type Args = React.ComponentProps<typeof Link>; | ||
|
||
export const Default: StoryObj<Args> = {}; | ||
|
||
export const LinkWithChevron: StoryObj<Args> = { | ||
args: { | ||
children: 'Default', | ||
context: 'standalone', | ||
icon: 'chevron-right', | ||
}, | ||
}; | ||
|
||
export const LinkWithOpenIcon: StoryObj<Args> = { | ||
args: { | ||
children: 'Default', | ||
context: 'standalone', | ||
icon: 'open-in-new', | ||
}, | ||
}; | ||
|
||
export const Emphasis: StoryObj<Args> = { | ||
args: { | ||
size: 'md', | ||
context: 'standalone', | ||
}, | ||
render: (args) => { | ||
return ( | ||
<div> | ||
<Link {...args} emphasis="default"> | ||
Default Emphasis | ||
</Link> | ||
<Link {...args} emphasis="high"> | ||
High Emphasis | ||
</Link> | ||
<Link {...args} emphasis="low"> | ||
Low Emphasis | ||
</Link> | ||
</div> | ||
); | ||
}, | ||
}; | ||
|
||
export const LinkInParagraphContext: StoryObj<Args> = { | ||
render: ( | ||
args: React.JSX.IntrinsicAttributes & | ||
(LinkProps & React.RefAttributes<HTMLAnchorElement>), | ||
) => ( | ||
<div> | ||
Lorem ipsum dolor sit amet,{' '} | ||
<Link {...args} href="https://go.czi.team/eds"> | ||
consectetur adipiscing elit | ||
</Link> | ||
. Morbi porta at ante quis molestie. Nam scelerisque id diam at iaculis. | ||
Nullam sit amet iaculis erat. Nulla id tellus ante.{' '} | ||
<Link {...args} href="https://go.czi.team/eds"> | ||
Aliquam pellentesque ipsum sagittis, commodo neque at, ornare est. | ||
Maecenas a malesuada sem, vitae euismod erat. Nullam molestie nunc non | ||
dui dignissim fermentum. | ||
</Link>{' '} | ||
Aliquam id volutpat nulla, sed auctor orci. Fusce cursus leo nisi. Fusce | ||
vehicula vitae nisl nec ultricies. Cras ut enim nec magna semper egestas. | ||
Sed sed quam id nisl bibendum convallis. Proin suscipit, odio{' '} | ||
<Link {...args} href="https://go.czi.team/eds"> | ||
vel pulvinar | ||
</Link>{' '} | ||
euismod, risus eros ullamcorper lectus, non blandit nulla dui eget massa. | ||
</div> | ||
), | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import clsx from 'clsx'; | ||
import React, { forwardRef } from 'react'; | ||
import type { Size } from '../../util/variant-types'; | ||
import type { IconName } from '../Icon'; | ||
import Icon from '../Icon'; | ||
|
||
import styles from './Link-v2.module.css'; | ||
|
||
export type LinkProps = React.AnchorHTMLAttributes<HTMLAnchorElement> & { | ||
// Component API | ||
/** | ||
* Component used to render the element. Meant to support interaction with framework navigation libraries. | ||
* TODO-AH: support frameworks that may not use (or replace) `href` for some other prop | ||
* | ||
* **Default is `"a"`**. | ||
*/ | ||
as: string | React.ElementType; | ||
/** | ||
* The link contents or label. | ||
*/ | ||
children: string; | ||
// Design API | ||
/** | ||
* Where `Link` sits alongside other text and content: | ||
* | ||
* * **inline** - Inline link inherits the text size established within the `<p>` paragraph they are embedded in. | ||
* * **standalone** - Users can choose from the available sizes. | ||
*/ | ||
context?: 'inline' | 'standalone'; | ||
/** | ||
* (trailing) icon to use with the link | ||
*/ | ||
icon?: Extract<IconName, 'chevron-right' | 'open-in-new'>; | ||
/** | ||
* Extra or lowered colors added to a link | ||
*/ | ||
emphasis?: 'default' | 'high' | 'low'; | ||
|
||
/** | ||
* Link size inherits from the surrounding text. | ||
*/ | ||
size?: Extract<Size, 'xs' | 'sm' | 'md' | 'lg' | 'xl'>; | ||
}; | ||
|
||
/** | ||
* `import {Link} from "@chanzuckerberg/eds";` | ||
* | ||
* Component for making styled anchor tags. Links allow users to navigate within or between a web page(s) or app(s). | ||
* | ||
*/ | ||
export const Link = forwardRef<HTMLAnchorElement, LinkProps>( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't wait until React removes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ohh, what will happen instead? I never read the upcoming docs for things besides HTML/CSS/JS :P |
||
( | ||
{ | ||
as: Component = 'a', | ||
children, | ||
className, | ||
context, | ||
emphasis = 'default', | ||
icon, | ||
size = 'md', | ||
...other | ||
}, | ||
ref, | ||
) => { | ||
const componentClassName = clsx( | ||
className, | ||
styles['link'], | ||
context && styles[`link--context-${context}`], | ||
emphasis && styles[`link--emphasis-${emphasis}`], | ||
icon && styles['link--has-right-icon'], | ||
size && styles[`link--size-${size}`], | ||
); | ||
|
||
const iconSize = size && (['xl', 'lg'].includes(size) ? '1.5rem' : '1rem'); | ||
|
||
return ( | ||
<Component className={componentClassName} ref={ref} {...other}> | ||
{children} | ||
{icon && context === 'standalone' && ( | ||
<Icon | ||
className={styles['link__icon']} | ||
name={icon} | ||
purpose="decorative" | ||
size={iconSize} | ||
/> | ||
)} | ||
</Component> | ||
); | ||
}, | ||
); | ||
|
||
Link.displayName = 'Link'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export { Link as default } from './Link'; | ||
export type { LinkProps } from './Link'; | ||
export { Link as LinkV2 } from './Link-v2'; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding this to support links link in Remix. Will likely need some work to support fully, but will be able to test once i get thru the first wave of component implementations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Challenge I see: Remix links currently use
to
instead ofhref
So to enable passing in a Remix link to here, we'd probably need to figure out how to support passing the EDS Link's
href
prop to the Remix Link'sto
somehow.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to replicate what we do using
ClickableStyle
and also get rid of that component in the next version :).I didn't want to copy how
ClickableStyle
works in here, b/c it seems to lose all the typing information and converts everything toany
:( What does make sense over there is that it uses a type param to combine the types of Remix'sLink
with the component props.I'm guessing this was part of why you needed to export the types earlier?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree on that goal, and not wanting to do ClickableStyle.
My point is that to achieve:
we'll need to figure out how to handle href vs to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One way to do that would be for the Eds Link to take
href
and always pass both it as bothhref
andto
on to theas
component...Kind of annoying, but that's the simplest thing I can see (at least until Remix updates its Link to use the standard
href
).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yah, I think you misunderstood. The way
ClickableStyle
supports to/href is weird, but "works". So we are saying the same thing basically.I want to avoid polluting EDS with anything specific to Remix or some other framework, as well. I like the TypeParam approach (e.g., combine
EDSLink
with Framework type, with option or toOmit
). Once I get thru the re-theming, I'll try a few things.