Skip to content

Commit

Permalink
feat(Link)!: introduce v2.0 component (#1890)
Browse files Browse the repository at this point in the history
- add stories and styles to match new design
- update snapshots
- also add in the nested V2 folder in storybook, and export
  • Loading branch information
booc0mtaco authored Mar 19, 2024
1 parent e6fffa2 commit bdce10a
Showing 4 changed files with 274 additions and 0 deletions.
93 changes: 93 additions & 0 deletions src/components/Link/Link-v2.module.css
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;
}
88 changes: 88 additions & 0 deletions src/components/Link/Link-v2.stories.tsx
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>
),
};
92 changes: 92 additions & 0 deletions src/components/Link/Link-v2.tsx
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>(
(
{
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';
1 change: 1 addition & 0 deletions src/components/Link/index.ts
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';

0 comments on commit bdce10a

Please sign in to comment.