fix: Input affix use inline-flex (#20872)

* fix: Input affix use inline-flex

* update snapshot
This commit is contained in:
二货机器人 2020-01-14 11:59:38 +08:00 committed by GitHub
parent 9d7edcd38b
commit 8bf66ce8be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 187 additions and 233 deletions

View File

@ -25,6 +25,7 @@ interface BasicProps {
style?: object;
disabled?: boolean;
direction?: any;
focused?: boolean;
}
/**
@ -65,34 +66,44 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
}
renderLabeledIcon(prefixCls: string, element: React.ReactElement<any>) {
const props = this.props;
const suffix = this.renderSuffix(prefixCls);
if (!hasPrefixSuffix(props)) {
const {
focused,
value,
prefix,
className,
size,
suffix,
disabled,
allowClear,
direction,
style,
} = this.props;
const suffixNode = this.renderSuffix(prefixCls);
if (!hasPrefixSuffix(this.props)) {
return React.cloneElement(element, {
value: props.value,
value,
});
}
const prefix = props.prefix ? (
<span className={`${prefixCls}-prefix`}>{props.prefix}</span>
) : null;
const prefixNode = prefix ? <span className={`${prefixCls}-prefix`}>{prefix}</span> : null;
const affixWrapperCls = classNames(props.className, `${prefixCls}-affix-wrapper`, {
[`${prefixCls}-affix-wrapper-sm`]: props.size === 'small',
[`${prefixCls}-affix-wrapper-lg`]: props.size === 'large',
[`${prefixCls}-affix-wrapper-input-with-clear-btn`]:
props.suffix && props.allowClear && this.props.value,
[`${prefixCls}-affix-wrapper-rtl`]: props.direction === 'rtl',
const affixWrapperCls = classNames(className, `${prefixCls}-affix-wrapper`, {
[`${prefixCls}-affix-wrapper-focused`]: focused,
[`${prefixCls}-affix-wrapper-disabled`]: disabled,
[`${prefixCls}-affix-wrapper-sm`]: size === 'small',
[`${prefixCls}-affix-wrapper-lg`]: size === 'large',
[`${prefixCls}-affix-wrapper-input-with-clear-btn`]: suffix && allowClear && value,
[`${prefixCls}-affix-wrapper-rtl`]: direction === 'rtl',
});
return (
<span className={affixWrapperCls} style={props.style}>
{prefix}
<span className={affixWrapperCls} style={style}>
{prefixNode}
{React.cloneElement(element, {
style: null,
value: props.value,
className: getInputClassName(prefixCls, props.size, props.disabled),
value,
className: getInputClassName(prefixCls, size, disabled),
})}
{suffix}
{suffixNode}
</span>
);
}

View File

@ -72,6 +72,7 @@ export function getInputClassName(
export interface InputState {
value: any;
focused: boolean;
/** `value` from prev props */
prevValue: any;
}
@ -102,6 +103,7 @@ class Input extends React.Component<InputProps, InputState> {
const value = typeof props.value === 'undefined' ? props.defaultValue : props.value;
this.state = {
value,
focused: false,
// eslint-disable-next-line react/no-unused-state
prevValue: props.value,
};
@ -160,6 +162,22 @@ class Input extends React.Component<InputProps, InputState> {
this.input = input;
};
onFocus: React.FocusEventHandler<HTMLInputElement> = e => {
const { onFocus } = this.props;
this.setState({ focused: true });
if (onFocus) {
onFocus(e);
}
};
onBlur: React.FocusEventHandler<HTMLInputElement> = e => {
const { onBlur } = this.props;
this.setState({ focused: false });
if (onBlur) {
onBlur(e);
}
};
setValue(value: string, callback?: () => void) {
if (this.props.value === undefined) {
this.setState({ value }, callback);
@ -194,6 +212,8 @@ class Input extends React.Component<InputProps, InputState> {
<input
{...otherProps}
onChange={this.handleChange}
onFocus={this.onFocus}
onBlur={this.onBlur}
onKeyDown={this.handleKeyDown}
className={classNames(
getInputClassName(prefixCls, customizeSize || size, disabled, this.direction),
@ -235,7 +255,7 @@ class Input extends React.Component<InputProps, InputState> {
};
renderComponent = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
const { value } = this.state;
const { value, focused } = this.state;
const { prefixCls: customizePrefixCls } = this.props;
const prefixCls = getPrefixCls('input', customizePrefixCls);
this.direction = direction;
@ -251,6 +271,7 @@ class Input extends React.Component<InputProps, InputState> {
handleReset={this.handleReset}
ref={this.saveClearableInput}
direction={direction}
focused={focused}
/>
)}
</SizeContext.Consumer>

View File

@ -68,11 +68,14 @@ exports[`Input.Password should change type when click 1`] = `
<input
action="click"
className="ant-input ant-input-password"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="password"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -92,7 +95,9 @@ exports[`Input.Password should change type when click 1`] = `
<input
action="click"
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="password"
@ -235,11 +240,14 @@ exports[`Input.Password should change type when click 2`] = `
<input
action="click"
className="ant-input ant-input-password"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -259,7 +267,9 @@ exports[`Input.Password should change type when click 2`] = `
<input
action="click"
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -386,11 +396,14 @@ exports[`Input.Password should change type when click 3`] = `
<input
action="click"
className="ant-input ant-input-password"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="password"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -410,7 +423,9 @@ exports[`Input.Password should change type when click 3`] = `
<input
action="click"
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="password"

View File

@ -1782,6 +1782,28 @@ exports[`renders ./components/input/demo/presuffix.md correctly 1`] = `
RMB
</span>
</span>
<br />
<br />
<span
class="ant-input-affix-wrapper ant-input-affix-wrapper-disabled"
>
<span
class="ant-input-prefix"
>
</span>
<input
class="ant-input ant-input-disabled"
disabled=""
type="text"
value=""
/>
<span
class="ant-input-suffix"
>
RMB
</span>
</span>
</div>
`;

View File

@ -10,11 +10,14 @@ exports[`Input allowClear should change type when click 1`] = `
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -26,7 +29,9 @@ exports[`Input allowClear should change type when click 1`] = `
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -133,11 +138,14 @@ exports[`Input allowClear should change type when click 2`] = `
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -149,7 +157,9 @@ exports[`Input allowClear should change type when click 2`] = `
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -175,11 +185,14 @@ exports[`Input allowClear should not show icon if defaultValue is undefined, nul
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -191,7 +204,9 @@ exports[`Input allowClear should not show icon if defaultValue is undefined, nul
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -215,11 +230,14 @@ exports[`Input allowClear should not show icon if defaultValue is undefined, nul
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -231,7 +249,9 @@ exports[`Input allowClear should not show icon if defaultValue is undefined, nul
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -257,11 +277,14 @@ exports[`Input allowClear should not show icon if defaultValue is undefined, nul
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -273,7 +296,9 @@ exports[`Input allowClear should not show icon if defaultValue is undefined, nul
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -298,12 +323,15 @@ exports[`Input allowClear should not show icon if value is undefined, null or em
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
value={null}
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -315,7 +343,9 @@ exports[`Input allowClear should not show icon if value is undefined, null or em
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -339,11 +369,14 @@ exports[`Input allowClear should not show icon if value is undefined, null or em
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -355,7 +388,9 @@ exports[`Input allowClear should not show icon if value is undefined, null or em
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -380,12 +415,15 @@ exports[`Input allowClear should not show icon if value is undefined, null or em
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
value=""
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -397,7 +435,9 @@ exports[`Input allowClear should not show icon if value is undefined, null or em
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -435,11 +475,14 @@ exports[`Input should support maxLength 1`] = `
<input
className="ant-input"
maxLength={3}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
maxLength={3}
@ -450,7 +493,9 @@ exports[`Input should support maxLength 1`] = `
<input
className="ant-input"
maxLength={3}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
value=""
@ -485,11 +530,14 @@ exports[`Input.Search should support suffix 1`] = `
element={
<input
className="ant-input ant-input-search"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
onChange={[Function]}
@ -512,7 +560,9 @@ exports[`Input.Search should support suffix 1`] = `
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"

View File

@ -31,6 +31,11 @@ ReactDOM.render(
<br />
<br />
<Input prefix="¥" suffix="RMB" />
<br />
<br />
<Input prefix="¥" suffix="RMB" disabled />
</div>,
mountNode,
);

View File

@ -1,6 +1,8 @@
@import './index';
@import './mixin';
@input-affix-margin: 4px;
.@{ant-prefix}-input {
&-affix-wrapper {
.input();
@ -9,6 +11,16 @@
> .@{ant-prefix}-input {
padding: 0;
border: none;
outline: none;
&:focus {
box-shadow: none;
}
}
.@{ant-prefix}-input-clear-icon {
margin: 0 @input-affix-margin;
vertical-align: -1px;
}
}
@ -16,110 +28,23 @@
&-suffix {
flex: none;
}
&-prefix {
margin-right: @input-affix-margin;
}
&-suffix {
margin-left: @input-affix-margin;
}
// ======================== RTL ========================
&-affix-wrapper-rtl {
.@{ant-prefix}-input-prefix {
margin: 0 0 0 @input-affix-margin;
}
.@{ant-prefix}-input-suffix {
margin: 0 @input-affix-margin 0 0;
}
}
}
// // Input with affix: prefix or suffix
// .@{ant-prefix}-input-affix-wrapper {
// .reset-component;
// .input-affix-wrapper(~'@{ant-prefix}-input');
// // https://github.com/ant-design/ant-design/issues/6144
// .@{ant-prefix}-input {
// min-height: 100%; // use min-height, assume that no smaller height to override
// }
// }
// .input-affix-wrapper(@inputClass) {
// position: relative;
// display: inline-block;
// width: 100%;
// text-align: start;
// &:hover .@{inputClass}:not(.@{inputClass}-disabled) {
// .hover();
// }
// .@{inputClass} {
// position: relative;
// text-align: inherit;
// }
// // Should not break align of icon & text
// // https://github.com/ant-design/ant-design/issues/18087
// // https://github.com/ant-design/ant-design/issues/17414
// // https://github.com/ant-design/ant-design/pull/17684
// // https://codesandbox.io/embed/pensive-paper-di2wk
// // https://codesandbox.io/embed/nifty-benz-gb7ml
// .@{inputClass}-prefix,
// .@{inputClass}-suffix {
// position: absolute;
// top: 50%;
// z-index: 2;
// display: flex;
// align-items: center;
// color: @input-icon-color;
// line-height: 0;
// transform: translateY(-50%);
// :not(.anticon) {
// line-height: @line-height-base;
// }
// }
// .@{inputClass}-disabled ~ .@{inputClass}-suffix {
// .anticon {
// color: @disabled-color;
// cursor: not-allowed;
// }
// }
// .@{inputClass}-prefix {
// left: @input-padding-horizontal-base + 1px;
// .@{inputClass}-affix-wrapper-rtl& {
// right: @input-padding-horizontal-base + 1px;
// left: auto;
// }
// }
// .@{inputClass}-suffix {
// right: @input-padding-horizontal-base + 1px;
// .@{inputClass}-affix-wrapper-rtl& {
// right: auto;
// left: @input-padding-horizontal-base + 1px;
// }
// }
// .@{inputClass}:not(:first-child) {
// padding-left: @input-padding-horizontal-base + @input-affix-width;
// }
// .@{inputClass}:not(:last-child) {
// padding-right: @input-padding-horizontal-base + @input-affix-width;
// }
// // Needed to change priority of classes in rtl direction (last-child comes before first-child)
// .@{inputClass}-affix-wrapper-rtl& .@{inputClass}:not(:last-child) {
// padding-right: @input-padding-horizontal-base;
// padding-left: @input-padding-horizontal-base + @input-affix-width;
// }
// .@{inputClass}-affix-wrapper-rtl& .@{inputClass}:not(:first-child) {
// padding-right: @input-padding-horizontal-base + @input-affix-width;
// padding-left: @input-padding-horizontal-base;
// }
// &.@{inputClass}-affix-wrapper-input-with-clear-btn .@{inputClass}:not(:last-child) {
// padding-right: @input-padding-horizontal-base + @input-affix-with-clear-btn-width;
// .@{inputClass}-affix-wrapper-rtl& {
// padding-right: @input-padding-horizontal-base;
// padding-left: @input-padding-horizontal-base + @input-affix-with-clear-btn-width;
// }
// }
// &.@{inputClass}-affix-wrapper-textarea-with-clear-btn .@{inputClass} {
// padding-right: 22px;
// }
// }

View File

@ -1,6 +1,7 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@import './mixin';
@import './affix';
// Input styles
.@{ant-prefix}-input {
@ -26,17 +27,6 @@
}
}
// Input with affix: prefix or suffix
.@{ant-prefix}-input-affix-wrapper {
.reset-component;
.input-affix-wrapper(~'@{ant-prefix}-input');
// https://github.com/ant-design/ant-design/issues/6144
.@{ant-prefix}-input {
min-height: 100%; // use min-height, assume that no smaller height to override
}
}
.@{ant-prefix}-input-password-icon {
color: @text-color-secondary;
cursor: pointer;

View File

@ -3,7 +3,6 @@
@input-rtl-cls: ~'@{ant-prefix}-input-rtl';
@input-affix-width: 19px;
@input-affix-with-clear-btn-width: 38px;
// size mixins for input
@ -77,7 +76,8 @@
.hover();
}
&:focus {
&:focus,
&-focused {
.active();
}
@ -420,101 +420,6 @@
}
}
.input-affix-wrapper(@inputClass) {
position: relative;
display: inline-block;
width: 100%;
text-align: start;
&:hover .@{inputClass}:not(.@{inputClass}-disabled) {
.hover();
}
.@{inputClass} {
position: relative;
text-align: inherit;
}
// Should not break align of icon & text
// https://github.com/ant-design/ant-design/issues/18087
// https://github.com/ant-design/ant-design/issues/17414
// https://github.com/ant-design/ant-design/pull/17684
// https://codesandbox.io/embed/pensive-paper-di2wk
// https://codesandbox.io/embed/nifty-benz-gb7ml
.@{inputClass}-prefix,
.@{inputClass}-suffix {
position: absolute;
top: 50%;
z-index: 2;
display: flex;
align-items: center;
color: @input-icon-color;
line-height: 0;
transform: translateY(-50%);
:not(.anticon) {
line-height: @line-height-base;
}
}
.@{inputClass}-disabled ~ .@{inputClass}-suffix {
.anticon {
color: @disabled-color;
cursor: not-allowed;
}
}
.@{inputClass}-prefix {
left: @input-padding-horizontal-base + 1px;
.@{inputClass}-affix-wrapper-rtl& {
right: @input-padding-horizontal-base + 1px;
left: auto;
}
}
.@{inputClass}-suffix {
right: @input-padding-horizontal-base + 1px;
.@{inputClass}-affix-wrapper-rtl& {
right: auto;
left: @input-padding-horizontal-base + 1px;
}
}
.@{inputClass}:not(:first-child) {
padding-left: @input-padding-horizontal-base + @input-affix-width;
}
.@{inputClass}:not(:last-child) {
padding-right: @input-padding-horizontal-base + @input-affix-width;
}
// Needed to change priority of classes in rtl direction (last-child comes before first-child)
.@{inputClass}-affix-wrapper-rtl& .@{inputClass}:not(:last-child) {
padding-right: @input-padding-horizontal-base;
padding-left: @input-padding-horizontal-base + @input-affix-width;
}
.@{inputClass}-affix-wrapper-rtl& .@{inputClass}:not(:first-child) {
padding-right: @input-padding-horizontal-base + @input-affix-width;
padding-left: @input-padding-horizontal-base;
}
&.@{inputClass}-affix-wrapper-input-with-clear-btn .@{inputClass}:not(:last-child) {
padding-right: @input-padding-horizontal-base + @input-affix-with-clear-btn-width;
.@{inputClass}-affix-wrapper-rtl& {
padding-right: @input-padding-horizontal-base;
padding-left: @input-padding-horizontal-base + @input-affix-with-clear-btn-width;
}
}
&.@{inputClass}-affix-wrapper-textarea-with-clear-btn .@{inputClass} {
padding-right: 22px;
}
}
.clear-icon() {
color: @disabled-color;
font-size: @font-size-sm;

View File

@ -16,13 +16,16 @@ exports[`Transfer.Search should show cross icon when input value exists 1`] = `
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder=""
type="text"
value=""
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
onChange={[Function]}
@ -33,7 +36,9 @@ exports[`Transfer.Search should show cross icon when input value exists 1`] = `
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder=""
type="text"
@ -138,13 +143,16 @@ exports[`Transfer.Search should show cross icon when input value exists 2`] = `
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder=""
type="text"
value="a"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
onChange={[Function]}
@ -155,7 +163,9 @@ exports[`Transfer.Search should show cross icon when input value exists 2`] = `
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder=""
type="text"