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

Clear methods to work with custom components #54

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

AmirTugi
Copy link

@AmirTugi AmirTugi commented Jan 9, 2021

  • Fixes clear* methods don't allow for sufficient customization #53.
  • Assuming custom components will use components from react-select - Change the clearFirst and clearAll methods to work with the specific class names (${classNamePrefix}__multi-value_remove and ${classNamePrefix}__clear-indicator).
  • Add tests to support the custom components clear.

Important! this PR is blocked until we get answer/solution about those specific classes being added only if the user defined classNamePrefix prop (here).

Copy link
Owner

@romgain romgain left a comment

Choose a reason for hiding this comment

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

Thank you very much @AmirTugi !

Looks like this needs a bit more work to keep backwards compatibility and to get the CI to pass, but that’s a good idea 👍

@@ -232,7 +232,7 @@ describe("The select event helpers", () => {
<Select {...defaultProps} defaultValue={OPTIONS[0]} isClearable />
);
expect(form).toHaveFormValues({ food: "chocolate" });
await selectEvent.clearFirst(input);
await selectEvent.clearAll(input);
Copy link
Owner

Choose a reason for hiding this comment

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

Can you revert this change? This test case tests the clearFirst utility.

@@ -241,7 +241,7 @@ describe("The select event helpers", () => {
<Select {...defaultProps} defaultValue={OPTIONS[0]} isClearable />
);
expect(form).toHaveFormValues({ food: "chocolate" });
await selectEvent.clearFirst(input);
await selectEvent.clearAll(input);
Copy link
Owner

Choose a reason for hiding this comment

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

Same here, let’s leave the clearFirst

const clearButton = container.querySelector('svg[aria-hidden="true"]')!;
// The "clear" button is constructed from the user-defined `${classNamePrefix}__multi-value__remove`.
// This is built from the internal util `cx` of react-select, so we take advantage of the attribute selector here.
const clearButton = container.querySelector('[class*="multi-value__remove"]')!;
Copy link
Owner

Choose a reason for hiding this comment

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

We need to keep backwards compatibility with older react-select versions.

What would be the best way to achieve this?
Do we need to default to the svg selector of the new one doesn’t match anything?

@ebonow
Copy link

ebonow commented Jan 20, 2021

Greetings all,

I appreciate the work being done to support react-select and providing better testing tools. I wanted to stop by here to provide more clarification in regards to the ask, the issues, and a proposed solution.

First, @AmirTugi made a request for react-select to provide a default `classNamePrefix. This is not something that the react-select team feels is in the best interest of all of its users, especially those who choose not to pollute their DOM with extra class name attributes for the sake of providing DOM attribute selectors.

I believe this request was made with a misunderstanding of how the classNames and styles for react-select are generated. I have attempted to clarify this in the thread, but long story short, that bit is left to Emotion as the underlying CSS-in-JS solution. It should also be noted that those elements which return a className ending in the name of the related component are done via a label api which is fairly easy to implement.

I think it would be beneficial to have "labels" provided for the interactive components (dropdownIndicator, clearIndicator, multiValueClear) and wouldn't add any extra new classes to the DOM (just simply appending defined string names to the end).

This would produce something to the effect of:

<div aria-hidden="true" class="css-tlfecz-indicatorContainer">
  <svg height="20" width="20" viewBox="0 0 20 20" aria-hidden="true" focusable="false" class="css-6q0nyr-Svg-dropdownIndicator">
    <path d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"></path>
  </svg>
</div>

With a className of css-6q0nyr-Svg-dropdownIndicator, this would allow you to target the DOM:

const dropdownIndicator = selectEl.querySelector('class*=dropdownIndicator')

If this is a viable solution, we can have this considered as an addition to an already existing PR JedWatson/react-select#4342 which is being considered for next release.

@romgain
Copy link
Owner

romgain commented Jan 20, 2021

Hi @ebonow , this sounds great!
Thank you very much for looking into this!

@th3fallen
Copy link
Contributor

@AmirTugi could you try testing your custom components on version 5.4.0 of this, I'm curious if my update to how the container is found will resolve this too.

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.

clear* methods don't allow for sufficient customization
4 participants