@umituz/web-design-system 1.3.1 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/web-design-system",
3
- "version": "1.3.1",
3
+ "version": "1.5.1",
4
4
  "private": false,
5
5
  "description": "Web Design System - Atomic Design components (Atoms, Molecules, Organisms, Templates) for React applications",
6
6
  "main": "./src/index.ts",
@@ -52,15 +52,20 @@
52
52
  "url": "git+https://github.com/umituz/web-design-system.git"
53
53
  },
54
54
  "peerDependencies": {
55
+ "@radix-ui/react-accordion": ">=1.0.0",
56
+ "@radix-ui/react-select": ">=2.0.0",
57
+ "clsx": ">=2.0.0",
55
58
  "react": ">=18.0.0",
56
59
  "react-dom": ">=18.0.0",
57
- "clsx": ">=2.0.0",
58
60
  "tailwind-merge": ">=2.0.0"
59
61
  },
60
62
  "devDependencies": {
63
+ "@radix-ui/react-accordion": "^1.2.12",
64
+ "@radix-ui/react-select": "^2.2.6",
61
65
  "@types/react": "^18.0.0",
62
66
  "@types/react-dom": "^18.0.0",
63
67
  "clsx": "^2.1.1",
68
+ "lucide-react": "^0.577.0",
64
69
  "react": "^18.0.0",
65
70
  "react-dom": "^18.0.0",
66
71
  "tailwind-merge": "^3.5.0",
@@ -1,16 +1,13 @@
1
1
  /**
2
2
  * Avatar Component (Molecule)
3
- * @description User avatar with fallback
3
+ * @description User avatar with image and fallback (shadcn/ui compatible)
4
4
  */
5
5
 
6
- import { forwardRef, type HTMLAttributes } from 'react';
6
+ import { forwardRef, type HTMLAttributes, type ElementType, type ComponentPropsWithoutRef } from 'react';
7
7
  import { cn } from '../../infrastructure/utils';
8
8
  import type { BaseProps, SizeVariant } from '../../domain/types';
9
9
 
10
10
  export interface AvatarProps extends HTMLAttributes<HTMLDivElement>, BaseProps {
11
- src?: string;
12
- alt?: string;
13
- fallback?: string;
14
11
  size?: Extract<SizeVariant, 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'>;
15
12
  }
16
13
 
@@ -23,30 +20,61 @@ const sizeStyles: Record<'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl', string> = {
23
20
  '2xl': 'h-20 w-20 text-2xl',
24
21
  };
25
22
 
26
- export const Avatar = forwardRef<HTMLDivElement, AvatarProps>(
27
- ({ className, src, alt, fallback, size = 'md', ...props }, ref) => {
28
- const hasError = !src;
29
-
23
+ const Avatar = forwardRef<HTMLDivElement, AvatarProps>(
24
+ ({ className, size = 'md', ...props }, ref) => {
30
25
  return (
31
26
  <div
32
27
  ref={ref}
33
28
  className={cn(
34
- 'relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-muted',
29
+ 'relative flex shrink-0 overflow-hidden rounded-full',
35
30
  sizeStyles[size],
36
31
  className
37
32
  )}
38
33
  {...props}
39
- >
40
- {hasError ? (
41
- <span className="font-medium text-muted-foreground">
42
- {fallback || '?'}
43
- </span>
44
- ) : (
45
- <img src={src} alt={alt || 'Avatar'} className="h-full w-full object-cover" />
46
- )}
47
- </div>
34
+ />
48
35
  );
49
36
  }
50
37
  );
51
38
 
52
39
  Avatar.displayName = 'Avatar';
40
+
41
+ export interface AvatarImageProps extends ComponentPropsWithoutRef<'img'> {
42
+ asChild?: boolean;
43
+ }
44
+
45
+ const AvatarImage = forwardRef<HTMLImageElement, AvatarImageProps>(
46
+ ({ className, src, alt, ...props }, ref) => {
47
+ return (
48
+ <img
49
+ ref={ref}
50
+ src={src}
51
+ alt={alt}
52
+ className={cn('aspect-square h-full w-full object-cover', className)}
53
+ {...props}
54
+ />
55
+ );
56
+ }
57
+ );
58
+
59
+ AvatarImage.displayName = 'AvatarImage';
60
+
61
+ export interface AvatarFallbackProps extends HTMLAttributes<HTMLDivElement> {}
62
+
63
+ const AvatarFallback = forwardRef<HTMLDivElement, AvatarFallbackProps>(
64
+ ({ className, ...props }, ref) => {
65
+ return (
66
+ <div
67
+ ref={ref}
68
+ className={cn(
69
+ 'flex h-full w-full items-center justify-center rounded-full bg-muted',
70
+ className
71
+ )}
72
+ {...props}
73
+ />
74
+ );
75
+ }
76
+ );
77
+
78
+ AvatarFallback.displayName = 'AvatarFallback';
79
+
80
+ export { Avatar, AvatarImage, AvatarFallback };
@@ -1,41 +1,160 @@
1
1
  /**
2
2
  * Select Component (Molecule)
3
- * @description Dropdown select input
3
+ * @description Dropdown select (Shadcn/Radix UI compatible)
4
4
  */
5
5
 
6
- import { forwardRef, type SelectHTMLAttributes } from 'react';
6
+ import * as React from 'react';
7
+ import * as SelectPrimitive from '@radix-ui/react-select';
8
+ import { Check, ChevronDown, ChevronUp } from 'lucide-react';
7
9
  import { cn } from '../../infrastructure/utils';
8
- import type { BaseProps } from '../../domain/types';
9
-
10
- export interface SelectProps extends SelectHTMLAttributes<HTMLSelectElement>, BaseProps {
11
- error?: boolean;
12
- options: Array<{ value: string; label: string; disabled?: boolean }>;
13
- }
14
-
15
- export const Select = forwardRef<HTMLSelectElement, SelectProps>(
16
- ({ className, error, options, disabled, ...props }, ref) => {
17
- return (
18
- <select
19
- ref={ref}
20
- disabled={disabled}
10
+
11
+ const Select = SelectPrimitive.Root;
12
+
13
+ const SelectGroup = SelectPrimitive.Group;
14
+
15
+ const SelectValue = SelectPrimitive.Value;
16
+
17
+ const SelectTrigger = React.forwardRef<
18
+ React.ElementRef<typeof SelectPrimitive.Trigger>,
19
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
20
+ >(({ className, children, ...props }, ref) => (
21
+ <SelectPrimitive.Trigger
22
+ ref={ref}
23
+ className={cn(
24
+ 'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
25
+ className
26
+ )}
27
+ {...props}
28
+ >
29
+ {children}
30
+ <SelectPrimitive.Icon asChild>
31
+ <ChevronDown className="h-4 w-4 opacity-50" />
32
+ </SelectPrimitive.Icon>
33
+ </SelectPrimitive.Trigger>
34
+ ));
35
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
36
+
37
+ const SelectScrollUpButton = React.forwardRef<
38
+ React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
39
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
40
+ >(({ className, ...props }, ref) => (
41
+ <SelectPrimitive.ScrollUpButton
42
+ ref={ref}
43
+ className={cn(
44
+ 'flex cursor-default items-center justify-center py-1',
45
+ className
46
+ )}
47
+ {...props}
48
+ >
49
+ <ChevronUp className="h-4 w-4" />
50
+ </SelectPrimitive.ScrollUpButton>
51
+ ));
52
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
53
+
54
+ const SelectScrollDownButton = React.forwardRef<
55
+ React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
56
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
57
+ >(({ className, ...props }, ref) => (
58
+ <SelectPrimitive.ScrollDownButton
59
+ ref={ref}
60
+ className={cn(
61
+ 'flex cursor-default items-center justify-center py-1',
62
+ className
63
+ )}
64
+ {...props}
65
+ >
66
+ <ChevronDown className="h-4 w-4" />
67
+ </SelectPrimitive.ScrollDownButton>
68
+ ));
69
+ SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
70
+
71
+ const SelectContent = React.forwardRef<
72
+ React.ElementRef<typeof SelectPrimitive.Content>,
73
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
74
+ >(({ className, children, position = 'popper', ...props }, ref) => (
75
+ <SelectPrimitive.Portal>
76
+ <SelectPrimitive.Content
77
+ ref={ref}
78
+ className={cn(
79
+ 'relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
80
+ position === 'popper' &&
81
+ 'data-[side=bottom]:translate-y-1 data-[side=left]:translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:translate-y-1',
82
+ className
83
+ )}
84
+ position={position}
85
+ {...props}
86
+ >
87
+ <SelectScrollUpButton />
88
+ <SelectPrimitive.Viewport
21
89
  className={cn(
22
- 'flex h-9 w-full rounded-md border border-input bg-background px-3 py-2',
23
- 'text-sm ring-offset-background',
24
- 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
25
- 'disabled:cursor-not-allowed disabled:opacity-50',
26
- error && 'border-destructive',
27
- className
90
+ 'p-1',
91
+ position === 'popper' &&
92
+ 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]'
28
93
  )}
29
- {...props}
30
94
  >
31
- {options.map((option) => (
32
- <option key={option.value} value={option.value} disabled={option.disabled}>
33
- {option.label}
34
- </option>
35
- ))}
36
- </select>
37
- );
38
- }
39
- );
40
-
41
- Select.displayName = 'Select';
95
+ {children}
96
+ </SelectPrimitive.Viewport>
97
+ <SelectScrollDownButton />
98
+ </SelectPrimitive.Content>
99
+ </SelectPrimitive.Portal>
100
+ ));
101
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
102
+
103
+ const SelectLabel = React.forwardRef<
104
+ React.ElementRef<typeof SelectPrimitive.Label>,
105
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
106
+ >(({ className, ...props }, ref) => (
107
+ <SelectPrimitive.Label
108
+ ref={ref}
109
+ className={cn('py-1.5 pl-8 pr-2 text-sm font-semibold', className)}
110
+ {...props}
111
+ />
112
+ ));
113
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
114
+
115
+ const SelectItem = React.forwardRef<
116
+ React.ElementRef<typeof SelectPrimitive.Item>,
117
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
118
+ >(({ className, children, ...props }, ref) => (
119
+ <SelectPrimitive.Item
120
+ ref={ref}
121
+ className={cn(
122
+ 'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
123
+ className
124
+ )}
125
+ {...props}
126
+ >
127
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
128
+ <SelectPrimitive.ItemIndicator>
129
+ <Check className="h-4 w-4" />
130
+ </SelectPrimitive.ItemIndicator>
131
+ </span>
132
+ {children}
133
+ </SelectPrimitive.Item>
134
+ ));
135
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
136
+
137
+ const SelectSeparator = React.forwardRef<
138
+ React.ElementRef<typeof SelectPrimitive.Separator>,
139
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
140
+ >(({ className, ...props }, ref) => (
141
+ <SelectPrimitive.Separator
142
+ ref={ref}
143
+ className={cn('-mx-1 my-1 h-px bg-muted', className)}
144
+ {...props}
145
+ />
146
+ ));
147
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
148
+
149
+ export {
150
+ Select,
151
+ SelectGroup,
152
+ SelectValue,
153
+ SelectTrigger,
154
+ SelectContent,
155
+ SelectLabel,
156
+ SelectItem,
157
+ SelectSeparator,
158
+ SelectScrollUpButton,
159
+ SelectScrollDownButton,
160
+ };
@@ -10,8 +10,8 @@ export type { FormFieldProps } from './FormField';
10
10
  export { SearchBox } from './SearchBox';
11
11
  export type { SearchBoxProps } from './SearchBox';
12
12
 
13
- export { Avatar } from './Avatar';
14
- export type { AvatarProps } from './Avatar';
13
+ export { Avatar, AvatarImage, AvatarFallback } from './Avatar';
14
+ export type { AvatarProps, AvatarImageProps, AvatarFallbackProps } from './Avatar';
15
15
 
16
16
  export { Chip } from './Chip';
17
17
  export type { ChipProps } from './Chip';
@@ -19,7 +19,7 @@ export type { ChipProps } from './Chip';
19
19
  export { Toggle } from './Toggle';
20
20
  export type { ToggleProps } from './Toggle';
21
21
 
22
- export { Select } from './Select';
22
+ export { Select, SelectGroup, SelectValue, SelectTrigger, SelectContent, SelectLabel, SelectItem, SelectSeparator, SelectScrollUpButton, SelectScrollDownButton } from './Select';
23
23
  export type { SelectProps } from './Select';
24
24
 
25
25
  export { Textarea } from './Textarea';
@@ -1,117 +1,59 @@
1
1
  /**
2
2
  * Accordion Component (Organism)
3
- * @description Collapsible content sections
3
+ * @description Collapsible content sections (Shadcn/ui compatible)
4
4
  */
5
5
 
6
- import { useState, useCallback, type ReactNode, type HTMLAttributes } from 'react';
6
+ import * as React from 'react';
7
+ import * as AccordionPrimitive from '@radix-ui/react-accordion';
8
+ import { ChevronDown } from 'lucide-react';
7
9
  import { cn } from '../../infrastructure/utils';
8
- import type { BaseProps } from '../../domain/types';
9
- import { Icon } from '../atoms/Icon';
10
10
 
11
- export interface AccordionItem {
12
- value: string;
13
- title: string;
14
- content: ReactNode;
15
- disabled?: boolean;
16
- }
17
-
18
- export interface AccordionProps extends HTMLAttributes<HTMLDivElement>, BaseProps {
19
- items: AccordionItem[];
20
- allowMultiple?: boolean;
21
- defaultValue?: string[];
22
- variant?: 'default' | 'bordered' | 'ghost';
23
- }
24
-
25
- const variantStyles: Record<'default' | 'bordered' | 'ghost', string> = {
26
- default: 'border-b',
27
- bordered: 'border rounded-lg mb-2',
28
- ghost: 'border-0',
29
- };
30
-
31
- export function Accordion({
32
- items,
33
- allowMultiple = false,
34
- defaultValue = [],
35
- variant = 'default',
36
- className,
37
- ...props
38
- }: AccordionProps) {
39
- const [openItems, setOpenItems] = useState<string[]>(defaultValue);
40
-
41
- const toggleItem = useCallback((value: string) => {
42
- setOpenItems((prev) => {
43
- const isOpen = prev.includes(value);
44
-
45
- if (allowMultiple) {
46
- return isOpen
47
- ? prev.filter((v) => v !== value)
48
- : [...prev, value];
49
- } else {
50
- return isOpen ? [] : [value];
51
- }
52
- });
53
- }, [allowMultiple]);
54
-
55
- return (
56
- <div className={cn('w-full', className)} {...props}>
57
- {items.map((item, index) => {
58
- const isOpen = openItems.includes(item.value);
59
-
60
- return (
61
- <div
62
- key={item.value}
63
- className={cn(
64
- 'group',
65
- variantStyles[variant],
66
- variant === 'bordered' && isOpen && 'ring-1 ring-ring'
67
- )}
68
- >
69
- {/* Header */}
70
- <button
71
- onClick={() => toggleItem(item.value)}
72
- disabled={item.disabled}
73
- className={cn(
74
- 'flex w-full items-center justify-between py-4 font-medium transition-all',
75
- 'hover:text-foreground',
76
- item.disabled && 'opacity-50 cursor-not-allowed',
77
- variant === 'bordered' && 'px-4'
78
- )}
79
- >
80
- <span>{item.title}</span>
81
- <Icon
82
- className={cn(
83
- 'transition-transform duration-200',
84
- isOpen && 'rotate-180'
85
- )}
86
- size="sm"
87
- >
88
- <path
89
- strokeLinecap="round"
90
- strokeLinejoin="round"
91
- d="M19.5 8.25l-7.5 7.5-7.5-7.5"
92
- />
93
- </Icon>
94
- </button>
95
-
96
- {/* Content */}
97
- {isOpen && (
98
- <div
99
- className={cn(
100
- 'overflow-hidden',
101
- 'animate-accordion-down',
102
- variant === 'bordered' && 'px-4 pb-4'
103
- )}
104
- >
105
- <div className="pb-4 text-sm text-muted-foreground">
106
- {item.content}
107
- </div>
108
- </div>
109
- )}
110
- </div>
111
- );
112
- })}
113
- </div>
114
- );
115
- }
116
-
117
- Accordion.displayName = 'Accordion';
11
+ const Accordion = AccordionPrimitive.Root;
12
+
13
+ const AccordionItem = React.forwardRef<
14
+ React.ElementRef<typeof AccordionPrimitive.Item>,
15
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
16
+ >(({ className, ...props }, ref) => (
17
+ <AccordionPrimitive.Item
18
+ ref={ref}
19
+ className={cn('border-b', className)}
20
+ {...props}
21
+ />
22
+ ));
23
+ AccordionItem.displayName = 'AccordionItem';
24
+
25
+ const AccordionTrigger = React.forwardRef<
26
+ React.ElementRef<typeof AccordionPrimitive.Trigger>,
27
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
28
+ >(({ className, children, ...props }, ref) => (
29
+ <AccordionPrimitive.Header className="flex">
30
+ <AccordionPrimitive.Trigger
31
+ ref={ref}
32
+ className={cn(
33
+ 'flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180',
34
+ className
35
+ )}
36
+ {...props}
37
+ >
38
+ {children}
39
+ <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
40
+ </AccordionPrimitive.Trigger>
41
+ </AccordionPrimitive.Header>
42
+ ));
43
+ AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
44
+
45
+ const AccordionContent = React.forwardRef<
46
+ React.ElementRef<typeof AccordionPrimitive.Content>,
47
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
48
+ >(({ className, children, ...props }, ref) => (
49
+ <AccordionPrimitive.Content
50
+ ref={ref}
51
+ className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
52
+ {...props}
53
+ >
54
+ <div className={cn('pb-4 pt-0', className)}>{children}</div>
55
+ </AccordionPrimitive.Content>
56
+ ));
57
+ AccordionContent.displayName = AccordionPrimitive.Content.displayName;
58
+
59
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
@@ -1,96 +1,63 @@
1
1
  /**
2
2
  * Alert Component (Organism)
3
- * @description Feedback message with icon
3
+ * @description Feedback message (Shadcn/ui compatible)
4
4
  */
5
5
 
6
- import { forwardRef, type HTMLAttributes } from 'react';
6
+ import * as React from 'react';
7
+ import { cva, type VariantProps } from 'class-variance-authority';
7
8
  import { cn } from '../../infrastructure/utils';
8
- import type { BaseProps, ChildrenProps, ColorVariant } from '../../domain/types';
9
- import { Icon } from '../atoms/Icon';
10
9
 
11
- export type AlertVariant = Extract<ColorVariant, 'success' | 'warning' | 'destructive'> | 'info';
12
-
13
- export interface AlertProps extends HTMLAttributes<HTMLDivElement>, BaseProps {
14
- variant?: AlertVariant;
15
- showIcon?: boolean;
16
- }
10
+ const alertVariants = cva(
11
+ 'relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground',
12
+ {
13
+ variants: {
14
+ variant: {
15
+ default: 'bg-background text-foreground',
16
+ destructive: 'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive',
17
+ },
18
+ },
19
+ defaultVariants: {
20
+ variant: 'default',
21
+ },
22
+ }
23
+ );
17
24
 
18
- const variantStyles: Record<AlertVariant, { container: string; iconColor: string }> = {
19
- success: {
20
- container: 'border-success bg-success/10 text-success',
21
- iconColor: 'text-success',
22
- },
23
- warning: {
24
- container: 'border-warning bg-warning/10 text-warning',
25
- iconColor: 'text-warning',
26
- },
27
- destructive: {
28
- container: 'border-destructive bg-destructive/10 text-destructive',
29
- iconColor: 'text-destructive',
30
- },
31
- info: {
32
- container: 'border-primary bg-primary/10 text-primary',
33
- iconColor: 'text-primary',
34
- },
35
- };
25
+ export interface AlertProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof alertVariants> {}
36
26
 
37
- const icons: Record<AlertVariant, React.ReactNode> = {
38
- success: (
39
- <path
40
- strokeLinecap="round"
41
- strokeLinejoin="round"
42
- d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
43
- />
44
- ),
45
- warning: (
46
- <path
47
- strokeLinecap="round"
48
- strokeLinejoin="round"
49
- d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"
50
- />
51
- ),
52
- destructive: (
53
- <path
54
- strokeLinecap="round"
55
- strokeLinejoin="round"
56
- d="M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"
57
- />
58
- ),
59
- info: (
60
- <path
61
- strokeLinecap="round"
62
- strokeLinejoin="round"
63
- d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z"
27
+ const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
28
+ ({ className, variant, ...props }, ref) => (
29
+ <div
30
+ ref={ref}
31
+ role="alert"
32
+ className={cn(alertVariants({ variant }), className)}
33
+ {...props}
64
34
  />
65
- ),
66
- };
67
-
68
- export const Alert = forwardRef<HTMLDivElement, AlertProps>(
69
- ({ className, variant = 'info', showIcon = true, children, ...props }, ref) => {
70
- const styles = variantStyles[variant];
71
-
72
- return (
73
- <div
74
- ref={ref}
75
- role="alert"
76
- className={cn(
77
- 'relative w-full rounded-lg border p-4',
78
- styles.container,
79
- className
80
- )}
81
- {...props}
82
- >
83
- <div className="flex items-start gap-3">
84
- {showIcon && (
85
- <Icon className={cn('shrink-0 mt-0.5', styles.iconColor)} size="sm">
86
- {icons[variant]}
87
- </Icon>
88
- )}
89
- <div className="flex-1">{children}</div>
90
- </div>
91
- </div>
92
- );
93
- }
35
+ )
94
36
  );
95
-
96
37
  Alert.displayName = 'Alert';
38
+
39
+ const AlertTitle = React.forwardRef<
40
+ HTMLParagraphElement,
41
+ React.HTMLAttributes<HTMLHeadingElement>
42
+ >(({ className, ...props }, ref) => (
43
+ <h5
44
+ ref={ref}
45
+ className={cn('mb-1 font-medium leading-none tracking-tight', className)}
46
+ {...props}
47
+ />
48
+ ));
49
+ AlertTitle.displayName = 'AlertTitle';
50
+
51
+ const AlertDescription = React.forwardRef<
52
+ HTMLParagraphElement,
53
+ React.HTMLAttributes<HTMLParagraphElement>
54
+ >(({ className, ...props }, ref) => (
55
+ <div
56
+ ref={ref}
57
+ className={cn('text-sm [&_p]:leading-relaxed', className)}
58
+ {...props}
59
+ />
60
+ ));
61
+ AlertDescription.displayName = 'AlertDescription';
62
+
63
+ export { Alert, AlertTitle, AlertDescription };
@@ -7,8 +7,8 @@
7
7
  export { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from './Card';
8
8
  export type { CardProps } from './Card';
9
9
 
10
- export { Alert } from './Alert';
11
- export type { AlertProps, AlertVariant } from './Alert';
10
+ export { Alert, AlertTitle, AlertDescription } from './Alert';
11
+ export type { AlertProps } from './Alert';
12
12
 
13
13
  export { Modal, ModalHeader, ModalTitle, ModalDescription, ModalContent, ModalFooter } from './Modal';
14
14
  export type { ModalProps } from './Modal';
@@ -31,8 +31,7 @@ export type { TableProps } from './Table';
31
31
  export { Tabs } from './Tabs';
32
32
  export type { TabsProps, Tab } from './Tabs';
33
33
 
34
- export { Accordion } from './Accordion';
35
- export type { AccordionProps, AccordionItem } from './Accordion';
34
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from './Accordion';
36
35
 
37
36
  export { Breadcrumbs } from './Breadcrumb';
38
37
  export type { BreadcrumbsProps, BreadcrumbItem } from './Breadcrumb';