diff --git a/.github/workflows/deploy-storybook.yml b/.github/workflows/deploy-storybook.yml
index be0edcd..735acf5 100644
--- a/.github/workflows/deploy-storybook.yml
+++ b/.github/workflows/deploy-storybook.yml
@@ -39,4 +39,7 @@ jobs:
run: yarn build
- name: Deploy Storybook to GitHub Pages
- run: npx gh-pages -d storybook-static -b storybook-ui
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ npx gh-pages -d storybook-static -b storybook-ui -r https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }}.git
diff --git a/src/components/baseDialog/BaseDialog.tsx b/src/components/baseDialog/BaseDialog.tsx
new file mode 100644
index 0000000..c75349f
--- /dev/null
+++ b/src/components/baseDialog/BaseDialog.tsx
@@ -0,0 +1,116 @@
+import { IconWeight, X } from '@phosphor-icons/react';
+
+export interface BaseDialogProps {
+ isOpen: boolean;
+ title?: string;
+ hideCloseButton?: boolean;
+ subTitle?: string;
+ dialogRounded?: boolean;
+ children: JSX.Element | JSX.Element[];
+ classes?: string;
+ titleClasses?: string;
+ panelClasses?: string;
+ closeClass?: string;
+ weightIcon?: IconWeight;
+ bgColor?: string;
+ onClose: () => void;
+ dataTest?: string;
+}
+
+/**
+ * BaseDialog component
+ *
+ * @property {boolean} isOpen
+ * - Controls whether the dialog is open or closed. If true, the dialog is visible.
+ *
+ * @property {string} [title]
+ * - The title of the dialog, displayed at the top of the dialog box.
+ *
+ * @property {boolean} [hideCloseButton]
+ * - If true, hides the close button (X icon) in the top right corner of the dialog.
+ *
+ * @property {string} [subTitle]
+ * - A subtitle for the dialog, displayed below the title.
+ *
+ * @property {boolean} [dialogRounded]
+ * - If true, applies a more rounded corner style to the dialog.
+ *
+ * @property {JSX.Element | JSX.Element[]} children
+ * - The content to be displayed inside the dialog. Can be a single JSX element or an array of elements.
+ *
+ * @property {string} [classes]
+ * - Custom classes for the outermost container of the dialog. Allows additional styling like margins or padding.
+ *
+ * @property {string} [titleClasses]
+ * - Custom classes for styling the title element. Can modify font size, weight, etc.
+ *
+ * @property {string} [panelClasses]
+ * - Custom classes for the main dialog panel, where the content is displayed.
+ *
+ * @property {string} [closeClass]
+ * - Custom classes for the close button, allowing for customization of the button's appearance.
+ *
+ * @property {IconWeight} [weightIcon]
+ * - Controls the thickness of the close button icon (X). Options range from "thin" to "bold".
+ *
+ * @property {string} [bgColor]
+ * - Custom background color for the dialog. Defaults to a light surface color if not provided.
+ *
+ * @property {() => void} onClose
+ * - Callback function triggered when the close button or overlay is clicked, used to close the dialog.
+ */
+
+const BaseDialog = ({
+ isOpen,
+ title,
+ subTitle,
+ dialogRounded,
+ children,
+ onClose,
+ classes,
+ panelClasses,
+ titleClasses,
+ closeClass,
+ weightIcon,
+ bgColor,
+ dataTest,
+ hideCloseButton,
+}: BaseDialogProps): JSX.Element => {
+ return (
+
+
+
+ {title ? (
+
+
+ {title}
+
+ {subTitle}
+
+ ) : null}
+ {hideCloseButton ? null : (
+
+
+
+ )}
+
+ {children}
+
+
+ );
+};
+
+export default BaseDialog;
diff --git a/src/components/baseDialog/__test__/BaseDialog.test.tsx b/src/components/baseDialog/__test__/BaseDialog.test.tsx
new file mode 100644
index 0000000..1f81ee7
--- /dev/null
+++ b/src/components/baseDialog/__test__/BaseDialog.test.tsx
@@ -0,0 +1,94 @@
+import React from 'react';
+import { render, fireEvent } from '@testing-library/react';
+import { afterEach, describe, expect, it, vi } from 'vitest';
+import BaseDialog from '../BaseDialog';
+
+describe('BaseDialog', () => {
+ const onCloseMock = vi.fn();
+ const defaultProps = {
+ title: 'Dialog Title',
+ subTitle: 'This is a subtitle',
+ isOpen: true,
+ onClose: onCloseMock,
+ children:
Dialog content
,
+ };
+ const renderBaseDialog = (props = {}) => render();
+
+ afterEach(() => {
+ vi.clearAllMocks();
+ });
+
+ it('should match snapshot', () => {
+ const baseDialog = renderBaseDialog();
+ expect(baseDialog).toMatchSnapshot();
+ });
+
+ it('should render the dialog when isOpen is true', () => {
+ const { container } = renderBaseDialog();
+ expect(container.firstChild).toHaveClass('flex');
+ });
+
+ it('should not render the dialog when isOpen is false', () => {
+ const { container } = renderBaseDialog({ isOpen: false });
+ expect(container.firstChild).toHaveClass('hidden');
+ });
+
+ it('should trigger onClose when the close button is clicked', () => {
+ const { getByRole } = renderBaseDialog();
+ const closeButton = getByRole('button');
+
+ fireEvent.click(closeButton);
+ expect(onCloseMock).toHaveBeenCalledTimes(1);
+ });
+
+ it('should apply custom class names correctly', () => {
+ const { container } = renderBaseDialog({ classes: 'custom-class' });
+ expect(container.firstChild).toHaveClass('custom-class');
+ });
+
+ it('should render the title and subtitle when provided', () => {
+ const { getByText } = renderBaseDialog();
+
+ expect(getByText('Dialog Title')).toBeInTheDocument();
+ expect(getByText('This is a subtitle')).toBeInTheDocument();
+ });
+
+ it('should not render the title div when title is not provided', () => {
+ const { container } = renderBaseDialog({ title: undefined });
+ const titleDiv = container.querySelector('[title]');
+ expect(titleDiv).not.toBeInTheDocument();
+ });
+
+ it('should not render the subtitle when subTitle is not provided', () => {
+ const { container } = renderBaseDialog({ subTitle: undefined });
+ const subTitleElement = container.querySelector('.justify-between.bg-gray-1.p-5');
+ expect(subTitleElement).not.toBeInTheDocument();
+ });
+
+ it('should render children content inside the dialog', () => {
+ const { getByText } = renderBaseDialog();
+ expect(getByText('Dialog content')).toBeInTheDocument();
+ });
+
+ it('should hide close button when hideCloseButton is true', () => {
+ const { queryByRole } = renderBaseDialog({ hideCloseButton: true });
+ expect(queryByRole('button')).toBeNull();
+ });
+
+ it('should apply the bgColor prop if provided', () => {
+ const { container } = renderBaseDialog({ bgColor: 'bg-red' });
+ expect(container.firstChild?.firstChild).toHaveClass('bg-red');
+ });
+
+ it('should render with rounded-2xl class when dialogRounded is true', () => {
+ const { container } = renderBaseDialog({ dialogRounded: true });
+ const dialogPanel = container.querySelector('.rounded-2xl');
+ expect(dialogPanel).toBeInTheDocument();
+ });
+
+ it('should render with rounded-lg and pt-8 classes when dialogRounded is false', () => {
+ const { container } = renderBaseDialog({ dialogRounded: false });
+ const dialogPanel = container.querySelector('.rounded-lg.pt-8');
+ expect(dialogPanel).toBeInTheDocument();
+ });
+});
diff --git a/src/components/baseDialog/__test__/__snapshots__/BaseDialog.test.tsx.snap b/src/components/baseDialog/__test__/__snapshots__/BaseDialog.test.tsx.snap
new file mode 100644
index 0000000..831d09c
--- /dev/null
+++ b/src/components/baseDialog/__test__/__snapshots__/BaseDialog.test.tsx.snap
@@ -0,0 +1,160 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`BaseDialog > should match snapshot 1`] = `
+{
+ "asFragment": [Function],
+ "baseElement":
+