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

Add showMoreLimit prop #245

Merged
merged 24 commits into from
Jul 25, 2022
Merged

Add showMoreLimit prop #245

merged 24 commits into from
Jul 25, 2022

Conversation

ElemelonWind
Copy link
Contributor

@ElemelonWind ElemelonWind commented Jul 19, 2022

Add a showMoreLimit prop to StandardFacet. When the number of options exceeds this limit, display only that many options, a searchable facets input, and a show more button. The show more button, when clicked displays all the options. If the number of options is less than the limit, show all the options and no search bar

J=SLAP-2252
TEST=auto

Added two new stories: one to show the prop at work, and the second to show what happens when the show more button is pressed

Note: Coveralls decreased by 0.3% because it doesn't count stories as test coverage

@coveralls
Copy link

coveralls commented Jul 19, 2022

Coverage Status

Coverage decreased (-0.1%) to 84.291% when pulling 34a9b68 on dev/standardfacets-showmorelimit into 21087c8 on main.

@ElemelonWind ElemelonWind marked this pull request as ready for review July 21, 2022 14:15
@ElemelonWind ElemelonWind requested a review from a team as a code owner July 21, 2022 14:15
tests/components/StandardFacets.stories.tsx Outdated Show resolved Hide resolved
src/components/FilterGroup.tsx Outdated Show resolved Hide resolved
const limited = filterOptions.length > showMoreLimit;
const [showAll, setShowAll] = useState<boolean>(!limited);

function toggleShowAll() {
Copy link
Contributor

Choose a reason for hiding this comment

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

At first I thought we might want to wrap this in a useCallback, if only for consistency, but after thinking about it more we can probably omit it.

Out of curiosity, if you use an arrow function instead like onClick={e => setShowAll(!showAll)} does a react-perf eslint rule complain? I was thinking that it might be better to use an arrow function and an eslint-ignore comment, just to be explicit here.

Since toggleShowAll is just passed into a regular button and not another component I don't think there's benefits of wrapping this in useCallback

@@ -104,7 +100,8 @@ export function FilterGroup({
/>
);
})}
{limited && <button className='text-blue-500 py-1 text-sm' onClick={toggleShowAll}>{showAll ? 'Show Less' : 'Show More'}</button>}
{/* eslint-disable-next-line react-perf/jsx-no-new-function-as-prop */}
{limited && <button className='text-primary py-1 text-sm' onClick={_e => setShowAll(!showAll)}>{showAll ? 'Show Less' : 'Show More'}</button>}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can this be multiple lines? You can also replace the _e with ()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not sure if I formatted it right lol, could you take a look?

@@ -85,7 +91,7 @@ export function FilterGroup({
{renderTitle()}
<CollapsibleSection className={cssClasses.optionsContainer}>
{searchable && <SearchInput className={cssClasses.searchInput} />}
{filterOptions.map(o => {
{filterOptions.slice(0, showAll ? filterOptions.length : showMoreLimit).map(o => {
Copy link
Contributor

@nmanu1 nmanu1 Jul 21, 2022

Choose a reason for hiding this comment

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

did you test if this works properly when typing in the search input? it seems like the search would only be performed on this slice of filter options instead of searching all of the options and then displaying the first few

typing in the search input should also change whether show more/less is displayed depending on how many options match the input text

@@ -94,6 +100,11 @@ export function FilterGroup({
/>
);
})}
{limited &&
/* eslint-disable-next-line react-perf/jsx-no-new-function-as-prop */
<button className='text-primary py-1 text-sm' onClick={() => setShowAll(!showAll)}>
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of using the eslint disable, can we extract the function and call it in onClick?

Copy link
Contributor

@oshi97 oshi97 Jul 22, 2022

Choose a reason for hiding this comment

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

I wanted to specifically use the eslint disable instead of using useCallback.

Extracting it to a function doesn't actually give it a stable reference, you have to use useCallback or pull the function out to the top level.
I'm fine with useCallback as well I just think it hurts performance a little because we don't actually need the memoization since this is going into a default button element and not another component (even then it's very arguable but we've been doing it everywhere so should be consistent for now and refactor everything later if we decide otherwise). But performance is not really a concern here! useCallback also sgtm

Copy link
Contributor

@alextaing alextaing Jul 22, 2022

Choose a reason for hiding this comment

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

ohhh I see-- I totally missed that comment earlier, that's fine we can totally leave it haha

Copy link
Contributor

Choose a reason for hiding this comment

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

@yen-tt @nmanu1 do you guys prefer useCallback here? I'm really 50/50 and it's probably not a decision worth stressing over but just wondering

Copy link
Contributor

Choose a reason for hiding this comment

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

I think I have a slight preference for not using useCallback here. just because it's not really needed and I'm in favor of not wrapping in useMemo/useCallback unless it adds some value

@@ -69,6 +72,9 @@ export function FilterGroup({
};
}, [customCssClasses]);

const limited = filterOptions.length > showMoreLimit;
Copy link
Contributor

@alextaing alextaing Jul 22, 2022

Choose a reason for hiding this comment

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

Super subjective, but since this is a boolean it might be a tad more legible for the future if it were called isLimited-- but it's tiny haha

@@ -94,6 +100,11 @@ export function FilterGroup({
/>
);
})}
{limited &&
/* eslint-disable-next-line react-perf/jsx-no-new-function-as-prop */
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's a little nicer if we indent everything after the && in this conditional (lines 104-107) and move the last brace to the next line

@ElemelonWind
Copy link
Contributor Author

I'll be removing the shouldRenderOption logic from CheckboxOption and putting it into CheckboxOptions after demos but wanted to push in case people had any feedback for the new internal component

{children}
</CollapsibleSection>
</FilterGroupProvider>
);
}

function CheckboxOptions({
filterOptions,
Copy link
Contributor

Choose a reason for hiding this comment

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

Do these parameters have type any if you don't specify a type?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should I make an interface for it?

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah

Copy link
Contributor

Choose a reason for hiding this comment

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

You could also specify it inline

Copy link
Contributor

Choose a reason for hiding this comment

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

like { myParam }: { myParam: string }


return (
<>
{filterOptions.filter(o => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this can just be filterOptions.filter(shouldRenderOption)

}) {
const searchUtilities = useSearchUtilities();
const { searchValue } = useFilterGroupContext();
const shouldRenderOption = useCallback((option: { displayName: string, value: unknown }) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

does this need a useCallback? We're not passing this function anywhere

{children}
</CollapsibleSection>
</FilterGroupProvider>
);
}

function CheckboxOptions({
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it make sense to put this component in a separate file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Tom said since it's an internal component we can just keep it in the same file

@ElemelonWind ElemelonWind removed the wip label Jul 25, 2022
@@ -119,7 +120,12 @@ function CheckboxOptions({
}) {
const searchUtilities = useSearchUtilities();
const { searchValue } = useFilterGroupContext();
const shouldRenderOption = useCallback((option: { displayName: string, value: unknown }) => {
const shouldRenderOption = (option:
{ displayName?: unknown, value: string | number | boolean | NumberRangeValue }) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Instead of unknown, could we do string | undefined here? I can't remember off the top of my head, but we may also be able to do displayName?: string. The string | undefined may be redundant because of the optional nature of `displayName.

@@ -119,7 +120,12 @@ function CheckboxOptions({
}) {
const searchUtilities = useSearchUtilities();
const { searchValue } = useFilterGroupContext();
const shouldRenderOption = useCallback((option: { displayName: string, value: unknown }) => {
const shouldRenderOption = (option:
Copy link
Collaborator

Choose a reason for hiding this comment

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

@oshi97 do we not want to wrap this in a useMemo or a useCallback? I'm wondering if, as is, we could erroneously re-render if searchValue and searchUtilities remained the same.

{isLimited &&
/* eslint-disable-next-line react-perf/jsx-no-new-function-as-prop */
<button className='text-primary py-1 text-sm' onClick={() => setShowAll(!showAll)}>
{showAll ? 'Show Less' : 'Show More'}
Copy link
Contributor

Choose a reason for hiding this comment

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

would this scenario be handled correctly?

  • filterOptions > showMoreLimit, so the options are searchable and have a Show More button displayed
  • user types in the input which narrows down the matching options to fewer than showMoreLimit
  • there probably shouldn't be a Show More/Less button displayed anymore

src/components/FilterGroup.tsx Outdated Show resolved Hide resolved
src/components/FilterGroup.tsx Outdated Show resolved Hide resolved
@tmeyer2115 tmeyer2115 self-requested a review July 25, 2022 18:44
@ElemelonWind ElemelonWind merged commit d4c0f98 into main Jul 25, 2022
@ElemelonWind ElemelonWind deleted the dev/standardfacets-showmorelimit branch July 25, 2022 18:45
ElemelonWind added a commit that referenced this pull request Jul 25, 2022
Follow-up to (#245) - jest tests didn't catch the bug :(
yen-tt pushed a commit that referenced this pull request Sep 28, 2022
Add a `showMoreLimit` prop to `StandardFacet`. When the number of options exceeds this limit, display only that many options, a searchable facets input, and a show more button. The show more button, when clicked displays all the options. If the number of options is less than the limit, show all the options and no search bar

J=SLAP-2252
TEST=auto

Added two new stories: one to show the prop at work, and the second to show what happens when the show more button is pressed
yen-tt pushed a commit that referenced this pull request Sep 28, 2022
Follow-up to (#245) - jest tests didn't catch the bug :(
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.

None yet

7 participants