Fix bug where 'other homeserver' would unfocus
It turns out the answer to this was not all that complex: we had two nested <label>s: one for the radio button and one for the Field, which presumably causes both of them to generate click events and focus something and what ends up focused is some kind of race condition depending on, apparently, how fast you click. Notes: Fix bug where the 'other homeserver' field in the server selection dialog would become briefly focus and then unfocus when clicked.
This commit is contained in:
parent
b55f69a74c
commit
f9b45677d6
3 changed files with 34 additions and 7 deletions
|
@ -46,7 +46,7 @@ limitations under the License.
|
||||||
width: $font-16px;
|
width: $font-16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> input[type=radio] {
|
input[type=radio] {
|
||||||
// Remove the OS's representation
|
// Remove the OS's representation
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -112,6 +112,12 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_RadioButton_innerLabel {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
top: 4px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RadioButton_outlined {
|
.mx_RadioButton_outlined {
|
||||||
|
|
|
@ -205,13 +205,14 @@ export default class ServerPickerDialog extends React.PureComponent<IProps, ISta
|
||||||
className="mx_ServerPickerDialog_otherHomeserverRadio"
|
className="mx_ServerPickerDialog_otherHomeserverRadio"
|
||||||
checked={!this.state.defaultChosen}
|
checked={!this.state.defaultChosen}
|
||||||
onChange={this.onOtherChosen}
|
onChange={this.onOtherChosen}
|
||||||
|
childrenInLabel={false}
|
||||||
>
|
>
|
||||||
<Field
|
<Field
|
||||||
type="text"
|
type="text"
|
||||||
className="mx_ServerPickerDialog_otherHomeserver"
|
className="mx_ServerPickerDialog_otherHomeserver"
|
||||||
label={_t("Other homeserver")}
|
label={_t("Other homeserver")}
|
||||||
onChange={this.onHomeserverChange}
|
onChange={this.onHomeserverChange}
|
||||||
onClick={this.onOtherChosen}
|
onFocus={this.onOtherChosen}
|
||||||
ref={this.fieldRef}
|
ref={this.fieldRef}
|
||||||
onValidate={this.onHomeserverValidate}
|
onValidate={this.onHomeserverValidate}
|
||||||
value={this.state.otherHomeserver}
|
value={this.state.otherHomeserver}
|
||||||
|
|
|
@ -20,6 +20,10 @@ import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
|
|
||||||
interface IProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
interface IProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
||||||
outlined?: boolean;
|
outlined?: boolean;
|
||||||
|
// If true (default), the children will be contained within a <label> element
|
||||||
|
// If false, they'll be in a div. Putting interactive components like Fields in labels can
|
||||||
|
// cause strange bugs like https://github.com/vector-im/element-web/issues/18031
|
||||||
|
childrenInLabel?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
|
@ -29,10 +33,11 @@ interface IState {
|
||||||
export default class StyledRadioButton extends React.PureComponent<IProps, IState> {
|
export default class StyledRadioButton extends React.PureComponent<IProps, IState> {
|
||||||
public static readonly defaultProps = {
|
public static readonly defaultProps = {
|
||||||
className: '',
|
className: '',
|
||||||
|
childrenInLabel: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const { children, className, disabled, outlined, ...otherProps } = this.props;
|
const { children, className, disabled, outlined, childrenInLabel, ...otherProps } = this.props;
|
||||||
const _className = classnames(
|
const _className = classnames(
|
||||||
'mx_RadioButton',
|
'mx_RadioButton',
|
||||||
className,
|
className,
|
||||||
|
@ -42,12 +47,27 @@ export default class StyledRadioButton extends React.PureComponent<IProps, IStat
|
||||||
"mx_RadioButton_checked": this.props.checked,
|
"mx_RadioButton_checked": this.props.checked,
|
||||||
"mx_RadioButton_outlined": outlined,
|
"mx_RadioButton_outlined": outlined,
|
||||||
});
|
});
|
||||||
return <label className={_className}>
|
|
||||||
|
const radioButton = <React.Fragment>
|
||||||
<input type='radio' disabled={disabled} {...otherProps} />
|
<input type='radio' disabled={disabled} {...otherProps} />
|
||||||
{/* Used to render the radio button circle */}
|
{/* Used to render the radio button circle */}
|
||||||
<div><div /></div>
|
<div><div /></div>
|
||||||
|
</React.Fragment>;
|
||||||
|
|
||||||
|
if (childrenInLabel) {
|
||||||
|
return <label className={_className}>
|
||||||
|
{radioButton}
|
||||||
<div className="mx_RadioButton_content">{children}</div>
|
<div className="mx_RadioButton_content">{children}</div>
|
||||||
<div className="mx_RadioButton_spacer" />
|
<div className="mx_RadioButton_spacer" />
|
||||||
</label>;
|
</label>;
|
||||||
|
} else {
|
||||||
|
return <div className={_className}>
|
||||||
|
<label className="mx_RadioButton_innerLabel">
|
||||||
|
{radioButton}
|
||||||
|
</label>
|
||||||
|
<div className="mx_RadioButton_content">{children}</div>
|
||||||
|
<div className="mx_RadioButton_spacer" />
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue