Skip to content
Components

Filters layout

A composable and responsive layout component for filters

Basic usage

First, import the components.

import {FiltersLayout, SortSelect} from '@pleo-io/telescope'

FiltersLayout places a search field, a group of filters, a sort select and the filter results in a consistent, responsive layout. Use it with Search, Filter menu or FilterButton, and Filter results.

Show code
const Example = () => {
    const [search, setSearch] = React.useState('')
    const [sorting, setSorting] = React.useState('newest')
    const [hasAppliedFilters, setHasAppliedFilters] = React.useState(false)


    return (
        <FiltersLayout>
            <FiltersLayout.SearchWrapper>
                <Search label="Search expenses" value={search} onValueChange={setSearch} />
            </FiltersLayout.SearchWrapper>
            <FiltersLayout.FiltersWrapper>
                <FiltersLayout.FiltersGroup>
                    <FilterButton
                        hasAppliedFilters={hasAppliedFilters}
                        onClick={() => setHasAppliedFilters((applied) => !applied)}
                    >
                        Category
                    </FilterButton>
                    <FilterButton>Status</FilterButton>
                </FiltersLayout.FiltersGroup>
                <SortSelect
                    options={[
                        {label: 'Newest first', value: 'newest'},
                        {label: 'Oldest first', value: 'oldest'},
                    ]}
                    value={sorting}
                    onChange={setSorting}
                />
            </FiltersLayout.FiltersWrapper>
            <FiltersLayout.FiltersResultsWrapper isVisible={hasAppliedFilters}>
                <FilterResults>
                    <FilterResults.Text>1 filter applied</FilterResults.Text>
                    <FilterResults.Clear onClick={() => setHasAppliedFilters(false)}>
                        Clear filters
                    </FilterResults.Clear>
                </FilterResults>
            </FiltersLayout.FiltersResultsWrapper>
        </FiltersLayout>
    )
}


render(<Example />)

Layout

  • FiltersLayout.SearchWrapper sizes the search field. It takes at least 320px and grows to fill the row. Pass $stacked to give it a full row of its own, or $withoutFilters to keep it at 320px when there are no filters next to it.
  • FiltersLayout.FiltersWrapper holds the filters. When it has a second child, such as a SortSelect, that child is pushed to the end of the row.
  • FiltersLayout.FiltersGroup wraps a group of filters onto several lines on small screens.
  • FiltersLayout.FiltersResultsWrapper animates the filter results in and out when isVisible changes, and respects the user's reduced motion setting.

Sorting

SortSelect is a non-searchable Select with a sort icon. It is controlled: pass the options, the selected value and an onChange handler, which receives the value of the selected option.

Show code
const Example = () => {
    const [sorting, setSorting] = React.useState('newest')


    return (
        <SortSelect
            options={[
                {label: 'Newest first', value: 'newest'},
                {label: 'Oldest first', value: 'oldest'},
            ]}
            value={sorting}
            onChange={setSorting}
        />
    )
}


render(<Example />)

Localisation

SortSelect is named "Sort by:" for assistive technology. The label comes from the TelescopeProvider translations under FiltersLayout.SortByLabel.

Accessibility

  • The parts render in reading order, so keyboard users move from the search field through the filters to the sort select.
  • SortSelect has an accessible name from the localised FiltersLayout.SortByLabel translation.
  • FiltersLayout.FiltersResultsWrapper skips its animation when the user prefers reduced motion.

API reference

FiltersLayout

PropTypeDefault
testId
enum

FiltersResultsWrapper

PropTypeDefault
isVisible (required)
boolean

SortSelect

PropTypeDefault
disabled
boolean
onChange (required)
function
onOpen
enum
options (required)
Record<"label" | "value", string>[]
testId
enum
value (required)
string
Didn't find what you were looking for?
Edit this page