The PlumaSearch component builds upon the TextField component, providing additional functionality tailored for search use cases.

Importing

The component can be imported via:

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

Usage

<Search 
    value="Foo" 
    ariaLabel="React demo input" 
    onSearch={(value) => console.log('Search triggered:', value)}
    onSearchInput={(value) => console.log('Search input changed:', value)}
    shouldSearchOnEnter={true}
/>

Search Trigger Options

By default, the PlumaSearch component will not trigger a search. You can enable search actions with the following options:

  • shouldSearchOnBlur (boolean): Triggers a search when the input loses focus. Defaults to false.
  • shouldSearchOnDebounce (number): Triggers a search after the specified debounce interval (in milliseconds). Must be greater than 0 to enable. Defaults to 0.
  • shouldSearchOnInput (boolean): Triggers a search whenever the input value changes. Defaults to false.
  • shouldSearchOnEnter (boolean): Triggers a search when the Enter key is pressed. Defaults to false.
  • shouldSearchOnClear (boolean): Triggers a search when the input is cleared via the clear button. Defaults to false.

For server-side search, you should use shouldSearchOnEnter and shouldSearchOnClear. Check with the back-end team and, if there is not a performance concern with extra queries, consider using shouldSearchOnDebounce for a better user experience.

For client-side search, you should use shouldSearchOnInput and shouldSearchOnClear. If it is a large dataset, consider using shouldSearchOnDebounce for a better user experience.

Accessibility

The PlumaSearch component inherits accessibility features from the TextField component, including teh requirement for ariaLabel, label, or ariaLabelledby.

Errors

The PlumaSearch component accepts an isInvalid prop, which will render the input in an error state:

<Search
  label="Email address"
  isInvalid={true}
/>

It is also highly recommended to provide an error message when the input is invalid. This will render below the input:

<Search
  label="Email address"
  isInvalid={true}
  error="Please enter a valid email address"
/>

Icons

While you can set the icon, the search icon is used by default and should not be overridden without a very good reason from a designer.

<Search
  label="Search"
  icon="a-b-test"
/>

Customizing labels

If a string label is not sufficient, a component can be used to render the label.

In React, the label prop accepts any ReactNode.

import { Search, Icon } from '@customerio/pluma-components/react';
import { useState } from 'react';

export default function Example() {
  const [value, setValue] = useState('');

  return <Search
    label={<>Custom label <Icon name="campaigns" isInline={true} size="sm" /></>}
    value={value}
    onInput={(e) => {
      setValue(e.target.value);
    }}
  />
}

Customizing descriptions

If a string description is not sufficient, a component can be used to render the description.

In React, the description prop accepts any ReactNode.

import { Search, Link } from '@customerio/pluma-components/react';
import { useState } from 'react';

export default function Example() {
  const [value, setValue] = useState('');

  return <Search
    ariaLabel="Custom description input"
    description={<>Custom description, <Link href="https://docs.customer.io" isExternal={true} variant="secondary">see docs for details</Link></>}
    value={value}
    onInput={(e) => {
      setValue(e.target.value);
    }}
  />
}

Customizing errors

If a string error is not sufficient, a component can be used to render the error.

In React, the error prop accepts any ReactNode.

import { Search, Link } from '@customerio/pluma-components/react';
import { useState } from 'react';

export default function Example() {
  const [value, setValue] = useState('');

  return <Search
    ariaLabel="Custom error input"
    error={<>Custom error, <Link href="https://docs.customer.io" isExternal={true} variant="secondary">see docs for help</Link></>}
    value={value}
    onInput={(e) => {
      setValue(e.target.value);
    }}
  />
}

API

Element (or elements) that describe the form field. Also used for error messages, as aria-errormessage isn't supported in all assistive technologies: https://a11ysupport.io/tech/aria/aria-errormessage_attribute

String value that labels the form field.

Element (or elements) that label the form field.

Additional classes to be applied to the top-level container. This is necessary as an argument in Ember, where we apply splattributes on the "input" itself, which means we can't pass a custom class to the containing element the classic way.

A description for the field, providing additional context or hints.

An error message associated with the form field. Boolean: Ember-only. If the error named block is used, this prop can be set to true to indicate an error is present, which will make the error block render.

The name of an icon (from Pluma Icons) to be rendered on the left side of the input.

An optional id to be assigned to the input element. Also used to generate ids for labels and error messages. If one isn't provided, it will be generated.

Whether the input should render in an "active" styled state.

Whether the form field is disabled.

Whether the form field is in an invalid state.

Whether the input should show a loading spinner.

The label text to show with the form field.

The name attribute is used for HTML forms

Called when the clear button is clicked.

The function called when the search should be done

Any changes to the value for the search input

Placeholder text to show inside the field.

Whether to allow browser autofill and password managers. When false (default), adds attributes to disable password managers (1Password, LastPass, Bitwarden, Dashlane). Set to true for fields where autofill is desired (e.g., email, password, address fields).

Whether the generated description id should be included in the input's aria-describedby attribute. Disable this when a label`` tag surrounds the input as well as it's description text, for example in an OptionCard` component.

Whether the generated label id should be included in the input's aria-labelledby attribute. Disable this when the label tag surrounds the input as well as it's label text, for example in an OptionCard component.

Whether to search when the search input is blurred.

Whether to search when the clear button is pressed.

Whether to search on a specific debounced interval, must be greater than 0 to trigger a search.

Whether to search when Enter is pressed.

Whether to search when the value changes.

By default, form elements will throw an error if no label or aria-label is provided. Disable this to suppress the error, for example when building a custom form element, and you want to handle labeling yourself.

The type of input that should be rendered. Defaults to text.

Pluma internal property to set a component name used for logging. Only use if building a custom component that wraps this one and need to make it more obvious where errors, for example, come from.

Additional classes to be applied to the description element.

Additional classes to be applied to the error element.

Additional classes to be applied to the field node.

Additional classes to be applied to the footer element.

Ember-only: this is used internally to detect whether a label named block is present, and to ignore empty label props if so.

Additional classes to be applied to the input node.

Sets the size attribute on the input element. This controls the visible width of the input in characters.

Additional classes to be applied to the div that wraps the input element.

Whether the component should render with "legacy" styles.

Additional classes to be applied to the label node.

Whether to apply the center-baseline variant.

Ember only: a modifier to apply on the input's wrapper element.

React only: a ref to the input's wrapper element.