Skip to content
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(badge): v15适配 #2826

Open
wants to merge 15 commits into
base: feat_v3.x
Choose a base branch
from
7 changes: 2 additions & 5 deletions migrate-from-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -667,11 +667,8 @@ plugins: [

#### Badge

- 移除 `zIndex`,目前没有用到,也不生效,直接去掉。
- 移除 `icon`,自定义 `icon` 可放在 `value` 中实现,扩充了 `value` 的类型。
- 修改 `max` 的最大值为99(之前为10000),比较贴合实际场景。
- 主题定制的 `css` 变量中,去掉和 `dot` 有关的其他值,只保留 `width`。其他值由 `width` 计算而来.
- 主题定制,增加包含 icon 情况下的样式变量。
- 新增 `size` 属性,dot 尺寸,当 dot 等于 `true` 时生效
Copy link
Collaborator

Choose a reason for hiding this comment

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

上面的内容是 v2 的,可以删除了。

- 移除 `徽标背景颜色`,通过css变量`--nutui-badge-background-color`实现

#### CircleProgress

Expand Down
3 changes: 2 additions & 1 deletion src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,7 @@
"sort": 4,
"show": true,
"taro": true,
"v14": true,
"author": "lzz"
},
{
Expand Down Expand Up @@ -1274,4 +1275,4 @@
]
}
]
}
}
5 changes: 3 additions & 2 deletions src/packages/badge/__test__/__snapshots__/badge.spec.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ exports[`should match custom icon 1`] = `
>
<div
class="nut-badge-content nut-badge-icon"
style="top: 0px; right: 0px;"
>
<svg
aria-labelledby="Checklist"
Expand All @@ -32,8 +33,8 @@ exports[`should match snapshot 1`] = `
class="nut-badge"
>
<div
class="nut-badge-content nut-badge-sup nut-badge-one"
style="top: -4px; right: 8px;"
class="nut-badge-sup nut-badge-number nut-badge-one"
style="top: 0px; right: 0px;"
>
8
</div>
Expand Down
38 changes: 7 additions & 31 deletions src/packages/badge/__test__/badge.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ test('should match snapshot', () => {

test('should match value is string', () => {
const { container } = render(<Badge value="new" />)
const badgeContent = container.querySelectorAll('.nut-badge-content')[0]
const badgeContent = container.querySelectorAll('.nut-badge-sup')[0]
expect(badgeContent).toHaveTextContent('new')
})

test('should match max size', () => {
const { container } = render(<Badge value={200} max={9} />)
const badgeContent = container.querySelectorAll('.nut-badge-content')[0]
const badgeContent = container.querySelectorAll('.nut-badge-sup')[0]
expect(badgeContent.textContent).toBe('9+')
})

Expand All @@ -29,42 +29,18 @@ test('should match dot', () => {
})

test('should match top、right: bad number', () => {
const { container } = render(<Badge value={10} top="--10" right="0" />)
const badgeContent = container.querySelectorAll('.nut-badge-content')[0]
expect(badgeContent).toHaveStyle({ top: '0px' })
})

test('should match top、right: have px', () => {
const { container } = render(<Badge value={10} top="-10" right="0" />)
const badgeContent = container.querySelectorAll('.nut-badge-content')[0]
expect(badgeContent).toHaveStyle({ top: '10px', right: '0px' })
const { container } = render(<Badge value={10} top="10" right="0" />)
const badgeContent = container.querySelectorAll('.nut-badge-sup')[0]
expect(badgeContent).toHaveStyle({ top: '10px' })
})

test('should match top、right: float', () => {
const { container } = render(<Badge value={10} top="-10.8" right="0.5px" />)
const badgeContent = container.querySelectorAll('.nut-badge-content')[0]
const { container } = render(<Badge value={10} top="10.8" right="0.5" />)
const badgeContent = container.querySelectorAll('.nut-badge-sup')[0]
expect(badgeContent).toHaveStyle({ top: '10.8px', right: '0.5px' })
})

test('should match custom color', () => {
const { container } = render(<Badge value={200} color="orange" />)
const badgeContent = container.querySelectorAll('.nut-badge-content')[0]
expect(badgeContent).toHaveStyle({ 'background-color': 'orange' })
})

test('should match custom icon', () => {
const { asFragment } = render(<Badge value={<Checklist />} />)
expect(asFragment()).toMatchSnapshot()
})

test('should match custom color when fill = outline', () => {
const { container } = render(
<Badge value={200} color="orange" fill="outline" />
)
const badgeContent = container.querySelectorAll('.nut-badge-content')[0]
expect(badgeContent).toHaveStyle({
border: '1px solid orange',
color: 'orange',
background: '#fff',
})
})
95 changes: 61 additions & 34 deletions src/packages/badge/badge.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,14 @@
position: relative;
display: inline-flex;
width: auto;
/* #ifdef harmony */
min-width: 1px;
/* #endif */
/* #ifndef harmony */
min-width: auto;
/* #endif */

&-icon {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
background: $badge-background-color;
padding: $badge-icon-padding;
text-align: center;
border: $badge-border;
border-radius: $badge-border-radius;
z-index: $badge-z-index;

.nut-icon {
Expand All @@ -27,53 +19,88 @@
}
}

&-sup,
&-icon {
border-radius: $badge-border-radius;
&::after {
content: '';
position: absolute;
top: -50%;
bottom: -50%;
left: -50%;
right: -50%;
transform: scale(0.5);
border: $badge-border;
border-radius: $badge-border-radius;
}
}

&-sup {
height: $badge-height;
position: absolute;
display: flex;
display: inline-flex;
justify-content: center;
align-items: center;
/* #ifdef harmony */
background: $color-primary;
/* #endif */
/* #ifndef harmony */
background: $badge-background-color;
/* #endif */
color: $badge-color;
height: $badge-height;
min-width: $badge-min-width;
padding: $badge-padding;
box-sizing: border-box;
color: $badge-color;
font-size: $badge-font-size;
font-weight: normal;
text-align: center;
border: $badge-border;
border-radius: $badge-border-radius;
min-width: $badge-min-width;
line-height: 12px;
white-space: nowrap;
font-weight: normal;
vertical-align: middle;
background: $badge-background-color;
z-index: 1;
}

&-number {
font-family: 'JD';
/* #ifdef harmony */
line-height: 12px;
/* #endif */
/* #ifndef harmony */
line-height: 13px;
/* #endif */
}
Comment on lines +55 to +63
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

建议重新考虑字体设置

直接使用 font-family: 'JD' 可能存在兼容性问题:

  1. 如果 JD 字体未能成功加载,可能会影响数字显示
  2. 建议添加降级字体方案
-  font-family: 'JD';
+  font-family: 'JD', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', sans-serif;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
&-number {
font-family: 'JD';
/* #ifdef harmony */
line-height: 12px;
/* #endif */
/* #ifndef harmony */
line-height: 13px;
/* #endif */
}
&-number {
font-family: 'JD', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', sans-serif;
/* #ifdef harmony */
line-height: 12px;
/* #endif */
/* #ifndef harmony */
line-height: 13px;
/* #endif */
}


&-one {
height: $badge-height;
width: $badge-height;
padding: 0;
}

&-content {
/* #ifndef rn */
position: absolute;
transform: $badge-content-transform;
/* #endif */
}

&-dot {
width: $badge-dot-width;
height: $badge-dot-width;
border: $badge-dot-border;
border-radius: $badge-dot-width;
padding: 0;
border-radius: 50%;
&::after {
border: $badge-dot-border;
border-radius: 50%;
}
&-normal {
min-width: $badge-dot-width;
width: $badge-dot-width;
height: $badge-dot-width;
}
&-small {
min-width: $badge-dot-small-width;
width: $badge-dot-small-width;
height: $badge-dot-small-width;
}
&-large {
min-width: $badge-dot-large-width;
width: $badge-dot-large-width;
height: $badge-dot-large-width;
}
}

&-outline {
background: $color-primary-text;
border: 1px solid $color-primary;
color: $color-primary;
color: $badge-outline-color;
&::after {
border: $badge-outline-border;
}
}
}
72 changes: 17 additions & 55 deletions src/packages/badge/badge.taro.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,27 @@
import React, {
CSSProperties,
FunctionComponent,
ReactNode,
useEffect,
useRef,
useState,
} from 'react'
import classNames from 'classnames'
import { View } from '@tarojs/components'
import { BasicComponent, ComponentDefaults } from '@/utils/typings'
import { ComponentDefaults } from '@/utils/typings'
import { useRtl } from '@/packages/configprovider/index.taro'
import pxTransform from '@/utils/px-transform'
import { getRectByTaro } from '@/utils/get-rect-by-taro'
import { harmony, rn } from '@/utils/platform-taro'
import { harmony } from '@/utils/platform-taro'
import { BadgeProps } from './types'

export type BadgeFill = 'solid' | 'outline'
export interface BadgeProps extends BasicComponent {
value: ReactNode
dot: boolean
max: number
top: string | number
right: string | number
color: string
fill: BadgeFill
}
const defaultProps = {
...ComponentDefaults,
value: '',
dot: false,
max: 99,
top: '4',
right: '8',
color: '',
top: 0,
right: 0,
fill: 'solid',
size: 'large',
} as BadgeProps
export const Badge: FunctionComponent<Partial<BadgeProps>> = (props) => {
const rtl = useRtl()
Expand All @@ -45,8 +34,8 @@
dot,
top,
right,
color,
fill,
size,
} = {
...defaultProps,
...props,
Expand Down Expand Up @@ -77,56 +66,32 @@
if (typeof value === 'string' && value) return value
}

const contentClasses = classNames(`${classPrefix}-content`, {
const contentClasses = classNames({
[`${classPrefix}-sup`]: isNumber() || isString() || dot,
[`${classPrefix}-number`]: isNumber(),
[`${classPrefix}-one`]:
typeof content() === 'string' && `${content()}`?.length === 1,
[`${classPrefix}-dot`]: dot,
[`${classPrefix}-dot-${size}`]: dot,
[`${classPrefix}-${fill}`]: fill === 'outline',
[`${classPrefix}-content`]: children,
})

useEffect(() => {
if (badgeRef.current) {
getPositionStyle()
}
}, [])

Check warning on line 84 in src/packages/badge/badge.taro.tsx

View workflow job for this annotation

GitHub Actions / lint

React Hook useEffect has a missing dependency: 'getPositionStyle'. Either include it or remove the dependency array
const getPositionStyle = async () => {
const style: CSSProperties = {}
style.top = pxTransform(-Number(top) || 0)
if (rn()) {
const reacts = await getRectByTaro(badgeRef.current)
style.left =
reacts?.width && reacts?.width > Number(right)
? pxTransform(reacts.width - Number(right))
: 0
} else {
const dir = rtl ? 'left' : 'right'
style[dir] = isHarmony
? pxTransform(Number(right))
: `${Number(right) || parseFloat(String(right)) || 0}px`
}
style.top = pxTransform(Number(top) || 0)
const dir = rtl ? 'left' : 'right'
style[dir] = isHarmony
? pxTransform(Number(right))
: `${Number(right) || 0}px`
setContentStyle(style)
}

const getStyle = () => {
const style: CSSProperties = {}
if (color) {
if (fill === 'outline') {
style.color = color
isHarmony
? (style.backgroundColor = '#fff')
: (style.background = '#fff')
if (!color?.includes('gradient')) {
style.borderColor = color
}
} else {
style.color = '#fff'
isHarmony ? (style.backgroundColor = color) : (style.background = color)
}
}
return style
}

return (
<View className={classes} style={style} ref={badgeRef}>
{isIcon() && (
Expand All @@ -142,10 +107,7 @@
)}
{children}
{!isIcon() && (
<View
className={contentClasses}
style={{ ...contentStyle, ...getStyle() }}
>
<View className={contentClasses} style={contentStyle}>
{content()}
</View>
)}
Expand Down
Loading
Loading