Skip to content

Commit

Permalink
feat(radio): 重构radio dom接口,补充对应文档和适配样式
Browse files Browse the repository at this point in the history
fix #461
  • Loading branch information
byq1213 committed Aug 23, 2024
1 parent 52910ba commit fa6d0ab
Show file tree
Hide file tree
Showing 28 changed files with 2,305 additions and 316 deletions.
2 changes: 1 addition & 1 deletion site/mobile/mobile.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default {
{
title: 'Radio 单选框',
name: 'radio',
component: () => import('tdesign-mobile-react/radio/_example/index.jsx'),
component: () => import('tdesign-mobile-react/radio/_example/index.tsx'),
},
{
title: 'Rate 评分',
Expand Down
2 changes: 1 addition & 1 deletion src/_common
128 changes: 67 additions & 61 deletions src/radio/Radio.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import React, { createContext, CSSProperties, forwardRef, Ref, useContext, useRef } from 'react';
import React, { createContext, forwardRef, useContext, useRef } from 'react';
import type { CSSProperties, Ref } from 'react';
import classNames from 'classnames';
import { CheckIcon } from 'tdesign-icons-react';
import { CheckIcon, CheckCircleFilledIcon } from 'tdesign-icons-react';
import forwardRefWithStatics from '../_util/forwardRefWithStatics';
import useConfig from '../_util/useConfig';
import useDefault from '../_util/useDefault';
import { TdRadioProps } from './type';
import RadioGroup from './RadioGroup';
import type { TdRadioProps } from './type';
import RadioGroup from './RadioGroup old';
import useDefaultProps from '../hooks/useDefaultProps';
import { radioDefaultProps } from './defaultProps';

export interface RadioProps extends TdRadioProps {
ref?: Ref<HTMLDivElement>;
Expand All @@ -31,23 +34,23 @@ const Radio = forwardRef((_props: RadioProps, ref: Ref<HTMLDivElement>) => {
const props = context ? context.inject(_props) : _props;

const {
align = 'left',
allowUncheck = false,
checked = false,
defaultChecked = false,
children,
allowUncheck,
block,
checked,
content,
defaultChecked,
contentDisabled,
placement,
disabled,
icon,
label,
maxContentRow = 5,
maxLabelRow = 3,
maxContentRow,
maxLabelRow,
name,
value,
// borderless = false,
borderless,
onChange,
} = props;
} = useDefaultProps<TdRadioProps>(props, radioDefaultProps);

const [radioChecked, setRadioChecked] = useDefault(checked, defaultChecked, onChange);

Expand All @@ -66,40 +69,42 @@ const Radio = forwardRef((_props: RadioProps, ref: Ref<HTMLDivElement>) => {

const renderIcon = () => {
if (Array.isArray(icon)) {
return radioChecked ? icon[0] : icon[1] ?? null;
return radioChecked ? icon[0] : (icon[1] ?? null);
}
if (radioChecked) {
if (icon === 'circle') {
return <CheckCircleFilledIcon className={`${classPrefix}__icon-wrap`} />;
}
if (icon === 'line') {
return <CheckIcon className={`${classPrefix}__icon-wrap`} />;
}
if (icon === 'dot') {
let dotIconClassName = `${classPrefix}__icon-${icon}`;
disabled && (dotIconClassName += ` ${classPrefix}__icon-${icon}--disabled`);
return <div className={dotIconClassName} />;
}
} else {
if (icon === 'circle' || icon === 'dot') {
let circleIconClassName = `${classPrefix}__icon-circle`;
disabled && (circleIconClassName += ` ${classPrefix}__icon-circle--disabled`);
return <div className={circleIconClassName} />;
}
if (icon === 'line') {
return <div className="placeholder" />;
}
}
return (
<div
className={classNames(
`${classPrefix}__icon`, {
[`${classPrefix}__icon--checked`]: radioChecked,
[`${classPrefix}__icon--disabled`]: disabled,
// [`${classPrefix}__icon--strock`]: icon === 'stroke-line',
[`${classPrefix}__icon--custom`]: Array.isArray(icon),
})}
>
<CheckIcon size={16} />
</div>
);
};

const labelStyle = {
...getLimitRow(maxLabelRow),
color: disabled ? '#dcdcdc' : 'inherit',
};

const radioClassName = classNames(
`${classPrefix}`,
{ [`${prefix}-is-checked`]: radioChecked },
{ [`${prefix}-is-disabled`]: disabled },

);
const radioClassName = classNames(`${classPrefix}`, `${classPrefix}--${placement}`, {
[`${classPrefix}--block`]: block,
});

const titleClassName = classNames(
`${prefix}__content-title`,
{ [`${prefix}-is-disabled`]: disabled },
{ [`${prefix}__content-right-title`]: align === 'right' },
)
const titleClassName = classNames(`${classPrefix}__title`, { [`${classPrefix}__title--disabled`]: disabled });

const input = (
<input
Expand All @@ -110,7 +115,7 @@ const Radio = forwardRef((_props: RadioProps, ref: Ref<HTMLDivElement>) => {
// @ts-ignore
value={value}
disabled={disabled}
className={classNames(`${classPrefix}__original-${align}`)}
className={classNames(`${classPrefix}__original`)}
checked={radioChecked}
onClick={(e) => {
e.stopPropagation();
Expand All @@ -122,30 +127,31 @@ const Radio = forwardRef((_props: RadioProps, ref: Ref<HTMLDivElement>) => {
/>
);

const iconClass = classNames(`${classPrefix}__icon`, `${classPrefix}__icon--${placement}`, {
[`${classPrefix}__icon--checked`]: radioChecked,
[`${classPrefix}__icon--disabled`]: disabled,
});
return (
<div className={radioClassName} ref={ref} onClick={() => switchRadioChecked()}>
<span className={`${classPrefix}__content-wrap`}>
{align === 'left' &&<span className={ `${classPrefix}__icon-wrap ${classPrefix}__icon-left-wrap`}>
{input}
{renderIcon()}
</span>}
<span className={`${classPrefix}__label-wrap`}>
{label && <span className={titleClassName} style={labelStyle}>{label}</span>}
{(children || content) && (
<div className={`${classPrefix}__content-inner`} style={getLimitRow(maxContentRow)}>
{children || content}
</div>
)}
</span>
{align === 'right' &&<span className={ `${classPrefix}__icon-wrap ${classPrefix}__icon-right-wrap`}>
{input}
{renderIcon()}
</span>}
</span>
{/* 下边框 */}
{ <div className={`${classPrefix}__border ${classPrefix}__border--${align}`}></div>}
{/* { !borderless && <div className={`${classPrefix}__border ${classPrefix}__border--${align}`}></div>} */}
<div ></div>
{input}
<div className={iconClass}>{renderIcon()}</div>
<div className={`${classPrefix}__content`}>
{label && (
<span className={titleClassName} style={labelStyle}>
{label}
</span>
)}
{content && (
<div
className={`${classPrefix}__description ${disabled && `${classPrefix}__description--disabled`}`}
style={getLimitRow(maxContentRow)}
>
{content}
</div>
)}
</div>

{!borderless && block && <div className={`${classPrefix}__border ${classPrefix}__border--${placement}`}></div>}
</div>
);
});
Expand Down
13 changes: 5 additions & 8 deletions src/radio/RadioGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React, { FC, ReactNode, useRef } from 'react';
import React, { useRef } from 'react';
import type { FC, ReactNode } from 'react';
import useConfig from '../_util/useConfig';
import Radio, { RadioContext, RadioContextValue, RadioProps } from './Radio';
import { TdRadioGroupProps } from './type';
import useDefault from '../_util/useDefault';
import type { TdRadioGroupProps } from './type';

export interface RadioGroupProps extends TdRadioGroupProps {
children?: ReactNode;
Expand Down Expand Up @@ -53,12 +54,8 @@ const RadioGroup: FC<RadioGroupProps> = (props) => {
);
});
return (
<div ref={groupRef} className={`${classPrefix}-radio-group`}>
<div className={`${classPrefix}-cell-group`}>
<div className={`${classPrefix}cell-group__container`}>
<RadioContext.Provider value={context}>{options?.length ? renderOptions() : children}</RadioContext.Provider>
</div>
</div>
<div ref={groupRef} className={`${classPrefix}-radio-group ${props.className || ''}`}>
<RadioContext.Provider value={context}>{options?.length ? renderOptions() : children}</RadioContext.Provider>
</div>
);
};
Expand Down
8 changes: 5 additions & 3 deletions src/radio/_example/base.jsx → src/radio/_example/base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ export default function Base() {
<Radio label="单选" value="idx0"></Radio>
<Radio label="单选" value="idx1"></Radio>
<Radio label="单选单选单选单选单选单选单选单选单选单选单选单选单选单选单选单选单选单选" value="idx2"></Radio>
<Radio label="单选" value="idx3">
单选单选单选单选单选单选单选单选单选单选单选单选单选单选单选单选单选单选单选单选单选
</Radio>
<Radio
label="单选"
value="idx3"
content="描述信息描述信息描述信息描述信息描述信息描述信息描述信息描述信息描述信息描述信息"
></Radio>
</RadioGroup>
);
}
25 changes: 25 additions & 0 deletions src/radio/_example/card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { useState } from 'react';
import { Radio, RadioGroup } from 'tdesign-mobile-react';

export default function () {
const [defaultValue, setDefaultValue] = useState('1');
const options = [
{
value: '1',
label: '单选',
},
{
value: '2',
label: '单选',
},
{
value: '3',
label: '单选标题多行单选标题多行单选标题多行单选标题多行单选标题多行',
},
];
return (
<RadioGroup className="theme-card" value={defaultValue} onChange={setDefaultValue}>
{options.map((opt) => <Radio value={opt.value} label={opt.label} key={opt.value}></Radio>)}
</RadioGroup>
);
}
39 changes: 39 additions & 0 deletions src/radio/_example/custom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React, { useState } from 'react';
import { Radio, RadioGroup } from 'tdesign-mobile-react';
import { Icon } from 'tdesign-icons-react';
import TDemoBlock from '../../../site/mobile/components/DemoBlock';

export default function () {
const [defaultValue, setDefaultValue] = useState(0);
const [defaultValueH, setDefaultValueH] = useState(0);
return (
<>
<TDemoBlock summary="单选框尺寸规格">
<RadioGroup value={defaultValue} onChange={(value) => setDefaultValue(value)}>
{Array.from(Array(3), (_, key) => (
<div className={`card ${defaultValue === key ? 'card--active' : ''}`} key={key}>
{defaultValue === key && <Icon name="check" color="#fff" className="card__icon" />}
<Radio
value={key}
borderless
label="单选"
content="描述信息描述信息描述信息描述信息描述信息"
icon="none"
></Radio>
</div>
))}
</RadioGroup>
</TDemoBlock>
<TDemoBlock summary="横向卡片单选框">
<RadioGroup className="horizontal-box" value={defaultValueH} onChange={(value) => setDefaultValueH(value)}>
{Array.from(Array(3), (_, key) => (
<div className={`card ${defaultValueH === key ? 'card--active' : ''}`} key={key}>
{defaultValueH === key && <Icon name="check" color="#fff" className="card__icon" />}
<Radio borderless value={key} label="单选" icon="none"></Radio>
</div>
))}
</RadioGroup>
</TDemoBlock>
</>
);
}
40 changes: 0 additions & 40 deletions src/radio/_example/group.jsx

This file was deleted.

13 changes: 13 additions & 0 deletions src/radio/_example/horizontal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React, { useState } from 'react';
import { Radio, RadioGroup } from 'tdesign-mobile-react';

export default function Base() {
const [defaultValue, setDefaultValue] = useState('idx0');
return (
<RadioGroup value={defaultValue} className="box" onChange={(value) => setDefaultValue(value)}>
<Radio block={false} label="单选标题" value="idx0"></Radio>
<Radio block={false} label="单选标题" value="idx1"></Radio>
<Radio block={false} label="单选标题" value="idx2"></Radio>
</RadioGroup>
);
}
15 changes: 0 additions & 15 deletions src/radio/_example/icon.jsx

This file was deleted.

11 changes: 11 additions & 0 deletions src/radio/_example/icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import { Radio } from 'tdesign-mobile-react';

export default function () {
return (
<>
<Radio label="单选" icon="line" defaultChecked></Radio>
<Radio label="单选" icon="dot" defaultChecked></Radio>
</>
);
}
Loading

0 comments on commit fa6d0ab

Please sign in to comment.