diff --git a/src-docs/src/views/inline_edit/inline_edit_confirm.tsx b/src-docs/src/views/inline_edit/inline_edit_confirm.tsx index 2443db20b1e..ec930061870 100644 --- a/src-docs/src/views/inline_edit/inline_edit_confirm.tsx +++ b/src-docs/src/views/inline_edit/inline_edit_confirm.tsx @@ -17,7 +17,7 @@ export default () => { defaultValue="Hello World!" size="m" editModeProps={{ - icon: 'cross', + inputProps: { icon: 'cross' }, }} readModeProps={{ color: 'success', diff --git a/src-docs/src/views/inline_edit/inline_edit_example.js b/src-docs/src/views/inline_edit/inline_edit_example.js index 41587e0f19b..1c92571b730 100644 --- a/src-docs/src/views/inline_edit/inline_edit_example.js +++ b/src-docs/src/views/inline_edit/inline_edit_example.js @@ -3,6 +3,7 @@ import React from 'react'; import { GuideSectionTypes } from '../../components'; import { + EuiCode, EuiText, EuiInlineEditText, EuiInlineEditTitle, @@ -17,6 +18,9 @@ const inlineEditTitleSource = require('!!raw-loader!./inline_edit_title'); import InlineEditConfirm from './inline_edit_confirm'; const inlineEditConfirmSource = require('!!raw-loader!././inline_edit_confirm'); +import InlineEditStates from './inline_edit_states'; +const inlineEditStatesSource = require('!!raw-loader!././inline_edit_states'); + export const InlineEditExample = { title: 'Inline edit', intro: ( @@ -37,7 +41,7 @@ export const InlineEditExample = { ), source: [ { - type: GuideSectionTypes.JS, + type: GuideSectionTypes.TSX, code: inlineEditTextSource, }, ], @@ -56,7 +60,7 @@ export const InlineEditExample = { ), source: [ { - type: GuideSectionTypes.JS, + type: GuideSectionTypes.TSX, code: inlineEditTitleSource, }, ], @@ -75,12 +79,37 @@ export const InlineEditExample = { ), source: [ { - type: GuideSectionTypes.JS, + type: GuideSectionTypes.TSX, code: inlineEditConfirmSource, }, ], demo: , props: { EuiInlineEditText }, }, + { + title: 'Loading and invalid states', + text: ( + <> +

+ Setting the isLoading prop to true will add a + spinner to the input element in editMode and add + the loading state to the confirm and cancel input buttons. +

+

+ Setting the isInvalid prop to true will display{' '} + EuiInlineEdit's error state. Optionally, use{' '} + editModeProps.formRowProps.error to pass an error + message that will be displayed on the form control. +

+ + ), + source: [ + { + type: GuideSectionTypes.TSX, + code: inlineEditStatesSource, + }, + ], + demo: , + }, ], }; diff --git a/src-docs/src/views/inline_edit/inline_edit_states.tsx b/src-docs/src/views/inline_edit/inline_edit_states.tsx new file mode 100644 index 00000000000..76eb115b944 --- /dev/null +++ b/src-docs/src/views/inline_edit/inline_edit_states.tsx @@ -0,0 +1,45 @@ +import React, { useState } from 'react'; +import { + EuiFlexGroup, + EuiInlineEditText, + EuiSwitch, + EuiSpacer, +} from '../../../../src'; + +export default () => { + const [toggleLoading, setToggleLoading] = useState(true); + + const [toggleValid, setToggleValid] = useState(false); + + const errorMessage = ["Here's an example of an error"]; + + return ( + <> + + setToggleLoading(e.target.checked)} + /> + + setToggleValid(e.target.checked)} + /> + + + + + + + ); +}; diff --git a/src-docs/src/views/inline_edit/inline_edit_title.tsx b/src-docs/src/views/inline_edit/inline_edit_title.tsx index 9484bd0a954..b35c24c9fce 100644 --- a/src-docs/src/views/inline_edit/inline_edit_title.tsx +++ b/src-docs/src/views/inline_edit/inline_edit_title.tsx @@ -59,12 +59,6 @@ export default () => { defaultValue="Hello World (but as a title)!" size={toggleTitleButtonSize} heading="h3" - editModeProps={{ - icon: 'cross', - }} - readModeProps={{ - color: 'success', - }} /> ); diff --git a/src/components/inline_edit/inline_edit_form.tsx b/src/components/inline_edit/inline_edit_form.tsx index 7afcaa57c5f..f256b1dfa7e 100644 --- a/src/components/inline_edit/inline_edit_form.tsx +++ b/src/components/inline_edit/inline_edit_form.tsx @@ -10,10 +10,19 @@ import React, { ReactNode, FunctionComponent, useState } from 'react'; import classNames from 'classnames'; import { CommonProps } from '../common'; -import { EuiFormRow, EuiFieldText, EuiForm, EuiFieldTextProps } from '../form'; +import { + EuiFormRow, + EuiFormRowProps, + EuiFieldText, + EuiForm, + EuiFieldTextProps, +} from '../form'; +import { euiFormVariables } from '../form/form.styles'; import { EuiButtonIcon, EuiButtonEmpty, EuiButtonEmptyProps } from '../button'; import { EuiButtonEmptyPropsForButton } from '../button/button_empty/button_empty'; import { EuiFlexGroup, EuiFlexItem } from '../flex'; +import { EuiSkeletonRectangle } from '../skeleton'; +import { useEuiTheme } from '../../services'; import { useEuiI18n } from '../i18n'; import { useGeneratedHtmlId } from '../../services/accessibility'; @@ -49,9 +58,21 @@ export type EuiInlineEditCommonProps = CommonProps & { */ readModeProps?: Omit; /** - * Props that will be applied directly to the EuiFieldText displayed in editMode + * Props that will be applied directly to the `EuiFormRow` and `EuiFieldText` input displayed in editMode */ - editModeProps?: EuiFieldTextProps; + editModeProps?: { + formRowProps?: Partial; + inputProps?: Partial; + }; + /** + * Loading state when changes are saved in editMode + */ + isLoading?: boolean; + + /** + * Validation for the form control used to edit text in editMode + */ + isInvalid?: boolean; }; // Internal-only props, passed by the consumer-facing components @@ -94,13 +115,16 @@ export const EuiInlineEditForm: FunctionComponent = ({ startWithEditOpen, readModeProps, editModeProps, + isLoading, + isInvalid, }) => { const classes = classNames('euiInlineEdit', className); - // Styles to come later! (Styling editMode text to match the size of its readMode counterpart) - /*const theme = useEuiTheme(); - const styles = euiInlineEditStyles(theme); - const cssStyles = [styles.euiInlineEdit];*/ + const euiTheme = useEuiTheme(); + const { controlHeight, controlCompressedHeight } = euiFormVariables(euiTheme); + const loadingSkeletonSize = sizes.compressed + ? controlCompressedHeight + : controlHeight; const defaultSaveButtonAriaLabel = useEuiI18n( 'euiInlineEditForm.saveButtonAriaLabel', @@ -139,44 +163,69 @@ export const EuiInlineEditForm: FunctionComponent = ({ - { - setEditModeValue(e.target.value); - }} - aria-label={inputAriaLabel} - autoFocus - compressed={sizes.compressed} - {...editModeProps} - /> + + { + setEditModeValue(e.target.value); + }} + aria-label={inputAriaLabel} + autoFocus + compressed={sizes.compressed} + isInvalid={isInvalid} + isLoading={isLoading} + {...editModeProps?.inputProps} + /> + - + + + - + + + diff --git a/src/components/inline_edit/inline_edit_text.tsx b/src/components/inline_edit/inline_edit_text.tsx index caf7cae4ae1..1719e369fdd 100644 --- a/src/components/inline_edit/inline_edit_text.tsx +++ b/src/components/inline_edit/inline_edit_text.tsx @@ -39,6 +39,8 @@ export const EuiInlineEditText: FunctionComponent = ({ startWithEditOpen, readModeProps, editModeProps, + isLoading = false, + isInvalid = false, ...rest }) => { const classes = classNames('euiInlineEditText', className); @@ -60,6 +62,8 @@ export const EuiInlineEditText: FunctionComponent = ({ startWithEditOpen, readModeProps, editModeProps, + isLoading, + isInvalid, }; return ( diff --git a/src/components/inline_edit/inline_edit_title.tsx b/src/components/inline_edit/inline_edit_title.tsx index e8a92f79709..a35ee2f8ef2 100644 --- a/src/components/inline_edit/inline_edit_title.tsx +++ b/src/components/inline_edit/inline_edit_title.tsx @@ -45,6 +45,8 @@ export const EuiInlineEditTitle: FunctionComponent = ({ startWithEditOpen = false, readModeProps, editModeProps, + isLoading = false, + isInvalid = false, ...rest }) => { const classes = classNames('euiInlineEditTitle', className); @@ -68,6 +70,8 @@ export const EuiInlineEditTitle: FunctionComponent = ({ startWithEditOpen, readModeProps, editModeProps, + isLoading, + isInvalid, }; return (