Add a form field component for the redesign

The label moves into the border on focus and after being filled. A valid color
is applied to the label and input border. Other states like invalid can be added
later as needed.

Adapted from @ara4n's experiment into a React component with a CSS only
approach.
This commit is contained in:
J. Ryan Stinnett 2019-01-19 22:11:20 -06:00
parent 7c9509ceb8
commit efd5405267
5 changed files with 137 additions and 2 deletions

View file

@ -59,6 +59,7 @@
@import "./views/elements/_DirectorySearchBox.scss"; @import "./views/elements/_DirectorySearchBox.scss";
@import "./views/elements/_Dropdown.scss"; @import "./views/elements/_Dropdown.scss";
@import "./views/elements/_EditableItemList.scss"; @import "./views/elements/_EditableItemList.scss";
@import "./views/elements/_Field.scss";
@import "./views/elements/_ImageView.scss"; @import "./views/elements/_ImageView.scss";
@import "./views/elements/_InlineSpinner.scss"; @import "./views/elements/_InlineSpinner.scss";
@import "./views/elements/_MemberEventListSummary.scss"; @import "./views/elements/_MemberEventListSummary.scss";

View file

@ -0,0 +1,77 @@
/*
Copyright 2019 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* TODO: Consider unifying with general input styles in _dharma.scss */
.mx_Field {
position: relative;
margin: 1em 0;
}
.mx_Field input {
font-weight: normal;
border-radius: 4px;
transition: border-color 0.25s;
border: 1px solid $input-border-color;
padding: 8px 10px;
}
.mx_Field input:focus {
outline: 0;
border-color: $input-valid-border-color;
}
.mx_Field input::placeholder {
transition: color 0.25s ease-in 0s;
color: transparent;
}
.mx_Field input:placeholder-shown:focus::placeholder {
transition: color 0.25s ease-in 0.1s;
color: $greyed-fg-color;
}
.mx_Field label {
transition:
font-size 0.25s ease-out 0.1s,
color 0.25s ease-out 0.1s,
top 0.25s ease-out 0.1s,
background-color 0.25s ease-out 0.1s;
color: $primary-fg-color;
background-color: transparent;
font-size: 14px;
position: absolute;
left: 0px;
top: 0px;
margin: 6px 8px;
padding: 2px;
}
.mx_Field input:focus + label,
.mx_Field input:not(:placeholder-shown) + label {
transition:
font-size 0.25s ease-out 0s,
color 0.25s ease-out 0s,
top 0.25s ease-out 0s,
background-color 0.25s ease-out 0s;
font-size: 10px;
top: -14px;
background-color: $field-focused-label-bg-color;
}
.mx_Field input:focus + label {
color: $input-valid-border-color;
}

View file

@ -71,6 +71,9 @@ $input-darker-bg-color: rgba(193, 201, 214, 0.29);
$input-darker-fg-color: #9fa9ba; $input-darker-fg-color: #9fa9ba;
$input-lighter-bg-color: #f2f5f8; $input-lighter-bg-color: #f2f5f8;
$input-lighter-fg-color: $input-darker-fg-color; $input-lighter-fg-color: $input-darker-fg-color;
$input-valid-border-color: #7ac9a1;
$field-focused-label-bg-color: #ffffff;
$button-bg-color: #7ac9a1; $button-bg-color: #7ac9a1;
$button-fg-color: white; $button-fg-color: white;
@ -198,8 +201,8 @@ $memberstatus-placeholder-color: $roomtile-name-color;
.mx_MatrixChat { .mx_MatrixChat {
:not(.mx_textinput) > input[type=text], :not(.mx_textinput):not(.mx_Field) > input[type=text],
:not(.mx_textinput) > input[type=search], :not(.mx_textinput):not(.mx_Field) > input[type=search],
.mx_textinput { .mx_textinput {
display: block; display: block;
margin: 9px; margin: 9px;

View file

@ -73,6 +73,9 @@ $button-bg-color: #7ac9a1;
$button-fg-color: white; $button-fg-color: white;
// apart from login forms, which have stronger border // apart from login forms, which have stronger border
$strong-input-border-color: #c7c7c7; $strong-input-border-color: #c7c7c7;
$input-valid-border-color: #7ac9a1;
$field-focused-label-bg-color: #ffffff;
// used for UserSettings EditableText // used for UserSettings EditableText
$input-underline-color: rgba(151, 151, 151, 0.5); $input-underline-color: rgba(151, 151, 151, 0.5);

View file

@ -0,0 +1,51 @@
/*
Copyright 2019 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import PropTypes from 'prop-types';
export default class Field extends React.PureComponent {
static propTypes = {
// The field's id, which binds the input and label together.
id: PropTypes.string.isRequired,
// The field's <input> type. Defaults to "text".
type: PropTypes.string,
// The field's label string.
label: PropTypes.string,
// The field's placeholder string.
placeholder: PropTypes.string,
// All other props pass through to the <input>.
}
render() {
const extraProps = Object.assign({}, this.props);
// Remove explicit props
delete extraProps.id;
delete extraProps.type;
delete extraProps.placeholder;
delete extraProps.label;
return <div className="mx_Field">
<input id={this.props.id}
type={this.props.type || "text"}
placeholder={this.props.placeholder}
{...extraProps}
/>
<label htmlFor={this.props.id}>{this.props.label}</label>
</div>;
}
}