From 2e53d2ebcf629c57bd17864bd91f10e50c2002b9 Mon Sep 17 00:00:00 2001 From: Michal Zielenkiewicz Date: Fri, 15 Aug 2025 12:12:27 +0200 Subject: [PATCH 1/2] Create custom Alert component --- src/components/alert/index.tsx | 62 +++++++++++++++++++++++++++++ src/stories/Alert/Alert.stories.tsx | 35 ++++++++++------ 2 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 src/components/alert/index.tsx diff --git a/src/components/alert/index.tsx b/src/components/alert/index.tsx new file mode 100644 index 00000000..2675e958 --- /dev/null +++ b/src/components/alert/index.tsx @@ -0,0 +1,62 @@ +import { FC } from 'react' +import { CircleAlert, Info, TriangleAlert } from 'lucide-react' +import { cva, type VariantProps } from 'class-variance-authority' +import { cn } from '../../lib/utils' +import { Alert as BaseAlert, AlertDescription, AlertTitle } from '../ui/alert' + +const alertVariants = cva('p-2 md:p-4 gap-1 rounded-lg border', { + variants: { + variant: { + info: 'bg-background border-border', + error: 'bg-background border-destructive dark:border-[#7F2424] text-destructive', + warning: 'bg-background border-warning/50 text-warning', + 'error-filled': 'bg-destructive/10 border-destructive dark:border-[#7F2424] text-destructive', + 'warning-filled': + 'bg-yellow-50 border-warning/50 text-warning dark:bg-yellow-900/10 dark:border-yellow-900/50 dark:text-yellow-500', + }, + }, + defaultVariants: { + variant: 'info', + }, +}) + +type AlertProps = { + className?: string + title?: string + children?: React.ReactNode + sticky?: boolean +} & VariantProps + +export const Alert: FC = ({ className, title, variant = 'info', sticky = false, children }) => { + const iconMap = { + info: Info, + error: CircleAlert, + warning: TriangleAlert, + 'error-filled': CircleAlert, + 'warning-filled': TriangleAlert, + } + const Icon = iconMap[variant || 'info'] + + return ( + + +
+ {title && {title}} + {children} +
+
+ ) +} diff --git a/src/stories/Alert/Alert.stories.tsx b/src/stories/Alert/Alert.stories.tsx index 7c3a7688..2ba0d386 100644 --- a/src/stories/Alert/Alert.stories.tsx +++ b/src/stories/Alert/Alert.stories.tsx @@ -1,6 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react-vite' -import { Alert, AlertDescription, AlertTitle } from '../../components/ui/alert.tsx' -import { InfoIcon } from 'lucide-react' +import { Alert } from '../../components/alert' import { expect, within } from 'storybook/test' const meta: Meta = { @@ -19,23 +18,33 @@ const meta: Meta = { }, }, tags: ['autodocs'], + argTypes: { + variant: { + control: 'select', + options: ['info', 'error', 'warning', 'error-filled', 'warning-filled'], + description: 'The variant of the alert', + table: { + defaultValue: { summary: 'info' }, + }, + }, + sticky: { + control: 'boolean', + description: 'Makes the alert stick to the top of its container', + table: { + defaultValue: { summary: 'false' }, + }, + }, + }, } export default meta type Story = StoryObj -export const Default: Story = { +export const Info: Story = { args: { - children: ( - <> - - Information - - Alert description provides additional information about the alert. - - - ), - variant: 'default', + children: <>Alert description provides additional information about the alert., + variant: 'info', + title: '', }, play: async ({ canvasElement }) => { const canvas = within(canvasElement) From 25b7edf122b960051a8c5e6f43b6756f5c1b51a1 Mon Sep 17 00:00:00 2001 From: Michal Zielenkiewicz Date: Mon, 18 Aug 2025 12:59:24 +0200 Subject: [PATCH 2/2] Add success variant to Alert component --- src/components/alert/index.tsx | 8 ++++++-- src/stories/Alert/Alert.stories.tsx | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/alert/index.tsx b/src/components/alert/index.tsx index 2675e958..32c435b1 100644 --- a/src/components/alert/index.tsx +++ b/src/components/alert/index.tsx @@ -1,5 +1,5 @@ import { FC } from 'react' -import { CircleAlert, Info, TriangleAlert } from 'lucide-react' +import { CircleAlert, CircleCheck, Info, TriangleAlert } from 'lucide-react' import { cva, type VariantProps } from 'class-variance-authority' import { cn } from '../../lib/utils' import { Alert as BaseAlert, AlertDescription, AlertTitle } from '../ui/alert' @@ -13,6 +13,8 @@ const alertVariants = cva('p-2 md:p-4 gap-1 rounded-lg border', { 'error-filled': 'bg-destructive/10 border-destructive dark:border-[#7F2424] text-destructive', 'warning-filled': 'bg-yellow-50 border-warning/50 text-warning dark:bg-yellow-900/10 dark:border-yellow-900/50 dark:text-yellow-500', + success: 'bg-background border-success text-success', + 'success-filled': 'bg-success/10 border-success text-success', }, }, defaultVariants: { @@ -30,9 +32,11 @@ type AlertProps = { export const Alert: FC = ({ className, title, variant = 'info', sticky = false, children }) => { const iconMap = { info: Info, + success: CircleCheck, + 'success-filled': CircleCheck, error: CircleAlert, - warning: TriangleAlert, 'error-filled': CircleAlert, + warning: TriangleAlert, 'warning-filled': TriangleAlert, } const Icon = iconMap[variant || 'info'] diff --git a/src/stories/Alert/Alert.stories.tsx b/src/stories/Alert/Alert.stories.tsx index 2ba0d386..43994fe7 100644 --- a/src/stories/Alert/Alert.stories.tsx +++ b/src/stories/Alert/Alert.stories.tsx @@ -21,7 +21,7 @@ const meta: Meta = { argTypes: { variant: { control: 'select', - options: ['info', 'error', 'warning', 'error-filled', 'warning-filled'], + options: ['info', 'success', 'success-filled', 'warning', 'warning-filled', 'error', 'error-filled'], description: 'The variant of the alert', table: { defaultValue: { summary: 'info' },