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

feat(dropdown): SingleSelect with search filter #903

Merged
merged 11 commits into from Jun 17, 2020

Conversation

jandrade
Copy link
Member

@jandrade jandrade commented May 21, 2020

Summary

Similar to the MultiSelect component (#479), these changes introduce the isFilterable prop to <SingleSelect />.

This allows us to filter options inside the single select component.

Test plan

  1. Open https://5e1bf4b385e3fb0020b7073c-vojuppvbfz.chromatic.com/?path=/story/dropdown-singleselect--custom-styles
  2. Verify that the search input is present and that we can filter options by query.

single-filter

@jandrade jandrade requested a review from a team May 21, 2020 00:34
@codecov
Copy link

codecov bot commented May 21, 2020

Codecov Report

Merging #903 into master will increase coverage by 0.02%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #903      +/-   ##
==========================================
+ Coverage   96.16%   96.19%   +0.02%     
==========================================
  Files         139      139              
  Lines        2373     2391      +18     
  Branches      454      457       +3     
==========================================
+ Hits         2282     2300      +18     
  Misses         85       85              
  Partials        6        6              
Impacted Files Coverage Δ
.../wonder-blocks-dropdown/components/multi-select.js 96.73% <100.00%> (+0.03%) ⬆️
...wonder-blocks-dropdown/components/single-select.js 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 889c44a...ed62431. Read the comment docs.

Copy link
Member

@kevinbarabash kevinbarabash left a comment

Choose a reason for hiding this comment

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

I'm excited that you're back porting this functionality from webapp to wonder-blocks. At a high-level I think we need to decide if we want this functionality in all of our dropdown types. If we do, it shouldn't be too much work to push the logic down into dropdown-core.js.

Requesting the following changes:

  • expand the testing to verify the interaction of selection and fitlering
  • fix what appears to be a missing return in getMenuItems
  • enable screenshotting on a story with the dropdown open on page load (if possible)

There are some other nits in the comments which I leave to your discretion.

Comment on lines 438 to 439
// Assert
expect(wrapper.find(IconButton).exists()).toBe(true);
Copy link
Member

Choose a reason for hiding this comment

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

Asserting on the props of SearchTextInput would be more robust since what SearchTextInput renders may change. Also, it's possible that the OptionItems might change in the future to render an IconButton.

Copy link
Member Author

@jandrade jandrade May 26, 2020

Choose a reason for hiding this comment

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

Now that you mention it, I think it makes more sense to move this test inside search-text-input.test.js. The SingleSelect shouldn't worry about these specific details, and we are checking if the search input is present in the previous test.

Comment on lines 492 to 493
// Arrange
// Arrange
Copy link
Member

Choose a reason for hiding this comment

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

nit

// Assert
expect(wrapper).toHaveState({searchText: ""});
});
});
Copy link
Member

Choose a reason for hiding this comment

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

It would be good to have some tests that cover the interaction between filtering and selection. If the selected item doesn't match the search filter doesn't it still appear? If so, where does it appear? If not, how doesn't navigation from the selected item work?

Copy link
Member

Choose a reason for hiding this comment

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

@jandrade friendly ping.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh I forgot this comment. Thanks for the reminder.

},
});

export const customStyles = () => <SingleSelectWithCustomStyles />;
Copy link
Member

Choose a reason for hiding this comment

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

The name of this story should have something about filter/search in the title.

Seeing, this I just realized that if we allow hooks in wonder-block at least, we wouldn't need a class component here.

Aside: it would be nice if we could reuse certain stories in the docs instead of having to duplicate the same code in two places.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good call, I'll change that. About hooks, I thought about that, but I'd prefer to keep using classes as examples here in case folks using Webapp can refer to these snippets in a way they can directly use in Webapp.

I'll gladly replace these examples once we fully enable hooks in Webapp.

Re: aside: I'll be reusing those stories in my next PR (Storybook Docs)... wait for it :)

import * as React from "react";
import {shallow} from "enzyme";

import SearchTextInput from "../search-text-input.js";
Copy link
Member

Choose a reason for hiding this comment

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

naming suggestion: SearchField. You using this terminology elsewhere in this PR, but beyond that I think it generalizes better, e.g.

  • TextField
  • PasswordField
  • SearchField

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree, but I'd prefer to keep it that way to avoid modifying the functionality we already have in place for MultiSelect. I wanted to touch as less as I could here to avoid doing any unnecessary refactors on the original implementation. As you mentioned I'll add a new ticket/TODO to work on this in the future.

const wrapper = shallow(
<SearchTextInput
searchText="query"
testId="search-text-input"
Copy link
Member

Choose a reason for hiding this comment

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

nit: is the testId necessary?

describe("SearchTextInput", () => {
it("text input container should be focused when focusing on the input", () => {
// Arrange
const wrapper = shallow(
Copy link
Member

Choose a reason for hiding this comment

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

Nice use of shallow. 🎉

@@ -669,7 +669,7 @@ describe("wonder-blocks-dropdown", () => {
darkBackgroundWrapper: {
flexDirection: "row",
justifyContent: "flex-end",
backgroundColor: Color.darkBlue,
background: Color.darkBlue,
Copy link
Member

Choose a reason for hiding this comment

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

Why the switch to background?

Copy link
Member Author

Choose a reason for hiding this comment

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

For some reason, the tests were throwing a warning about using background and backgroundColor, but I don't remember what was, and now I don't see it, so I 'll revert back to bgColor.

Comment on lines +120 to +124
/**
* The text input to filter the items by their label. Defaults to an empty
* string.
*/
searchText: string,
Copy link
Member

Choose a reason for hiding this comment

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

Is this something that we'll want to have on MultiSelect and ActionMenu as well? If so, it might make sense to push some of the logic you added to this component into dropdown-core.js.

Copy link
Member

Choose a reason for hiding this comment

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

I see now that searchText is already part of DropdownCore.

* When this is true, the dropdown body shows a search text input at the
* top. The items will be filtered by the input.
*/
isFilterable?: boolean,
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we should allow the filter algorithm to be overridden?

There are some really handy filtering rules besides "contains case insensitive match" such as the filtering rules that VSCode has for finding files, like matching starts of words. For example, ABC would match "Always Be Closing".

Copy link
Member

Choose a reason for hiding this comment

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

@lillialexis wrote a pretty awesome smart matching algorithm for our github CLI tools would be nice to use.

Copy link
Member

Choose a reason for hiding this comment

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

@@ -13,7 +13,7 @@ jobs:
- name: Use Node.js 12.x
uses: actions/setup-node@v1
with:
node-version: 12.x
node-version: 12.16.x
Copy link
Member Author

Choose a reason for hiding this comment

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

I changed this b/c storybook/chromatic was failing to build: storybookjs/storybook#10477 (comment)

Copy link
Member

Choose a reason for hiding this comment

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

Hopefully they'll fix the underlying issue in the future.

@@ -35,5 +35,5 @@ jobs:
- uses: chromaui/action@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
appCode: ${{ secrets.CHROMATIC_APP_CODE }}
projectToken: ${{ secrets.CHROMATIC_APP_CODE }}
Copy link
Member Author

Choose a reason for hiding this comment

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

Changed it to remove a Chromatic warning.

Copy link
Member

@kevinbarabash kevinbarabash left a comment

Choose a reason for hiding this comment

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

LGTM. There are maybe a few additional tests that could be added, see my friendly ping, but nothing blocking. Thanks for adding filtering to SingleSelect. ❤️

@jandrade jandrade merged commit 28063d8 into master Jun 17, 2020
@jandrade jandrade deleted the dropdown-single-filter branch June 17, 2020 19:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants