Skip to content

Commit

Permalink
feat(Badge): use new style
Browse files Browse the repository at this point in the history
  • Loading branch information
anlyyao committed Aug 22, 2024
1 parent 7a81db2 commit 0f0f504
Show file tree
Hide file tree
Showing 17 changed files with 1,542 additions and 413 deletions.
2 changes: 1 addition & 1 deletion site/mobile/mobile.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export default {
{
title: 'Badge 徽标',
name: 'badge',
component: () => import('tdesign-mobile-react/badge/_example/index.jsx'),
component: () => import('tdesign-mobile-react/badge/_example/index.tsx'),
},
{
title: 'CountDown 倒计时',
Expand Down
111 changes: 55 additions & 56 deletions src/badge/Badge.tsx
Original file line number Diff line number Diff line change
@@ -1,90 +1,89 @@
import React, { forwardRef, useContext, useMemo } from 'react';
import cls from 'classnames';
import { ConfigContext } from '../config-provider';
import React, { forwardRef, useMemo } from 'react';
import classNames from 'classnames';
import type { StyledProps } from '../common';
import type { TdBadgeProps } from './type';
import { badgeDefaultProps } from './defaultProps';
import parseTNode from '../_util/parseTNode';
import useDefaultProps from '../hooks/useDefaultProps';
import useConfig from '../hooks/useConfig';
import { usePrefixClass } from '../hooks/useClass';

export interface BadgeProps extends TdBadgeProps, StyledProps {}

function resolveOffset(ofs): number | string | undefined {
if (typeof ofs === 'undefined') return ofs;
if (Number.isNaN(ofs)) return;
if (typeof ofs === 'number') return (ofs * -1) as number;
return (ofs as string).startsWith('-') ? ofs.replace(/^-/, '') : `-${ofs}`;
}
const hasUnit = (unit: string) =>
unit.indexOf('px') > 0 ||
unit.indexOf('rpx') > 0 ||
unit.indexOf('em') > 0 ||
unit.indexOf('rem') > 0 ||
unit.indexOf('%') > 0 ||
unit.indexOf('vh') > 0 ||
unit.indexOf('vm') > 0;

const Badge = forwardRef<HTMLDivElement, BadgeProps>((props, ref) => {
const {
children,
className,
style,
color = '',
content,
count = 0,
dot = false,
maxCount = 99,
offset,
shape = 'circle',
showZero = false,
size = 'medium',
...resetProps
} = props;
const { classPrefix } = useContext(ConfigContext);
const name = useMemo(() => `${classPrefix}-badge`, [classPrefix]);
const hasChildren = useMemo(() => !!(content || children), [content, children]);
// const isRibbon = useMemo(() => !dot && shape === 'ribbon', [shape, dot]);
const Badge = forwardRef<HTMLDivElement, BadgeProps>((originProps, ref) => {
const props = useDefaultProps(originProps, badgeDefaultProps);
const { children, className, style, color, content, count, dot, maxCount, offset, shape, showZero, size } = props;

const { classPrefix } = useConfig();
const badgeClass = usePrefixClass('badge');

// 徽标自定义样式
const computedStyle = useMemo(() => {
const mergedStyle = { ...style };
const badgeInnerStyles = useMemo(() => {
const mergedStyle: React.CSSProperties = {};
if (color) mergedStyle.backgroundColor = color;
if (offset && Array.isArray(offset)) {
const [right, top] = offset;
mergedStyle.right = resolveOffset(right);
mergedStyle.top = resolveOffset(top);
const [right = 0, top = 0]: Array<string | number> = offset;
mergedStyle.right = hasUnit(right.toString()) ? right : `${right}px`;
mergedStyle.top = hasUnit(top.toString()) ? top : `${top}px`;
}
return mergedStyle;
}, [style, color, offset]);
}, [color, offset]);

// 徽标外层样式类
const badgeClasses = cls({
[`${name}`]: true,
// [`${name}__ribbon--outer`]: isRibbon,
const badgeClasses = classNames(className, {
[`${badgeClass}`]: true,
[`${badgeClass}__ribbon-outer`]: shape === 'ribbon',
});

// 徽标内层样式类
const badgeInnerClasses = cls(
{
[`${name}__inner`]: true,
[`${name}--dot`]: dot,
[`${name}--${shape}`]: !dot && shape,
[`${classPrefix}-badge--has-children`]: hasChildren,
},
size === 'small' ? `${name}--${size}` : `${name}--medium`,
className,
);
const badgeInnerClasses = classNames({
[`${badgeClass}--basic`]: true,
[`${badgeClass}--dot`]: dot,
[`${badgeClass}--${size}`]: true,
[`${badgeClass}--${shape}`]: true,
[`${badgeClass}--count`]: !dot && count,
[`${classPrefix}-has-count`]: true,
});

const renderBadgeContent = useMemo(() => {
const readerCount = useMemo(() => {
if (dot) return null;
if (typeof count === 'number') {
if (count === 0) {
return showZero ? count : null;
}
return count >= +maxCount ? maxCount : count;
}
return count;
return parseTNode(count);
}, [dot, count, maxCount, showZero]);

const renderBadge = (
<div className={badgeInnerClasses} style={computedStyle}>
{renderBadgeContent}
const childNode = content || children;

const readerContent = () =>
childNode && (
<div className={`${badgeClass}__content`}>
<span className={`${badgeClass}__content-text`}>{parseTNode(childNode)}</span>
</div>
);

const readerBadge = () => (
<div className={badgeInnerClasses} style={badgeInnerStyles}>
{readerCount}
</div>
);

return (
<div ref={ref} className={badgeClasses} {...resetProps}>
{renderBadge}
{content || children}
<div ref={ref} className={badgeClasses} style={style}>
{readerContent()}
{readerBadge()}
</div>
);
});
Expand Down
23 changes: 0 additions & 23 deletions src/badge/_example/base.jsx

This file was deleted.

38 changes: 38 additions & 0 deletions src/badge/_example/base.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import { Badge, Button } from 'tdesign-mobile-react';
import { NotificationIcon } from 'tdesign-icons-react';

export default function BaseBadge() {
return (
<>
<div className="summary">红点徽标</div>
<div className="badge-demo">
<Badge dot className="badge-item" content="消息" />
<Badge dot offset={[1, -1]} className="badge-item">
<NotificationIcon size="24" />
</Badge>
<Badge dot offset={[1, 1]} className="badge-item">
<Button>按钮</Button>
</Badge>
</div>

<div className="summary">数字徽标</div>
<div className="badge-demo">
<Badge count="8" content="消息" offset={[-8, 0]} className="badge-item" />
<Badge count="2" offset={[-2, -2]} className="badge-item">
<NotificationIcon size="24" />
</Badge>
<Badge count="8" offset={[2, 2]} className="badge-item">
<Button>按钮</Button>
</Badge>
</div>

<div className="summary">自定义徽标</div>
<div className="badge-demo">
<Badge count="NEW" offset={[0, 2]}>
<Button icon={<NotificationIcon />} shape="square" size="large" />
</Badge>
</div>
</>
);
}
40 changes: 0 additions & 40 deletions src/badge/_example/button.jsx

This file was deleted.

24 changes: 0 additions & 24 deletions src/badge/_example/cell.jsx

This file was deleted.

22 changes: 12 additions & 10 deletions src/badge/_example/index.jsx → src/badge/_example/index.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import React from 'react';
import TDemoBlock from '../../../site/mobile/components/DemoBlock';
import TDemoHeader from '../../../site/mobile/components/DemoHeader';
import BaseDemo from './base';
import ButtonDemo from './button';
import CellDemo from './cell';

import BaseBadge from './base';
import ThemeBadge from './theme';
import SizeBadge from './size';

import './style/index.less';

export default function BadgeDemo() {
return (
<div className="badge-demo">
<div className="tdesign-mobile-demo">
<TDemoHeader title="Badge 徽标" summary="用于告知用户,该区域的状态变化或者待处理任务的数量。" />
<TDemoBlock title="01 类型" summary="徽标主要分红点、数字、文字和角标提醒">
<BaseDemo />
<TDemoBlock title="01 组件类型">
<BaseBadge />
</TDemoBlock>
<TDemoBlock>
<ButtonDemo />
<TDemoBlock title="02 组件样式">
<ThemeBadge />
</TDemoBlock>
<TDemoBlock>
<CellDemo />
<TDemoBlock title="03 组件尺寸">
<SizeBadge />
</TDemoBlock>
</div>
);
Expand Down
19 changes: 19 additions & 0 deletions src/badge/_example/size.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { Avatar } from 'tdesign-mobile-react';
import { UserIcon } from 'tdesign-icons-react';

export default function SizeBadge() {
return (
<>
<div className="summary">Large</div>
<div className="block">
<Avatar icon={<UserIcon />} size="large" badgeProps={{ count: 8, size: 'large', offset: [7, 7] }} />
</div>

<div className="summary">Middle</div>
<div className="block">
<Avatar icon={<UserIcon />} badgeProps={{ count: 8, offset: [5, 5] }} />
</div>
</>
);
}
28 changes: 13 additions & 15 deletions src/badge/_example/style/index.less
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
.tdesign-mobile-demo {
.badge-demo {
display: flex;
padding: 16px 0;
width: 100%;
.badge-demo {
display: flex;
margin-top: 28px;
margin-bottom: 24px;
margin-left: 16px;
align-items: center;
color: var(--td-text-color-primary, rgba(0, 0, 0, 0.9));

&__container {
width: 24%;
text-align: center;
position: relative;
}

.badge-item {
width: 24%;
text-align: center;
}
.badge-item {
margin-right: 48px;
}
}

.block {
padding: 16px 16px 24px;
}
Loading

0 comments on commit 0f0f504

Please sign in to comment.