Skip to content

Commit

Permalink
feat: created toggle and checkbox components and added stories for th…
Browse files Browse the repository at this point in the history
…em (#3082)

Co-authored-by: Akshat Nema <[email protected]>
  • Loading branch information
devilkiller-ag and akshatnema authored Aug 30, 2024
1 parent 04a2825 commit 51b23cd
Show file tree
Hide file tree
Showing 9 changed files with 213 additions and 37 deletions.
45 changes: 45 additions & 0 deletions components/tools/Checkbox.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useArgs } from '@storybook/preview-api';
import type { Meta, StoryObj } from '@storybook/react';

import type { CheckboxProps } from '@/types/components/tools/CheckboxPropsType';

import Checkbox from './Checkbox';

const meta: Meta<typeof Checkbox> = {
title: 'Components/Checkbox',
component: Checkbox
};

export default meta;

type Story = StoryObj<typeof Checkbox>;

export const DefaultCheckbox: Story = {
args: {
name: 'Check me!',
checked: true
},

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

const handleClickOption = () => {
updateArgs({ checked: !checked });
};

return <Checkbox {...args} checked={checked} handleClickOption={handleClickOption} />;
}
};

export const ColorfulCheckbox: Story = {
...DefaultCheckbox,

args: {
...DefaultCheckbox.args,
bgColor: 'bg-gray-200',
textColor: 'text-primary-500',
borderColor: 'border-primary-500',
checkedStateBgColor: 'bg-primary-500',
checkedStateTextColor: 'text-white'
}
};
40 changes: 40 additions & 0 deletions components/tools/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { twMerge } from 'tailwind-merge';

import type { CheckboxProps } from '@/types/components/tools/CheckboxPropsType';

/**
* This component renders a checkbox.
*/
const Checkbox = ({
name,
checked,
bgColor = 'bg-white',
textColor = 'text-secondary-600',
borderColor = 'border-secondary-600',
checkedStateBgColor = 'bg-secondary-600',
checkedStateTextColor = 'text-white',
handleClickOption
}: CheckboxProps) => {
const handleClick = (event: React.MouseEvent) => {
event.stopPropagation(); // Prevents the event from propagating to parent elements
handleClickOption(name);
};

return (
<div
className={twMerge(
`border ${borderColor} ${bgColor} ${textColor} p-1 pb-0 rounded-2xl flex gap-1 cursor-pointer items-start ${checked ? `${checkedStateBgColor} ${checkedStateTextColor}` : ''}`
)}
onClick={handleClick}
>
{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'>{name}</div>
</div>
);
};

export default Checkbox;
16 changes: 2 additions & 14 deletions components/tools/Filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import ArrowDown from '../icons/ArrowDown';
import { CardData } from './CardData';
import FiltersDisplay from './FiltersDisplay';
import FiltersDropdown from './FiltersDropdown';
import Toggle from './Toggle';

interface FiltersProps {
setOpenFilter: React.Dispatch<React.SetStateAction<boolean>>;
Expand Down Expand Up @@ -164,20 +165,7 @@ export default function Filters({ setOpenFilter }: FiltersProps) {
/>
</div>
<div className='flex gap-4'>
<label className='relative inline-flex cursor-pointer items-center'>
<input
type='checkbox'
value={isAsyncAPIOwner ? 'true' : 'false'}
className='peer sr-only'
onChange={() => setCheckOwner(!checkOwner)}
/>
<div
className={twMerge(
`w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all ${checkOwner ? 'after:translate-x-full after:border-white bg-secondary-500' : ''}`
)}
></div>
</label>
<div className='text-sm font-medium'>Show only AsyncAPI-owned tools</div>
<Toggle checked={checkOwner} setChecked={setCheckOwner} label='Show only AsyncAPI-owned tools' />
</div>
</div>
<hr className='my-4' />
Expand Down
21 changes: 4 additions & 17 deletions components/tools/FiltersDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ 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 {
Expand All @@ -25,7 +27,7 @@ export default function FiltersDropdown({
setCheckedOptions,
className = ''
}: FiltersDropdownProps) {
const handleClickOption = (event: React.MouseEvent, option: string) => {
const handleClickOption = (option: string) => {
const isChecked = checkedOptions.includes(option);
const updatedOptions = isChecked ? checkedOptions.filter((item) => item !== option) : [...checkedOptions, option];

Expand All @@ -40,22 +42,7 @@ export default function FiltersDropdown({
{dataList.map((data, index) => {
const checked = checkedOptions.includes(data.name);

return (
<div
key={index}
className={twMerge(
`border border-secondary-600 text-secondary-600 p-1 pb-0 rounded-2xl flex gap-1 cursor-pointer items-start ${checked ? 'bg-secondary-600 text-white' : ''}`
)}
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>
);
return <Checkbox key={index} name={data.name} checked={checked} handleClickOption={handleClickOption} />;
})}
</div>
);
Expand Down
42 changes: 42 additions & 0 deletions components/tools/Toggle.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useArgs } from '@storybook/preview-api';
import type { Meta, StoryObj } from '@storybook/react';

import type { ToggleProps } from '@/types/components/tools/TogglePropsType';

import Toggle from './Toggle';

const meta: Meta<typeof Toggle> = {
title: 'Components/Toggle',
component: Toggle
};

export default meta;

type Story = StoryObj<typeof Toggle>;

export const DefaultToggle: Story = {
args: {
checked: true,
label: 'Toggle me!'
},

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

const setChecked = () => {
updateArgs({ checked: !checked });
};

return <Toggle {...args} checked={checked} setChecked={setChecked} />;
}
};

export const ColorfulToggle: Story = {
...DefaultToggle,

args: {
...DefaultToggle.args,
bgColor: 'bg-gray-200',
checkedStateBgColor: 'bg-primary-500'
}
};
33 changes: 33 additions & 0 deletions components/tools/Toggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { twMerge } from 'tailwind-merge';

import type { ToggleProps } from '@/types/components/tools/TogglePropsType';

/**
* Toggle component for displaying and controlling a toggle switch.
*/
const Toggle = ({
checked,
setChecked,
label,
bgColor = 'bg-gray-200',
checkedStateBgColor = 'bg-secondary-500'
}: ToggleProps) => {
return (
<label className='relative inline-flex cursor-pointer items-center'>
<input
type='checkbox'
value={checked ? 'true' : 'false'}
className='peer sr-only'
onChange={() => setChecked(!checked)}
/>
<div
className={twMerge(
`w-11 h-6 ${bgColor} peer-focus:outline-none rounded-full peer after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all ${checked ? `after:translate-x-full after:border-white ${checkedStateBgColor}` : ''}`
)}
></div>
{label && <div className='ml-2 text-sm font-medium'>{label}</div>}
</label>
);
};

export default Toggle;
8 changes: 2 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions types/components/tools/CheckboxPropsType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export interface CheckboxProps {
// eslint-disable-next-line prettier/prettier

/** The name to be displayed inside the checkbox. */
name: string;

/** If the checkbox is checked or not. */
checked: boolean;

/** The background color of the checkbox. */
bgColor?: string;

/** The text color of the checkbox. */
textColor?: string;

/** The border color of the checkbox. */
borderColor?: string;

/** The background color of the checkbox when it is checked. */
checkedStateBgColor?: string;

/** The text color of the checkbox when it is checked. */
checkedStateTextColor?: string;

/** Function to handle the click event of the checkbox. */
handleClickOption: (name: string) => void;
}
18 changes: 18 additions & 0 deletions types/components/tools/TogglePropsType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export interface ToggleProps {
// eslint-disable-next-line prettier/prettier

/** Current state of the toggle. */
checked: boolean;

/** Function to update the toggle state. */
setChecked: React.Dispatch<React.SetStateAction<boolean>>;

/** Label text for the toggle. */
label?: string;

/** The background color of the checkbox. */
bgColor?: string;

/** The background color of the checkbox when it is checked. */
checkedStateBgColor?: string;
}

0 comments on commit 51b23cd

Please sign in to comment.