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

fix(badge): 四端适配 #2620

Merged
merged 21 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion scripts/rn/copy-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ const removeFile = async (url) => {
}

const modify = (fileUrl, importStatement) => {
if(!fse.ensureFileSync(fileUrl)) return
fse.readFile(fileUrl, 'utf8').then((content) => {
let modifiedContent = content
modifiedContent = [importStatement, modifiedContent.slice(0)].join('')
Expand Down
2 changes: 1 addition & 1 deletion src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@
"author": "dsj"
},
{
"version": "2.0.0",
"version": "3.0.0",
"name": "Badge",
"type": "component",
"cName": "徽标",
Expand Down
31 changes: 14 additions & 17 deletions src/packages/badge/badge.harmony.css
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
.nut-badge {
position: relative;
display: inline-block;
display: inline-flex;
width: auto;
/* #ifdef harmony */
min-width: 1px;
Copy link
Collaborator

Choose a reason for hiding this comment

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

应该写 min-width:1px; #ifndef harmony min-width:auto。因为组件库纯H5 和 多端同一套样式文件。

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

已修改

/* #endif */
}
.nut-badge-icon {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(135deg, #FF0F23 0%, #FF0F23 100%);
top: -10%;
right: -15%;
background: #ff0f23;
padding: 3px;
text-align: center;
border: 0px solid #ffffff;
Expand All @@ -27,7 +29,7 @@
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(135deg, #FF0F23 0%, #FF0F23 100%);
background: #ff0f23;
color: #fff;
padding: 0 4px;
font-size: 10px;
Expand All @@ -45,7 +47,9 @@
padding: 0;
}
.nut-badge-content {
transform: translateY(-50%) translateX(100%);
/* #ifndef rn */
transform: translateX(100%);
/* #endif */
}
.nut-badge-dot {
width: 7px;
Expand All @@ -54,15 +58,8 @@
border-radius: 7px;
padding: 0;
}

[dir=rtl] .nut-badge-icon,
.nut-rtl .nut-badge-icon {
right: auto;
left: -15%;
}
[dir=rtl] .nut-badge-content {
transform: translateY(-50%) translateX(-100%);
}
.nut-rtl .nut-badge-content {
transform: translateY(-50%) translateX(-100%);
.nut-badge-outline {
background: #ffffff;
border: 1px solid #ff0f23;
color: #ff0f23;
}
34 changes: 10 additions & 24 deletions src/packages/badge/badge.scss
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
.nut-badge {
position: relative;
display: inline-block;

display: inline-flex;
width: auto;
/* #ifdef harmony */
min-width: 1px;
/* #endif */
&-icon {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
background: $badge-background-color;
top: -10%;
right: -15%;
padding: $badge-icon-padding;
text-align: center;
border: $badge-border;
Expand Down Expand Up @@ -49,7 +50,9 @@
}

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

&-dot {
Expand All @@ -61,25 +64,8 @@
}

&-outline {
.nut-badge-content {
background: $color-primary-text;
border: 1px solid $color-primary;
color: $color-primary;
}
}
}

[dir='rtl'] .nut-badge,
.nut-rtl .nut-badge {
&-icon {
right: auto;
left: -15%;
}

&-content {
transform: var(
--nutui-badge-content-transform,
translateY(-50%) translateX(-100%)
);
background: $color-primary-text;
border: 1px solid $color-primary;
color: $color-primary;
}
}
86 changes: 64 additions & 22 deletions src/packages/badge/badge.taro.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import React, { CSSProperties, FunctionComponent, ReactNode } from 'react'
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 { 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'

export type BadgeFill = 'solid' | 'outline'
export interface BadgeProps extends BasicComponent {
Expand Down Expand Up @@ -42,9 +52,9 @@ export const Badge: FunctionComponent<Partial<BadgeProps>> = (props) => {
...props,
}
const classPrefix = 'nut-badge'
const classes = classNames(classPrefix, className, {
[`${classPrefix}-${fill}`]: fill === 'outline',
})
const classes = classNames(classPrefix, className)
const badgeRef = useRef(null)
const [contentStyle, setContentStyle] = useState({})

function content() {
if (dot || typeof value === 'object' || value === 0) return null
Expand All @@ -66,41 +76,73 @@ export const Badge: FunctionComponent<Partial<BadgeProps>> = (props) => {
if (typeof value === 'string' && value) return value
}

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

useEffect(() => {
if (badgeRef.current) {
getPositionStyle()
}
)
const getStyle = () => {
}, [badgeRef.current])
irisSong marked this conversation as resolved.
Show resolved Hide resolved
const getPositionStyle = async () => {
const style: CSSProperties = {}
style.top = `${Number(top) || parseFloat(String(top)) || 0}px`
const dir = rtl ? 'left' : 'right'
style[dir] = `${Number(right) || parseFloat(String(right)) || 0}px`
style.top = pxTransform(Number(-top) || 0)
if (rn()) {
irisSong marked this conversation as resolved.
Show resolved Hide resolved
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] = harmony()
? pxTransform(Number(right))
: `${Number(right) || parseFloat(String(right)) || 0}px`
}
setContentStyle(style)
}

const getStyle = () => {
const style: CSSProperties = {}
if (color) {
if (fill === 'outline') {
style.color = color
style.background = '#fff'
style.backgroundColor = '#fff'
if (!color?.includes('gradient')) {
style.border = `1px solid ${color}`
style.borderColor = color
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

[建议] 避免在样式中硬编码颜色值,提升组件的可定制性

在第 115 行,style.backgroundColor = '#fff' 将背景颜色固定为白色,可能限制了组件的灵活性。如果用户希望自定义边框模式下的背景颜色,当前实现无法满足需求。

建议允许通过属性传入背景颜色,或者使用一个默认值,同时提供自定义的可能性:

- style.backgroundColor = '#fff'
+ style.backgroundColor = backgroundColor || '#fff'

并在 BadgeProps 中添加 backgroundColor 属性:

export interface BadgeProps extends BasicComponent {
  // 其他属性...
  backgroundColor?: string
}

}
} else {
style.color = '#fff'
style.background = color
style.backgroundColor = color
}
}
return style
}

return (
<View className={classes} style={style}>
{isIcon() && <View className={`${classPrefix}-icon`}>{value}</View>}
<View className={classes} style={style} ref={badgeRef}>
{isIcon() && (
<View
className={classNames(`${classPrefix}-content`, {
[`${classPrefix}-icon`]: true,
[`${classPrefix}-icon-rtl`]: rtl,
})}
style={contentStyle}
>
{value}
</View>
)}
{children}
{!isIcon() && (
<View className={contentClasses} style={getStyle()}>
<View
className={contentClasses}
style={{ ...contentStyle, ...getStyle() }}
>
{content()}
</View>
)}
Expand Down
29 changes: 18 additions & 11 deletions src/packages/badge/badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,16 @@ export const Badge: FunctionComponent<Partial<BadgeProps>> = (props) => {
if (typeof value === 'string' && value) return value
}

const contentClasses = classNames(
{ [`${classPrefix}-dot`]: dot },
`${classPrefix}-content`,
{ [`${classPrefix}-sup`]: isNumber() || isString() || dot },
{
[`${classPrefix}-one`]:
typeof content() === 'string' && `${content()}`?.length === 1,
}
)
const contentClasses = classNames(`${classPrefix}-content`, {
[`${classPrefix}-sup`]: isNumber() || isString() || dot,
[`${classPrefix}-one`]:
typeof content() === 'string' && `${content()}`?.length === 1,
[`${classPrefix}-dot`]: dot,
[`${classPrefix}-${fill}`]: fill === 'outline',
})
const getStyle = () => {
const style: CSSProperties = {}
style.top = `${Number(top) || parseFloat(String(top)) || 0}px`
style.top = `${Number(-top) || parseFloat(String(-top)) || 0}px`
const dir = rtl ? 'left' : 'right'
style[dir] = `${Number(right) || parseFloat(String(right)) || 0}px`

Expand All @@ -97,7 +95,16 @@ export const Badge: FunctionComponent<Partial<BadgeProps>> = (props) => {
}
return (
<div className={classes} style={style}>
{isIcon() && <div className={`${classPrefix}-icon`}>{value}</div>}
{isIcon() && (
<div
className={classNames(`${classPrefix}-content`, {
[`${classPrefix}-icon`]: true,
[`${classPrefix}-icon-rtl`]: rtl,
})}
>
{value}
</div>
)}
{children}
{!isIcon() && (
<div className={contentClasses} style={getStyle()}>
Expand Down
30 changes: 22 additions & 8 deletions src/packages/badge/demos/taro/demo1.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
import { User } from '@nutui/icons-react-taro'
import { Avatar, Badge, Cell } from '@nutui/nutui-react-taro'
import React from 'react'
import pxTransform from '@/utils/px-transform'
import { harmonyAndRn } from '@/utils/platform-taro'

const Demo1 = () => {
const isRnAndHarmony = harmonyAndRn()
const renderChildren = () => {
return (
<>
{isRnAndHarmony ? (
<Avatar shape="square">N</Avatar>
) : (
<Avatar icon={<User />} shape="square" />
)}
</>
)
}
return (
<Cell>
<Badge style={{ marginInlineEnd: '40px' }} value={8}>
<Avatar icon={<User />} shape="square" />
<Badge style={{ marginRight: pxTransform(40) }} value={8}>
{renderChildren()}
</Badge>
<Badge style={{ marginInlineEnd: '40px' }} value={76}>
<Avatar icon={<User />} shape="square" />
<Badge style={{ marginRight: pxTransform(40) }} value={76}>
{renderChildren()}
</Badge>
<Badge style={{ marginInlineEnd: '40px' }} value="NEW">
<Avatar icon={<User />} shape="square" />
<Badge style={{ marginRight: pxTransform(40) }} value="NEW">
{renderChildren()}
</Badge>
<Badge style={{ marginInlineEnd: '40px' }} dot top="2" right="4">
<Avatar icon={<User />} shape="square" />
<Badge style={{ marginRight: pxTransform(40) }} dot top="2" right="4">
{renderChildren()}
</Badge>
</Cell>
)
Expand Down
26 changes: 20 additions & 6 deletions src/packages/badge/demos/taro/demo2.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
import { User } from '@nutui/icons-react-taro'
import { Avatar, Badge, Cell } from '@nutui/nutui-react-taro'
import React from 'react'
import pxTransform from '@/utils/px-transform'
import { harmonyAndRn } from '@/utils/platform-taro'

const Demo2 = () => {
const isRnAndHarmony = harmonyAndRn()
const renderChildren = () => {
return (
<>
{isRnAndHarmony ? (
<Avatar shape="square">N</Avatar>
) : (
<Avatar icon={<User />} shape="square" />
)}
</>
)
}
return (
<Cell>
<Badge style={{ marginInlineEnd: '40px' }} value={200} max={9}>
<Avatar icon={<User />} shape="square" />
<Badge style={{ marginRight: pxTransform(40) }} value={200} max={9}>
{renderChildren()}
</Badge>
<Badge style={{ marginInlineEnd: '40px' }} value={200} max={20}>
<Avatar icon={<User />} shape="square" />
<Badge style={{ marginRight: pxTransform(40) }} value={200} max={20}>
{renderChildren()}
</Badge>
<Badge style={{ marginInlineEnd: '40px' }} value={200} max={99}>
<Avatar icon={<User />} shape="square" />
<Badge style={{ marginRight: pxTransform(40) }} value={200} max={99}>
{renderChildren()}
</Badge>
</Cell>
)
Expand Down
Loading