diff --git a/docs/frontend/filter.md b/docs/frontend/filter.md
new file mode 100644
index 0000000000..5787ad9808
--- /dev/null
+++ b/docs/frontend/filter.md
@@ -0,0 +1,148 @@
+# Filter Component
+
+The Filter component provides a standardized way to implement filtering functionality across your application. It creates a consistent user experience by managing filter fields, filter triggers, and reset functionality.
+
+## Features
+
+- Unified interface for multiple filter fields
+- Configurable filter and reset buttons
+- Namespace support for unique identification
+- Flexible field composition
+
+## Installation
+
+#### Dokan lite
+
+```jsx
+import Filter from '../components';
+```
+
+#### Dokan pro or external plugins
+
+```jsx
+import { Filter } from '@dokan/components';
+```
+
+## Usage
+
+```jsx
+,
+
+ ]}
+ onFilter={handleFilter}
+ onReset={clearFilter}
+ showFilter={true}
+ showReset={true}
+ namespace="product_table_filters"
+/>
+```
+
+## Props
+
+| Prop | Type | Required | Description |
+|------|------|----------|-------------|
+| `fields` | `ReactNode[]` | No | Array of filter field components to be rendered |
+| `onFilter` | `() => void` | No | Handler function called when the filter button is clicked |
+| `onReset` | `() => void` | No | Handler function called when the reset button is clicked |
+| `showFilter` | `boolean` | No | Controls visibility of the filter button (default: true) |
+| `showReset` | `boolean` | No | Controls visibility of the reset button (default: true) |
+| `namespace` | `string` | Yes | Unique identifier for the filter group |
+
+## Example Implementation
+
+```jsx
+import { Filter, CustomerFilter, DateFilter } from '@your-package/components';
+
+const MyTableComponent = () => {
+ const [filterArgs, setFilterArgs] = useState({});
+ const [searchedCustomer, setSearchedCustomer] = useState(null);
+
+ const handleFilter = () => {
+ // Implement your filter logic here
+ fetchFilteredData(filterArgs);
+ };
+
+ const clearFilter = () => {
+ setFilterArgs({});
+ setSearchedCustomer(null);
+ };
+
+ const handleCustomerSearch = (customer) => {
+ setSearchedCustomer(customer);
+ };
+
+ return (
+
+ ,
+
+ ]}
+ onFilter={handleFilter}
+ onReset={clearFilter}
+ showFilter={true}
+ showReset={true}
+ namespace="my_table_filters"
+ />
+ {/* Table component */}
+
+ );
+};
+```
+
+## Creating Custom Filter Fields
+
+When creating custom filter field components to use with the Filter component:
+
+1. Each field component should manage its own state
+2. Field components should update the parent's filterArgs through props
+3. Include a unique key prop for each field
+4. Handle reset functionality through props
+
+Example custom filter field:
+
+```jsx
+const CustomFilter = ({ filterArgs, setFilterArgs }) => {
+ const handleChange = (value) => {
+ setFilterArgs({
+ ...filterArgs,
+ customField: value
+ });
+ };
+
+ return (
+ handleChange(e.target.value)}
+ />
+ );
+};
+```
+
+## Best Practices
+
+1. Always provide unique keys for field components
+2. Implement proper type checking for filter arguments
+3. Handle edge cases in reset functionality
+4. Use consistent naming conventions for filter arguments
+5. Include error handling in filter and reset handlers
+
+## Notes
+
+- The Filter component is designed to work with table components but can be used in other contexts
+- All filter fields should be controlled components
+- The namespace prop is used internally for generating unique identifiers
+- Filter and reset functionality should be implemented in the parent component
diff --git a/package.json b/package.json
index cecb8571d4..d34fcf0595 100644
--- a/package.json
+++ b/package.json
@@ -50,7 +50,8 @@
"vue-wp-list-table": "^1.3.0",
"vue2-daterange-picker": "^0.6.8",
"vuedraggable": "^2.24.3",
- "wp-readme-to-markdown": "^1.0.1"
+ "wp-readme-to-markdown": "^1.0.1",
+ "tailwind-merge": "^2.6.0"
},
"dependencies": {
"@getdokan/dokan-ui": "^1.0.18",
diff --git a/src/components/Filter.tsx b/src/components/Filter.tsx
new file mode 100644
index 0000000000..955c661e1f
--- /dev/null
+++ b/src/components/Filter.tsx
@@ -0,0 +1,78 @@
+import { Button } from '@getdokan/dokan-ui';
+import { __ } from '@wordpress/i18n';
+import { twMerge } from 'tailwind-merge';
+// @ts-ignore
+// eslint-disable-next-line import/no-unresolved
+import { snakeCase, kebabCase } from '../utilities';
+
+interface FilterProps {
+ /** Namespace for the filter, used to generate unique IDs */
+ namespace: string;
+ /** Array of React nodes representing the filter fields */
+ fields?: React.ReactNode[];
+ /** Whether to show the reset button */
+ showReset?: boolean;
+ /** Whether to show the filter button */
+ showFilter?: boolean;
+ /** Callback function to handle filter action */
+ onFilter?: () => void;
+ /** Callback function to handle reset action */
+ onReset?: () => void;
+ /** Additional class names for the filter container */
+ className?: string;
+}
+
+const Filter = ( {
+ namespace = '',
+ fields = [],
+ showReset = true,
+ showFilter = true,
+ onFilter = () => {},
+ onReset = () => {},
+ className = '',
+}: FilterProps ) => {
+ const snakeCaseNamespace = snakeCase( namespace );
+ const filterId = `dokan_${ snakeCaseNamespace }_filters`;
+
+ // @ts-ignore
+ const filteredFields = wp.hooks.applyFilters( filterId, fields );
+
+ return (
+
+ { filteredFields.map( ( fieldNode: React.ReactNode, index ) => {
+ return (
+
+ { fieldNode }
+
+ );
+ } ) }
+
+ { showFilter && (
+
+ ) }
+
+ { showReset && (
+
+ ) }
+
+ );
+};
+
+export default Filter;
diff --git a/src/components/index.tsx b/src/components/index.tsx
index 56aed60b58..0c86eab8a0 100644
--- a/src/components/index.tsx
+++ b/src/components/index.tsx
@@ -7,3 +7,5 @@ export {
filterSortAndPaginate,
isItemValid
} from '@wordpress/dataviews/wp';
+
+export { default as Filter } from './Filter';