Skip to content

Commit 0b79d98

Browse files
authored
feat(QuickFilter): add QuickFilter component (#2546)
* feat: quick filter base * chore: remove onClick * chore: remove trailing element * chore: quick filter changes * chore: more fixes * chore: added tests * chore: add support for test id and meta attributes * chore: change type of quick filter card * chore: change type * chore: update snap * chore: update story * chore: set state empty * chore: update example * chore: update snap , stories * chore: add changeset * chore: minor changes * chore: change chageset * refactor: quickfilter name * refactor: onChange * refactor: context * chore: remove attributes * chore: change trailingElement to trailing * chore: remove quick filters * chore: make api similar to quick filters * chore: added name * chore: update tests * chore: more refactor * chore: make api similar and update docs * chore: export quick filter * chore: update snaps and remove baseBox and other functions * chore: remove blade common events * fix: build
1 parent 3edf28b commit 0b79d98

14 files changed

+1658
-0
lines changed

.changeset/real-dodos-pull.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@razorpay/blade': minor
3+
---
4+
5+
feat(QuickFilter): Add QuickFilters component
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import React, { forwardRef } from 'react';
2+
import type { QuickFilterProps, QuickFilterContentProps } from './types';
3+
import { useQuickFilterGroupContext } from './QuickFilterGroup';
4+
import { Card, CardBody } from '~components/Card';
5+
import { Box } from '~components/Box';
6+
import { Text } from '~components/Typography';
7+
import { Radio } from '~components/Radio';
8+
import { Checkbox } from '~components/Checkbox';
9+
import { makeAnalyticsAttribute } from '~utils/makeAnalyticsAttribute';
10+
import { metaAttribute } from '~utils/metaAttribute';
11+
import BaseBox from '~components/Box/BaseBox';
12+
import type { BladeElementRef } from '~utils/types';
13+
14+
const QuickFilterContent = ({
15+
value,
16+
title,
17+
trailing,
18+
selectionType = 'single',
19+
isSelected = false,
20+
}: QuickFilterContentProps): React.ReactElement => {
21+
return (
22+
<BaseBox
23+
display="flex"
24+
flexDirection="row"
25+
gap="spacing.3"
26+
width="fit-content"
27+
justifyContent="center"
28+
alignItems="center"
29+
paddingY="spacing.3"
30+
paddingLeft="spacing.3"
31+
paddingRight="spacing.4"
32+
>
33+
<Box
34+
display="flex"
35+
flexDirection="row"
36+
gap="spacing.2"
37+
justifyContent="center"
38+
alignItems="center"
39+
>
40+
{selectionType === 'single' ? <Radio value={value} /> : <Checkbox value={value} />}
41+
<Text
42+
variant="body"
43+
size="medium"
44+
color={isSelected ? 'interactive.text.primary.subtle' : 'interactive.text.gray.subtle'}
45+
weight="medium"
46+
>
47+
{title}
48+
</Text>
49+
</Box>
50+
51+
{trailing}
52+
</BaseBox>
53+
);
54+
};
55+
56+
const QuickFilter = forwardRef<BladeElementRef, QuickFilterProps>(
57+
({ title, value, trailing, testID, ...rest }, ref): React.ReactElement => {
58+
const { selectedQuickFilters, selectionType } = useQuickFilterGroupContext();
59+
60+
const isQuickFilterSelected = selectedQuickFilters.includes(value);
61+
return (
62+
<Card
63+
padding="spacing.0"
64+
as="label"
65+
accessibilityLabel={title}
66+
borderRadius="medium"
67+
elevation="none"
68+
isSelected={isQuickFilterSelected}
69+
ref={ref}
70+
{...makeAnalyticsAttribute(rest)}
71+
{...metaAttribute({ testID })}
72+
>
73+
<CardBody>
74+
<QuickFilterContent
75+
value={value}
76+
title={title}
77+
trailing={trailing}
78+
selectionType={selectionType}
79+
isSelected={isQuickFilterSelected}
80+
{...rest}
81+
/>
82+
</CardBody>
83+
</Card>
84+
);
85+
},
86+
);
87+
export { QuickFilter };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import React from 'react';
2+
import type { QuickFilterGroupContextType } from '../types';
3+
4+
const QuickFilterGroupContext = React.createContext<QuickFilterGroupContextType>({
5+
selectionType: 'single',
6+
selectedQuickFilters: [],
7+
});
8+
const QuickFilterGroupProvider = QuickFilterGroupContext.Provider;
9+
10+
const useQuickFilterGroupContext = (): QuickFilterGroupContextType => {
11+
const context = React.useContext(QuickFilterGroupContext);
12+
return context;
13+
};
14+
15+
export { useQuickFilterGroupContext, QuickFilterGroupProvider };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import React from 'react';
2+
import type { QuickFilterGroupProps, QuickFilterWrapperProps } from '../types';
3+
import { QuickFilterGroupProvider, useQuickFilterGroupContext } from './QuickFilterContext';
4+
import { RadioGroup } from '~components/Radio';
5+
import BaseBox from '~components/Box/BaseBox';
6+
import { CheckboxGroup } from '~components/Checkbox';
7+
import { useControllableState } from '~utils/useControllable';
8+
import { useId } from '~utils/useId';
9+
10+
const QuickFilterWrapper = ({
11+
children,
12+
onChange,
13+
setSelectedQuickFilters,
14+
...rest
15+
}: QuickFilterWrapperProps): React.ReactElement => {
16+
const { selectedQuickFilters, selectionType } = useQuickFilterGroupContext();
17+
18+
if (selectionType === 'single') {
19+
return (
20+
<RadioGroup
21+
value={selectedQuickFilters[0]}
22+
onChange={({ value }) => {
23+
setSelectedQuickFilters(() => [value]);
24+
}}
25+
size="small"
26+
{...rest}
27+
>
28+
{children}
29+
</RadioGroup>
30+
);
31+
}
32+
return (
33+
<CheckboxGroup
34+
value={selectedQuickFilters}
35+
onChange={({ values }) => {
36+
setSelectedQuickFilters(() => values);
37+
}}
38+
size="small"
39+
{...rest}
40+
>
41+
{children}
42+
</CheckboxGroup>
43+
);
44+
};
45+
46+
const QuickFilterGroup = ({
47+
children,
48+
testID,
49+
value,
50+
defaultValue,
51+
onChange,
52+
name,
53+
selectionType,
54+
...rest
55+
}: QuickFilterGroupProps): React.ReactElement => {
56+
const idBase = useId('quick-filter-group');
57+
const [selectedQuickFilters, setSelectedQuickFilters] = useControllableState({
58+
value: (value && selectionType === 'single' ? [value] : value) as string[] | undefined,
59+
// If selectionType is single, we need to convert the value to an array
60+
defaultValue: (defaultValue && selectionType === 'single'
61+
? [defaultValue]
62+
: defaultValue ?? []) as string[] | undefined,
63+
onChange: (values: string[]) => onChange?.({ values, name: name ?? idBase }),
64+
});
65+
return (
66+
<QuickFilterGroupProvider value={{ selectionType, selectedQuickFilters }}>
67+
<QuickFilterWrapper
68+
onChange={onChange}
69+
setSelectedQuickFilters={setSelectedQuickFilters}
70+
{...rest}
71+
>
72+
<BaseBox display="flex" flexDirection="row" gap="spacing.3">
73+
{children}
74+
</BaseBox>
75+
</QuickFilterWrapper>
76+
</QuickFilterGroupProvider>
77+
);
78+
};
79+
80+
export { QuickFilterGroup };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { QuickFilterGroup } from './QuickFilterGroup';
2+
export { useQuickFilterGroupContext, QuickFilterGroupProvider } from './QuickFilterContext';

0 commit comments

Comments
 (0)