Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EuiInlineEdit] (POC Review) Create Component Directory and Base Functionality #6533

Conversation

breehall
Copy link
Contributor

@breehall breehall commented Jan 18, 2023

Relates to #3928

Note to Reviewer

  • Please feel free to fully mark this PR! I'd like to solidify the base of this component before adding in the code for props from my other branch. I'm open to any changes to the code and design for this. I'm purposely leaving this PR in draft for the first round of reviews because there will likely need to be changes before merging this into the feature branch.

  • Things I'm looking for:

    • [Code] Does this structure make sense? It's intended to be flexible in case we want to add more editView components in the future, but I partially believe it could be a lot cleaner if I just focus on the three intended components
    • [Design] The original design used he empty buttons for readView. Is this still OK?
    • [Accessibility] Are there any accessibility concerns with this component?
  • In your opinion, does a multiple select combo box make sense for this component? Should this be a single select combo box if anything?

Summary

(Associated with #3928)

Spec Doc: EuiInlineEdit Spec Doc

This is the first PR for the new EuiInlineEdit component. This PR creates the required directories for the component and the component docs. The EuiInlineEdit component accepts three form controls (EuiFieldText, EuiTextarea, and EuiComboBox) and allows users to toggle between two states to view and edit the controls.

The base functionality for EuiInlineEdit includes:

  • Toggling between readView and editView for the three accepted form controls
    • readView should display an EuiEmptyButton with text (for EuiFieldText and EuiTextarea) or badges (for EuiComboBox) with the saved or default text and selections
    • editView should display the desired form control
  • Saving text and selections using a save button when the component is in editView
    • Basic validation that does not allow the form controls to be saved when they contain no text / selections. If they are empty and a save is attempted, the component returns to readView with the text / selections prior to editing
  • Canceling and not saving text and selections using a cancel button when the component is in editView

QA

  • Saving new text within EuiInlineEdit FieldText and TextArea
    Click on the helloWorldmessage or the cupcake ipsum message, change the text inside of the text box, use the submit button to save results. The new message should persist.
ED29CA17-C3BD-4D50-8A34-C175089B0E6D_2_0_a.mov
  • Saving new text within EuiInlineEdit ComboBox
    Click on the badges to open an EuiComboBox. Select different options with the dropdown to add them to your list. Use the submit button to save results. A badge for each option selected should appear.
3BA244C8-9BB1-4862-96B2-611B2A6CB4C2_2_0_a.mov
  • Cancelling an action withinEuiInlineEdit FieldText and TextArea
    Click on the helloWorldmessage or the cupcake ipsum message, change the text inside of the text box, use the cancel button. The new message should not persist.

  • Saving new text within EuiInlineEdit ComboBox
    Click on the badges to open an EuiComboBox. Select different options with the dropdown to add them to your list. Use the cancel button to save results. The badges and their values should not change.

General checklist

  • Checked in both light and dark modes
  • Checked in mobile
  • Checked in Chrome, Safari, Edge, and Firefox
  • Props have proper autodocs and playground toggles
  • Added documentation
  • Checked Code Sandbox works for any docs examples
  • Added or updated jest and cypress tests
  • Checked for breaking changes and labeled appropriately
  • Checked for accessibility including keyboard-only and screenreader modes
  • Updated the Figma library counterpart
  • A changelog entry exists and is marked appropriately

…ase component that accepts the EuiText, EuiTextarea, and EuiComboBox controls and provides both read and edit modes.
…it. WithDefaultProps checks to ensure that the editViewTypeProps matches the editViewType being passed in. For exmaple, if the editViewType is EuiFieldText, WithDefaultProps ensure that editViewTypeProps matches the shape of the props for EuiFieldText.
…ontrols from being saved when there is no text or combo box selections.
…when a save was attempted with no selections
@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_6533/

@breehall breehall changed the title [EuiInlineEdit] Create Component Directory and Base Functionality [EuiInlineEdit] (POC Review) Create Component Directory and Base Functionality Jan 26, 2023
@breehall breehall requested a review from 1Copenut January 26, 2023 17:06
Comment on lines +21 to +23
| typeof EuiTextArea
| typeof EuiFieldText
| typeof EuiComboBox;
Copy link
Contributor

Choose a reason for hiding this comment

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

Quick FYI - typeof will get unspeakably spicy/gnarly if any of these components are class components that need to be wrapped in the withEuiTheme HOC during Emotion conversions.

I'm particularly leery of EuiComboBox (complex class component, unlikely to be converted to function). Do we know for sure that inline editing badges is necessary / desired by any specific team? Maybe I'm just confused by why UX-wise, a designer wouldn't use a EuiComboBox in the first place? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm particularly leery of EuiComboBox

So am I and it was actually one of the most tricky pieces of this so far. Adding in ComboBox was a "blue sky" idea that came directly from the Atlassian design system as inspo. I never got a real use case for where this would be useful. I talked with Jason not too long ago about moving forward with the text options for now if there's no practical need for it at this very moment.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would strongly strongly push for shipping initially without EuiComboBox and just text/textarea/number to start. I'm not seeing anything in the original GH issue/discussion or the spec doc that shows selection anywhere, so I really don't think this needs to be something we try to support without a strong use case or team asking for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Quick FYI - typeof will get unspeakably spicy/gnarly if any of these components are class components that need to be wrapped in the withEuiTheme HOC during Emotion conversions.

By chance, do we have another component I can use as a guide for this? Or do we have a pattern in place that I can reference instead of using typeof?

Copy link
Contributor

Choose a reason for hiding this comment

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

EuiDualRange and EuiAccordion are two class components wrapped with withEuiTheme that you can try using off the top of my head. Here's my most recent comment with more context as to how we know the typing starts getting Very Bad: #6539 (comment)

/**
* Props for the form control created by editViewType
*/
editViewTypeProps?: WithDefaultPropsApplied<T>;
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm struggling to understand the type usecase of Defaultize<> here - is there any specific reason why React.ComponentProps<T> doesn't just work as-is? We're not really expecting consumers to pass in any props that are defaults, just props to override defaults, right?

</>
);

const comboBoxReadViewElement = (
Copy link
Contributor

Choose a reason for hiding this comment

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

[attaching to a semi random line for threading]

At first glance through this file, the code feels elegant and easy to read/understand for just the text implementation. Adding the combobox into the mix makes it significantly harder to follow. If we're going to move ahead with including EuiComboBox, I would strongly suggest making it its own separate component, e.g. InlineEditSelect instead to help make code less convoluted/branching.

id={inlineTextEditInputId}
value={textEditViewValue}
onChange={editTextViewOnChange}
{...(rest as any)}
Copy link
Contributor

Choose a reason for hiding this comment

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

UX/accessibility note - can we try adding an autoFocus to the props here so that keyboard focus automatically transfers into the editable field?

Copy link
Contributor

Choose a reason for hiding this comment

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

+1. autoFocus for the input will cause screen readers to announce the accessible label immediately, and help users understand what the button click changed in UI.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd also be in favor of setting focus back on the button when users confirm or cancel their edit. That's taking a page out of the modal dialog playbook, but feels like the right UX for keyboard and screen reader navigation.

Comment on lines +63 to +65
//@ts-ignore TypeScript sad :(
editViewType = EuiFieldText,
editViewTypeProps,
Copy link
Contributor

@cee-chen cee-chen Jan 26, 2023

Choose a reason for hiding this comment

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

[just writing this out as a stream of consciousness thought, this is not a change request]

Just curious - if we do want to make the decision to make this a more restricted component in terms of types of inputs/fields allowed, why not do something like this:

type: 'text' | 'textarea' | 'number', // use a switch statement to determine input based on this type
inputProps, // whatever is passed to the input/field component

I kind of see the goal here of making this a very 'extensible' component that allows potentially wildcard kinds of inputs/fields... but I don't fully see the advantage of someone being able to (e.g.) pass a raw <input> - EUI is already an opinionated design system with styling OOTB, not a lower level library 🤷

FWIW, the main disadvantage of my proposal is that conditional inputProps typing based on the type prop becomes a bit of a headache / starts getting into ExclusiveUnion land 😅

Copy link
Contributor

Choose a reason for hiding this comment

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

After having written that all out, I actually think I've managed to convince myself against my own train of thought. I could go either way, but I do like the current approach that gives consumers the ability to pass in whatever insane component they want as a more permissive escape hatch. Leaving this thread up though in case other folks have more thoughts!

@JasonStoltz
Copy link
Member

In your opinion, does a multiple select combo box make sense for this component? Should this be a single select combo box if anything?

Quick temperature check from the rest of the team. Would it simplify things to limit this just to text, and drop support for a combo box? At least, for a first iteration of this component?

@elizabetdev
Copy link
Contributor

It's looking good @breehall!

I agree with @cee-chen

I would strongly strongly push for shipping initially without EuiComboBox

I think we should just focus on EuiInlineEdit Text and TextArea for now.

I created a new Figma project for the design, it is still a work in progress. I will need to go through some flows to see how the component will work: https://www.figma.com/file/v9DYJMnt7ynEycyR8iYfhz/EuiInlineEdit?t=ZHot1OojvzVOc9hm-6.

But I have some initial questions related with the props. It accepts a defaultValue but this component is suppose to inline edit for example a title. So how can I make sure the defaultValue is styled as a title? Like in the following example of Observability -> Cases.

Screenshot 2023-01-27 at 15 51 02

Also one thing that concerns me on the current design is that there is no clue that the text is editable. For example, for the same example from Observability -> Cases let's say I didn't have that edit icon. How would I know that the title is editable? Just by hovering that title?

Metrics-inventory-Cases-Observability-Elastic

On the following example from enterprise search, let's say I would click the edit button and I would only want to allow inline edit the name. I would need to mouse hover all the fields to know what I can edit.

Credentials-App-Search-Elastic

I will continue going trough the design and explore some user flows. I will also talk with @MichaelMarcialis to try to understand his use cases for this component (#3928 (comment)).

Then we can have a zoom call and go through the flows.

Copy link
Contributor

@1Copenut 1Copenut left a comment

Choose a reason for hiding this comment

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

This is going to be an excellent addition to EUI @breehall! I left some first-impression a11y comments, trying to offer guidance than be prescriptive. Feel free to holler at me next week to keep testing as you add to the PR, or to discuss any feedback. Much appreciated!

id={inlineTextEditInputId}
value={textEditViewValue}
onChange={editTextViewOnChange}
{...(rest as any)}
Copy link
Contributor

Choose a reason for hiding this comment

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

+1. autoFocus for the input will cause screen readers to announce the accessible label immediately, and help users understand what the button click changed in UI.

Comment on lines +60 to +62
<h3>EuiInlineEdit - Text</h3>
<EuiInlineEdit
editViewType={EuiFieldText}
Copy link
Contributor

Choose a reason for hiding this comment

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

When I started reviewing these with VoiceOver, I noticed it was reading back the input (or textarea) text but not the heading I presumed was the visual / accessible label. I think you could go a couple of directions here:

  1. Add documentation encouraging users to set unique IDs on each heading and pass that ID into an aria-labelledby prop in the EuiInlineEdit when it's in edit state.
  2. Make label a required prop so it adds a visual and accessible label to the input. This gets in the way of the heading text in your examples.
  3. Set a required aria-label prop on the EuiInlineEdit component that gets passed to the input or textarea. This is my least favorite option.

This change feels like it could affect visual and structural order, so happy to discuss it more next week and look for a good working solution.

Comment on lines +123 to +132
<EuiButtonIcon
iconType="check"
aria-label={confirmButtonAriaLabel || 'confirm'}
onClick={
EditViewType === EuiComboBox
? saveComboBoxEditValue
: saveTextEditValue
} // this should be a conditional to switch between text and combobox saves
/>
<EuiButtonIcon
Copy link
Contributor

Choose a reason for hiding this comment

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

These are good aria-label suggestions with fallbacks. I'm considering if we can build on the announcement by adding an aria-describedby that references either a label ID or a heading ID (see my previous comment about the accessible labels when in isInEdit state.

This would cause the button to read out "Confirm, button. pause EuiInlineEdit - Text". It adds a level of reinforcement what the user is editing or canceling. Not as necessary or useful on a text input, but the benefit increases greatly when users are editing a textarea and it's potentially been a minute since they heard what the label / group name was.

id={inlineTextEditInputId}
value={textEditViewValue}
onChange={editTextViewOnChange}
{...(rest as any)}
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd also be in favor of setting focus back on the button when users confirm or cancel their edit. That's taking a page out of the modal dialog playbook, but feels like the right UX for keyboard and screen reader navigation.

@breehall
Copy link
Contributor Author

POC Review Action Plan

Spec Changes

  • TL;DR - ComboBox is out...for now
    In an effort to simplify this component and address inline edit use cases that have been identified, the option to render editView as an EuiComboBox will be removed for the time being. As suggested here, if we decide to allow the Combo Box control in the future it should likely be its own component.

  • Add autoFocus prop to editView controls
    For UX and accessibility, the autoFocus prop will be added to the editView text control when the state change occurs.
    (Mentioned here)

Accessibility Updates

  • Reset focus back on the empty button when a user confirms on cancels their changes from editView
  • Create a better pattern that will allow screen readers to read the label for the input and not just assume it's a visual label. There are great options mentioned here

Display as a Title
In Elizabet's research, she found instances where a title is editable. This should be an option, like a display prop, that allows consumers to still use EuiFieldText for the editView, but show the text in a title in readView. That research can be found here

@breehall breehall deleted the branch elastic:feature/inline-edit February 13, 2023 21:14
@breehall breehall closed this Feb 13, 2023
@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_6533/

@breehall breehall deleted the inline-edit/base-structure branch September 18, 2023 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants