mirror of
https://github.com/element-hq/element-web
synced 2024-11-29 04:48:50 +03:00
Add prefix support to Fields
This allows Fields to have an optional prefix component which is placed inside the border of the Field and to the left of the input. Since this label animation would be complex to get right for this case, it is instead fixed to the top left if there is a prefix component. This canonical example of this today would be a phone number field which includes a country dropdown.
This commit is contained in:
parent
ae5c32d28b
commit
26b2aa174b
2 changed files with 27 additions and 3 deletions
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
/* TODO: Consider unifying with general input styles in _light.scss */
|
/* TODO: Consider unifying with general input styles in _light.scss */
|
||||||
|
|
||||||
.mx_Field {
|
.mx_Field {
|
||||||
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
@ -24,6 +25,10 @@ limitations under the License.
|
||||||
border: 1px solid $input-border-color;
|
border: 1px solid $input-border-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_Field_prefix {
|
||||||
|
border-right: 1px solid $input-border-color;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_Field input,
|
.mx_Field input,
|
||||||
.mx_Field select,
|
.mx_Field select,
|
||||||
.mx_Field textarea {
|
.mx_Field textarea {
|
||||||
|
@ -106,7 +111,8 @@ limitations under the License.
|
||||||
.mx_Field input:not(:placeholder-shown) + label,
|
.mx_Field input:not(:placeholder-shown) + label,
|
||||||
.mx_Field textarea:focus + label,
|
.mx_Field textarea:focus + label,
|
||||||
.mx_Field textarea:not(:placeholder-shown) + label,
|
.mx_Field textarea:not(:placeholder-shown) + label,
|
||||||
.mx_Field select + label /* Always show a select's label on top to not collide with the value */ {
|
.mx_Field select + label /* Always show a select's label on top to not collide with the value */,
|
||||||
|
.mx_Field_labelAlwaysTopLeft label {
|
||||||
transition:
|
transition:
|
||||||
font-size 0.25s ease-out 0s,
|
font-size 0.25s ease-out 0s,
|
||||||
color 0.25s ease-out 0s,
|
color 0.25s ease-out 0s,
|
||||||
|
|
|
@ -16,6 +16,7 @@ limitations under the License.
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
export default class Field extends React.PureComponent {
|
export default class Field extends React.PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -30,6 +31,8 @@ export default class Field extends React.PureComponent {
|
||||||
label: PropTypes.string,
|
label: PropTypes.string,
|
||||||
// The field's placeholder string. Defaults to the label.
|
// The field's placeholder string. Defaults to the label.
|
||||||
placeholder: PropTypes.string,
|
placeholder: PropTypes.string,
|
||||||
|
// Optional component to include inside the field before the input.
|
||||||
|
prefix: PropTypes.node,
|
||||||
// All other props pass through to the <input>.
|
// All other props pass through to the <input>.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,7 +49,7 @@ export default class Field extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { element, children, ...inputProps } = this.props;
|
const { element, prefix, children, ...inputProps } = this.props;
|
||||||
|
|
||||||
const inputElement = element || "input";
|
const inputElement = element || "input";
|
||||||
|
|
||||||
|
@ -57,7 +60,22 @@ export default class Field extends React.PureComponent {
|
||||||
|
|
||||||
const fieldInput = React.createElement(inputElement, inputProps, children);
|
const fieldInput = React.createElement(inputElement, inputProps, children);
|
||||||
|
|
||||||
return <div className={`mx_Field mx_Field_${inputElement}`}>
|
let prefixContainer = null;
|
||||||
|
if (prefix) {
|
||||||
|
prefixContainer = <span className="mx_Field_prefix">
|
||||||
|
{prefix}
|
||||||
|
</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const classes = classNames("mx_Field", `mx_Field_${inputElement}`, {
|
||||||
|
// If we have a prefix element, leave the label always at the top left and
|
||||||
|
// don't animate it, as it looks a bit clunky and would add complexity to do
|
||||||
|
// properly.
|
||||||
|
mx_Field_labelAlwaysTopLeft: prefix,
|
||||||
|
});
|
||||||
|
|
||||||
|
return <div className={classes}>
|
||||||
|
{prefixContainer}
|
||||||
{fieldInput}
|
{fieldInput}
|
||||||
<label htmlFor={this.props.id}>{this.props.label}</label>
|
<label htmlFor={this.props.id}>{this.props.label}</label>
|
||||||
</div>;
|
</div>;
|
||||||
|
|
Loading…
Reference in a new issue