-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(link): add link component (#1360)
- Loading branch information
Showing
19 changed files
with
290 additions
and
158 deletions.
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 |
---|---|---|
|
@@ -36,3 +36,4 @@ storybook-static | |
*-report.json | ||
*-report.xml | ||
build-storybook.log | ||
.eslintcache |
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
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,66 @@ | ||
import React from 'react'; | ||
import classnames from 'classnames'; | ||
import { usePrefixCls } from '@gio-design/utils'; | ||
import { LinkProps } from './interface'; | ||
|
||
export { LinkProps } from './interface'; | ||
|
||
const Link: React.FC<LinkProps> = (props: LinkProps) => { | ||
const { | ||
component = 'a', | ||
to = '', | ||
disabled, | ||
prefix: customPrefixCls, | ||
className, | ||
children, | ||
icon, | ||
...otherProps | ||
} = props; | ||
|
||
const prefixCls = usePrefixCls('link', customPrefixCls); | ||
const cls = classnames(className, prefixCls, { | ||
[`${prefixCls}--disabled`]: disabled, | ||
}); | ||
|
||
const handleClick = (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => { | ||
if (disabled) { | ||
e.preventDefault(); | ||
return; | ||
} | ||
|
||
if (otherProps.onClick) { | ||
otherProps.onClick(e); | ||
return; | ||
} | ||
|
||
if (to) { | ||
window.location.href = to; | ||
} | ||
}; | ||
|
||
const componentProps = { | ||
className: cls, | ||
...otherProps, | ||
onClick: handleClick, | ||
}; | ||
|
||
if (component === 'a' && !otherProps.onClick) { | ||
return ( | ||
// eslint-disable-next-line react/jsx-props-no-spreading | ||
<a href={to} {...componentProps}> | ||
{icon} | ||
{children} | ||
</a> | ||
); | ||
} | ||
|
||
const ComponentProp = component; | ||
return ( | ||
<ComponentProp {...componentProps}> | ||
{icon} | ||
{children} | ||
</ComponentProp> | ||
); | ||
}; | ||
|
||
export default Link; |
File renamed without changes.
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,49 @@ | ||
import React from 'react'; | ||
import { Story, Meta } from '@storybook/react/types-6-0'; | ||
import { withDesign } from 'storybook-addon-designs'; | ||
import { FilterOutlined } from '@gio-design/icons'; | ||
import Docs from './LinkPage'; | ||
import Link from '../index'; | ||
import { ILinkProps } from '../interface'; | ||
// import '../style'; | ||
|
||
export default { | ||
title: 'Basic Components/Link', | ||
component: Link, | ||
decorators: [withDesign], | ||
parameters: { | ||
design: { | ||
type: 'figma', | ||
url: 'https://www.figma.com/file/kP3A6S2fLUGVVMBgDuUx0f/GrowingIO-Design-Components?node-id=1%3A1310', | ||
allowFullscreen: true, | ||
}, | ||
docs: { | ||
page: Docs, | ||
}, | ||
}, | ||
} as Meta; | ||
|
||
const Template: Story<ILinkProps> = (args) => ( | ||
<div> | ||
<Link {...args}>GrowingIO</Link> | ||
<Link {...args} to="https://growingio.com"> | ||
GrowingIO | ||
</Link> | ||
<Link {...args} icon={<FilterOutlined />} to="https://growingio.com" onClick={() => window.alert('被点击')}> | ||
GrowingIO | ||
</Link> | ||
</div> | ||
); | ||
|
||
export const Default = Template.bind({}); | ||
Default.args = {}; | ||
|
||
export const Disabled = Template.bind({}); | ||
Disabled.args = { | ||
disabled: true, | ||
}; | ||
|
||
export const CustomComponent = Template.bind({}); | ||
CustomComponent.args = { | ||
component: 'span', | ||
}; |
File renamed without changes.
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,5 @@ | ||
import Link from './Link'; | ||
|
||
export { LinkProps } from './interface'; | ||
|
||
export default 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 |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* eslint-disable @typescript-eslint/ban-types */ | ||
import { OverrideProps } from '../../utils/interfaces'; | ||
|
||
export type HtmlElement = keyof React.ReactHTML; | ||
|
||
export interface ILinkProps { | ||
/** | ||
* 自定义 Link 根元素使用的组件 | ||
*/ | ||
component?: React.ElementType; | ||
/** | ||
* 跳转目标链接 | ||
*/ | ||
to?: string; | ||
/** | ||
* 失效状态 | ||
*/ | ||
disabled?: boolean; | ||
/** | ||
* 替代 Link 组件 class 的 gio-link 前缀 | ||
*/ | ||
prefix?: string; | ||
|
||
/** | ||
* ICON | ||
*/ | ||
icon?: React.ReactNode; | ||
} | ||
|
||
export interface LinkTypeMap<P = {}, D extends React.ElementType = 'a'> { | ||
props: P & ILinkProps; | ||
defaultComponent: D; | ||
} | ||
|
||
export type LinkProps<D extends React.ElementType = LinkTypeMap['defaultComponent'], P = {}> = OverrideProps< | ||
LinkTypeMap<P, D>, | ||
D | ||
>; |
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,51 @@ | ||
@import '../../../stylesheet/index.less'; | ||
|
||
@gio-link-prefix: ~'@{component-prefix}-link'; | ||
@gio-link-disabled: ~'@{gio-link-prefix}--disabled'; | ||
@iconfont-css-prefix: ~'@{component-prefix}-icon'; | ||
|
||
// normal | ||
.@{gio-link-prefix} { | ||
display: inline-block; | ||
margin-right: 8px; | ||
margin-left: 8px; | ||
color: @palette-blue-4; | ||
font-size: 14px; | ||
line-height: 22px; | ||
text-decoration: none; | ||
vertical-align: middle; | ||
cursor: pointer; | ||
|
||
&:hover { | ||
color: @palette-blue-5; | ||
text-decoration: none; | ||
} | ||
|
||
&:active { | ||
color: @palette-blue-3; | ||
} | ||
|
||
.@{iconfont-css-prefix} { | ||
width: 14px; | ||
height: 14px; | ||
margin-right: 8px; | ||
svg { | ||
width: 14px; | ||
height: auto; | ||
} | ||
} | ||
} | ||
|
||
// disabled | ||
.@{gio-link-disabled} { | ||
color: @palette-black-3; | ||
cursor: not-allowed; | ||
|
||
&.@{gio-link-prefix} { | ||
&:hover, | ||
&:active { | ||
color: @palette-black-3; | ||
text-decoration: none; | ||
} | ||
} | ||
} |
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 @@ | ||
import './index.less'; |
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,66 +1,40 @@ | ||
import { LoadingOutlined } from '@gio-design/icons'; | ||
import classNames from 'classnames'; | ||
import React from 'react'; | ||
import classnames from 'classnames'; | ||
import { usePrefixCls } from '@gio-design/utils'; | ||
import usePrefixCls from '../utils/hooks/use-prefix-cls'; | ||
import { LinkProps } from './interface'; | ||
|
||
export { LinkProps } from './interface'; | ||
const Link = React.forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => { | ||
const { className, children, prefix, loading = false, disabled = false, ...restProps } = props; | ||
|
||
const Link: React.FC<LinkProps> = (props: LinkProps) => { | ||
const { | ||
component = 'a', | ||
to = '', | ||
disabled, | ||
prefix: customPrefixCls, | ||
className, | ||
children, | ||
icon, | ||
...otherProps | ||
} = props; | ||
|
||
const prefixCls = usePrefixCls('link', customPrefixCls); | ||
const cls = classnames(className, prefixCls, { | ||
[`${prefixCls}--disabled`]: disabled, | ||
const prefixCls = usePrefixCls('link'); | ||
const classes = classNames([prefixCls, className], { | ||
[`${prefixCls}_disabled`]: disabled, | ||
[`${prefixCls}_loading`]: loading, | ||
}); | ||
|
||
const handleClick = (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => { | ||
if (disabled) { | ||
e.preventDefault(); | ||
return; | ||
} | ||
|
||
if (otherProps.onClick) { | ||
otherProps.onClick(e); | ||
return; | ||
} | ||
|
||
if (to) { | ||
window.location.href = to; | ||
} | ||
}; | ||
|
||
const componentProps = { | ||
className: cls, | ||
...otherProps, | ||
onClick: handleClick, | ||
}; | ||
|
||
if (component === 'a' && !otherProps.onClick) { | ||
return ( | ||
// eslint-disable-next-line react/jsx-props-no-spreading | ||
<a href={to} {...componentProps}> | ||
{icon} | ||
{children} | ||
</a> | ||
); | ||
} | ||
const prefixIcon = loading ? ( | ||
<span className={`${prefixCls}-prefix-icon`}> | ||
<LoadingOutlined rotating /> | ||
</span> | ||
) : ( | ||
prefix && <span className={`${prefixCls}-prefix-icon`}>{prefix}</span> | ||
); | ||
|
||
const ComponentProp = component; | ||
return ( | ||
<ComponentProp {...componentProps}> | ||
{icon} | ||
// eslint-disable-next-line react/jsx-props-no-spreading | ||
<a className={classes} ref={ref} aria-disabled={disabled || loading} {...restProps}> | ||
{prefixIcon} | ||
{children} | ||
</ComponentProp> | ||
</a> | ||
); | ||
}); | ||
|
||
Link.displayName = 'Link'; | ||
|
||
Link.defaultProps = { | ||
loading: false, | ||
disabled: false, | ||
}; | ||
|
||
export default 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,49 +1,22 @@ | ||
import React from 'react'; | ||
import { Story, Meta } from '@storybook/react/types-6-0'; | ||
import { withDesign } from 'storybook-addon-designs'; | ||
import { FilterOutlined } from '@gio-design/icons'; | ||
import Docs from './LinkPage'; | ||
import Link from '../index'; | ||
import { ILinkProps } from '../interface'; | ||
import { PlusOutlined } from '@gio-design/icons'; | ||
import { LinkProps } from '../interface'; | ||
import Link from '../Link'; | ||
import '../style'; | ||
|
||
export default { | ||
title: 'Basic Components/Link', | ||
title: 'Upgraded/Link', | ||
component: Link, | ||
decorators: [withDesign], | ||
parameters: { | ||
design: { | ||
type: 'figma', | ||
url: 'https://www.figma.com/file/kP3A6S2fLUGVVMBgDuUx0f/GrowingIO-Design-Components?node-id=1%3A1310', | ||
allowFullscreen: true, | ||
}, | ||
docs: { | ||
page: Docs, | ||
}, | ||
}, | ||
} as Meta; | ||
|
||
const Template: Story<ILinkProps> = (args) => ( | ||
<div> | ||
<Link {...args}>GrowingIO</Link> | ||
<Link {...args} to="https://growingio.com"> | ||
GrowingIO | ||
</Link> | ||
<Link {...args} icon={<FilterOutlined />} to="https://growingio.com" onClick={() => window.alert('被点击')}> | ||
GrowingIO | ||
</Link> | ||
</div> | ||
const Template: Story<LinkProps> = (args) => ( | ||
<Link prefix={<PlusOutlined />} {...args}> | ||
Test Link | ||
</Link> | ||
); | ||
|
||
export const Default = Template.bind({}); | ||
Default.args = {}; | ||
|
||
export const Disabled = Template.bind({}); | ||
Disabled.args = { | ||
disabled: true, | ||
}; | ||
|
||
export const CustomComponent = Template.bind({}); | ||
CustomComponent.args = { | ||
component: 'span', | ||
Default.args = { | ||
href: 'https://www.growingio.com', | ||
}; |
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,5 +1,5 @@ | ||
import Link from './Link'; | ||
|
||
export { LinkProps } from './interface'; | ||
export type { LinkProps } from './interface'; | ||
|
||
export default Link; |
Oops, something went wrong.
c4281f8
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.
Successfully deployed to the following URLs: