Imporve the UI 4
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import { LucideIcon } from 'lucide-react';
|
||||
import { Card } from '../Card';
|
||||
import { Button } from '../Button';
|
||||
import { ProgressBar } from '../ProgressBar';
|
||||
import { statusColors } from '../../../styles/colors';
|
||||
import { TextOverflowPrevention, overflowClasses, getScreenSize, safeText } from '../../../utils/textUtils';
|
||||
@@ -121,12 +120,12 @@ export const StatusCard: React.FC<StatusCardProps> = ({
|
||||
return (
|
||||
<Card
|
||||
className={`
|
||||
p-5 sm:p-6 transition-all duration-200 border-l-4 hover:shadow-lg
|
||||
p-3 sm:p-5 lg:p-6 transition-all duration-200 border-l-4 hover:shadow-lg
|
||||
${hasInteraction ? 'hover:shadow-xl cursor-pointer hover:scale-[1.01]' : ''}
|
||||
${statusIndicator.isCritical
|
||||
? 'ring-2 ring-red-200 shadow-md border-l-6 sm:border-l-8'
|
||||
? 'ring-2 ring-red-200 shadow-md sm:border-l-6 lg:border-l-8'
|
||||
: statusIndicator.isHighlight
|
||||
? 'ring-1 ring-yellow-200 border-l-6'
|
||||
? 'ring-1 ring-yellow-200 sm:border-l-6'
|
||||
: ''
|
||||
}
|
||||
${className}
|
||||
@@ -141,33 +140,33 @@ export const StatusCard: React.FC<StatusCardProps> = ({
|
||||
}}
|
||||
onClick={onClick}
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-3 sm:space-y-4">
|
||||
{/* Header with status indicator */}
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div className="flex items-start gap-3 flex-1 min-w-0">
|
||||
<div className="flex items-start justify-between gap-2 sm:gap-4">
|
||||
<div className="flex items-start gap-2 sm:gap-3 flex-1 min-w-0">
|
||||
<div
|
||||
className={`flex-shrink-0 p-2.5 sm:p-3 rounded-lg shadow-sm ${
|
||||
className={`flex-shrink-0 p-1.5 sm:p-2.5 lg:p-3 rounded-lg shadow-sm ${
|
||||
statusIndicator.isCritical ? 'ring-2 ring-white' : ''
|
||||
}`}
|
||||
style={{ backgroundColor: `${statusIndicator.color}20` }}
|
||||
>
|
||||
{StatusIcon && (
|
||||
<StatusIcon
|
||||
className="w-5 h-5 sm:w-6 sm:h-6"
|
||||
className="w-4 h-4 sm:w-5 sm:h-5 lg:w-6 lg:h-6"
|
||||
style={{ color: statusIndicator.color }}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div
|
||||
className={`font-semibold text-[var(--text-primary)] text-base sm:text-lg leading-tight mb-2 ${overflowClasses.truncate}`}
|
||||
className={`font-semibold text-[var(--text-primary)] text-sm sm:text-base lg:text-lg leading-tight mb-1 sm:mb-2 ${overflowClasses.truncate}`}
|
||||
title={title}
|
||||
>
|
||||
{truncationEngine.title(title)}
|
||||
</div>
|
||||
{subtitle && (
|
||||
<div
|
||||
className={`text-sm text-[var(--text-secondary)] mb-2 ${overflowClasses.truncate}`}
|
||||
className={`text-xs sm:text-sm text-[var(--text-secondary)] mb-1 sm:mb-2 ${overflowClasses.truncate}`}
|
||||
title={subtitle}
|
||||
>
|
||||
{truncationEngine.subtitle(subtitle)}
|
||||
@@ -175,13 +174,13 @@ export const StatusCard: React.FC<StatusCardProps> = ({
|
||||
)}
|
||||
<div className="flex items-center gap-2">
|
||||
<div
|
||||
className={`inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium transition-all ${
|
||||
className={`inline-flex items-center px-2 py-1 sm:px-3 sm:py-1.5 rounded-full text-xs font-medium transition-all ${
|
||||
statusIndicator.isCritical
|
||||
? 'bg-red-100 text-red-800 ring-2 ring-red-300 shadow-sm animate-pulse'
|
||||
: statusIndicator.isHighlight
|
||||
? 'bg-yellow-100 text-yellow-800 ring-1 ring-yellow-300 shadow-sm'
|
||||
: 'ring-1 shadow-sm'
|
||||
} max-w-[200px] sm:max-w-[220px]`}
|
||||
} max-w-full sm:max-w-[220px]`}
|
||||
style={{
|
||||
backgroundColor: statusIndicator.isCritical || statusIndicator.isHighlight
|
||||
? undefined
|
||||
@@ -208,16 +207,16 @@ export const StatusCard: React.FC<StatusCardProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right flex-shrink-0 min-w-0 max-w-[130px] sm:max-w-[160px]">
|
||||
<div className="text-right flex-shrink-0 min-w-[60px] sm:min-w-[80px] max-w-[100px] sm:max-w-[140px] lg:max-w-[160px]">
|
||||
<div
|
||||
className={`text-2xl sm:text-3xl font-bold text-[var(--text-primary)] leading-none mb-1 ${overflowClasses.truncate}`}
|
||||
className={`text-xl sm:text-2xl lg:text-3xl font-bold text-[var(--text-primary)] leading-none mb-0.5 sm:mb-1 ${overflowClasses.truncate}`}
|
||||
title={primaryValue?.toString()}
|
||||
>
|
||||
{safeText(primaryValue?.toString(), '0', isMobile ? 12 : 18)}
|
||||
{safeText(primaryValue?.toString(), '0', isMobile ? 10 : 18)}
|
||||
</div>
|
||||
{primaryValueLabel && (
|
||||
<div
|
||||
className={`text-xs text-[var(--text-tertiary)] uppercase tracking-wide ${overflowClasses.truncate}`}
|
||||
className={`text-[10px] sm:text-xs text-[var(--text-tertiary)] uppercase tracking-wide ${overflowClasses.truncate}`}
|
||||
title={primaryValueLabel}
|
||||
>
|
||||
{truncationEngine.primaryValueLabel(primaryValueLabel)}
|
||||
@@ -228,9 +227,9 @@ export const StatusCard: React.FC<StatusCardProps> = ({
|
||||
|
||||
{/* Secondary info - Mobile optimized */}
|
||||
{secondaryInfo && (
|
||||
<div className="flex items-center justify-between text-sm gap-2 min-w-0">
|
||||
<div className="flex items-center justify-between text-xs sm:text-sm gap-2 min-w-0">
|
||||
<span
|
||||
className={`text-[var(--text-secondary)] flex-shrink-0 ${overflowClasses.truncate} max-w-[100px] sm:max-w-[120px]`}
|
||||
className={`text-[var(--text-secondary)] flex-shrink-0 ${overflowClasses.truncate} max-w-[80px] sm:max-w-[120px]`}
|
||||
title={secondaryInfo.label}
|
||||
>
|
||||
{truncationEngine.secondaryLabel(secondaryInfo.label)}
|
||||
@@ -246,7 +245,7 @@ export const StatusCard: React.FC<StatusCardProps> = ({
|
||||
|
||||
{/* Progress indicator */}
|
||||
{progress && (
|
||||
<div className="space-y-3">
|
||||
<div className="space-y-2 sm:space-y-3">
|
||||
<ProgressBar
|
||||
value={progress.percentage}
|
||||
max={100}
|
||||
@@ -265,19 +264,19 @@ export const StatusCard: React.FC<StatusCardProps> = ({
|
||||
|
||||
{/* Metadata - Improved mobile layout with overflow prevention */}
|
||||
{metadata.length > 0 && (
|
||||
<div className="text-xs text-[var(--text-secondary)] space-y-1">
|
||||
{metadata.slice(0, isMobile ? 3 : 4).map((item, index) => (
|
||||
<div className="text-[10px] sm:text-xs text-[var(--text-secondary)] space-y-0.5 sm:space-y-1">
|
||||
{metadata.slice(0, isMobile ? 2 : 4).map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`${overflowClasses.truncate} ${overflowClasses.breakWords}`}
|
||||
className={`${overflowClasses.truncate} ${overflowClasses.breakWords} leading-tight`}
|
||||
title={item}
|
||||
>
|
||||
{truncationEngine.metadataItem(item)}
|
||||
</div>
|
||||
))}
|
||||
{metadata.length > (isMobile ? 3 : 4) && (
|
||||
<div className="text-[var(--text-tertiary)] italic">
|
||||
+{metadata.length - (isMobile ? 3 : 4)} más...
|
||||
{metadata.length > (isMobile ? 2 : 4) && (
|
||||
<div className="text-[var(--text-tertiary)] italic text-[10px]">
|
||||
+{metadata.length - (isMobile ? 2 : 4)} más...
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -285,9 +284,9 @@ export const StatusCard: React.FC<StatusCardProps> = ({
|
||||
|
||||
{/* Simplified Action System - Mobile optimized */}
|
||||
{actions.length > 0 && (
|
||||
<div className="pt-4 border-t border-[var(--border-primary)]">
|
||||
<div className="pt-2 sm:pt-4 border-t border-[var(--border-primary)]">
|
||||
{/* All actions in a clean horizontal layout */}
|
||||
<div className="flex items-center justify-between gap-3 flex-wrap">
|
||||
<div className="flex items-center justify-between gap-2 sm:gap-3 flex-wrap">
|
||||
|
||||
{/* Primary action as a subtle text button */}
|
||||
{primaryActions.length > 0 && (
|
||||
@@ -300,8 +299,8 @@ export const StatusCard: React.FC<StatusCardProps> = ({
|
||||
}}
|
||||
disabled={primaryActions[0].disabled}
|
||||
className={`
|
||||
flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-lg
|
||||
transition-all duration-200 hover:scale-105 active:scale-95 flex-shrink-0 max-w-[140px] sm:max-w-[160px]
|
||||
flex items-center gap-1.5 sm:gap-2 px-2 py-1.5 sm:px-3 sm:py-2 text-xs sm:text-sm font-medium rounded-lg
|
||||
transition-all duration-200 hover:scale-105 active:scale-95 flex-shrink-0 max-w-[120px] sm:max-w-[160px]
|
||||
${primaryActions[0].disabled
|
||||
? 'opacity-50 cursor-not-allowed'
|
||||
: primaryActions[0].destructive
|
||||
@@ -311,7 +310,7 @@ export const StatusCard: React.FC<StatusCardProps> = ({
|
||||
`}
|
||||
title={primaryActions[0].label}
|
||||
>
|
||||
{primaryActions[0].icon && React.createElement(primaryActions[0].icon, { className: "w-4 h-4 flex-shrink-0" })}
|
||||
{primaryActions[0].icon && React.createElement(primaryActions[0].icon, { className: "w-3.5 h-3.5 sm:w-4 sm:h-4 flex-shrink-0" })}
|
||||
<span className={`${overflowClasses.truncate} flex-1`}>
|
||||
{truncationEngine.actionLabel(primaryActions[0].label)}
|
||||
</span>
|
||||
@@ -319,7 +318,7 @@ export const StatusCard: React.FC<StatusCardProps> = ({
|
||||
)}
|
||||
|
||||
{/* Action icons for secondary actions */}
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-1.5 sm:gap-2">
|
||||
{secondaryActions.map((action, index) => (
|
||||
<button
|
||||
key={`action-${index}`}
|
||||
@@ -332,7 +331,7 @@ export const StatusCard: React.FC<StatusCardProps> = ({
|
||||
disabled={action.disabled}
|
||||
title={action.label}
|
||||
className={`
|
||||
p-2 rounded-lg transition-all duration-200 hover:scale-110 active:scale-95 hover:shadow-sm
|
||||
p-1.5 sm:p-2 rounded-lg transition-all duration-200 hover:scale-110 active:scale-95 hover:shadow-sm
|
||||
${action.disabled
|
||||
? 'opacity-50 cursor-not-allowed'
|
||||
: action.destructive
|
||||
@@ -343,7 +342,7 @@ export const StatusCard: React.FC<StatusCardProps> = ({
|
||||
}
|
||||
`}
|
||||
>
|
||||
{action.icon && React.createElement(action.icon, { className: "w-4 h-4" })}
|
||||
{action.icon && React.createElement(action.icon, { className: "w-3.5 h-3.5 sm:w-4 sm:h-4" })}
|
||||
</button>
|
||||
))}
|
||||
|
||||
@@ -360,7 +359,7 @@ export const StatusCard: React.FC<StatusCardProps> = ({
|
||||
disabled={action.disabled}
|
||||
title={action.label}
|
||||
className={`
|
||||
p-2 rounded-lg transition-all duration-200 hover:scale-110 active:scale-95 hover:shadow-sm
|
||||
p-1.5 sm:p-2 rounded-lg transition-all duration-200 hover:scale-110 active:scale-95 hover:shadow-sm
|
||||
${action.disabled
|
||||
? 'opacity-50 cursor-not-allowed'
|
||||
: action.destructive
|
||||
@@ -369,7 +368,7 @@ export const StatusCard: React.FC<StatusCardProps> = ({
|
||||
}
|
||||
`}
|
||||
>
|
||||
{action.icon && React.createElement(action.icon, { className: "w-4 h-4" })}
|
||||
{action.icon && React.createElement(action.icon, { className: "w-3.5 h-3.5 sm:w-4 sm:h-4" })}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user