Skip to content

Commit

Permalink
feat(link): support component prop (#1699)
Browse files Browse the repository at this point in the history
* feat(link): support `component` prop

* docs(link): add story

Co-authored-by: maxin <maxin@growingio.com>
  • Loading branch information
nnmax and maxin committed Dec 20, 2021
1 parent c3c718c commit 0bb93f0
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 58 deletions.
85 changes: 48 additions & 37 deletions src/link/Link.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,60 @@
import { LoadingOutlined } from '@gio-design/icons';
import classNames from 'classnames';
import React from 'react';
import { OverridableComponent } from '@gio-design/utils';
import usePrefixCls from '../utils/hooks/use-prefix-cls';
import { LinkProps } from './interface';
import { LinkTypeMap } from './interface';

const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(
({ className, children, prefix, loading = false, disabled: disabledProp = false, href, ...restProps }, ref) => {
const prefixCls = usePrefixCls('link');
const classes = classNames([prefixCls, className], {
[`${prefixCls}_disabled`]: disabledProp,
[`${prefixCls}_loading`]: loading,
});
export const Link = React.forwardRef((props, ref) => {
const {
className,
children,
prefix,
loading,
disabled: disabledProp,
href,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: 在使用 Link 组件的时候能识别出 component prop,但是在这里却无法识别
component = 'a',
...restProps
} = props;
const prefixCls = usePrefixCls('link');
const classes = classNames([prefixCls, className], {
[`${prefixCls}_disabled`]: disabledProp,
[`${prefixCls}_loading`]: loading,
});

const prefixIcon = loading ? (
<span className={`${prefixCls}-prefix-icon`}>
<LoadingOutlined rotating />
</span>
) : (
prefix && <span className={`${prefixCls}-prefix-icon`}>{prefix}</span>
);
const prefixIcon = loading ? (
<span className={`${prefixCls}-prefix-icon`}>
<LoadingOutlined rotating />
</span>
) : (
prefix && <span className={`${prefixCls}-prefix-icon`}>{prefix}</span>
);

const disabled = disabledProp || loading;
const disabled = disabledProp || loading;

return (
<a
className={classes}
ref={ref}
aria-disabled={disabled}
tabIndex={disabled ? -1 : 0}
data-testid="link"
href={disabled ? undefined : href}
{...restProps}
>
{prefixIcon}
{children}
</a>
);
}
);
const Component: React.ElementType = component;
return (
<Component
className={classes}
disabled={disabledProp}
aria-disabled={disabled}
tabIndex={disabled ? -1 : 0}
ref={ref}
href={disabled ? undefined : href}
data-testid="link"
loading={component === 'a' ? undefined : loading}
{...restProps}
>
{prefixIcon}
{children}
</Component>
);
}) as OverridableComponent<LinkTypeMap>;

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: 存在 displayName 属性
Link.displayName = 'Link';

Link.defaultProps = {
loading: false,
disabled: false,
};

export default Link;
15 changes: 15 additions & 0 deletions src/link/demos/Link.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { LinkProps } from '../interface';
import Link from '../Link';
import '../style';
import Docs from './LinkPage';
import { Button } from '../..';

export default {
title: 'Upgraded/Link',
Expand Down Expand Up @@ -102,3 +103,17 @@ IconLink.args = {
href: '//www.growingio.com',
prefix: <PlusOutlined />,
};

export const CustomRootNode = () => (
<>
<h4>支持渲染自定义跟组件</h4>
<p>如果您需要 Link 组件的根节点渲染特定的组件(比如 React-Router Link),可以传入 `component` prop。</p>
<Link component={Button} size="normal" href="https://growingio.com" type="text" style={{ marginRight: '2rem' }}>
Button
</Link>

<Link component="span" href="https://growingio.com">
span tag
</Link>
</>
);
7 changes: 6 additions & 1 deletion src/link/demos/LinkPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Canvas, Title, Heading, Story, Subheading, ArgsTable } from '@storybook
import { useIntl } from 'react-intl';
import Link from '../index';

export default function ButtonPage() {
export default function LinkPage() {
const { formatMessage } = useIntl();

return (
Expand All @@ -25,6 +25,7 @@ export default function ButtonPage() {
<li>样式变化:颜色变化</li>
<li> 支持原生a标签</li>
<li> 原 icon 现在需要在prefix内传入如&lt;PlusOutlined/&gt;</li>
<li>支持自定义渲染根组件</li>
</ul>
<Heading>{formatMessage({ defaultMessage: '代码演示' })}</Heading>
<Subheading>{formatMessage({ defaultMessage: '样例展示' })}</Subheading>
Expand All @@ -47,6 +48,10 @@ export default function ButtonPage() {
<Canvas>
<Story id="upgraded-link--icon-link" />
</Canvas>
<Subheading>{formatMessage({ defaultMessage: '自定义节点' })}</Subheading>
<Canvas>
<Story id="upgraded-link--custom-root-node" />
</Canvas>
<Heading>{formatMessage({ defaultMessage: '参数说明' })}</Heading>
<ArgsTable of={Link} />
</>
Expand Down
2 changes: 1 addition & 1 deletion src/link/index.tsx → src/link/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Link from './Link';

export type { LinkProps } from './interface';
export { LinkProps } from './interface';

export default Link;
42 changes: 23 additions & 19 deletions src/link/interface.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import { OverrideProps } from '@gio-design/utils/dist/interfaces';

export interface LinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'prefix' | 'href'> {
/**
* 文本前的图标
*/
prefix?: React.ReactNode;
export interface LinkTypeMap<T extends React.ElementType = 'a'> {
props: Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'prefix' | 'type'> & {
/**
* 文本前的图标
*/
prefix?: React.ReactNode;

/**
* 载入状态
* @default false
*/
loading?: boolean;
/**
* 载入状态
* @default false
*/
loading?: boolean;

/**
* 禁用状态
*/
disabled?: boolean

/**
* 包含超链接指向的 URL 或 URL 片段。`a` 标签的原生属性
*/
href?: string
/**
* 禁用状态
* @default false
*/
disabled?: boolean;
};
defaultComponent: T;
}

// prettier-ignore
export type LinkProps<
D extends React.ElementType = LinkTypeMap['defaultComponent']
> = OverrideProps<LinkTypeMap<D>, D>;

1 comment on commit 0bb93f0

@vercel
Copy link

@vercel vercel bot commented on 0bb93f0 Dec 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.