From b88b07c9cd85b169aed5048b6b13b5df9a772851 Mon Sep 17 00:00:00 2001
From: Bree Hall <40739624+breehall@users.noreply.github.com>
Date: Tue, 28 Mar 2023 15:56:40 -0400
Subject: [PATCH 01/23] [EuiInlineEdit] Create Component Directory and Base
Functionality (#6598)
* Initial directory setup for EuiInlineEdit
* Initial structure for EuiInlineEdit docs
* Created EuiInlineEdit base component that toggles between a text input and text or title.
* Replaced button icons with full EuiButtons with text. Positioned the buttons on the right side of the input
* Added early snapshot for component
* Added aria-labels with i18n for the editView input, save button, and cancel buttons. Updated the props to require an input aria label because the option to show the label on the input was removed. This was removed to preserve the layout and prevent the input from appearing to bounch when switching between editView and readView.
* Combined with last commit - forgot to hit save
* Made defaultValue a required field because if there is no value passed in, the button will be empty (with the exception of the edit icon)
* Updated basic snapshot tests, updated docs
* Added button groups to documentation to make toggling button sizes easier
* Update src/components/text/index.ts
Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com>
* Update src-docs/src/views/inline_edit/inline_edit.tsx
Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com>
* Update src-docs/src/views/inline_edit/inline_edit.tsx
Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com>
* Update src/components/inline_edit/inline_edit.tsx
Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com>
* Update src/components/inline_edit/inline_edit.tsx
Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com>
* Update src/components/inline_edit/inline_edit.test.tsx
Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com>
* Update src/components/inline_edit/inline_edit.tsx
Co-authored-by: Elizabet Oliveira
* Separated the two EuiInlineEdit examples into their own files
* Created additional logic to resize buttons and fieldtext elements when when the size of EuiInlineEdit is small or lower.
* Created a heading prop to allow consumers to choose the level heading they would like the InlineEdit (title) to be wrapped inside of. If one isn't provided, h2 will be the default.
* Updated basic test snapshots for EuiInlineEdit
* Updated new i18n tokens to be more explicit about their purpose
* Split EuiInlineEdit into three components: EuiInlineEditText, EuiInlineEditTitle, and EuiInlineEditButtons.
- Created utils and types file to share common props and utility functions between all three components
* Oops
* EuiInlineEdit Updates
- Updated the onConfirm prop to return a boolean flag that will determine if the text value is saved or not in editMode
- Updated edit/read prop variable names
- Exported EuiButtonEmptyPropsForButton because it's being used as a type for the new readMode prop
- Added base testing files for EuiInlineEditTitle and EuiInlineEditButtons
* Remove testing props from inline edit example
* Separated repeated logic inside of EuiInlineEditTitle and EuiInlineEditText into a new component called EuiInlineEditForm. This new form component is responsible for the toggling of readMode and editMode for EuiInlineEdit.
* Move types to shared internal form component
* Pass top-level props instead of in a `props` obj
* Remove top level read state, use render prop instead
- so that EuiInlineEditForm is completely in charge of state
* Remove EuiInlineEditButtons, roll into EuiInlineEditForm as inline
* Removed utility in favor of component-specific size logic
- while still DRYing out the underlying form sizes being used
* Fix types and update snapshots
* Clean up type def
---------
Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com>
Co-authored-by: Elizabet Oliveira
Co-authored-by: Constance Chen
---
src-docs/src/routes.js | 3 +
.../views/inline_edit/inline_edit_confirm.tsx | 29 +++
.../views/inline_edit/inline_edit_example.js | 86 ++++++++
.../views/inline_edit/inline_edit_text.tsx | 52 +++++
.../views/inline_edit/inline_edit_title.tsx | 71 ++++++
.../button/button_empty/button_empty.tsx | 4 +-
src/components/index.ts | 2 +
.../inline_edit_text.test.tsx.snap | 31 +++
.../inline_edit_title.test.tsx.snap | 31 +++
src/components/inline_edit/index.ts | 13 ++
.../inline_edit/inline_edit.styles.ts | 19 ++
.../inline_edit/inline_edit_form.tsx | 207 ++++++++++++++++++
.../inline_edit/inline_edit_text.test.tsx | 29 +++
.../inline_edit/inline_edit_text.tsx | 66 ++++++
.../inline_edit/inline_edit_title.test.tsx | 30 +++
.../inline_edit/inline_edit_title.tsx | 76 +++++++
16 files changed, 748 insertions(+), 1 deletion(-)
create mode 100644 src-docs/src/views/inline_edit/inline_edit_confirm.tsx
create mode 100644 src-docs/src/views/inline_edit/inline_edit_example.js
create mode 100644 src-docs/src/views/inline_edit/inline_edit_text.tsx
create mode 100644 src-docs/src/views/inline_edit/inline_edit_title.tsx
create mode 100644 src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
create mode 100644 src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
create mode 100644 src/components/inline_edit/index.ts
create mode 100644 src/components/inline_edit/inline_edit.styles.ts
create mode 100644 src/components/inline_edit/inline_edit_form.tsx
create mode 100644 src/components/inline_edit/inline_edit_text.test.tsx
create mode 100644 src/components/inline_edit/inline_edit_text.tsx
create mode 100644 src/components/inline_edit/inline_edit_title.test.tsx
create mode 100644 src/components/inline_edit/inline_edit_title.tsx
diff --git a/src-docs/src/routes.js b/src-docs/src/routes.js
index acf9ce0393c..122ddea5b0a 100644
--- a/src-docs/src/routes.js
+++ b/src-docs/src/routes.js
@@ -151,6 +151,8 @@ import { ImageExample } from './views/image/image_example';
import { InnerTextExample } from './views/inner_text/inner_text_example';
+import { InlineEditExample } from './views/inline_edit/inline_edit_example';
+
import { KeyPadMenuExample } from './views/key_pad_menu/key_pad_menu_example';
import { LinkExample } from './views/link/link_example';
@@ -561,6 +563,7 @@ const navigation = [
HealthExample,
IconExample,
ImageExample,
+ InlineEditExample,
ListGroupExample,
LoadingExample,
NotificationEventExample,
diff --git a/src-docs/src/views/inline_edit/inline_edit_confirm.tsx b/src-docs/src/views/inline_edit/inline_edit_confirm.tsx
new file mode 100644
index 00000000000..2443db20b1e
--- /dev/null
+++ b/src-docs/src/views/inline_edit/inline_edit_confirm.tsx
@@ -0,0 +1,29 @@
+import React from 'react';
+
+import { EuiInlineEditText } from '../../../../src';
+
+export default () => {
+ // TO DO: Convert this example to use something like a modal
+ const confirmInlineEditChanges = () => {
+ // eslint-disable-next-line no-restricted-globals
+ const flag = confirm('Are you sure you want to save?') ? true : false;
+ return flag;
+ };
+
+ return (
+ <>
+
+ >
+ );
+};
diff --git a/src-docs/src/views/inline_edit/inline_edit_example.js b/src-docs/src/views/inline_edit/inline_edit_example.js
new file mode 100644
index 00000000000..41587e0f19b
--- /dev/null
+++ b/src-docs/src/views/inline_edit/inline_edit_example.js
@@ -0,0 +1,86 @@
+import React from 'react';
+
+import { GuideSectionTypes } from '../../components';
+
+import {
+ EuiText,
+ EuiInlineEditText,
+ EuiInlineEditTitle,
+} from '../../../../src';
+
+import InlineEditText from './inline_edit_text';
+const inlineEditTextSource = require('!!raw-loader!./inline_edit_text');
+
+import InlineEditTitle from './inline_edit_title';
+const inlineEditTitleSource = require('!!raw-loader!./inline_edit_title');
+
+import InlineEditConfirm from './inline_edit_confirm';
+const inlineEditConfirmSource = require('!!raw-loader!././inline_edit_confirm');
+
+export const InlineEditExample = {
+ title: 'Inline edit',
+ intro: (
+ <>
+ This is where the description will go
+ >
+ ),
+ sections: [
+ {
+ title: 'InlineEditText',
+ text: (
+ <>
+
+ Description needed: how to use the EuiInlineEdit{' '}
+ component.
+
+`;
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
new file mode 100644
index 00000000000..bf0cc76fdcc
--- /dev/null
+++ b/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
@@ -0,0 +1,31 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`EuiInlineEditTitle props renders as title 1`] = `
+
+
+
+`;
diff --git a/src/components/inline_edit/index.ts b/src/components/inline_edit/index.ts
new file mode 100644
index 00000000000..fb491c0aa6b
--- /dev/null
+++ b/src/components/inline_edit/index.ts
@@ -0,0 +1,13 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+export { EuiInlineEditText } from './inline_edit_text';
+
+export { EuiInlineEditTitle } from './inline_edit_title';
+
+export type { EuiInlineEditTextSizes } from './inline_edit_text';
diff --git a/src/components/inline_edit/inline_edit.styles.ts b/src/components/inline_edit/inline_edit.styles.ts
new file mode 100644
index 00000000000..61cc6824225
--- /dev/null
+++ b/src/components/inline_edit/inline_edit.styles.ts
@@ -0,0 +1,19 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { css } from '@emotion/react';
+import { UseEuiTheme } from '../../services';
+
+export const euiInlineEditStyles = ({ euiTheme }: UseEuiTheme) => {
+ return {
+ euiInlineEdit: css`
+ // Always start the object with the first key being the name of the component
+ color: ${euiTheme.colors.primaryText};
+ `,
+ };
+};
diff --git a/src/components/inline_edit/inline_edit_form.tsx b/src/components/inline_edit/inline_edit_form.tsx
new file mode 100644
index 00000000000..7afcaa57c5f
--- /dev/null
+++ b/src/components/inline_edit/inline_edit_form.tsx
@@ -0,0 +1,207 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React, { ReactNode, FunctionComponent, useState } from 'react';
+import classNames from 'classnames';
+
+import { CommonProps } from '../common';
+import { EuiFormRow, EuiFieldText, EuiForm, EuiFieldTextProps } from '../form';
+import { EuiButtonIcon, EuiButtonEmpty, EuiButtonEmptyProps } from '../button';
+import { EuiButtonEmptyPropsForButton } from '../button/button_empty/button_empty';
+import { EuiFlexGroup, EuiFlexItem } from '../flex';
+import { useEuiI18n } from '../i18n';
+import { useGeneratedHtmlId } from '../../services/accessibility';
+
+// Props shared between the internal form component as well as consumer-facing components
+export type EuiInlineEditCommonProps = CommonProps & {
+ defaultValue: string;
+ /**
+ * Allow users to pass in a function that is called when the confirm button is clicked
+ * The function should return a boolean flag that will determine if the value will be saved.
+ * When the flag is true, the value will be saved. When the flag is false, the user will be
+ * returned to editMode.
+ */
+ onConfirm?: () => boolean;
+ /**
+ * Form label that appears above the form control
+ * This is required for accessibility because there is no visual label on the input
+ */
+ inputAriaLabel: string;
+ /**
+ * Aria-label for save button in editMode
+ */
+ saveButtonAriaLabel?: string;
+ /**
+ * Aria-label for cancel button in editMode
+ */
+ cancelButtonAriaLabel?: string;
+ /**
+ * Start in editMode
+ */
+ startWithEditOpen?: boolean;
+ /**
+ * Props that will be applied directly to the EuiEmptyButton displayed in readMode
+ */
+ readModeProps?: Omit;
+ /**
+ * Props that will be applied directly to the EuiFieldText displayed in editMode
+ */
+ editModeProps?: EuiFieldTextProps;
+};
+
+// Internal-only props, passed by the consumer-facing components
+export type EuiInlineEditFormProps = EuiInlineEditCommonProps & {
+ /**
+ * Form sizes
+ */
+ sizes: {
+ compressed: boolean;
+ buttonSize: EuiButtonEmptyProps['size'];
+ iconSize: EuiButtonEmptyProps['iconSize'];
+ };
+ /**
+ * Render prop that returns the read mode value as an arg
+ */
+ children: (readModeValue: ReactNode) => ReactNode;
+};
+
+export const SMALL_SIZE_FORM = {
+ iconSize: 's',
+ compressed: true,
+ buttonSize: 's',
+} as const;
+
+export const MEDIUM_SIZE_FORM = {
+ iconSize: 'm',
+ compressed: false,
+ buttonSize: 'm',
+} as const;
+
+export const EuiInlineEditForm: FunctionComponent = ({
+ className,
+ children,
+ sizes,
+ defaultValue,
+ onConfirm,
+ inputAriaLabel,
+ saveButtonAriaLabel,
+ cancelButtonAriaLabel,
+ startWithEditOpen,
+ readModeProps,
+ editModeProps,
+}) => {
+ 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 defaultSaveButtonAriaLabel = useEuiI18n(
+ 'euiInlineEditForm.saveButtonAriaLabel',
+ 'Save edit'
+ );
+ const defaultCancelButtonAriaLabel = useEuiI18n(
+ 'euiInlineEditForm.cancelButtonAriaLabel',
+ 'Cancel edit'
+ );
+
+ const [isEditing, setIsEditing] = useState(false || startWithEditOpen);
+ const inlineEditInputId = useGeneratedHtmlId({ prefix: '__inlineEditInput' });
+
+ const [editModeValue, setEditModeValue] = useState(defaultValue);
+ const [readModeValue, setReadModeValue] = useState(defaultValue);
+
+ const cancelInlineEdit = () => {
+ setEditModeValue(readModeValue);
+ setIsEditing(!isEditing);
+ };
+
+ const saveInlineEditValue = () => {
+ if (editModeValue && onConfirm && !onConfirm()) {
+ // If there is text, an onConfirm method is present, and it has returned false, cancel the action
+ return;
+ } else if (editModeValue) {
+ setReadModeValue(editModeValue);
+ setIsEditing(!isEditing);
+ } else {
+ // If there's no text, cancel the action, reset the input text, and return to readMode
+ cancelInlineEdit();
+ }
+ };
+
+ const editModeForm = (
+
+
+
+ {
+ setEditModeValue(e.target.value);
+ }}
+ aria-label={inputAriaLabel}
+ autoFocus
+ compressed={sizes.compressed}
+ {...editModeProps}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+
+ const readModeElement = (
+ {
+ setIsEditing(!isEditing);
+ }}
+ {...readModeProps}
+ >
+ {children(readModeValue)}
+
+ );
+
+ return (
+
{isEditing ? editModeForm : readModeElement}
+ );
+};
diff --git a/src/components/inline_edit/inline_edit_text.test.tsx b/src/components/inline_edit/inline_edit_text.test.tsx
new file mode 100644
index 00000000000..eb47d25e5b8
--- /dev/null
+++ b/src/components/inline_edit/inline_edit_text.test.tsx
@@ -0,0 +1,29 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React from 'react';
+import { render } from '../../test/rtl';
+import { requiredProps } from '../../test/required_props';
+
+import { EuiInlineEditText } from './inline_edit_text';
+
+describe('EuiInlineEditText', () => {
+ describe('props', () => {
+ test('renders as text', () => {
+ const { container } = render(
+
+ );
+
+ expect(container.firstChild).toMatchSnapshot();
+ });
+ });
+});
diff --git a/src/components/inline_edit/inline_edit_text.tsx b/src/components/inline_edit/inline_edit_text.tsx
new file mode 100644
index 00000000000..c761481e578
--- /dev/null
+++ b/src/components/inline_edit/inline_edit_text.tsx
@@ -0,0 +1,66 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React, { FunctionComponent } from 'react';
+import classNames from 'classnames';
+import { EuiText, EuiTextProps } from '../text';
+import {
+ EuiInlineEditCommonProps,
+ EuiInlineEditForm,
+ SMALL_SIZE_FORM,
+ MEDIUM_SIZE_FORM,
+} from './inline_edit_form';
+
+export type EuiInlineEditTextSizes = Exclude;
+
+export type EuiInlineEditTextProps = EuiInlineEditCommonProps & {
+ /**
+ * Text size level
+ */
+ size?: EuiInlineEditTextSizes;
+};
+
+export const EuiInlineEditText: FunctionComponent = ({
+ children,
+ className,
+ size = 'm',
+ defaultValue,
+ onConfirm,
+ inputAriaLabel,
+ saveButtonAriaLabel,
+ cancelButtonAriaLabel,
+ startWithEditOpen,
+ readModeProps,
+ editModeProps,
+ ...rest
+}) => {
+ const classes = classNames('euiInlineEditText', className);
+
+ const isSmallSize = ['xs', 's'].includes(size);
+ const sizes = isSmallSize ? SMALL_SIZE_FORM : MEDIUM_SIZE_FORM;
+
+ const formProps = {
+ sizes,
+ defaultValue,
+ onConfirm,
+ inputAriaLabel,
+ saveButtonAriaLabel,
+ cancelButtonAriaLabel,
+ startWithEditOpen,
+ readModeProps,
+ editModeProps,
+ };
+
+ return (
+
+ {(textReadModeValue) => (
+ {textReadModeValue}
+ )}
+
+ );
+};
diff --git a/src/components/inline_edit/inline_edit_title.test.tsx b/src/components/inline_edit/inline_edit_title.test.tsx
new file mode 100644
index 00000000000..9104347af45
--- /dev/null
+++ b/src/components/inline_edit/inline_edit_title.test.tsx
@@ -0,0 +1,30 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React from 'react';
+import { render } from '../../test/rtl';
+import { requiredProps } from '../../test/required_props';
+
+import { EuiInlineEditTitle } from './inline_edit_title';
+
+describe('EuiInlineEditTitle', () => {
+ describe('props', () => {
+ test('renders as title', () => {
+ const { container } = render(
+
+ );
+
+ expect(container.firstChild).toMatchSnapshot();
+ });
+ });
+});
diff --git a/src/components/inline_edit/inline_edit_title.tsx b/src/components/inline_edit/inline_edit_title.tsx
new file mode 100644
index 00000000000..c612199d2b0
--- /dev/null
+++ b/src/components/inline_edit/inline_edit_title.tsx
@@ -0,0 +1,76 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React, { FunctionComponent } from 'react';
+import classNames from 'classnames';
+import { EuiTitle, EuiTitleSize } from '../title';
+import {
+ EuiInlineEditCommonProps,
+ EuiInlineEditForm,
+ SMALL_SIZE_FORM,
+ MEDIUM_SIZE_FORM,
+} from './inline_edit_form';
+
+export const HEADINGS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as const;
+type Heading = typeof HEADINGS[number];
+
+export type EuiInlineEditTitleProps = EuiInlineEditCommonProps & {
+ /**
+ * Title size level
+ */
+ size?: EuiTitleSize;
+ /**
+ * Level of heading to be used for the title
+ */
+ heading: Heading;
+};
+
+export const EuiInlineEditTitle: FunctionComponent = ({
+ children,
+ className,
+ size = 'm',
+ heading,
+ defaultValue,
+ onConfirm,
+ inputAriaLabel,
+ saveButtonAriaLabel,
+ cancelButtonAriaLabel,
+ startWithEditOpen = false,
+ readModeProps,
+ editModeProps,
+ ...rest
+}) => {
+ const classes = classNames('euiInlineEditTitle', className);
+
+ const H: Heading = heading;
+
+ const isSmallSize = ['xxxs', 'xxs', 'xs', 's'].includes(size);
+ const sizes = isSmallSize ? SMALL_SIZE_FORM : MEDIUM_SIZE_FORM;
+
+ const formProps = {
+ sizes,
+ defaultValue,
+ onConfirm,
+ inputAriaLabel,
+ saveButtonAriaLabel,
+ cancelButtonAriaLabel,
+ startWithEditOpen,
+ readModeProps,
+ editModeProps,
+ };
+
+ return (
+
+ {(titleReadModeValue) => (
+
+ {titleReadModeValue}
+
+ )}
+
+ );
+};
From d69c093b8cf744c285923e63f2e738c527707da3 Mon Sep 17 00:00:00 2001
From: Bree Hall <40739624+breehall@users.noreply.github.com>
Date: Thu, 30 Mar 2023 14:02:43 -0400
Subject: [PATCH 02/23] [EuiInlineEdit] Add Dynamic Font Sizing & Truncation
Styling (#6660)
* Created styling for EuiInlineEdit text and title components that adjusts the font-size used within the editMode form control. Added styling to ensure that very long text is truncated inside of the EuiEmptyButton used in readMode
* Updated snapshot tests for EuiInlineEdit
* Update src/components/inline_edit/inline_edit_title.tsx
Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com>
* Update src/components/inline_edit/inline_edit_text.tsx
Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com>
* Updated snapshots for EuiInlineEdit test cases after modification in Github UI
---------
Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com>
---
.../inline_edit_text.test.tsx.snap | 4 +-
.../inline_edit_title.test.tsx.snap | 4 +-
.../inline_edit/inline_edit_text.styles.ts | 37 +++++++++++++
.../inline_edit/inline_edit_text.tsx | 17 +++++-
.../inline_edit/inline_edit_title.styles.ts | 52 +++++++++++++++++++
.../inline_edit/inline_edit_title.tsx | 15 +++++-
6 files changed, 121 insertions(+), 8 deletions(-)
create mode 100644 src/components/inline_edit/inline_edit_text.styles.ts
create mode 100644 src/components/inline_edit/inline_edit_title.styles.ts
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
index e235f18852d..345679c9b9a 100644
--- a/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
+++ b/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
@@ -2,7 +2,7 @@
exports[`EuiInlineEditText props renders as text 1`] = `
-
- Press Enter to save your edited text. Press Escape to cancel your edit.
-
-
-
-
-
-
-
- Loaded
-
-
-
-
-
-
-
-
-
-
+ Press Enter to save your edited text. Press Escape to cancel your edit.
+
+
+
-
-
-
-
- Loaded
-
-
-
-
-
-
-
-
+
+
+
+
+
@@ -1014,6 +648,7 @@ exports[`EuiInlineEditForm Read Mode readModeProps 1`] = `
class="euiInlineEdit testClass1 testClass2"
>
+
+ Click this button to edit this text inline.
+
`;
@@ -1041,6 +682,7 @@ exports[`EuiInlineEditForm Read Mode renders 1`] = `
class="euiInlineEdit testClass1 testClass2"
>
+
+ Click this button to edit this text inline.
+
`;
@@ -1068,6 +716,7 @@ exports[`EuiInlineEditForm Read Mode sizes 1`] = `
class="euiInlineEdit testClass1 testClass2"
>
+
+ Click this button to edit this text inline.
+
`;
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
index 42d20b7f64e..c84ffa0c68a 100644
--- a/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
+++ b/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
@@ -5,6 +5,7 @@ exports[`EuiInlineEditText renders 1`] = `
class="euiInlineEdit euiInlineEditText testClass1 testClass2 emotion-euiInlineEditText-m-m"
>
+
+ Click this button to edit this text inline.
+
`;
@@ -36,6 +43,7 @@ exports[`EuiInlineEditText text sizes renders m 1`] = `
class="euiInlineEdit euiInlineEditText testClass1 testClass2 emotion-euiInlineEditText-m-m"
>
+
+ Click this button to edit this text inline.
+
`;
@@ -67,6 +81,7 @@ exports[`EuiInlineEditText text sizes renders s 1`] = `
class="euiInlineEdit euiInlineEditText testClass1 testClass2 emotion-euiInlineEditText-s-s"
>
+
+ Click this button to edit this text inline.
+
`;
@@ -98,6 +119,7 @@ exports[`EuiInlineEditText text sizes renders xs 1`] = `
class="euiInlineEdit euiInlineEditText testClass1 testClass2 emotion-euiInlineEditText-xs-xs"
>
+
+ Click this button to edit this text inline.
+
`;
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
index 19a670a600d..58527fff8f8 100644
--- a/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
+++ b/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
@@ -5,6 +5,7 @@ exports[`EuiInlineEditTitle renders 1`] = `
class="euiInlineEdit euiInlineEditTitle testClass1 testClass2 emotion-euiInlineEditTitle-m-m"
>
+
+ Click this button to edit this text inline.
+
`;
@@ -36,6 +43,7 @@ exports[`EuiInlineEditTitle title sizes renders size l 1`] = `
class="euiInlineEdit euiInlineEditTitle testClass1 testClass2 emotion-euiInlineEditTitle-l-l"
>
+
+ Click this button to edit this text inline.
+
- To validate text when the user presses the save button but before
- the user is returned to read mode, return a boolean (or an async
- promise returning a boolean) from your onSave{' '}
- callback.
+ Return a boolean from your onSave callback to
+ validate text after pressing Save. You can also return a boolean from a
+ promise. Validation happens before the user returns to read mode.
Returning false from onSave{' '}
From 469ab654a97e273ec0bf93a121198df95b37e1b9 Mon Sep 17 00:00:00 2001
From: Bree Hall <40739624+breehall@users.noreply.github.com>
Date: Thu, 18 May 2023 05:22:52 -0700
Subject: [PATCH 12/23] Update src/components/inline_edit/inline_edit_form.tsx
Co-authored-by: Trevor Pierce <1Copenut@users.noreply.github.com>
---
src/components/inline_edit/inline_edit_form.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/inline_edit/inline_edit_form.tsx b/src/components/inline_edit/inline_edit_form.tsx
index eb655660b9d..7b8f4845433 100644
--- a/src/components/inline_edit/inline_edit_form.tsx
+++ b/src/components/inline_edit/inline_edit_form.tsx
@@ -318,7 +318,7 @@ export const EuiInlineEditForm: FunctionComponent = ({
>
From e11c50fdda48edd87538a1b6ecb1bb00f68b5746 Mon Sep 17 00:00:00 2001
From: Bree Hall <40739624+breehall@users.noreply.github.com>
Date: Thu, 18 May 2023 05:23:39 -0700
Subject: [PATCH 13/23] Update
src-docs/src/views/inline_edit/inline_edit_example.js
Co-authored-by: Trevor Pierce <1Copenut@users.noreply.github.com>
---
src-docs/src/views/inline_edit/inline_edit_example.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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 94debdc9ae1..9bb5983e0bf 100644
--- a/src-docs/src/views/inline_edit/inline_edit_example.js
+++ b/src-docs/src/views/inline_edit/inline_edit_example.js
@@ -73,7 +73,7 @@ export const InlineEditExample = {
<>
The EuiInlineEdit components are useful for updating
- single-line text outside of a form. The component has two states:{' '}
+ single lines of text outside a form. The component has two states:{' '}
readMode shows editable text inside of a button and{' '}
editMode displays a form control to update the text.
From abce4048e78fef6464a7093dcd8a7db1c5f1e926 Mon Sep 17 00:00:00 2001
From: Bree Hall <40739624+breehall@users.noreply.github.com>
Date: Thu, 18 May 2023 10:23:11 -0400
Subject: [PATCH 14/23] [EuiInlineEdit] `CHANGELOG` & Copy Linting (#6788)
* Changelog & text linting from changes made in Github UI
* Snapshot update as a result of updating the copy of the aria-describedby used by inline edit
---
.../src/views/inline_edit/inline_edit_example.js | 7 ++++---
.../__snapshots__/inline_edit_form.test.tsx.snap | 6 +++---
.../__snapshots__/inline_edit_text.test.tsx.snap | 8 ++++----
.../__snapshots__/inline_edit_title.test.tsx.snap | 14 +++++++-------
upcoming_changelogs/6757.md | 2 ++
5 files changed, 20 insertions(+), 17 deletions(-)
create mode 100644 upcoming_changelogs/6757.md
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 9bb5983e0bf..cb8f06645c8 100644
--- a/src-docs/src/views/inline_edit/inline_edit_example.js
+++ b/src-docs/src/views/inline_edit/inline_edit_example.js
@@ -155,9 +155,10 @@ export const InlineEditExample = {
mode.
- Return a boolean from your onSave callback to
- validate text after pressing Save. You can also return a boolean from a
- promise. Validation happens before the user returns to read mode.
+ Return a boolean from your onSave callback to
+ validate text after pressing Save. You can also return a boolean
+ from a promise. Validation happens before the user returns to read
+ mode.
Returning false from onSave{' '}
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap
index 44d0882bc92..789434c3736 100644
--- a/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap
+++ b/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap
@@ -672,7 +672,7 @@ exports[`EuiInlineEditForm Read Mode readModeProps 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
@@ -706,7 +706,7 @@ exports[`EuiInlineEditForm Read Mode renders 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
@@ -740,7 +740,7 @@ exports[`EuiInlineEditForm Read Mode sizes 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
index c84ffa0c68a..88c3fcab517 100644
--- a/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
+++ b/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
@@ -33,7 +33,7 @@ exports[`EuiInlineEditText renders 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
@@ -71,7 +71,7 @@ exports[`EuiInlineEditText text sizes renders m 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
@@ -109,7 +109,7 @@ exports[`EuiInlineEditText text sizes renders s 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
@@ -147,7 +147,7 @@ exports[`EuiInlineEditText text sizes renders xs 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
index 58527fff8f8..aabe6e1a00e 100644
--- a/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
+++ b/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
@@ -33,7 +33,7 @@ exports[`EuiInlineEditTitle renders 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
@@ -71,7 +71,7 @@ exports[`EuiInlineEditTitle title sizes renders size l 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
@@ -109,7 +109,7 @@ exports[`EuiInlineEditTitle title sizes renders size m 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
@@ -147,7 +147,7 @@ exports[`EuiInlineEditTitle title sizes renders size s 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
@@ -185,7 +185,7 @@ exports[`EuiInlineEditTitle title sizes renders size xs 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
@@ -223,7 +223,7 @@ exports[`EuiInlineEditTitle title sizes renders size xxs 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
@@ -261,7 +261,7 @@ exports[`EuiInlineEditTitle title sizes renders size xxxs 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
diff --git a/upcoming_changelogs/6757.md b/upcoming_changelogs/6757.md
new file mode 100644
index 00000000000..f2c3b6287b4
--- /dev/null
+++ b/upcoming_changelogs/6757.md
@@ -0,0 +1,2 @@
+- Added `EuiInlineEditText` and `EuiInlineEditTitle` components
+
From a864a9f1a7b06d5327bf84b33ca099eb547ccb44 Mon Sep 17 00:00:00 2001
From: Bree Hall <40739624+breehall@users.noreply.github.com>
Date: Thu, 18 May 2023 10:58:20 -0400
Subject: [PATCH 15/23] [EuiInlineEdit] Create `isReadOnly` Prop for Read Mode
(#6777)
* [EuiInlineEdit] Add the isReadOnly prop that locks the component in read mode and does not allow the user to update text
* [EuiInlineEdit] Update snapshots to account for new inline_edit_form styles. Added a test case for the new isReadOnly prop
* [EuiInlineEdit] Forgot to add snapshot updates
* [REVERT] Add documentation example to InlineEdit Text to display isReadOnly prop
* Revert "[REVERT] Add documentation example to InlineEdit Text to display isReadOnly prop"
This reverts commit 8a7b117f8caf591794b6747963ed049943461d54.
Revert change made to demo for testing
* [PR Review]
- Add an official example for the isReadOnly prop
- Name correction in edit mode props example
* [PR Feedback]
- Updated the name of Emotion style object to indicate we're styling the read mode button, not the entire form
- Conditionally hide the text content of aria-describedby when isReadOnly is true
- Conditionally add a role (and aria-level where required) to the read mode button when isReadOnly is true
* Update and add test cases
* [PR Feedback] - Update conditional aria-describedby span to surround the text instead of the entire span.
- Clean up logic related to adding aria-live and role attributes when isReadOnly is true
* Update src-docs/src/views/inline_edit/inline_edit_read_only.tsx
Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com>
* Update src/components/inline_edit/inline_edit_form.styles.ts
Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com>
* [PR Feedback] -Add note in inline_edit_form.style.ts that we should reevaluate styles once EuiEmptyButton is converted to Eotion.
- Updated render condition for edit mode to ensure if isReadOnly is true, we stay / kick back to read mode
- Test case & snapshot updates
* [PR Feedback] Move the isReadOnly prop example up in the documentation
* Snapshots
* Update src-docs/src/views/inline_edit/inline_edit_example.js
Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com>
* [PR Feedback] - Removed conditiona lo logic to force a toggle from read mode to edit mode when isReadOnly is true. Opted for a useEffect that will handle the change instead
* Oops!
---------
Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com>
---
.../views/inline_edit/inline_edit_example.js | 30 ++++++++++-
.../inline_edit/inline_edit_read_only.tsx | 39 +++++++++++++++
.../inline_edit_form.test.tsx.snap | 36 +++++++++++--
.../inline_edit_text.test.tsx.snap | 43 ++++++++++++++--
.../inline_edit_title.test.tsx.snap | 50 ++++++++++++++++---
.../inline_edit/inline_edit_form.styles.ts | 26 ++++++++++
.../inline_edit/inline_edit_form.test.tsx | 14 ++++++
.../inline_edit/inline_edit_form.tsx | 36 +++++++++++--
.../inline_edit/inline_edit_text.test.tsx | 13 +++++
.../inline_edit/inline_edit_text.tsx | 15 +++++-
.../inline_edit/inline_edit_title.test.tsx | 17 +++++++
.../inline_edit/inline_edit_title.tsx | 22 +++++++-
12 files changed, 317 insertions(+), 24 deletions(-)
create mode 100644 src-docs/src/views/inline_edit/inline_edit_read_only.tsx
create mode 100644 src/components/inline_edit/inline_edit_form.styles.ts
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 cb8f06645c8..2855a752bac 100644
--- a/src-docs/src/views/inline_edit/inline_edit_example.js
+++ b/src-docs/src/views/inline_edit/inline_edit_example.js
@@ -67,6 +67,14 @@ const inlineEditModeSaveSnippet = ``;
+
export const InlineEditExample = {
title: 'Inline edit',
intro: (
@@ -176,6 +184,26 @@ export const InlineEditExample = {
],
demo: ,
},
+ {
+ title: 'Read only',
+ text: (
+ <>
+
+ Use the isReadOnly prop to lock{' '}
+ EuiInlineEdit in read mode and display the text
+ value. This does not affect the input form control in edit mode.
+
+
+
+
+
+ Click this button to edit this text inline.
+
+
+`;
+
exports[`EuiInlineEditText renders 1`] = `
@@ -44,7 +79,7 @@ exports[`EuiInlineEditText text sizes renders m 1`] = `
>
@@ -82,7 +117,7 @@ exports[`EuiInlineEditText text sizes renders s 1`] = `
>
@@ -120,7 +155,7 @@ exports[`EuiInlineEditText text sizes renders xs 1`] = `
>
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
index aabe6e1a00e..1def24c3dfc 100644
--- a/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
+++ b/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
@@ -1,12 +1,48 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`EuiInlineEditTitle isReadOnly 1`] = `
+
+
+
+
+
+ Hello World!
+
+
+
+
+
+ Click this button to edit this text inline.
+
+
+`;
+
exports[`EuiInlineEditTitle renders 1`] = `
@@ -44,7 +80,7 @@ exports[`EuiInlineEditTitle title sizes renders size l 1`] = `
>
@@ -82,7 +118,7 @@ exports[`EuiInlineEditTitle title sizes renders size m 1`] = `
>
@@ -120,7 +156,7 @@ exports[`EuiInlineEditTitle title sizes renders size s 1`] = `
>
@@ -158,7 +194,7 @@ exports[`EuiInlineEditTitle title sizes renders size xs 1`] = `
>
@@ -196,7 +232,7 @@ exports[`EuiInlineEditTitle title sizes renders size xxs 1`] = `
>
@@ -234,7 +270,7 @@ exports[`EuiInlineEditTitle title sizes renders size xxxs 1`] = `
>
diff --git a/src/components/inline_edit/inline_edit_form.styles.ts b/src/components/inline_edit/inline_edit_form.styles.ts
new file mode 100644
index 00000000000..15baae937a3
--- /dev/null
+++ b/src/components/inline_edit/inline_edit_form.styles.ts
@@ -0,0 +1,26 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { css } from '@emotion/react';
+import { UseEuiTheme } from '../../services';
+
+export const euiInlineEditFormStyles = ({ euiTheme }: UseEuiTheme) => {
+ return {
+ euiInlineEditButton: css``,
+
+ // Override the cursor and allow users to highlight text when read mode is in the read only state
+ // Once EuiEmptyButton has been converted to Emotion, remove this extra selector
+ isReadOnly: css`
+ &.euiButtonEmpty:disabled {
+ cursor: text;
+ color: ${euiTheme.colors.text};
+ user-select: text;
+ }
+ `,
+ };
+};
diff --git a/src/components/inline_edit/inline_edit_form.test.tsx b/src/components/inline_edit/inline_edit_form.test.tsx
index 49c9e7de684..0d133d8aabf 100644
--- a/src/components/inline_edit/inline_edit_form.test.tsx
+++ b/src/components/inline_edit/inline_edit_form.test.tsx
@@ -36,6 +36,20 @@ describe('EuiInlineEditForm', () => {
expect(container.firstChild).toMatchSnapshot();
});
+ test('isReadOnly', () => {
+ const { container, getByTestSubject } = render(
+
+ );
+
+ expect(container.firstChild).toMatchSnapshot();
+
+ expect(getByTestSubject('euiInlineReadModeButton')).toBeDisabled();
+ });
+
test('readModeProps', () => {
const { container, getByTestSubject } = render(
&
@@ -80,6 +82,10 @@ export type EuiInlineEditCommonProps = HTMLAttributes &
* Invalid state - only displayed edit mode
*/
isInvalid?: boolean;
+ /**
+ * Locks inline edit in read mode and displays the text value
+ */
+ isReadOnly?: boolean;
};
// Internal-only props, passed by the consumer-facing components
@@ -122,10 +128,18 @@ export const EuiInlineEditForm: FunctionComponent = ({
isLoading = false,
isInvalid,
onSave,
+ isReadOnly,
}) => {
const classes = classNames('euiInlineEdit', className);
const euiTheme = useEuiTheme();
+
+ const styles = euiInlineEditFormStyles(euiTheme);
+ const readOnlyStyles = [
+ styles.euiInlineEditButton,
+ isReadOnly && styles.isReadOnly,
+ ];
+
const { controlHeight, controlCompressedHeight } = euiFormVariables(euiTheme);
const loadingSkeletonSize = sizes.compressed
? controlCompressedHeight
@@ -195,6 +209,13 @@ export const EuiInlineEditForm: FunctionComponent = ({
}
};
+ // If the state of isReadOnly changes while in edit mode, switch back to read mode
+ useEffect(() => {
+ if (isReadOnly) {
+ setIsEditing(false);
+ }
+ }, [isReadOnly]);
+
const editModeForm = (
@@ -228,11 +249,14 @@ export const EuiInlineEditForm: FunctionComponent = ({
)}
/>
+
-
+ {!isReadOnly && (
+
+ )}
@@ -296,12 +320,14 @@ export const EuiInlineEditForm: FunctionComponent = ({
<>
{
expect(container.firstChild).toMatchSnapshot();
});
+ test('isReadOnly', () => {
+ const { container, getByTestSubject } = render(
+
+ );
+
+ expect(container.firstChild).toMatchSnapshot();
+
+ expect(getByTestSubject('euiInlineReadModeButton')).toHaveAttribute(
+ 'role',
+ 'paragraph'
+ );
+ });
+
describe('text sizes', () => {
// Remove 'relative' from text sizes available for EuiInlineEditText
const availableTextSizes = TEXT_SIZES.filter((size) => size !== 'relative');
diff --git a/src/components/inline_edit/inline_edit_text.tsx b/src/components/inline_edit/inline_edit_text.tsx
index 49921fd6d83..8015b7ac141 100644
--- a/src/components/inline_edit/inline_edit_text.tsx
+++ b/src/components/inline_edit/inline_edit_text.tsx
@@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
-import React, { FunctionComponent } from 'react';
+import React, { useMemo, FunctionComponent } from 'react';
import classNames from 'classnames';
import { EuiText, EuiTextProps } from '../text';
import {
@@ -34,10 +34,11 @@ export const EuiInlineEditText: FunctionComponent = ({
defaultValue,
inputAriaLabel,
startWithEditOpen,
- readModeProps,
+ readModeProps: _readModeProps,
editModeProps,
isLoading,
isInvalid,
+ isReadOnly,
...rest
}) => {
const classes = classNames('euiInlineEditText', className);
@@ -49,6 +50,15 @@ export const EuiInlineEditText: FunctionComponent = ({
const isSmallSize = ['xs', 's'].includes(size);
const sizes = isSmallSize ? SMALL_SIZE_FORM : MEDIUM_SIZE_FORM;
+ const readModeProps = useMemo(() => {
+ if (!isReadOnly) return _readModeProps;
+
+ return {
+ ..._readModeProps,
+ role: 'paragraph',
+ };
+ }, [_readModeProps, isReadOnly]);
+
const formProps = {
sizes,
defaultValue,
@@ -58,6 +68,7 @@ export const EuiInlineEditText: FunctionComponent = ({
editModeProps,
isLoading,
isInvalid,
+ isReadOnly,
};
return (
diff --git a/src/components/inline_edit/inline_edit_title.test.tsx b/src/components/inline_edit/inline_edit_title.test.tsx
index 84363d4fd11..6de83071e6c 100644
--- a/src/components/inline_edit/inline_edit_title.test.tsx
+++ b/src/components/inline_edit/inline_edit_title.test.tsx
@@ -39,6 +39,23 @@ describe('EuiInlineEditTitle', () => {
expect(container.querySelector('h3')).toBeTruthy();
});
+ test('isReadOnly', () => {
+ const { container, getByTestSubject } = render(
+
+ );
+
+ expect(container.firstChild).toMatchSnapshot();
+
+ expect(getByTestSubject('euiInlineReadModeButton')).toHaveAttribute(
+ 'role',
+ 'heading'
+ );
+ expect(getByTestSubject('euiInlineReadModeButton')).toHaveAttribute(
+ 'aria-level',
+ '1'
+ );
+ });
+
describe('title sizes', () => {
TITLE_SIZES.forEach((size) => {
it(`renders size ${size}`, () => {
diff --git a/src/components/inline_edit/inline_edit_title.tsx b/src/components/inline_edit/inline_edit_title.tsx
index 6f9d3d0b1d4..451cd1a4697 100644
--- a/src/components/inline_edit/inline_edit_title.tsx
+++ b/src/components/inline_edit/inline_edit_title.tsx
@@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
-import React, { FunctionComponent } from 'react';
+import React, { useMemo, FunctionComponent } from 'react';
import classNames from 'classnames';
import { EuiTitle, EuiTitleSize } from '../title';
import {
@@ -41,10 +41,11 @@ export const EuiInlineEditTitle: FunctionComponent = ({
defaultValue,
inputAriaLabel,
startWithEditOpen,
- readModeProps,
+ readModeProps: _readModeProps,
editModeProps,
isLoading,
isInvalid,
+ isReadOnly,
...rest
}) => {
const classes = classNames('euiInlineEditTitle', className);
@@ -58,6 +59,22 @@ export const EuiInlineEditTitle: FunctionComponent = ({
const isSmallSize = ['xxxs', 'xxs', 'xs', 's'].includes(size);
const sizes = isSmallSize ? SMALL_SIZE_FORM : MEDIUM_SIZE_FORM;
+ const readModeProps = useMemo(() => {
+ if (!isReadOnly) return _readModeProps;
+
+ const headingNumber = Number(heading.substring(1));
+ return headingNumber
+ ? {
+ ..._readModeProps,
+ role: 'heading',
+ 'aria-level': headingNumber,
+ }
+ : {
+ ..._readModeProps,
+ role: 'paragraph',
+ };
+ }, [_readModeProps, isReadOnly, heading]);
+
const formProps = {
sizes,
defaultValue,
@@ -67,6 +84,7 @@ export const EuiInlineEditTitle: FunctionComponent = ({
editModeProps,
isLoading,
isInvalid,
+ isReadOnly,
};
return (
From 83d2cd3fdcf7e958049825d6e973bb31fa6bd7d1 Mon Sep 17 00:00:00 2001
From: Constance Chen
Date: Tue, 23 May 2023 14:03:41 -0700
Subject: [PATCH 16/23] Snapshots
---
.../inline_edit/__snapshots__/inline_edit_form.test.tsx.snap | 2 +-
.../inline_edit/__snapshots__/inline_edit_text.test.tsx.snap | 2 +-
.../inline_edit/__snapshots__/inline_edit_title.test.tsx.snap | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap
index 767fb2a97a4..1cb43f93a8d 100644
--- a/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap
+++ b/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap
@@ -668,7 +668,7 @@ exports[`EuiInlineEditForm Read Mode isReadOnly 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
index dd5d5976f1f..c3e7dcba701 100644
--- a/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
+++ b/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
@@ -30,7 +30,7 @@ exports[`EuiInlineEditText isReadOnly 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
index 1def24c3dfc..393e8d316f1 100644
--- a/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
+++ b/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
@@ -31,7 +31,7 @@ exports[`EuiInlineEditTitle isReadOnly 1`] = `
hidden=""
id="inlineEdit_generated-id"
>
- Click this button to edit this text inline.
+ Click to edit this text inline.
`;
From cee0519078e0c2cb072c5ce51ad2f28161f8a270 Mon Sep 17 00:00:00 2001
From: Cee Chen <549407+cee-chen@users.noreply.github.com>
Date: Wed, 24 May 2023 18:00:58 -0700
Subject: [PATCH 17/23] [EuiInlineEdit] Final screen reader / a11y polish pass
(#6805)
* Fix conditional readonly aria-describedby
- it was wrapped around the wrong SR text
* Prevent double heading roles when readonly
- leave role as undefined/unset otherwise, as `span` elements should not have a `heading` role
* (hopefully) Fix enter screen reader behavior
* Fix VO announcing EuiInlineEditText as `clickable` in read only mode
* Revert "Fix VO announcing EuiInlineEditText as `clickable` in read only mode"
This reverts commit 0f483bd24dc68d5342c7aab1c3acd83cbd93d982.
* NVDA browser mode fix
---
.../inline_edit_form.test.tsx.snap | 4 +---
.../inline_edit_text.test.tsx.snap | 4 +---
.../inline_edit_title.test.tsx.snap | 5 ++--
.../inline_edit/inline_edit_form.tsx | 23 ++++++++++---------
.../inline_edit/inline_edit_title.tsx | 4 +++-
5 files changed, 19 insertions(+), 21 deletions(-)
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap
index 1cb43f93a8d..4e8db2e6eb0 100644
--- a/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap
+++ b/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap
@@ -667,9 +667,7 @@ exports[`EuiInlineEditForm Read Mode isReadOnly 1`] = `
- Click to edit this text inline.
-
+ />
`;
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
index c3e7dcba701..c5d30da1fe7 100644
--- a/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
+++ b/src/components/inline_edit/__snapshots__/inline_edit_text.test.tsx.snap
@@ -29,9 +29,7 @@ exports[`EuiInlineEditText isReadOnly 1`] = `
- Click to edit this text inline.
-
+ />
`;
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
index 393e8d316f1..1db0a616d9a 100644
--- a/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
+++ b/src/components/inline_edit/__snapshots__/inline_edit_title.test.tsx.snap
@@ -21,6 +21,7 @@ exports[`EuiInlineEditTitle isReadOnly 1`] = `
>
Hello World!
@@ -30,9 +31,7 @@ exports[`EuiInlineEditTitle isReadOnly 1`] = `
- Click to edit this text inline.
-
+ />
`;
diff --git a/src/components/inline_edit/inline_edit_form.tsx b/src/components/inline_edit/inline_edit_form.tsx
index 9806fab5d15..b0df19e44e9 100644
--- a/src/components/inline_edit/inline_edit_form.tsx
+++ b/src/components/inline_edit/inline_edit_form.tsx
@@ -201,9 +201,11 @@ export const EuiInlineEditForm: FunctionComponent = ({
const editModeInputOnKeyDown = (event: KeyboardEvent) => {
switch (event.key) {
case keys.ENTER:
+ event.preventDefault(); // Enter keypresses will not proceed otherwise on webkit browsers & screen readers
saveInlineEditValue();
break;
case keys.ESCAPE:
+ event.preventDefault(); // NVDA will trigger Browse mode otherwise
cancelInlineEdit();
break;
}
@@ -249,14 +251,11 @@ export const EuiInlineEditForm: FunctionComponent = ({
)}
/>
-
- {!isReadOnly && (
-
- )}
+
@@ -342,10 +341,12 @@ export const EuiInlineEditForm: FunctionComponent = ({
{children(readModeValue)}
-
+ {!isReadOnly && (
+
+ )}
>
);
diff --git a/src/components/inline_edit/inline_edit_title.tsx b/src/components/inline_edit/inline_edit_title.tsx
index 451cd1a4697..ffa1b7ea077 100644
--- a/src/components/inline_edit/inline_edit_title.tsx
+++ b/src/components/inline_edit/inline_edit_title.tsx
@@ -96,7 +96,9 @@ export const EuiInlineEditTitle: FunctionComponent = ({
>
{(titleReadModeValue) => (
- {titleReadModeValue}
+
+ {titleReadModeValue}
+
)}
From 98a264add84f77d7417b5f3548654d41e2c8f445 Mon Sep 17 00:00:00 2001
From: Cee Chen <549407+cee-chen@users.noreply.github.com>
Date: Thu, 25 May 2023 09:45:45 -0700
Subject: [PATCH 18/23] Revert Escape preventDefault
- not actually doing anything :wompwomp:
---
src/components/inline_edit/inline_edit_form.tsx | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/components/inline_edit/inline_edit_form.tsx b/src/components/inline_edit/inline_edit_form.tsx
index b0df19e44e9..d9f812d9742 100644
--- a/src/components/inline_edit/inline_edit_form.tsx
+++ b/src/components/inline_edit/inline_edit_form.tsx
@@ -205,7 +205,6 @@ export const EuiInlineEditForm: FunctionComponent = ({
saveInlineEditValue();
break;
case keys.ESCAPE:
- event.preventDefault(); // NVDA will trigger Browse mode otherwise
cancelInlineEdit();
break;
}
From 08bfd424cea6ab59134d2c2d71788da041a8376e Mon Sep 17 00:00:00 2001
From: Constance Chen
Date: Thu, 25 May 2023 10:30:19 -0700
Subject: [PATCH 19/23] [misc UX enhancement]
Set `readOnly` on input / prevent further user editing when saving & is in `isLoading` state
- docs only improvement as I don't want to tie the two props together (slightly opinionated), but hopefully consumers copy it
---
src-docs/src/views/inline_edit/inline_edit_validation.tsx | 1 +
1 file changed, 1 insertion(+)
diff --git a/src-docs/src/views/inline_edit/inline_edit_validation.tsx b/src-docs/src/views/inline_edit/inline_edit_validation.tsx
index 4c178eb9440..f3977e7da3c 100644
--- a/src-docs/src/views/inline_edit/inline_edit_validation.tsx
+++ b/src-docs/src/views/inline_edit/inline_edit_validation.tsx
@@ -25,6 +25,7 @@ export default () => {
editModeProps={{
formRowProps: { error: errors },
cancelButtonProps: { onClick: () => setErrors([]) },
+ inputProps: { readOnly: isLoading },
}}
isInvalid={isInvalid}
isLoading={isLoading}
From 52ef4696bf3f7bb6ec8b3485934382898f33945f Mon Sep 17 00:00:00 2001
From: Constance Chen
Date: Thu, 25 May 2023 10:32:53 -0700
Subject: [PATCH 20/23] [mobile] Fix edit mode buttons wrapping to next line in
small screens
---
.../__snapshots__/inline_edit_form.test.tsx.snap | 14 +++++++-------
src/components/inline_edit/inline_edit_form.tsx | 2 +-
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap
index 4e8db2e6eb0..acc40d34c0e 100644
--- a/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap
+++ b/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap
@@ -5,7 +5,7 @@ exports[`EuiInlineEditForm Edit Mode editModeProps.cancelButtonProps 1`] = `
class="euiInlineEdit testClass1 testClass2"
>
- Use the isReadOnly prop to lock{' '}
- EuiInlineEdit in read mode and display the text
- value. This does not affect the input form control in edit mode.
-
- >
+
+ Use the isReadOnly prop to lock{' '}
+ EuiInlineEdit in read mode and display the text
+ value. This does not affect the input form control in edit mode.
+
),
source: [
{
diff --git a/src-docs/src/views/inline_edit/inline_edit_start_in_edit.tsx b/src-docs/src/views/inline_edit/inline_edit_start_in_edit.tsx
new file mode 100644
index 00000000000..0c2ed4bdf2a
--- /dev/null
+++ b/src-docs/src/views/inline_edit/inline_edit_start_in_edit.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+
+import {
+ EuiInlineEditText,
+ EuiInlineEditTitle,
+ EuiSpacer,
+} from '../../../../src';
+
+export default () => {
+ return (
+ <>
+
+
+
+
+
+ >
+ );
+};
From 704d3727915fecf76c803fbd229cfa50238c1837 Mon Sep 17 00:00:00 2001
From: Constance Chen
Date: Thu, 25 May 2023 11:17:17 -0700
Subject: [PATCH 23/23] [misc cleanup/nits]
- rename exported form styles more accurately to their usage
- test name casing, + don't use camelCasing for non props
---
.../inline_edit_form.test.tsx.snap | 30 +++++++++----------
.../inline_edit_text.test.tsx.snap | 10 +++----
.../inline_edit_title.test.tsx.snap | 16 +++++-----
.../inline_edit/inline_edit_form.styles.ts | 4 +--
.../inline_edit/inline_edit_form.test.tsx | 20 ++++++-------
.../inline_edit/inline_edit_form.tsx | 12 ++++----
6 files changed, 46 insertions(+), 46 deletions(-)
diff --git a/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap
index acc40d34c0e..16d2621d462 100644
--- a/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap
+++ b/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`EuiInlineEditForm Edit Mode editModeProps.cancelButtonProps 1`] = `
+exports[`EuiInlineEditForm edit mode editModeProps.cancelButtonProps 1`] = `