Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import {Box} from 'grid-emotion';

const FormFieldControl = styled(Box)`
color: ${p => p.theme.gray3};
width: 50%;
padding-left: 10px;
position: relative;
overflow: hidden;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prevent controls with a long string from overflowing

`;

export default FormFieldControl;
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import styled from 'react-emotion';
import {Box} from 'grid-emotion';
import {Flex} from 'grid-emotion';

const FormFieldControlState = styled(Box)`
const FormFieldControlState = styled(Flex)`
position: relative;
width: 36px;
text-align: right;
flex-shrink: 0;
`;

export default FormFieldControlState;
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {Box} from 'grid-emotion';
const FormFieldDescription = styled(Box)`
width: 50%;
padding-right: 10px;
flex-shrink: 0;
`;

export default FormFieldDescription;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import SettingsInputField from '../styled/input';
import SettingsTextAreaField from '../styled/textarea';

const FormFieldWrapper = styled(({highlighted, ...props}) => <Flex {...props} />)`
padding: 15px 20px;
padding: 15px 0 15px 20px;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed right padding because of whitespace from control state icons

border-bottom: 1px solid ${p => p.theme.borderLight};
align-items: center;
transition: background 0.15s;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
import {Box, Flex} from 'grid-emotion';
import {Observer} from 'mobx-react';
import PropTypes from 'prop-types';
import React from 'react';
import ReactDOM from 'react-dom';
import styled from 'react-emotion';

import {defined} from '../../../../../utils';
import FormState from '../../../../../components/forms/state';
import FormFieldWrapper from './formFieldWrapper';
import FormFieldDescription from './formFieldDescription';
import {pulse, fadeOut} from '../styled/animations';
import FormFieldControl from './formFieldControl';
import FormFieldControlState from './formFieldControlState';
import FormFieldDescription from './formFieldDescription';
import FormFieldHelp from './formFieldHelp';
import FormFieldLabel from './formFieldLabel';
import FormFieldRequiredBadge from './formFieldRequiredBadge';

import FormFieldWrapper from './formFieldWrapper';
import FormState from '../../../../../components/forms/state';
import InlineSvg from '../../../../../components/inlineSvg';
import Spinner from '../styled/spinner';
import {pulse, fadeOut} from '../styled/animations';

// This wraps Control + ControlError message
// * can NOT be a flex box have because of position: absolute on "control error message"
// * can NOT have overflow hidden because "control error message" overflows
const FormFieldControlErrorWrapper = styled(Box)`
width: 50%;
padding-left: 10px;
`;

const FormFieldControlWrapper = styled(Flex)`
overflow: hidden;
`;

const FormFieldErrorReason = styled.div`
color: ${p => p.theme.redDark};
position: absolute;
background: #fff;
left: 10px;
padding: 6px 8px;
font-weight: 600;
font-size: 12px;
Expand All @@ -34,13 +45,23 @@ const FormFieldErrorReason = styled.div`
const FormFieldError = styled.div`
color: ${p => p.theme.redDark};
animation: ${pulse} 1s ease infinite;
width: 16px;
margin-left: auto;
`;

const FormFieldIsSaved = styled.div`
color: ${p => p.theme.green};
animation: ${fadeOut} 0.3s ease 2s 1 forwards;
position: absolute;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind of hacky, but would have weird behavior if "saved" happens followed by "error" where both will be rendered

(current prod)
image

top: 0;
bottom: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: center;
`;

const FormSpinner = styled(Spinner)`
margin-left: 0;
`;

/**
Expand Down Expand Up @@ -211,37 +232,77 @@ class FormField extends React.Component {
)}
{help && <FormFieldHelp>{help}</FormFieldHelp>}
</FormFieldDescription>
<FormFieldControl>
<Observer>
{() => {
let error = this.getError();
let value = model.getValue(this.props.name);

return (
<this.props.children
innerRef={this.handleInputMount}
{...{
...this.props,
id,
onKeyDown: this.handleKeyDown,
onChange: this.handleChange,
onBlur: this.handleBlur,
value,
error,
disabled: isDisabled,
}}
initialData={model.initialData}
/>
);
}}
</Observer>

{isDisabled &&
disabledReason && (
<span className="disabled-indicator tip" title={disabledReason}>
<span className="icon-question" />
</span>
)}
<FormFieldControlErrorWrapper>
<FormFieldControlWrapper shrink="0">
<FormFieldControl flex="1">
<Observer>
{() => {
let error = this.getError();
let value = model.getValue(this.props.name);

return (
<this.props.children
innerRef={this.handleInputMount}
{...{
...this.props,
id,
onKeyDown: this.handleKeyDown,
onChange: this.handleChange,
onBlur: this.handleBlur,
value,
error,
disabled: isDisabled,
}}
initialData={model.initialData}
/>
);
}}
</Observer>

{isDisabled &&
disabledReason && (
<span className="disabled-indicator tip" title={disabledReason}>
<span className="icon-question" />
</span>
)}
</FormFieldControl>

<FormFieldControlState justify="center" align="center">
<Observer>
{() => {
let isSaving = model.getFieldState(this.props.name, FormState.SAVING);
let isSaved = model.getFieldState(this.props.name, FormState.READY);

if (isSaving) {
return <FormSpinner />;
} else if (isSaved) {
return (
<FormFieldIsSaved>
<InlineSvg src="icon-checkmark-sm" size="18px" />
</FormFieldIsSaved>
);
}

return null;
}}
</Observer>

<Observer>
{() => {
let error = this.getError();

if (!error) return null;

return (
<FormFieldError>
<InlineSvg src="icon-warning-sm" size="18px" />
</FormFieldError>
);
}}
</Observer>
</FormFieldControlState>
</FormFieldControlWrapper>

<Observer>
{() => {
Expand All @@ -251,41 +312,7 @@ class FormField extends React.Component {
return <FormFieldErrorReason>{error}</FormFieldErrorReason>;
}}
</Observer>
</FormFieldControl>
<FormFieldControlState>
<Observer>
{() => {
let isSaving = model.getFieldState(this.props.name, FormState.SAVING);
let isSaved = model.getFieldState(this.props.name, FormState.READY);

if (isSaving) {
return <Spinner />;
} else if (isSaved) {
return (
<FormFieldIsSaved>
<InlineSvg src="icon-checkmark-sm" size="18px" />
</FormFieldIsSaved>
);
}

return null;
}}
</Observer>

<Observer>
{() => {
let error = this.getError();

if (!error) return null;

return (
<FormFieldError>
<InlineSvg src="icon-warning-sm" size="18px" />
</FormFieldError>
);
}}
</Observer>
</FormFieldControlState>
</FormFieldControlErrorWrapper>
</FormFieldWrapper>
);
}
Expand Down