Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1,797 changes: 1,119 additions & 678 deletions package-lock.json

Large diffs are not rendered by default.

46 changes: 23 additions & 23 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,40 +32,40 @@
"@fortawesome/react-fontawesome": "0.2.2",
"@hookform/resolvers": "4.1.0",
"@react-spring/web": "9.7.5",
"@tailwindcss/vite": "4.0.6",
"@tanstack/react-query": "5.66.2",
"@tanstack/react-query-devtools": "5.66.2",
"@tailwindcss/vite": "4.0.7",
"@tanstack/react-query": "5.66.9",
"@tanstack/react-query-devtools": "5.66.9",
"@tanstack/react-table": "8.21.2",
"axios": "1.7.9",
"class-variance-authority": "0.7.1",
"clsx": "2.1.1",
"dayjs": "1.11.13",
"i18next": "24.2.2",
"i18next-browser-languagedetector": "8.0.3",
"i18next-browser-languagedetector": "8.0.4",
"lodash": "4.17.21",
"qs": "6.14.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-hook-form": "7.54.2",
"react-i18next": "15.4.0",
"react-router-dom": "7.1.5",
"react-i18next": "15.4.1",
"react-router-dom": "7.2.0",
"recharts": "2.15.1",
"tailwind-merge": "3.0.1",
"tailwindcss": "4.0.6",
"uuid": "11.0.5",
"tailwindcss": "4.0.7",
"uuid": "11.1.0",
"yup": "1.6.1"
},
"devDependencies": {
"@chromatic-com/storybook": "3.2.4",
"@eslint/js": "9.20.0",
"@storybook/addon-essentials": "8.5.6",
"@storybook/addon-interactions": "8.5.6",
"@storybook/addon-onboarding": "8.5.6",
"@storybook/addon-themes": "8.5.6",
"@storybook/blocks": "8.5.6",
"@storybook/react": "8.5.6",
"@storybook/react-vite": "8.5.6",
"@storybook/test": "8.5.6",
"@storybook/addon-essentials": "8.5.8",
"@storybook/addon-interactions": "8.5.8",
"@storybook/addon-onboarding": "8.5.8",
"@storybook/addon-themes": "8.5.8",
"@storybook/blocks": "8.5.8",
"@storybook/react": "8.5.8",
"@storybook/react-vite": "8.5.8",
"@storybook/test": "8.5.8",
"@testing-library/jest-dom": "6.6.3",
"@testing-library/react": "16.2.0",
"@testing-library/user-event": "14.6.1",
Expand All @@ -76,21 +76,21 @@
"@types/react-dom": "18.3.1",
"@types/uuid": "10.0.0",
"@vitejs/plugin-react": "4.3.4",
"@vitest/coverage-v8": "3.0.5",
"@vitest/coverage-v8": "3.0.6",
"eslint": "9.20.1",
"eslint-plugin-react-hooks": "5.1.0",
"eslint-plugin-react-refresh": "0.4.19",
"eslint-plugin-storybook": "0.11.3",
"globals": "15.15.0",
"globals": "16.0.0",
"jsdom": "26.0.0",
"msw": "2.7.0",
"msw": "2.7.1",
"prettier": "3.5.1",
"prettier-plugin-tailwindcss": "0.6.11",
"rimraf": "6.0.1",
"storybook": "8.5.6",
"storybook": "8.5.8",
"typescript": "5.7.3",
"typescript-eslint": "8.24.0",
"vite": "6.1.0",
"vitest": "3.0.5"
"typescript-eslint": "8.24.1",
"vite": "6.1.1",
"vitest": "3.0.6"
}
}
33 changes: 25 additions & 8 deletions src/common/components/Alert/Alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import { cn } from 'common/utils/css';
/**
* Define the component base and variant styles.
*/
const variants = cva('flex items-center gap-2 rounded-md p-3', {
const variants = cva('flex gap-2 rounded-md p-3', {
variants: {
variant: {
error: 'bg-red-800/90 text-white/80',
danger: 'bg-red-800/90 text-white/80',
info: 'bg-neutral-200/90 text-slate-900',
success: 'bg-green-800/90 text-white/80',
warning: 'bg-amber-400/90 text-slate-900',
Expand All @@ -26,18 +26,35 @@ type AlertVariants = VariantProps<typeof variants>;

/**
* Properties for the `Alert` component.
* @see {@link PropsWithChildren}
* @see {@link BaseComponentProps}
*/
export interface AlertProps extends AlertVariants, PropsWithChildren, BaseComponentProps {}

/**
* The `Alert` React component formats and renders a styled message. Use the
* The `Alert` component formats and renders a styled message. Use the
* `variant` property to apply predefined styles.
* @param {AlertProps} props - Component properties, `AlertProps`.
* @returns {JSX.Element} JSX
*
* Compose an Alert using of combinations of: `FAIcon`, `AlertContent`,
* `AlertHeader`, `AlertTitle`, and `AlertDescription`.
*
* *Example:*
* ```
* <Alert variant="danger" className="my-4" testId="task-create-alert">
* <FAIcon icon="circleExclamation" size="lg" />
* <AlertContent>
* <AlertHeader>
* <AlertTitle>Unable to create task</AlertTitle>
* </AlertHeader>
* <AlertDescription>{error.message}</AlertDescription>
* </AlertContent>
* </Alert>
* ```
*/
const Alert = ({ children, className, variant, testId = 'alert' }: AlertProps): JSX.Element => {
const Alert = ({
children,
className,
variant = 'info',
testId = 'alert',
}: AlertProps): JSX.Element => {
return (
<div className={cn(variants({ variant, className }))} role="alert" data-testid={testId}>
{children}
Expand Down
28 changes: 28 additions & 0 deletions src/common/components/Alert/AlertContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { PropsWithChildren } from 'react';

import { BaseComponentProps } from 'common/utils/types';
import { cn } from 'common/utils/css';

/**
* Properties for the `AlertContent` component.
*/
export interface AlertContentProps extends BaseComponentProps, PropsWithChildren {}

/**
* The `AlertContent` component is a container for the main content of an
* `Alert`. AlertContent wraps the AlertHeader and AlertDescription. AlertContent
* is not used outside an `Alert`.
*/
const AlertContent = ({
children,
className,
testId = 'alert-content',
}: AlertContentProps): JSX.Element => {
return (
<div className={cn(className)} data-testid={testId}>
{children}
</div>
);
};

export default AlertContent;
27 changes: 27 additions & 0 deletions src/common/components/Alert/AlertDescription.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { PropsWithChildren } from 'react';

import { cn } from 'common/utils/css';
import { BaseComponentProps } from 'common/utils/types';

/**
* Properties for the `AlertDescription` component.
*/
export interface AlertDescriptionProps extends BaseComponentProps, PropsWithChildren {}

/**
* The `AlertDescription` component renders the styled description text for an
* `Alert`.
*/
const AlertDescription = ({
children,
className,
testId = 'alert-description',
}: AlertDescriptionProps): JSX.Element => {
return (
<div className={cn('leading-tight', className)} data-testid={testId}>
{children}
</div>
);
};

export default AlertDescription;
28 changes: 28 additions & 0 deletions src/common/components/Alert/AlertHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { PropsWithChildren } from 'react';

import { BaseComponentProps } from 'common/utils/types';
import { cn } from 'common/utils/css';

/**
* Properties for the `AlertHeader` component.
*/
export interface AlertHeaderProps extends BaseComponentProps, PropsWithChildren {}

/**
* The `AlertHeader` component is a container for the title and, optionally, the
* icon of an `Alert`. AlertHeader is a flex box ensuring the items within are evenly
* spaced and centered.
*/
const AlertHeader = ({
children,
className,
testId = 'alert-header',
}: AlertHeaderProps): JSX.Element => {
return (
<div className={cn('mb-1 flex items-center gap-2', className)} data-testid={testId}>
{children}
</div>
);
};

export default AlertHeader;
27 changes: 27 additions & 0 deletions src/common/components/Alert/AlertTitle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { PropsWithChildren } from 'react';

import { BaseComponentProps } from 'common/utils/types';
import { cn } from 'common/utils/css';

/**
* Properties for the `AlertTitle` component.
*/
export interface AlertTitleProps extends BaseComponentProps, PropsWithChildren {}

/**
* The `AlertTitle` component renders the styled title text for an `Alert`.
* AlertTitle is always within an `AlertHeader`.
*/
const AlertTitle = ({
children,
className,
testId = 'alert-title',
}: AlertTitleProps): JSX.Element => {
return (
<div className={cn('text-xl leading-none font-bold', className)} data-testid={testId}>
{children}
</div>
);
};

export default AlertTitle;
46 changes: 46 additions & 0 deletions src/common/components/Alert/ErrorAlert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { cn } from 'common/utils/css';
import FAIcon, { FAIconProps } from '../Icon/FAIcon';
import Alert, { AlertProps } from './Alert';
import AlertContent from './AlertContent';
import AlertDescription from './AlertDescription';
import AlertHeader from './AlertHeader';
import AlertTitle from './AlertTitle';

/**
* Properties for the `ErrorAlert` component.
*/
export interface ErrorAlertProps
extends Omit<AlertProps, 'variant'>,
Partial<Pick<FAIconProps, 'icon'>> {
title?: string;
description: string;
}

/**
* The `ErrorAlert` component renders a bespoke `Alert` layout for error
* messages.
*/
const ErrorAlert = ({
className,
description,
icon = 'circleExclamation',
testId = 'alert-error',
title,
...props
}: ErrorAlertProps): JSX.Element => {
return (
<Alert variant="danger" className={cn(className)} testId={testId} {...props}>
<FAIcon icon={icon} size="lg" testId={`${testId}-icon`} />
<AlertContent testId={`${testId}-content`}>
{!!title && (
<AlertHeader testId={`${testId}-header`}>
<AlertTitle testId={`${testId}-title`}>{title}</AlertTitle>
</AlertHeader>
)}
<AlertDescription testId={`${testId}-description`}>{description}</AlertDescription>
</AlertContent>
</Alert>
);
};

export default ErrorAlert;
Loading
Loading