Skip to content

Commit 22f5fbb

Browse files
committed
feat: add filter icon, custom icon support, option value using prop
1 parent 157f509 commit 22f5fbb

File tree

4 files changed

+70
-41
lines changed

4 files changed

+70
-41
lines changed

src/Shared/Components/SelectPicker/FilterSelectPicker.tsx

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
* Copyright (c) 2024. Devtron Inc.
33
*/
44

5-
import { useState } from 'react'
5+
import { useMemo, useState } from 'react'
6+
import { ReactComponent as ICFilter } from '@Icons/ic-filter.svg'
7+
import { ReactComponent as ICFilterApplied } from '@Icons/ic-filter-applied.svg'
68
import SelectPicker from './SelectPicker.component'
79
import { FilterSelectPickerProps, SelectPickerOptionType, SelectPickerProps } from './type'
810

@@ -17,6 +19,13 @@ const FilterSelectPicker = ({
1719
structuredClone(appliedFilterOptions ?? []),
1820
)
1921

22+
const appliedFiltersCount = appliedFilterOptions?.length ?? 0
23+
24+
const filterIcon = useMemo(
25+
() => (appliedFiltersCount ? <ICFilterApplied className="scn-6" /> : <ICFilter className="scn-6" />),
26+
[appliedFiltersCount],
27+
)
28+
2029
const openMenu = () => {
2130
setIsMenuOpen(true)
2231
}
@@ -34,40 +43,46 @@ const FilterSelectPicker = ({
3443
setSelectedOptions(structuredClone(appliedFilterOptions ?? []))
3544
}
3645

37-
const handleApplyClick = () => {
38-
handleApplyFilter(selectedOptions)
39-
closeMenu()
40-
}
46+
const renderApplyButton = (optionsSelected: Parameters<FilterSelectPickerProps['handleApplyFilter']>[0]) => {
47+
const handleApplyClick = () => {
48+
handleApplyFilter(optionsSelected)
49+
closeMenu()
50+
}
4151

42-
const renderApplyButton = () => (
43-
<div className="p-8 dc__border-top-n1">
44-
<button
45-
type="button"
46-
className="dc__unset-button-styles w-100 br-4 h-28 flex bcb-5 cn-0 fw-6 lh-28 fs-12 h-28 br-4 pt-5 pr-12 pb-5 pl-12"
47-
onClick={handleApplyClick}
48-
aria-label="Apply filters"
49-
>
50-
Apply
51-
</button>
52-
</div>
53-
)
52+
return (
53+
<div className="p-8 dc__border-top-n1">
54+
<button
55+
type="button"
56+
className="dc__unset-button-styles w-100 br-4 h-28 flex bcb-5 cn-0 fw-6 lh-28 fs-12 h-28 br-4 pt-5 pr-12 pb-5 pl-12"
57+
onClick={handleApplyClick}
58+
aria-label="Apply filters"
59+
>
60+
Apply
61+
</button>
62+
</div>
63+
)
64+
}
5465

5566
return (
56-
<SelectPicker
57-
{...props}
58-
options={options}
59-
value={selectedOptions}
60-
isMulti
61-
menuIsOpen={isMenuOpen}
62-
onMenuOpen={openMenu}
63-
onMenuClose={handleMenuClose}
64-
onChange={handleSelectOnChange}
65-
renderMenuListFooter={renderApplyButton}
66-
controlShouldRenderValue={false}
67-
showSelectedOptionsCount
68-
isSearchable
69-
isClearable={false}
70-
/>
67+
<div className="dc__mxw-250">
68+
<SelectPicker
69+
{...props}
70+
options={options}
71+
value={selectedOptions}
72+
isMulti
73+
menuIsOpen={isMenuOpen}
74+
onMenuOpen={openMenu}
75+
onMenuClose={handleMenuClose}
76+
onChange={handleSelectOnChange}
77+
renderMenuListFooter={renderApplyButton}
78+
controlShouldRenderValue={false}
79+
showSelectedOptionsCount
80+
isSearchable
81+
isClearable={false}
82+
customSelectedOptionsCount={appliedFiltersCount}
83+
icon={filterIcon}
84+
/>
85+
</div>
7186
)
7287
}
7388

src/Shared/Components/SelectPicker/SelectPicker.component.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ const SelectPicker = <OptionValue, IsMulti extends boolean>({
207207
selectRef,
208208
shouldMenuAlignRight = false,
209209
fullWidth = false,
210+
customSelectedOptionsCount = null,
210211
...props
211212
}: SelectPickerProps<OptionValue, IsMulti>) => {
212213
const { inputId, required, isDisabled, controlShouldRenderValue = true, value, options } = props
@@ -268,14 +269,18 @@ const SelectPicker = <OptionValue, IsMulti extends boolean>({
268269
shouldRenderCustomOptions={shouldRenderCustomOptions}
269270
/>
270271
),
271-
[shouldRenderCustomOptions, renderMenuListFooter, renderCustomOptions],
272+
[shouldRenderCustomOptions],
272273
)
273274

274275
const renderValueContainer = useCallback(
275276
(valueContainerProps: ValueContainerProps<SelectPickerOptionType<OptionValue>>) => (
276-
<SelectPickerValueContainer {...valueContainerProps} showSelectedOptionsCount={showSelectedOptionsCount} />
277+
<SelectPickerValueContainer
278+
{...valueContainerProps}
279+
showSelectedOptionsCount={showSelectedOptionsCount}
280+
customSelectedOptionsCount={customSelectedOptionsCount}
281+
/>
277282
),
278-
[showSelectedOptionsCount],
283+
[showSelectedOptionsCount, customSelectedOptionsCount],
279284
)
280285

281286
const renderOption = useCallback(

src/Shared/Components/SelectPicker/common.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { noop } from '@Common/Helper'
3535
import { CHECKBOX_VALUE } from '@Common/Types'
3636
import { Checkbox } from '@Common/Checkbox'
3737
import { ReactSelectInputAction } from '@Common/Constants'
38+
import { isNullOrUndefined } from '@Shared/Helpers'
3839
import { SelectPickerGroupHeadingProps, SelectPickerOptionType, SelectPickerProps } from './type'
3940
import { getGroupCheckboxValue } from './utils'
4041

@@ -85,19 +86,22 @@ export const SelectPickerControl = <OptionValue, IsMulti extends boolean>({
8586

8687
export const SelectPickerValueContainer = <OptionValue, IsMulti extends boolean>({
8788
showSelectedOptionsCount,
89+
customSelectedOptionsCount,
8890
...props
8991
}: ValueContainerProps<SelectPickerOptionType<OptionValue>> &
90-
Pick<SelectPickerProps<OptionValue, IsMulti>, 'showSelectedOptionsCount'>) => {
92+
Pick<SelectPickerProps<OptionValue, IsMulti>, 'showSelectedOptionsCount' | 'customSelectedOptionsCount'>) => {
9193
const { getValue } = props
92-
const selectedOptionsLength = (getValue() ?? []).length
94+
const selectedOptionsLength = isNullOrUndefined(customSelectedOptionsCount)
95+
? (getValue() ?? []).length
96+
: customSelectedOptionsCount
9397

9498
return (
9599
<div className="flex left dc__gap-8 flex-grow-1">
96100
<div className="flex left">
97101
<components.ValueContainer {...props} />
98102
</div>
99103
{showSelectedOptionsCount && selectedOptionsLength > 0 && (
100-
<div className="bcb-5 dc__border-radius-4-imp pl-5 pr-5 cn-0 fs-12 fw-6 lh-18 dc__truncate dc__no-shrink">
104+
<div className="bcb-50 dc__border eb-2 dc__border-radius-4-imp pl-5 pr-5 cb-5 fs-12 fw-6 lh-18 dc__truncate dc__no-shrink">
101105
{selectedOptionsLength}
102106
</div>
103107
)}
@@ -181,7 +185,7 @@ export const SelectPickerMenuList = <OptionValue, IsMulti extends boolean>({
181185
>) => {
182186
const {
183187
children,
184-
selectProps: { inputValue },
188+
selectProps: { inputValue, value },
185189
} = props
186190

187191
return (
@@ -191,7 +195,8 @@ export const SelectPickerMenuList = <OptionValue, IsMulti extends boolean>({
191195
{/* Added to the bottom of menu list to prevent from hiding when the menu is opened close to the bottom of the screen */}
192196
{!shouldRenderCustomOptions && renderMenuListFooter && (
193197
<div className="dc__position-sticky dc__bottom-0 dc__bottom-radius-4 bcn-0 dc__zi-2">
194-
{renderMenuListFooter()}
198+
{/* Passing down value as a prop to ensure that the menu list is not re-rendered and scrolled to top on click */}
199+
{renderMenuListFooter(value)}
195200
</div>
196201
)}
197202
</components.MenuList>

src/Shared/Components/SelectPicker/type.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export type SelectPickerProps<OptionValue = number | string, IsMulti extends boo
8585
/**
8686
* Render function for the footer at the bottom of menu list. It is sticky by default
8787
*/
88-
renderMenuListFooter?: () => ReactNode
88+
renderMenuListFooter?: (selectedOptions: SelectProps<OptionValue, IsMulti>['value']) => ReactNode
8989
/**
9090
* Info text for the select, if any
9191
*/
@@ -101,6 +101,10 @@ export type SelectPickerProps<OptionValue = number | string, IsMulti extends boo
101101
* @default 'true'
102102
*/
103103
showSelectedOptionIcon?: boolean
104+
/**
105+
* Custom selected options count for use cases like filters
106+
*/
107+
customSelectedOptionsCount?: number
104108
/**
105109
* Height of the dropdown
106110
*

0 commit comments

Comments
 (0)