Skip to content

Commit

Permalink
Allow the select and multiselect filter controls to scroll content
Browse files Browse the repository at this point in the history
Add param `isScrollable`, and released css, to allow the patternfly
`Select` components at the core of `SelectFilterControl` and
`MultiselectFilterControl` to scroll its content as needed.  This
is a replication of the patternfly Menu `isScrollable` prop[1].

Summary of changes:
  - Add `isScrollable` (with a default value of `false`) to
    `SelectFilterControl` and `MultiselectFilterControl`

  - Add `select-overrides.css` to implement the scrolling for the
    components

  - Minor tweaks to the filter select controls to mirror code
    formatting as they are very similar components

Resolves: https://issues.redhat.com/browse/MTA-485
[1]: https://www.patternfly.org/v4/components/menu#scrollable-menus

Signed-off-by: Scott J Dickerson <sdickers@redhat.com>
  • Loading branch information
sjd78 committed Jul 6, 2023
1 parent 7130f44 commit 9a5178e
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const FilterControl = <TItem, TFilterCategoryKey extends string>({
if (category.type === FilterType.select) {
return (
<SelectFilterControl
isScrollable
category={category as ISelectFilterCategory<TItem, TFilterCategoryKey>}
{...props}
/>
Expand All @@ -49,6 +50,7 @@ export const FilterControl = <TItem, TFilterCategoryKey extends string>({
if (category.type === FilterType.multiselect) {
return (
<MultiselectFilterControl
isScrollable
category={
category as IMultiselectFilterCategory<TItem, TFilterCategoryKey>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ import {
IMultiselectFilterCategory,
OptionPropsWithKey,
} from "./FilterToolbar";
import { css } from "@patternfly/react-styles";

import "./select-overrides.css";

export interface IMultiselectFilterControlProps<
TItem,
TFilterCategoryKey extends string
> extends IFilterControlProps<TItem, TFilterCategoryKey> {
category: IMultiselectFilterCategory<TItem, TFilterCategoryKey>;
isScrollable?: boolean;
}

export const MultiselectFilterControl = <
Expand All @@ -30,6 +34,7 @@ export const MultiselectFilterControl = <
setFilterValue,
showToolbarItem,
isDisabled = false,
isScrollable = false,
}: React.PropsWithChildren<
IMultiselectFilterControlProps<TItem, TFilterCategoryKey>
>): JSX.Element | null => {
Expand All @@ -47,10 +52,12 @@ export const MultiselectFilterControl = <
const getChipFromOptionValue = (
optionValue: string | SelectOptionObject | undefined
) => (optionValue ? optionValue.toString() : "");

const getOptionKeyFromChip = (chip: string) =>
category.selectOptions.find(
(optionProps) => optionProps.value.toString() === chip
)?.key;

const getOptionValueFromOptionKey = (optionKey: string) =>
category.selectOptions.find((optionProps) => optionProps.key === optionKey)
?.value;
Expand All @@ -71,6 +78,7 @@ export const MultiselectFilterControl = <
}
}
};

const onFilterClear = (chip: string) => {
const optionKey = getOptionKeyFromChip(chip);
const newValue = filterValue
Expand All @@ -83,6 +91,7 @@ export const MultiselectFilterControl = <
const selections = filterValue
? filterValue.map(getOptionValueFromOptionKey)
: null;

const chips = selections ? selections.map(getChipFromOptionValue) : [];

const renderSelectOptions = (options: OptionPropsWithKey[]) =>
Expand Down Expand Up @@ -111,23 +120,25 @@ export const MultiselectFilterControl = <

return (
<ToolbarFilter
id={`filter-control-${category.key}`}
chips={chips}
deleteChip={(_, chip) => onFilterClear(chip as string)}
categoryName={category.title}
showToolbarItem={showToolbarItem}
>
<Select
variant={SelectVariant.checkbox}
className={css(isScrollable && "isScrollable")}
aria-label={category.title}
toggleId={`${category.key}-filter-value-select`}
onToggle={() => setIsFilterDropdownOpen(!isFilterDropdownOpen)}
selections={selections || []}
onSelect={(_, value) => onFilterSelect(value)}
isOpen={isFilterDropdownOpen}
placeholderText={category.placeholderText}
isDisabled={isDisabled || category.selectOptions.length === 0}
variant={SelectVariant.checkbox}
hasInlineFilter
onFilter={onOptionsFilter}
isDisabled={isDisabled || category.selectOptions.length === 0}
>
{renderSelectOptions(category.selectOptions)}
</Select>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ import {
SelectOptionObject,
} from "@patternfly/react-core";
import { IFilterControlProps } from "./FilterControl";
import { ISelectFilterCategory } from "./FilterToolbar";
import { ISelectFilterCategory, OptionPropsWithKey } from "./FilterToolbar";
import { css } from "@patternfly/react-styles";

import "./select-overrides.css";

export interface ISelectFilterControlProps<
TItem,
TFilterCategoryKey extends string
> extends IFilterControlProps<TItem, TFilterCategoryKey> {
category: ISelectFilterCategory<TItem, TFilterCategoryKey>;
isScrollable?: boolean;
}

export const SelectFilterControl = <TItem, TFilterCategoryKey extends string>({
Expand All @@ -21,6 +25,7 @@ export const SelectFilterControl = <TItem, TFilterCategoryKey extends string>({
setFilterValue,
showToolbarItem,
isDisabled = false,
isScrollable = false,
}: React.PropsWithChildren<
ISelectFilterControlProps<TItem, TFilterCategoryKey>
>): JSX.Element | null => {
Expand All @@ -32,13 +37,16 @@ export const SelectFilterControl = <TItem, TFilterCategoryKey extends string>({
category.selectOptions.find(
(optionProps) => optionProps.value === optionValue
)?.key;

const getChipFromOptionValue = (
optionValue: string | SelectOptionObject | undefined
) => (optionValue ? optionValue.toString() : "");

const getOptionKeyFromChip = (chip: string) =>
category.selectOptions.find(
(optionProps) => optionProps.value.toString() === chip
)?.key;

const getOptionValueFromOptionKey = (optionKey: string) =>
category.selectOptions.find((optionProps) => optionProps.key === optionKey)
?.value;
Expand All @@ -48,6 +56,7 @@ export const SelectFilterControl = <TItem, TFilterCategoryKey extends string>({
setFilterValue(optionKey ? [optionKey] : null);
setIsFilterDropdownOpen(false);
};

const onFilterClear = (chip: string) => {
const optionKey = getOptionKeyFromChip(chip);
const newValue = filterValue
Expand All @@ -60,8 +69,14 @@ export const SelectFilterControl = <TItem, TFilterCategoryKey extends string>({
const selections = filterValue
? filterValue.map(getOptionValueFromOptionKey)
: null;

const chips = selections ? selections.map(getChipFromOptionValue) : [];

const renderSelectOptions = (options: OptionPropsWithKey[]) =>
options.map((optionProps) => (
<SelectOption {...optionProps} key={optionProps.key} />

Check warning on line 77 in client/src/app/shared/components/FilterToolbar/SelectFilterControl.tsx

View check run for this annotation

Codecov / codecov/patch

client/src/app/shared/components/FilterToolbar/SelectFilterControl.tsx#L75-L77

Added lines #L75 - L77 were not covered by tests
));

return (
<ToolbarFilter
id={`filter-control-${category.key}`}
Expand All @@ -71,6 +86,7 @@ export const SelectFilterControl = <TItem, TFilterCategoryKey extends string>({
showToolbarItem={showToolbarItem}
>
<Select
className={css(isScrollable && "isScrollable")}
aria-label={category.title}
toggleId={`${category.key}-filter-value-select`}
onToggle={() => setIsFilterDropdownOpen(!isFilterDropdownOpen)}
Expand All @@ -80,9 +96,7 @@ export const SelectFilterControl = <TItem, TFilterCategoryKey extends string>({
placeholderText="Any"
isDisabled={isDisabled || category.selectOptions.length === 0}
>
{category.selectOptions.map((optionProps) => (
<SelectOption {...optionProps} key={optionProps.key} />
))}
{renderSelectOptions(category.selectOptions)}
</Select>
</ToolbarFilter>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.pf-c-select.isScrollable .pf-c-select__menu {
max-height: 60vh;
overflow-y: auto;
}

0 comments on commit 9a5178e

Please sign in to comment.