The Filters component is a versatile component that can be used to filter data based on user-defined criteria.

Importing

The component can be imported via:

import { 
  Filters, 
  FiltersActiveList, 
  FiltersAddButton, 
  FiltersClearAllButton 
} from '@customerio/pluma-components/react';

Usage

The Filters component provides a flexible way to implement filtering interfaces with different filter types. It includes subcomponents for displaying active filters, adding new filters, and clearing all filters.

import { Filters } from '@customerio/pluma-components/react';
import { useState } from 'react';

const filters = [
  {
    key: 'source',
    label: 'Source',
    type: 'radio',
    options: [
      { label: 'API', value: 'api' },
      { label: 'UI', value: 'ui' },
      { label: 'CSV', value: 'csv' },
    ],
  },
  {
    key: 'status',
    label: 'Status',
    type: 'checkbox',
    options: [
      { label: 'Pending', value: 'pending' },
      { label: 'Active', value: 'active' },
      { label: 'Failed', value: 'failed' },
    ],
  },
  {
    key: 'priority',
    label: 'Priority',
    type: 'select',
    options: [
      {
        label: 'Low',
        value: 'low',
      },
      {
        label: 'Medium',
        value: 'medium',
      },
      {
        label: 'High',
        value: 'high',
      },
      {
        label: 'Critical',
        value: 'critical',
      },
    ],
  },
  {
    key: 'team',
    label: 'Team',
    type: 'multiselect',
    isSearchable: true,
    options: [
      {
        label: 'Revenue Teams',
        icon: 'increasing',
        options: [
          { label: 'Marketing', value: 'marketing', icon: 'campaigns' },
          { label: 'Sales', value: 'sales', icon: 'increasing' },
        ],
      },
      {
        label: 'Support Teams',
        icon: 'chat',
        options: [
          { label: 'Support', value: 'support', icon: 'help' },
          { label: 'Success', value: 'success', icon: 'check' },
        ],
      },
      {
        label: 'Product Teams',
        icon: 'workspaces',
        options: [
          { label: 'Engineering', value: 'engineering', icon: 'editor-code' },
          { label: 'Product', value: 'product', icon: 'light-mode' },
        ],
      },
    ],
  },
  {
    key: 'start_date',
    label: 'Single date',
    type: 'date',
  },
  {
    key: 'metrics_range',
    label: 'Date range',
    type: 'daterange',
  }
];

export default function Example() {
  const [values, setValues] = useState([]);

  const handleChange = (key, value) => {
   const exists = values.some(v => v.key === key);
    const updated = exists
      ? values.map(v => v.key === key ? { ...v, value } : v)
      : [...values, { key, value }];
    setValues(updated);
  };

  const handleClear = (key) => {
    setValues(values.filter(v => v.key !== key));
  };

  const handleClearAll = () => {
    setValues([]);
  };

  return (
    <Filters
      filters={filters}
      values={values}
      onChange={handleChange}
      onClear={handleClear}
      onClearAll={handleClearAll}
    />
  );
}

Filter Types

The Filters component supports various types of filters:

  1. Radio filters: Allow selecting a single value from multiple options
  2. Checkbox filters: Allow selecting multiple values from multiple options
  3. Select filters: Allow selecting a single value from a Select popover
  • use isSearchable: true to enable search functionality within the popover
  1. Multiselect filters: Allow selecting multiple values from a Select popover
  • use isSearchable: true to enable search functionality within the popover
  1. Date filters: Allow selecting a single date
  2. Date range filters: Allow selecting a date range
  3. Custom filters: Render a custom filter in the popover

Custom filters

When using the custom type, it is required to also provide the following options with the filter definition:

  • selectedLabel - a function that accepts the current value and returns a string to display in the filter tag
  • editComponent - a component which will be rendered inside the popover when the filter tag is clicked. The component will receive the following props:
    • filter - the filter definition
    • value - the current value of the filter
    • onChange - a callback to call when the value of the filter is changed
    • closeDropdown - a function that can be called to close the dropdown programmatically
import { Box, Filters, SegmentedControl } from '@customerio/pluma-components/react';
import { useState } from 'react';

const filters = [
  {
    key: 'source',
    label: 'Source',
    type: 'radio',
    options: [
      { label: 'API', value: 'api' },
      { label: 'UI', value: 'ui' },
      { label: 'CSV', value: 'csv' },
    ],
  },
  {
    key: 'status',
    label: 'Status',
    type: 'checkbox',
    options: [
      { label: 'Pending', value: 'pending' },
      { label: 'Active', value: 'active' },
      { label: 'Failed', value: 'failed' },
    ],
  },
  {
    key: 'custom',
    label: 'Custom',
    type: 'custom',
    selectedLabel: (value) => `"${value}" attribute`,
    editComponent: ({ value, onChange }) => {
      return (
        <Box p="300">
          <SegmentedControl
            label="Custom value"
            value={value}
            onChange={onChange}
            options={[
              {
                value: 'lorem',
                label: 'lorem',
              },
              {
                value: 'ipsum',
                label: 'ipsum',
              },
              {
                value: 'dolor',
                label: 'dolor',
              },
            ]}
          />
        </Box>
      );
    },
  },
];

export default function Example() {
  const [values, setValues] = useState([]);

  const handleChange = (key, value) => {
   const exists = values.some(v => v.key === key);
    const updated = exists
      ? values.map(v => v.key === key ? { ...v, value } : v)
      : [...values, { key, value }];
    setValues(updated);
  };

  const handleClear = (key) => {
    setValues(values.filter(v => v.key !== key));
  };

  const handleClearAll = () => {
    setValues([]);
  };

  return (
    <Filters
      filters={filters}
      values={values}
      onChange={handleChange}
      onClear={handleClear}
      onClearAll={handleClearAll}
    />
  );
}

Always Shown Filters

Set isAlwaysShown: true to keep a filter always visible, even when empty. This is useful to highlight important filters that users are more likely to interact with.

import { Filters } from '@customerio/pluma-components/react';
import { useState } from 'react';

const filters = [
  {
    key: 'source',
    label: 'Source',
    type: 'radio',
    isAlwaysShown: true, // This filter will always be visible
    options: [
      { label: 'API', value: 'api' },
      { label: 'UI', value: 'ui' },
      { label: 'CSV', value: 'csv' },
    ],
  },
  {
    key: 'status',
    label: 'Status',
    type: 'checkbox',
    options: [
      { label: 'Pending', value: 'pending' },
      { label: 'Active', value: 'active' },
      { label: 'Failed', value: 'failed' },
    ],
  }
];

export default function Example() {
  const [values, setValues] = useState([]);

  const handleChange = (key, value) => {
   const exists = values.some(v => v.key === key);
    const updated = exists
      ? values.map(v => v.key === key ? { ...v, value } : v)
      : [...values, { key, value }];
    setValues(updated);
  };

  const handleClear = (key) => {
    setValues(values.filter(v => v.key !== key));
  };

  const handleClearAll = () => {
    setValues([]);
  };

  return (
    <Filters
      filters={filters}
      values={values}
      onChange={handleChange}
      onClear={handleClear}
      onClearAll={handleClearAll}
    />
  );
}

Custom Layouts

The Filters component can be used with a custom layout by providing children. The component provides a context value that contains all the necessary state and functions.

  • FiltersActiveList - Displays a list of active filters as tags. Each tag shows the filter label and its current value. Clicking on a tag opens a popover to edit the filter value.
  • FiltersAddButton - A button that opens a dropdown menu to add a new filter. The dropdown shows all filters that are not currently active.
  • FiltersClearAllButton - A button that clears all active filters. Only appears when there are active filters.
import { Filters } from '@customerio/pluma-components/react';
import { useState } from 'react';

const filters = [
  {
    key: 'source',
    label: 'Source',
    type: 'radio',
    options: [
      { label: 'API', value: 'api' },
      { label: 'UI', value: 'ui' },
      { label: 'CSV', value: 'csv' },
    ],
  },
  {
    key: 'status',
    label: 'Status',
    type: 'checkbox',
    options: [
      { label: 'Pending', value: 'pending' },
      { label: 'Active', value: 'active' },
      { label: 'Failed', value: 'failed' },
    ],
  }
];

export default function Example() {
  const [values, setValues] = useState([]);

  const handleChange = (key, value) => {
    const exists = values.some(v => v.key === key);
    const updated = exists
      ? values.map(v => v.key === key ? { ...v, value } : v)
      : [...values, { key, value }];
    setValues(updated);
  };

  const handleClear = (key) => {
    setValues(values.filter(v => v.key !== key));
  };

  const handleClearAll = () => {
    setValues([]);
  };

  return (
    <Filters
      filters={filters}
      values={values}
      onChange={handleChange}
      onClear={handleClear}
      onClearAll={handleClearAll}
    >
      <Box display="flex" flexDirection="column" gap="200">
        <Box display="flex" justifyContent="space-between">
          <FiltersAddButton />
          <FiltersClearAllButton />
        </Box>
        <FiltersActiveList />
      </Box>
    </Filters>
  );
}

API

Whether the "add button" dropdown should render in an open state by default.

Whether the filters are disabled

Called when a filter is selected within the dropdown

The values of the filters

Optional icon to display alongside the filter label

Whether to always show this filter, even if it's not filled. When enabled, the filter will always be visible in the active list.

The key of the filter

The label of the filter

Renders the text inside the pill when a value is set

The type of the filter

Optional icon to display alongside the filter label

Whether to always show this filter, even if it's not filled. When enabled, the filter will always be visible in the active list.

The key of the filter

The label of the filter

Renders the text inside the pill when a value is set

The type of the filter

Optional icon to display alongside the filter label

Whether to always show this filter, even if it's not filled. When enabled, the filter will always be visible in the active list.

Function to determine if a date is disabled and cannot be selected. This takes precedence over minDate and maxDate if provided.

The key of the filter

The label of the filter

The maximum selectable date.

The minimum selectable date.

Renders the text inside the pill when a value is set

The type of the filter

Optional icon to display alongside the filter label

Whether to always show this filter, even if it's not filled. When enabled, the filter will always be visible in the active list.

Function to determine if a date is disabled and cannot be selected. This takes precedence over minDate and maxDate if provided.

The key of the filter

The label of the filter

The maximum selectable date.

The minimum selectable date.

An array of presets to render instead of the default ones.

Renders the text inside the pill when a value is set

The type of the filter

Whether the date picker should show preset selection. Only available when isRange is true.

Optional icon to display alongside the filter label

Whether to always show this filter, even if it's not filled. When enabled, the filter will always be visible in the active list.

Whether the select options should be searchable (via an input inside the options menu).

The key of the filter

The label of the filter

The options for the filter. Supports all Select option features including groups, icons, descriptions, etc.

Renders the text inside the pill when a value is set

The type of the filter

Optional icon to display alongside the filter label

Whether to always show this filter, even if it's not filled. When enabled, the filter will always be visible in the active list.

Whether the select options should be searchable (via an input inside the options menu).

The key of the filter

The label of the filter

The options for the filter. Supports all Select option features including groups, icons, descriptions, etc.

Renders the text inside the pill when a value is set

The type of the filter

The component to render inside the popover when editing this filter

Optional icon to display alongside the filter label

Whether to always show this filter, even if it's not filled. When enabled, the filter will always be visible in the active list.

The key of the filter

The label of the filter

Renders the text inside the pill when a value is set

The type of the filter

Whether the filter is disabled

The key of the filter

The value of the filter

Custom className for each active item in the list. Use this with caution as it's not guaranteed to be stable between versions.

Whether the add button is disabled

Whether the clear all button is disabled