diff --git a/components/buttons/Button.stories.tsx b/components/buttons/Button.stories.tsx new file mode 100644 index 00000000000..a38eb40977f --- /dev/null +++ b/components/buttons/Button.stories.tsx @@ -0,0 +1,138 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import { ButtonIconPosition, ButtonSize, ButtonType } from '@/types/components/buttons/ButtonPropsType'; + +import AsyncAPI from '../icons/AsyncAPI'; +import Button from './Button'; + +const meta: Meta = { + title: 'Components/Buttons', + component: Button, + argTypes: { + text: { + control: { type: 'text' } + }, + type: { + options: Object.values(ButtonType), + control: { type: 'select' } + }, + buttonSize: { + options: Object.values(ButtonSize), + control: { type: 'select' } + }, + className: { + control: { type: 'text' } + }, + bgClassName: { + control: { type: 'text' } + }, + textClassName: { + control: { type: 'text' } + }, + icon: { + options: ['AsyncAPI Icon'], + mapping: { + 'AsyncAPI Icon': + } + }, + iconPosition: { + options: Object.values(ButtonIconPosition), + control: { type: 'select' } + }, + target: { + control: { type: 'text' } + } + } +}; + +export default meta; + +type Story = StoryObj; + +export const DefaultButton: Story = { + args: { + text: 'Default', + className: 'bg-gray-200 hover:bg-gray-100 text-gray-900' + } +}; + +export const PrimaryButton: Story = { + args: { + text: 'Primary' + } +}; + +export const SecondaryButton: Story = { + args: { + text: 'Secondary', + className: 'border border-secondary-500 bg-secondary-100 text-secondary-500 hover:bg-secondary-500 hover:text-white' + } +}; + +export const SubmitButton: Story = { + args: { + text: 'Submit', + type: ButtonType.SUBMIT + } +}; + +export const ResetButton: Story = { + args: { + text: 'Reset', + type: ButtonType.RESET + } +}; + +export const SmallButton: Story = { + args: { + text: 'Reset', + buttonSize: ButtonSize.SMALL + } +}; + +export const SuccessButton: Story = { + args: { + text: 'Success', + className: 'bg-[#2db84c] hover:bg-[#36de5b]' + } +}; + +export const WarningButton: Story = { + args: { + text: 'Warning', + className: 'bg-[#fbc000] hover:bg-[#ffd400]' + } +}; + +export const ErrorButton: Story = { + args: { + text: 'Error', + className: 'bg-[#e25a71] hover:bg-[#ff6575]' + } +}; + +export const ButtonWithIconOnLeft: Story = { + args: { + text: 'AsyncAPI icon on left', + className: 'flex items-center justify-center', + icon: 'AsyncAPI Icon', + iconPosition: ButtonIconPosition.LEFT + } +}; + +export const ButtonWithIconOnRight: Story = { + args: { + text: 'AsyncAPI icon on right', + className: 'flex items-center justify-center', + icon: 'AsyncAPI Icon', + iconPosition: ButtonIconPosition.RIGHT + } +}; + +export const ButtonWithOnlyIcon: Story = { + args: { + className: 'flex items-center justify-center', + icon: 'AsyncAPI Icon', + iconPosition: ButtonIconPosition.LEFT + } +}; diff --git a/components/buttons/Button.tsx b/components/buttons/Button.tsx index a6d4f62ddf9..2b4a30412c3 100644 --- a/components/buttons/Button.tsx +++ b/components/buttons/Button.tsx @@ -4,16 +4,38 @@ import { twMerge } from 'tailwind-merge'; import { ButtonIconPosition, ButtonSize, ButtonType } from '@/types/components/buttons/ButtonPropsType'; type IButtonProps = { + // eslint-disable-next-line prettier/prettier + + /** The text to be displayed on the button. */ text: string; + + /** The type of the button. Defaults to 'button'. */ + type?: ButtonType; + + /** The size of the button. Defaults to 'default'. */ + buttonSize?: ButtonSize; + + /** The class name to be applied to the button. */ + className?: string; + + /** The class name to be applied to the button's background. */ + bgClassName?: string; + + /** The class name to be applied to the button's text. */ + textClassName?: string; + + /** The icon to be displayed on the button. */ icon?: React.ReactNode; + + /** The position of the icon. Defaults to 'right'. */ iconPosition?: ButtonIconPosition; + + /** The target attribute for the anchor tag. Defaults to '_self'. */ target?: string; - bgClassName?: string; - textClassName?: string; - buttonSize?: ButtonSize; - type?: ButtonType; } & ( | ({ + // eslint-disable-next-line prettier/prettier + /** The href attribute for the anchor tag. */ href: string; } & React.AnchorHTMLAttributes) | ({ @@ -22,20 +44,9 @@ type IButtonProps = { ); /** - * @name Button - * @param {string} props.text - The text to be displayed on the button. - * @param {ButtonType} props.type - The type of the button. Defaults to 'button'. - * @param {string} props.target - The target attribute for the anchor tag. Defaults to '_self'. - * @param {React.ReactNode} props.icon - The icon to be displayed on the button. - * @param {ButtonIconPosition} props.iconPosition - The position of the icon. Defaults to 'right'. - * @param {string} props.className - The class name to be applied to the button. - * @param {string} props.bgClassName - The class name to be applied to the button's background. - * @param {string} props.textClassName - The class name to be applied to the button's text. - * @param {ButtonSize} props.buttonSize - The size of the button. Defaults to 'default'. - * @param {string} props.href - The href attribute for the anchor tag. - * @description The Button component is a reusable button component that can be used to render a button or an anchor tag - * @description The component accepts button or anchor tag props based on the presence of the href prop. - * @description If the href prop is present, the component will render an anchor tag, + * The Button component is a reusable button component that can be used to render a button or an anchor tag. + * The component accepts button or anchor tag props based on the presence of the href prop. + * If the href prop is present, the component will render an anchor tag, * otherwise it will render a button tag. */ export default function Button({ @@ -44,7 +55,7 @@ export default function Button({ target = '_self', icon, iconPosition = ButtonIconPosition.RIGHT, - className, + className = '', bgClassName = twMerge('bg-primary-500 hover:bg-primary-400'), textClassName = twMerge('text-white'), buttonSize, diff --git a/components/buttons/GithubButton.tsx b/components/buttons/GithubButton.tsx index d4ba248b331..571972d0869 100644 --- a/components/buttons/GithubButton.tsx +++ b/components/buttons/GithubButton.tsx @@ -1,9 +1,9 @@ import { ButtonIconPosition, ButtonSize } from '@/types/components/buttons/ButtonPropsType'; +import type { IButtonDefaultProps } from '../../types/components/buttons/types'; import { useTranslation } from '../../utils/i18n'; import IconGithub from '../icons/Github'; import Button from './Button'; -import type { IButtonDefaultProps } from './types'; interface IGithubButtonProps extends IButtonDefaultProps { inNav?: boolean; @@ -22,7 +22,7 @@ export default function GithubButton({ href = 'https://github.com/asyncapi', target = '_blank', iconPosition = ButtonIconPosition.LEFT, - className, + className = '', inNav }: IGithubButtonProps) { const { t } = useTranslation('common'); diff --git a/components/buttons/GoogleCalendarButton.tsx b/components/buttons/GoogleCalendarButton.tsx index d0329443fa4..114b60fb450 100644 --- a/components/buttons/GoogleCalendarButton.tsx +++ b/components/buttons/GoogleCalendarButton.tsx @@ -1,9 +1,9 @@ import { ButtonIconPosition } from '@/types/components/buttons/ButtonPropsType'; +import type { IButtonDefaultProps } from '../../types/components/buttons/types'; import { useTranslation } from '../../utils/i18n'; import IconGoogleCalendar from '../icons/GoogleCalendar'; import Button from './Button'; -import type { IButtonDefaultProps } from './types'; interface IGoogleCalendarButtonProps extends IButtonDefaultProps {} diff --git a/components/buttons/ICSFileButton.tsx b/components/buttons/ICSFileButton.tsx index 63609bacf69..ad03fac4d13 100644 --- a/components/buttons/ICSFileButton.tsx +++ b/components/buttons/ICSFileButton.tsx @@ -1,9 +1,9 @@ import { ButtonIconPosition } from '@/types/components/buttons/ButtonPropsType'; +import type { IButtonDefaultProps } from '../../types/components/buttons/types'; import { useTranslation } from '../../utils/i18n'; import IconCalendar from '../icons/Calendar'; import Button from './Button'; -import type { IButtonDefaultProps } from './types'; interface IICSFButtonProps extends IButtonDefaultProps {} diff --git a/components/buttons/SlackButton.tsx b/components/buttons/SlackButton.tsx index 270afc7c2e6..e30a87c2722 100644 --- a/components/buttons/SlackButton.tsx +++ b/components/buttons/SlackButton.tsx @@ -1,8 +1,8 @@ import { ButtonIconPosition } from '@/types/components/buttons/ButtonPropsType'; +import type { IButtonDefaultProps } from '../../types/components/buttons/types'; import IconSlack from '../icons/Slack'; import Button from './Button'; -import type { IButtonDefaultProps } from './types'; interface ISlackButtonProps extends IButtonDefaultProps {} @@ -19,7 +19,7 @@ export default function SlackButton({ href = '/slack-invite', target = '_blank', iconPosition = ButtonIconPosition.LEFT, - className + className = '' }: ISlackButtonProps) { return (