diff --git a/src/components/Examples/ExamplesCheckbox.tsx b/src/components/Examples/ExamplesCheckbox.tsx index 6c167ffc34..8551df3657 100644 --- a/src/components/Examples/ExamplesCheckbox.tsx +++ b/src/components/Examples/ExamplesCheckbox.tsx @@ -5,11 +5,17 @@ const ExamplesCheckbox = ({ label, name, value, + disabled = false, + isChecked = false, + isDefaultChecked = false, selectProductOrUseCase, }: { label: string; name: string; value: string; + disabled?: boolean; + isChecked?: boolean; + isDefaultChecked?: boolean; selectProductOrUseCase: (e: React.ChangeEvent) => void; }) => { return ( @@ -21,7 +27,9 @@ const ExamplesCheckbox = ({ name={name} className="ui-checkbox-input" value={value} - defaultChecked={value === 'all'} + checked={isChecked} + defaultChecked={isDefaultChecked} + disabled={disabled} onChange={(e) => selectProductOrUseCase(e)} />
diff --git a/src/components/Examples/ExamplesContent.tsx b/src/components/Examples/ExamplesContent.tsx index 7b2ab983b8..731f95668e 100644 --- a/src/components/Examples/ExamplesContent.tsx +++ b/src/components/Examples/ExamplesContent.tsx @@ -5,32 +5,60 @@ import ExamplesFilter from './ExamplesFilter'; import { ImageProps } from '../Image'; import examples from '../../data/examples'; import { filterSearchExamples } from './filter-search-examples'; +import ExamplesNoResults from './ExamplesNoResults'; const ExamplesContent = ({ exampleImages }: { exampleImages: ImageProps[] }) => { - const [selectedProducts, setSelectedProducts] = useState(['all']); - const [selectedUseCases, setSelectedUseCases] = useState(['all']); + const [selectedProducts, setSelectedProducts] = useState([]); + const [selectedUseCases, setSelectedUseCases] = useState([]); + const [checkAllProducts, setCheckAllProducts] = useState(true); + const [checkAllUseCases, setCheckAllUseCases] = useState(true); const [filteredExamples, setFilteredExamples] = useState(examples.examples); const selectProduct = (e: React.ChangeEvent) => { - if (e.target.checked) { - setSelectedProducts([...selectedProducts, e.target.value]); + const { value, checked } = e.target; + if (value === 'all') { + setCheckAllProducts(checked); + if (checked && selectedProducts.length > 0) { + setSelectedProducts([]); + } } else { - setSelectedProducts(selectedProducts.filter((product) => product !== e.target.value)); + if (checked) { + setSelectedProducts((prev) => [...prev, value].filter((v) => v !== 'all')); + setCheckAllProducts(false); + } else { + setSelectedProducts((prev) => prev.filter((product) => product !== value)); + } } }; const selectUseCases = (e: React.ChangeEvent) => { - if (e.target.checked) { - setSelectedUseCases([...selectedUseCases, e.target.value]); + const { value, checked } = e.target; + if (value === 'all') { + setCheckAllUseCases(checked); + if (checked && selectedUseCases.length > 0) { + setSelectedUseCases([]); + } } else { - setSelectedUseCases(selectedUseCases.filter((product) => product !== e.target.value)); + if (checked) { + setSelectedUseCases((prev) => [...prev, value].filter((v) => v !== 'all')); + setCheckAllUseCases(false); + } else { + setSelectedUseCases((prev) => prev.filter((product) => product !== value)); + } } }; useEffect(() => { const filteredExamples = filterSearchExamples(examples.examples, selectedProducts, selectedUseCases); setFilteredExamples(filteredExamples); - }, [selectedProducts, selectedUseCases]); + + if (selectedProducts.length === 0) { + setCheckAllProducts(true); + } + if (selectedUseCases.length === 0) { + setCheckAllUseCases(true); + } + }, [selectedProducts, selectedUseCases, checkAllProducts, checkAllUseCases]); return ( <> @@ -44,10 +72,21 @@ const ExamplesContent = ({ exampleImages }: { exampleImages: ImageProps[] }) =>
- +
- + {filteredExamples.length > 0 ? ( + + ) : ( + + )}
diff --git a/src/components/Examples/ExamplesFilter.tsx b/src/components/Examples/ExamplesFilter.tsx index bcdfea6ee5..9e54c0cb6e 100644 --- a/src/components/Examples/ExamplesFilter.tsx +++ b/src/components/Examples/ExamplesFilter.tsx @@ -3,13 +3,22 @@ import Icon from '@ably/ui/core/Icon'; import { products } from '@ably/ui/core/ProductTile/data'; import ExamplesCheckbox from './ExamplesCheckbox'; import examples from '../../data/examples'; +import './examples-checkbox.css'; const ExamplesFilter = ({ selectProduct, selectUseCases, + checkAllProducts, + selectedProducts, + checkAllUseCases, + selectedUseCases, }: { selectProduct: (e: React.ChangeEvent) => void; selectUseCases: (e: React.ChangeEvent) => void; + checkAllProducts: boolean; + selectedProducts: string[]; + checkAllUseCases: boolean; + selectedUseCases: string[]; }) => { return ( <> @@ -25,7 +34,14 @@ const ExamplesFilter = ({

PRODUCT

- + {Object.entries(products).map(([key, product]) => ( ))}
@@ -40,7 +58,14 @@ const ExamplesFilter = ({

USE CASE

- + {Object.entries(examples.useCases).map(([key, useCase]) => ( ))}
diff --git a/src/components/Examples/ExamplesNoResults.tsx b/src/components/Examples/ExamplesNoResults.tsx new file mode 100644 index 0000000000..cfe93c896d --- /dev/null +++ b/src/components/Examples/ExamplesNoResults.tsx @@ -0,0 +1,10 @@ +const ExamplesNoResults = () => { + return ( +
+

No Results

+

Sorry, no results found.

+
+ ); +}; + +export default ExamplesNoResults; diff --git a/src/components/Examples/examples-checkbox.css b/src/components/Examples/examples-checkbox.css new file mode 100644 index 0000000000..06775a3b5b --- /dev/null +++ b/src/components/Examples/examples-checkbox.css @@ -0,0 +1,3 @@ +.ui-checkbox-input:disabled + .ui-checkbox-styled { + +} diff --git a/src/components/Examples/filter-search-examples.ts b/src/components/Examples/filter-search-examples.ts index 494b2ae6e1..fc4e1965d6 100644 --- a/src/components/Examples/filter-search-examples.ts +++ b/src/components/Examples/filter-search-examples.ts @@ -8,7 +8,7 @@ export const filterSearchExamples = ( ) => { return examples.filter( (example) => - (selectedProducts.includes('all') || example.products.some((product) => selectedProducts.includes(product))) && - (selectedUseCases.includes('all') || example.useCases.some((useCase) => selectedUseCases.includes(useCase))), + (selectedProducts.length === 0 || example.products.some((product) => selectedProducts.includes(product))) && + (selectedUseCases.length === 0 || example.useCases.some((useCase) => selectedUseCases.includes(useCase))), ); };