@umituz/web-design-system 2.7.2 → 2.9.0

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.
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * QuickActionCard Component (Organism)
3
- * @description Card component for quick navigation actions with icon
3
+ * @description Card component for quick navigation actions with icon (Responsive)
4
4
  */
5
5
 
6
6
  import { forwardRef } from 'react';
7
- import { cn } from '../../infrastructure/utils';
7
+ import { cn, getSpacing, getIconSize, getContainerSize, getTextSize, getGap } from '../../infrastructure/utils';
8
8
  import type { BaseProps, SizeVariant } from '../../domain/types';
9
9
 
10
10
  export interface QuickActionCardProps extends BaseProps {
@@ -16,32 +16,9 @@ export interface QuickActionCardProps extends BaseProps {
16
16
  href?: string;
17
17
  size?: Extract<SizeVariant, 'sm' | 'md' | 'lg'>;
18
18
  target?: '_blank' | '_self' | '_parent' | '_top';
19
+ responsiveLayout?: boolean; // Enable responsive layout changes
19
20
  }
20
21
 
21
- const sizeStyles = {
22
- sm: 'p-3 gap-2',
23
- md: 'p-4 gap-3',
24
- lg: 'p-5 gap-4',
25
- };
26
-
27
- const iconSizeStyles = {
28
- sm: 'w-8 h-8',
29
- md: 'w-10 h-10',
30
- lg: 'w-12 h-12',
31
- };
32
-
33
- const iconInnerSizeStyles = {
34
- sm: 'h-4 w-4',
35
- md: 'h-5 w-5',
36
- lg: 'h-6 w-6',
37
- };
38
-
39
- const labelSizeStyles = {
40
- sm: 'text-xs',
41
- md: 'text-sm',
42
- lg: 'text-base',
43
- };
44
-
45
22
  export const QuickActionCard = forwardRef<HTMLAnchorElement | HTMLDivElement, QuickActionCardProps>(
46
23
  (
47
24
  {
@@ -54,6 +31,7 @@ export const QuickActionCard = forwardRef<HTMLAnchorElement | HTMLDivElement, Qu
54
31
  href,
55
32
  size = 'md',
56
33
  target = '_self',
34
+ responsiveLayout = true,
57
35
  ...props
58
36
  },
59
37
  ref
@@ -61,11 +39,15 @@ export const QuickActionCard = forwardRef<HTMLAnchorElement | HTMLDivElement, Qu
61
39
  const content = (
62
40
  <>
63
41
  {Icon && (
64
- <div className={cn(iconSizeStyles[size], 'rounded-lg flex items-center justify-center flex-shrink-0', iconBgColor)}>
65
- <Icon className={cn(iconInnerSizeStyles[size], iconColor)} />
42
+ <div className={cn(getContainerSize(size), 'rounded-lg flex items-center justify-center flex-shrink-0', iconBgColor)}>
43
+ <Icon className={cn(getIconSize(size), iconColor)} />
66
44
  </div>
67
45
  )}
68
- <span className={cn('font-medium text-foreground group-hover:text-primary transition-colors', labelSizeStyles[size])}>
46
+ <span className={cn(
47
+ 'font-medium text-foreground group-hover:text-primary transition-colors',
48
+ getTextSize(size),
49
+ responsiveLayout && 'text-center sm:text-left'
50
+ )}>
69
51
  {label}
70
52
  </span>
71
53
  </>
@@ -73,9 +55,10 @@ export const QuickActionCard = forwardRef<HTMLAnchorElement | HTMLDivElement, Qu
73
55
 
74
56
  const baseClasses = cn(
75
57
  'bg-card border border-border rounded-xl',
76
- 'flex items-center',
77
- 'hover:border-primary/50 transition-colors group',
78
- sizeStyles[size],
58
+ responsiveLayout ? 'flex flex-col sm:flex-row items-center justify-center sm:justify-start' : 'flex items-center',
59
+ 'hover:border-primary/50 hover:shadow-md transition-all duration-200 group',
60
+ getSpacing('p', size),
61
+ getGap(size === 'sm' ? 'sm' : size),
79
62
  className
80
63
  );
81
64
 
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * StatCard Component (Organism)
3
- * @description Enhanced metric card with progress bar and target tracking
3
+ * @description Enhanced metric card with progress bar and target tracking (Responsive)
4
4
  * Combines functionality of KPICard and StatsCard from main app
5
5
  */
6
6
 
7
7
  import { forwardRef, type ComponentType } from 'react';
8
- import { cn } from '../../infrastructure/utils';
8
+ import { cn, getSpacing, getIconSize, getContainerSize, getTextSize, getSpaceY, getGap } from '../../infrastructure/utils';
9
9
  import { Card, CardContent } from './Card';
10
10
  import { Progress } from '../atoms';
11
11
  import { ArrowUpRight, ArrowDownRight } from 'lucide-react';
@@ -28,39 +28,10 @@ export interface StatCardProps extends BaseProps {
28
28
  variant?: 'default' | 'gradient' | 'elevated';
29
29
  trendValueFormatter?: (value: number) => string;
30
30
  onClick?: () => void;
31
- changeLabel?: string; // For backward compatibility with StatsCard
31
+ changeLabel?: string;
32
+ responsiveLayout?: boolean;
32
33
  }
33
34
 
34
- const sizeStyles = {
35
- sm: 'p-3',
36
- md: 'p-4',
37
- lg: 'p-6',
38
- };
39
-
40
- const valueSizeStyles = {
41
- sm: 'text-lg',
42
- md: 'text-2xl',
43
- lg: 'text-3xl',
44
- };
45
-
46
- const iconSizeStyles = {
47
- sm: 'h-4 w-4',
48
- md: 'h-8 w-8',
49
- lg: 'h-12 w-12',
50
- };
51
-
52
- const labelSizeStyles = {
53
- sm: 'text-xs',
54
- md: 'text-sm',
55
- lg: 'text-base',
56
- };
57
-
58
- const iconBgSizeStyles = {
59
- sm: 'w-8 h-8',
60
- md: 'w-12 h-12',
61
- lg: 'w-16 h-16',
62
- };
63
-
64
35
  export const StatCard = forwardRef<HTMLDivElement, StatCardProps>(
65
36
  (
66
37
  {
@@ -76,14 +47,15 @@ export const StatCard = forwardRef<HTMLDivElement, StatCardProps>(
76
47
  trendValueFormatter = (v) => `${v > 0 ? '+' : ''}${Math.abs(v).toFixed(1)}%`,
77
48
  onClick,
78
49
  changeLabel,
50
+ responsiveLayout = true,
79
51
  ...props
80
52
  },
81
53
  ref
82
54
  ) => {
83
55
  const isPositive = trend?.value !== undefined && trend.value >= 0;
84
56
  const GrowthIcon = isPositive ? ArrowUpRight : ArrowDownRight;
85
- const trendColor = isPositive ? 'text-green-600' : 'text-red-600';
86
- const iconBgColor = isPositive ? 'text-green-500' : 'text-red-500';
57
+ const trendColor = isPositive ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400';
58
+ const iconBgColor = isPositive ? 'text-green-500 dark:text-green-400' : 'text-red-500 dark:text-red-400';
87
59
 
88
60
  const cardVariant = variant === 'elevated' ? 'elevated' : 'default';
89
61
 
@@ -93,32 +65,37 @@ export const StatCard = forwardRef<HTMLDivElement, StatCardProps>(
93
65
  variant={cardVariant}
94
66
  className={cn(
95
67
  'transition-all duration-300',
96
- variant === 'gradient' && 'bg-gradient-to-br from-white to-gray-50 hover:shadow-lg border-0 shadow-md',
68
+ variant === 'gradient' && 'bg-gradient-to-br from-white to-gray-50 dark:from-gray-800 dark:to-gray-900 hover:shadow-lg border-0 shadow-md',
97
69
  onClick && 'cursor-pointer hover:shadow-lg hover:border-primary/50',
98
70
  className
99
71
  )}
100
72
  onClick={onClick}
101
73
  {...props}
102
74
  >
103
- <CardContent className={cn(sizeStyles[size])}>
104
- <div className="flex items-center justify-between mb-4">
75
+ <CardContent className={getSpacing('p', size)}>
76
+ <div className={cn(
77
+ 'flex items-center justify-between mb-4',
78
+ getGap('md'),
79
+ 'flex-col sm:flex-row sm:mb-6'
80
+ )}>
105
81
  {Icon && (
106
82
  <div
107
83
  className={cn(
108
84
  'rounded-xl flex items-center justify-center',
109
85
  variant === 'gradient' && 'bg-gradient-to-br from-teal-500 to-cyan-500',
110
86
  variant !== 'gradient' && `bg-${iconColor.split('-')[1]}-500/10`,
111
- iconBgSizeStyles[size]
87
+ getContainerSize(size),
88
+ responsiveLayout && 'w-full sm:w-auto'
112
89
  )}
113
90
  >
114
- <Icon className={cn(iconSizeStyles[size], variant === 'gradient' ? 'text-white' : iconColor)} />
91
+ <Icon className={cn(getIconSize(size), variant === 'gradient' ? 'text-white' : iconColor)} />
115
92
  </div>
116
93
  )}
117
94
  {trend && (
118
95
  <span
119
96
  className={cn(
120
- 'text-sm font-medium px-2 py-1 rounded-full',
121
- isPositive ? 'text-green-700 bg-green-100' : 'text-red-700 bg-red-100'
97
+ 'text-xs sm:text-sm font-medium px-2 py-1 rounded-full whitespace-nowrap',
98
+ isPositive ? 'text-green-700 bg-green-100 dark:text-green-300 dark:bg-green-900/30' : 'text-red-700 bg-red-100 dark:text-red-300 dark:bg-red-900/30'
122
99
  )}
123
100
  >
124
101
  {changeLabel || trendValueFormatter(trend.value)}
@@ -126,29 +103,34 @@ export const StatCard = forwardRef<HTMLDivElement, StatCardProps>(
126
103
  )}
127
104
  </div>
128
105
 
129
- <div className="space-y-3">
130
- <div>
131
- <p className={cn('font-bold text-gray-900', valueSizeStyles[size])}>
106
+ <div className={getSpaceY('md')}>
107
+ <div className={cn(
108
+ responsiveLayout && 'text-center sm:text-left'
109
+ )}>
110
+ <p className={cn('font-bold text-gray-900 dark:text-gray-100', size === 'sm' ? 'text-lg sm:text-xl' : size === 'md' ? 'text-2xl sm:text-3xl' : 'text-3xl sm:text-4xl')}>
132
111
  {typeof value === 'number' ? value.toLocaleString() : value}
133
112
  </p>
134
- <p className={cn('text-muted-foreground', labelSizeStyles[size])}>{title}</p>
113
+ <p className={cn('text-muted-foreground', getTextSize(size))}>{title}</p>
135
114
  </div>
136
115
 
137
116
  {target && (
138
- <div className="space-y-1">
139
- <div className="flex justify-between text-xs">
117
+ <div className={getSpaceY('sm')}>
118
+ <div className="flex justify-between text-xs sm:text-sm">
140
119
  <span className="text-muted-foreground">Target: {target.value}</span>
141
- <span className="text-teal-600">{target.progress}%</span>
120
+ <span className="text-teal-600 dark:text-teal-400 font-medium">{target.progress}%</span>
142
121
  </div>
143
- <Progress value={target.progress} className="h-2" />
122
+ <Progress value={target.progress} className="h-2 sm:h-2.5" />
144
123
  </div>
145
124
  )}
146
125
 
147
126
  {trend && variant !== 'gradient' && (
148
- <div className="flex items-center mt-1">
149
- <GrowthIcon className={cn('h-3 w-3 mr-1', iconBgColor)} />
150
- <p className={cn('text-xs', trendColor)}>{trendValueFormatter(trend.value)}</p>
151
- {trend.label && <p className="text-xs text-muted-foreground ml-1">{trend.label}</p>}
127
+ <div className={cn(
128
+ 'flex items-center mt-1',
129
+ responsiveLayout && 'justify-center sm:justify-start'
130
+ )}>
131
+ <GrowthIcon className={cn('h-3 w-3 sm:h-4 sm:w-4 mr-1', iconBgColor)} />
132
+ <p className={cn('text-xs sm:text-sm', trendColor)}>{trendValueFormatter(trend.value)}</p>
133
+ {trend.label && <p className="text-xs text-muted-foreground ml-1 hidden xs:inline">{trend.label}</p>}
152
134
  </div>
153
135
  )}
154
136
  </div>
@@ -92,6 +92,9 @@ export type { StatCardProps } from './StatCard';
92
92
  export { FormModal } from './FormModal';
93
93
  export type { FormModalProps } from './FormModal';
94
94
 
95
+ export { Grid, GridItem } from './Grid';
96
+ export type { GridProps, GridItemProps } from './Grid';
97
+
95
98
  export { ConfirmDialog } from './ConfirmDialog';
96
99
  export type { ConfirmDialogProps } from './ConfirmDialog';
97
100