diff --git a/packages/website/ts/components/docs/sidebar/filter.tsx b/packages/website/ts/components/docs/sidebar/filter.tsx index 62b471fe42..bc6c25db83 100644 --- a/packages/website/ts/components/docs/sidebar/filter.tsx +++ b/packages/website/ts/components/docs/sidebar/filter.tsx @@ -6,6 +6,7 @@ import { colors } from 'ts/style/colors'; export interface IFilterProps extends IFilterCheckboxProps { label: string; customLabel?: string; + isDisabled?: boolean; value: string; refine: (value: string) => void; } @@ -14,22 +15,26 @@ interface IFilterCheckboxProps { isRefined: boolean; } -export const Filter: React.FC = ({ isRefined, label, value, customLabel, refine }) => { +export const Filter: React.FC = ({ isDisabled, isRefined, label, value, customLabel, refine }) => { const handleClick = () => refine(value); return ( - + {customLabel ? customLabel : label} ); }; -const FilterWrapper = styled.label` - cursor: pointer; +const FilterWrapper = styled.label<{ isDisabled: boolean }>` display: flex; align-items: center; margin-bottom: 0.83rem; + + cursor: ${({ isDisabled }) => (isDisabled ? 'not-allowed' : 'pointer')}; + pointer-events: ${({ isDisabled }) => isDisabled && 'none'}; + opacity: ${({ isDisabled }) => (isDisabled ? 0.3 : 1)}; + transition: opacity 250ms ease-in-out; `; const FilterCheckbox = styled.div<{ isRefined: boolean }>` diff --git a/packages/website/ts/components/docs/sidebar/filters.tsx b/packages/website/ts/components/docs/sidebar/filters.tsx index 2275e4d6e7..e9c08b27e5 100644 --- a/packages/website/ts/components/docs/sidebar/filters.tsx +++ b/packages/website/ts/components/docs/sidebar/filters.tsx @@ -13,6 +13,7 @@ interface IFiltersGroupProps { attribute: string; heading: string; customLabel?: string; + operator?: string; } const transformItems = (items: IFiltersGroupProps[]) => _.orderBy(items, 'label', 'asc'); @@ -20,7 +21,7 @@ const transformItems = (items: IFiltersGroupProps[]) => _.orderBy(items, 'label' export const Filters: React.FC = ({ filters }) => ( {filters.map((filter: IFiltersGroupProps, index: number) => ( - + ))} diff --git a/packages/website/ts/components/docs/sidebar/filters_group.tsx b/packages/website/ts/components/docs/sidebar/filters_group.tsx index 4cf1bbc6e7..ac0eca5129 100644 --- a/packages/website/ts/components/docs/sidebar/filters_group.tsx +++ b/packages/website/ts/components/docs/sidebar/filters_group.tsx @@ -9,13 +9,49 @@ import { styled } from 'ts/style/theme'; interface IFilterListProps { heading: string; customLabel?: string; + isDisabled?: boolean; items: IFilterProps[]; + operator: string; refine: (value: string) => void; transformItems: (items: IFilterProps[]) => void; } const FiltersList: React.FC = ({ items, customLabel, heading, refine }) => { - if (!items.length) { + const [filters, setFilters] = React.useState([]); + + // Note (Piotr): Whenever you choose a filter (refinement), algolia removes all filters that could not match the query. + // What we are doing instead is first grabbing the list of all possible filters on mount (or clearing all filters) and + // then visually disabling filters. That way the user is still able to see all filters, even those that do not apply to + // the current state of filtering. + + React.useEffect( + () => { + // This happens on mount when filters are empty or on clearing all filters, when the items number exceeds that of filters + if (!filters.length || items.length >= filters.length) { + setFilters(items); + } else { + const updatedFilters = [...filters]; + + for (const filter of updatedFilters) { + // Look for item corresponding to the filter we already have + const currentItem = items.find(item => item.label === filter.label); + // No match found means that algolia does not return the filter and we disable it on the initial list + if (!currentItem) { + filter.isDisabled = true; + } + // If there is a matching item and it is refined (active), we update our list of filters so that the filter is checked + if (currentItem && currentItem.isRefined) { + filter.isRefined = true; + } + } + + setFilters(updatedFilters); + } + }, + [items], + ); + + if (!filters.length) { return null; } @@ -24,8 +60,8 @@ const FiltersList: React.FC = ({ items, customLabel, heading, {heading} - {items.map((item: IFilterProps, index: number) => ( - + {filters.map((filter: IFilterProps, index: number) => ( + ))} );