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: Input & Input.TextArea support bordered prop #25617

Merged
merged 3 commits into from Jul 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 9 additions & 3 deletions components/input/ClearableLabeledInput.tsx
Expand Up @@ -28,6 +28,7 @@ interface BasicProps {
direction?: any;
focused?: boolean;
readOnly?: boolean;
bordered: boolean;
}

/**
Expand Down Expand Up @@ -102,6 +103,7 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
direction,
style,
readOnly,
bordered,
} = this.props;
const suffixNode = this.renderSuffix(prefixCls);
if (!hasPrefixSuffix(this.props)) {
Expand All @@ -120,6 +122,7 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
[`${prefixCls}-affix-wrapper-input-with-clear-btn`]: suffix && allowClear && value,
[`${prefixCls}-affix-wrapper-rtl`]: direction === 'rtl',
[`${prefixCls}-affix-wrapper-readonly`]: readOnly,
[`${prefixCls}-affix-wrapper-borderless`]: !bordered,
});
return (
<span
Expand All @@ -132,7 +135,7 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
{cloneElement(element, {
style: null,
value,
className: getInputClassName(prefixCls, size, disabled),
className: getInputClassName(prefixCls, bordered, size, disabled),
})}
{suffixNode}
</span>
Expand Down Expand Up @@ -178,7 +181,7 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
}

renderTextAreaWithClearIcon(prefixCls: string, element: React.ReactElement) {
const { value, allowClear, className, style, direction } = this.props;
const { value, allowClear, className, style, direction, bordered } = this.props;
if (!allowClear) {
return cloneElement(element, {
value,
Expand All @@ -187,8 +190,11 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
const affixWrapperCls = classNames(
className,
`${prefixCls}-affix-wrapper`,
{ [`${prefixCls}-affix-wrapper-rtl`]: direction === 'rtl' },
`${prefixCls}-affix-wrapper-textarea-with-clear-btn`,
{
[`${prefixCls}-affix-wrapper-rtl`]: direction === 'rtl',
[`${prefixCls}-affix-wrapper-borderless`]: !bordered,
},
);
return (
<span className={affixWrapperCls} style={style}>
Expand Down
12 changes: 9 additions & 3 deletions components/input/Input.tsx
Expand Up @@ -47,6 +47,7 @@ export interface InputProps
prefix?: React.ReactNode;
suffix?: React.ReactNode;
allowClear?: boolean;
bordered?: boolean;
}

export function fixControlledValue<T>(value: T) {
Expand Down Expand Up @@ -84,6 +85,7 @@ export function resolveOnChange(

export function getInputClassName(
prefixCls: string,
bordered: boolean,
size?: SizeType,
disabled?: boolean,
direction?: any,
Expand All @@ -93,6 +95,7 @@ export function getInputClassName(
[`${prefixCls}-lg`]: size === 'large',
[`${prefixCls}-disabled`]: disabled,
[`${prefixCls}-rtl`]: direction === 'rtl',
[`${prefixCls}-borderless`]: !bordered,
});
}

Expand Down Expand Up @@ -220,6 +223,7 @@ class Input extends React.Component<InputProps, InputState> {
renderInput = (
prefixCls: string,
size: SizeType | undefined,
bordered: boolean,
input: ConfigConsumerProps['input'] = {},
) => {
const { className, addonBefore, addonAfter, size: customizeSize, disabled } = this.props;
Expand All @@ -237,6 +241,7 @@ class Input extends React.Component<InputProps, InputState> {
'defaultValue',
'size',
'inputType',
'bordered',
]);
return (
<input
Expand All @@ -247,7 +252,7 @@ class Input extends React.Component<InputProps, InputState> {
onBlur={this.onBlur}
onKeyDown={this.handleKeyDown}
className={classNames(
getInputClassName(prefixCls, customizeSize || size, disabled, this.direction),
getInputClassName(prefixCls, bordered, customizeSize || size, disabled, this.direction),
{
[className!]: className && !addonBefore && !addonAfter,
},
Expand Down Expand Up @@ -287,7 +292,7 @@ class Input extends React.Component<InputProps, InputState> {

renderComponent = ({ getPrefixCls, direction, input }: ConfigConsumerProps) => {
const { value, focused } = this.state;
const { prefixCls: customizePrefixCls } = this.props;
const { prefixCls: customizePrefixCls, bordered = true } = this.props;
const prefixCls = getPrefixCls('input', customizePrefixCls);
this.direction = direction;

Expand All @@ -300,12 +305,13 @@ class Input extends React.Component<InputProps, InputState> {
prefixCls={prefixCls}
inputType="input"
value={fixControlledValue(value)}
element={this.renderInput(prefixCls, size, input)}
element={this.renderInput(prefixCls, size, bordered, input)}
handleReset={this.handleReset}
ref={this.saveClearableInput}
direction={direction}
focused={focused}
triggerFocus={this.focus}
bordered={bordered}
/>
)}
</SizeContext.Consumer>
Expand Down
14 changes: 10 additions & 4 deletions components/input/TextArea.tsx
@@ -1,12 +1,14 @@
import * as React from 'react';
import RcTextArea, { TextAreaProps as RcTextAreaProps, ResizableTextArea } from 'rc-textarea';
import omit from 'omit.js';
import classNames from 'classnames';
import ClearableLabeledInput from './ClearableLabeledInput';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import { fixControlledValue, resolveOnChange } from './Input';

export interface TextAreaProps extends RcTextAreaProps {
allowClear?: boolean;
bordered?: boolean;
}

export interface TextAreaState {
Expand Down Expand Up @@ -69,10 +71,13 @@ class TextArea extends React.Component<TextAreaProps, TextAreaState> {
resolveOnChange(this.resizableTextArea.textArea, e, this.props.onChange);
};

renderTextArea = (prefixCls: string) => {
renderTextArea = (prefixCls: string, bordered: boolean) => {
return (
<RcTextArea
{...omit(this.props, ['allowClear'])}
{...omit(this.props, ['allowClear', 'bordered'])}
className={classNames(this.props.className, {
[`${prefixCls}-borderless`]: !bordered,
})}
prefixCls={prefixCls}
onChange={this.handleChange}
ref={this.saveTextArea}
Expand All @@ -82,7 +87,7 @@ class TextArea extends React.Component<TextAreaProps, TextAreaState> {

renderComponent = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
const { value } = this.state;
const { prefixCls: customizePrefixCls } = this.props;
const { prefixCls: customizePrefixCls, bordered = true } = this.props;
const prefixCls = getPrefixCls('input', customizePrefixCls);
return (
<ClearableLabeledInput
Expand All @@ -91,10 +96,11 @@ class TextArea extends React.Component<TextAreaProps, TextAreaState> {
direction={direction}
inputType="text"
value={fixControlledValue(value)}
element={this.renderTextArea(prefixCls)}
element={this.renderTextArea(prefixCls, bordered)}
handleReset={this.handleReset}
ref={this.saveClearableInput}
triggerFocus={this.focus}
bordered={bordered}
/>
);
};
Expand Down
135 changes: 135 additions & 0 deletions components/input/__tests__/__snapshots__/demo.test.js.snap
Expand Up @@ -1063,6 +1063,141 @@ exports[`renders ./components/input/demo/basic.md correctly 1`] = `
/>
`;

exports[`renders ./components/input/demo/borderless.md correctly 1`] = `
<input
class="ant-input ant-input-borderless"
placeholder="Borderless"
type="text"
value=""
/>
`;

exports[`renders ./components/input/demo/borderless-debug.md correctly 1`] = `
<div
style="background-color:rgba(0, 0, 128, .2)"
>
<input
class="ant-input ant-input-borderless"
placeholder="Unbordered"
type="text"
value=""
/>
<input
class="ant-input ant-input-lg ant-input-borderless"
placeholder="Unbordered"
type="text"
value=""
/>
<textarea
class="ant-input ant-input-borderless"
placeholder="Unbordered"
/>
<span
class="ant-input-affix-wrapper ant-input-affix-wrapper-textarea-with-clear-btn ant-input-affix-wrapper-borderless"
>
<textarea
class="ant-input ant-input-borderless"
placeholder="Unbordered"
/>
<span
aria-label="close-circle"
class="anticon anticon-close-circle ant-input-textarea-clear-icon ant-input-textarea-clear-icon-hidden"
role="button"
tabindex="-1"
>
<svg
aria-hidden="true"
class=""
data-icon="close-circle"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"
/>
</svg>
</span>
</span>
<span
class="ant-input-affix-wrapper ant-input-affix-wrapper-borderless"
>
<input
class="ant-input ant-input-borderless"
placeholder="Unbordered"
type="text"
value=""
/>
<span
class="ant-input-suffix"
>
<span
aria-label="close-circle"
class="anticon anticon-close-circle ant-input-clear-icon ant-input-clear-icon-hidden"
role="button"
tabindex="-1"
>
<svg
aria-hidden="true"
class=""
data-icon="close-circle"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"
/>
</svg>
</span>
</span>
</span>
<span
class="ant-input-affix-wrapper ant-input-affix-wrapper-borderless"
>
<span
class="ant-input-prefix"
>
</span>
<input
class="ant-input ant-input-borderless"
type="text"
value=""
/>
<span
class="ant-input-suffix"
>
RMB
</span>
</span>
<span
class="ant-input-affix-wrapper ant-input-affix-wrapper-disabled ant-input-affix-wrapper-borderless"
>
<span
class="ant-input-prefix"
>
</span>
<input
class="ant-input ant-input-disabled ant-input-borderless"
disabled=""
type="text"
value=""
/>
<span
class="ant-input-suffix"
>
RMB
</span>
</span>
</div>
`;

exports[`renders ./components/input/demo/group.md correctly 1`] = `
<div
class="site-input-group-wrapper"
Expand Down
34 changes: 34 additions & 0 deletions components/input/demo/borderless-debug.md
@@ -0,0 +1,34 @@
---
order: 98
title:
zh-CN: Borderless Debug
en-US: Borderless Debug
debug: true
---

## zh-CN

Buggy!

## en-US

Buggy!

```jsx
import { Input } from 'antd';

const { TextArea } = Input;

ReactDOM.render(
<div style={{ backgroundColor: 'rgba(0, 0, 128, .2)' }}>
<Input placeholder="Unbordered" bordered={false} />
<Input placeholder="Unbordered" bordered={false} size="large" />
<TextArea placeholder="Unbordered" bordered={false} />
<TextArea placeholder="Unbordered" bordered={false} allowClear />
<Input placeholder="Unbordered" bordered={false} allowClear />
<Input prefix="¥" suffix="RMB" bordered={false} />
<Input prefix="¥" suffix="RMB" disabled bordered={false} />
</div>,
mountNode,
);
```
20 changes: 20 additions & 0 deletions components/input/demo/borderless.md
@@ -0,0 +1,20 @@
---
order: 20
title:
zh-CN: 无边框
en-US: Borderless
---

## zh-CN

没有边框。

## en-US

No border.

```jsx
import { Input } from 'antd';

ReactDOM.render(<Input placeholder="Borderless" bordered={false} />, mountNode);
```