Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5eda3ab
updated filters dropdown in tools
ashmitjsg Aug 29, 2024
08ce480
Merge branch 'master' into update-filters-dropdown
ashmitjsg Aug 29, 2024
67023b9
added stories for filters dropdown
ashmitjsg Sep 4, 2024
bf0d3c0
Merge branch 'master' into update-filters-dropdown
ashmitjsg Sep 4, 2024
5d83bdc
Merge branch 'master' into update-filters-dropdown
asyncapi-bot Sep 6, 2024
8d2b79d
Merge branch 'master' into update-filters-dropdown
ashmitjsg Sep 14, 2024
88db099
Merge branch 'master' into update-filters-dropdown
ashmitjsg Sep 15, 2024
bd3efbb
Merge branch 'master' into update-filters-dropdown
ashmitjsg Sep 17, 2024
09a5c76
Merge branch 'master' of https://github.com/asyncapi/website into upd…
ashmitjsg Sep 24, 2024
3d94fcd
Merge branch 'asyncapi:master' into update-filters-dropdown
ashmitjsg Sep 28, 2024
776008a
Merge branch 'asyncapi:master' into update-filters-dropdown
ashmitjsg Sep 30, 2024
1903c13
Merge branch 'master' of https://github.com/asyncapi/website into upd…
ashmitjsg Jan 6, 2025
f501d55
fixed ci issue, and updated the design
ashmitjsg Jan 6, 2025
36dcfd3
Merge branch 'asyncapi:master' into update-filters-dropdown
ashmitjsg Jan 8, 2025
9971ea0
Merge branch 'master' into update-filters-dropdown
ashmitjsg Jan 21, 2025
50ea482
Merge branch 'asyncapi:master' into update-filters-dropdown
ashmitjsg Jan 31, 2025
e4e5a7b
feat: shortened filters dropdown height and added functionality to pe…
ashmitjsg Jan 31, 2025
ec9aa51
fix: lint issue
ashmitjsg Jan 31, 2025
a39e73e
Merge branch 'master' into update-filters-dropdown
ashmitjsg Feb 10, 2025
6643255
Merge branch 'master' into update-filters-dropdown
ashmitjsg Mar 28, 2025
294f1e1
Merge branch 'master' into update-filters-dropdown
ashmitjsg Apr 15, 2025
89687a7
refactor(filters): simplify dropdown toggle logic in Filters component
ashmitjsg Apr 15, 2025
9540743
refactor: fix lint issue
ashmitjsg Apr 15, 2025
57cf809
Merge branch 'master' into update-filters-dropdown
TRohit20 Apr 17, 2025
13f5a35
Merge branch 'master' of https://github.com/devilkiller-ag/asyncapi-w…
ashmitjsg Oct 25, 2025
6602037
Merge branch 'master' into update-filters-dropdown
anshgoyalevil Dec 18, 2025
096dee0
add addons package correctly
milesxporter Dec 18, 2025
364b747
fix import
milesxporter Dec 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 32 additions & 15 deletions components/tools/Filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ interface FiltersProps {
setOpenFilter: React.Dispatch<React.SetStateAction<boolean>>;
}

enum OpenedFiltersDropdownType {
NONE = '',
LANGUAGE = 'language',
TECHNOLOGY = 'technology',
CATEGORY = 'category'
}

/**
* @description This component displays Filters.
* @param {FiltersProps} props - Props for Filters component.
Expand All @@ -30,9 +37,9 @@ export default function Filters({ setOpenFilter }: FiltersProps) {
const { isPaid, isAsyncAPIOwner, languages, technologies, categories } = useContext(ToolFilterContext);

// State variables to operate dropdowns of respective filters
const [openLanguage, setopenLanguage] = useState<boolean>(false);
const [openTechnology, setopenTechnology] = useState<boolean>(false);
const [openCategory, setopenCategory] = useState<boolean>(false);
const [openedFiltersDropown, setOpenedFiltersDropown] = useState<OpenedFiltersDropdownType>(
OpenedFiltersDropdownType.NONE
);

// Filter state variables for user checked values are created, initialising it with the values already set by user.
const [checkPaid, setCheckPaid] = useState<string>(isPaid);
Expand Down Expand Up @@ -113,6 +120,10 @@ export default function Filters({ setOpenFilter }: FiltersProps) {
setCheckOwner(isAsyncAPIOwner);
};

const toggleDropdown = (dropdownType: OpenedFiltersDropdownType) => {
setOpenedFiltersDropown(openedFiltersDropown === dropdownType ? OpenedFiltersDropdownType.NONE : dropdownType);
};

return (
<ToolFilter>
<div className='z-20 rounded-lg border border-gray-300 bg-white py-4 shadow-md' data-testid='Filters-div'>
Expand Down Expand Up @@ -183,9 +194,9 @@ export default function Filters({ setOpenFilter }: FiltersProps) {
<div className='w-full'>
<div
className={twMerge(
`px-4 py-2 flex justify-between rounded-lg border border-gray-400 w-full bg-gray-200 text-gray-700 shadow text-sm cursor-pointer ${openLanguage ? 'rounded-b-none' : ''}`
`px-4 py-2 flex justify-between rounded-lg border border-gray-400 w-full bg-gray-200 text-gray-700 shadow text-sm cursor-pointer ${openedFiltersDropown === OpenedFiltersDropdownType.LANGUAGE ? 'rounded-b-none' : ''}`
)}
onClick={() => setopenLanguage(!openLanguage)}
onClick={() => toggleDropdown(OpenedFiltersDropdownType.LANGUAGE)}
>
<div className='flex items-center text-dark'>
{/* eslint-disable-next-line no-nested-ternary */}
Expand All @@ -195,9 +206,11 @@ export default function Filters({ setOpenFilter }: FiltersProps) {
: `${checkedLanguage.length} options selected`
: 'Select Languages...'}
</div>
<ArrowDown className={`my-auto ${openLanguage ? 'rotate-180' : ''}`} />
<ArrowDown
className={`my-auto ${openedFiltersDropown === OpenedFiltersDropdownType.LANGUAGE ? 'rotate-180' : ''}`}
/>
</div>
{openLanguage && (
{openedFiltersDropown === OpenedFiltersDropdownType.LANGUAGE && (
<div className='w-auto overflow-x-auto rounded-b-lg border border-gray-400 bg-gray-200 duration-150'>
<FiltersDropdown
dataList={languageList}
Expand All @@ -223,9 +236,9 @@ export default function Filters({ setOpenFilter }: FiltersProps) {
<div className='w-full'>
<div
className={twMerge(
`px-4 py-2 flex justify-between rounded-lg border border-gray-400 w-full bg-gray-200 text-gray-700 shadow text-sm cursor-pointer ${openTechnology ? 'rounded-b-none' : ''}`
`px-4 py-2 flex justify-between rounded-lg border border-gray-400 w-full bg-gray-200 text-gray-700 shadow text-sm cursor-pointer ${openedFiltersDropown === OpenedFiltersDropdownType.TECHNOLOGY ? 'rounded-b-none' : ''}`
)}
onClick={() => setopenTechnology(!openTechnology)}
onClick={() => toggleDropdown(OpenedFiltersDropdownType.TECHNOLOGY)}
>
<div className='flex items-center text-dark'>
{/* eslint-disable-next-line no-nested-ternary */}
Expand All @@ -235,9 +248,11 @@ export default function Filters({ setOpenFilter }: FiltersProps) {
: `${checkedTechnology.length} options selected`
: 'Select Technologies...'}
</div>
<ArrowDown className={`my-auto ${openTechnology ? 'rotate-180' : ''}`} />
<ArrowDown
className={`my-auto ${openedFiltersDropown === OpenedFiltersDropdownType.TECHNOLOGY ? 'rotate-180' : ''}`}
/>
</div>
{openTechnology && (
{openedFiltersDropown === OpenedFiltersDropdownType.TECHNOLOGY && (
<div className='w-auto overflow-x-auto rounded-b-lg border border-gray-400 bg-gray-200 duration-150'>
<FiltersDropdown
dataList={technologyList}
Expand All @@ -263,9 +278,9 @@ export default function Filters({ setOpenFilter }: FiltersProps) {
<div className='w-full'>
<div
className={twMerge(
`px-4 py-2 flex justify-between rounded-lg border border-gray-400 w-full bg-gray-200 text-gray-700 shadow text-sm cursor-pointer ${openCategory ? 'rounded-b-none' : ''}`
`px-4 py-2 flex justify-between rounded-lg border border-gray-400 w-full bg-gray-200 text-gray-700 shadow text-sm cursor-pointer ${openedFiltersDropown === OpenedFiltersDropdownType.CATEGORY ? 'rounded-b-none' : ''}`
)}
onClick={() => setopenCategory(!openCategory)}
onClick={() => toggleDropdown(OpenedFiltersDropdownType.CATEGORY)}
>
<div className='flex items-center text-dark'>
{/* eslint-disable-next-line no-nested-ternary */}
Expand All @@ -275,9 +290,11 @@ export default function Filters({ setOpenFilter }: FiltersProps) {
: `${checkedCategory.length} options selected`
: 'Select Categories...'}
</div>
<ArrowDown className={`my-auto ${openCategory ? 'rotate-180' : ''}`} />
<ArrowDown
className={`my-auto ${openedFiltersDropown === OpenedFiltersDropdownType.CATEGORY ? 'rotate-180' : ''}`}
/>
</div>
{openCategory && (
{openedFiltersDropown === OpenedFiltersDropdownType.CATEGORY && (
<div className='w-auto overflow-x-auto rounded-b-lg border border-gray-400 bg-gray-200 duration-150'>
<FiltersDropdown
dataList={categoryList}
Expand Down
76 changes: 76 additions & 0 deletions components/tools/FiltersDropdown.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { useArgs } from '@storybook/preview-api';
import type { Meta, StoryObj } from '@storybook/react';
import React from 'react';

import type { Language, Technology } from '@/types/components/tools/ToolDataType';

import tags from '../../config/all-tags.json';
import FiltersDropdown from './FiltersDropdown';

const meta: Meta<typeof FiltersDropdown> = {
title: 'Components/FiltersDropdown',
component: FiltersDropdown,
argTypes: {
dataList: {
control: false
},
checkedOptions: {
control: {
type: 'object'
}
},
setCheckedOptions: {
control: false
}
}
};

export default meta;

type Story = StoryObj<typeof FiltersDropdown>;

const Dropdown: Story = {
args: {
checkedOptions: []
},

render: (args) => {
const [{ checkedOptions }, updateArgs] = useArgs();

const setCheckedOptions: React.Dispatch<React.SetStateAction<string[]>> = (newValue) => {
if (typeof newValue === 'function') {
const updatedValue = (newValue as (prevState: string[]) => string[])(checkedOptions);

updateArgs({ checkedOptions: updatedValue });
} else {
updateArgs({ checkedOptions: newValue });
}
};

return <FiltersDropdown {...args} checkedOptions={checkedOptions} setCheckedOptions={setCheckedOptions} />;
}
};

const languageList = tags.languages as Language[];

export const LanguageDropdown: Story = {
...Dropdown,

args: {
...Dropdown.args,
dataList: languageList,
checkedOptions: []
}
};

const technologyList = tags.technologies as Technology[];

export const TechnologyDropdown: Story = {
...Dropdown,

args: {
...Dropdown.args,
dataList: technologyList,
checkedOptions: []
}
};
27 changes: 21 additions & 6 deletions components/tools/FiltersDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ import { twMerge } from 'tailwind-merge';

import type { Category, Language, Technology } from '@/types/components/tools/ToolDataType';

import Checkbox from './Checkbox';

type DataList = Language[] | Technology[] | Category[];

interface FiltersDropdownProps {
export interface FiltersDropdownProps {
dataList?: DataList;
checkedOptions?: string[];
setCheckedOptions: React.Dispatch<React.SetStateAction<string[]>>;
Expand All @@ -28,7 +26,7 @@ export default function FiltersDropdown({
setCheckedOptions,
className = ''
}: FiltersDropdownProps) {
const handleClickOption = (option: string) => {
const handleClickOption = (event: React.MouseEvent<HTMLDivElement, MouseEvent>, option: string) => {
const isChecked = checkedOptions.includes(option);
const updatedOptions = isChecked ? checkedOptions.filter((item) => item !== option) : [...checkedOptions, option];

Expand All @@ -37,13 +35,30 @@ export default function FiltersDropdown({

return (
<div
className={twMerge(`max-w-lg flex gap-2 flex-wrap p-2 duration-200 delay-150 ${className}`)}
className={twMerge(
`max-w-lg flex flex-col max-h-[20vh] gap-1 overflow-y-auto p-2 px-0 duration-200 delay-150 bg-gray-200 ${className}`
)}
data-testid='FiltersDropdown-div'
>
{dataList.map((data, index) => {
const checked = checkedOptions.includes(data.name);

return <Checkbox key={index} name={data.name} checked={checked} handleClickOption={handleClickOption} />;
return (
<div
key={index}
className={twMerge(
`hover:bg-gray-300 text-black p-1 py-2 gap-1 flex cursor-pointer items-start ${checked ? 'bg-gray-400' : ''}`
)}
onClick={(event) => handleClickOption(event, data.name)}
>
{checked ? (
<img src='/img/illustrations/icons/CheckedIcon.svg' alt='checked' />
) : (
<img src='/img/illustrations/icons/UncheckedIcon.svg' alt='unchecked' />
)}
<div className='-mt-px mb-px text-xs'>{data.name}</div>
</div>
);
})}
</div>
);
Expand Down
Loading
Loading