fix: replace flex-shrink-0 with shrink-0 for consistent styling across components
This commit is contained in:
2930
frontend/package-lock.json
generated
2930
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -72,8 +72,20 @@
|
||||
"@vitest/ui": "^4.0.18",
|
||||
"autoprefixer": "^10.4.27",
|
||||
"eslint": "^9.39.3 <10.0.0",
|
||||
"eslint-import-resolver-typescript": "^4.4.4",
|
||||
"eslint-plugin-import-x": "^4.16.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||
"eslint-plugin-no-unsanitized": "^4.1.5",
|
||||
"eslint-plugin-promise": "^7.2.1",
|
||||
"eslint-plugin-react-compiler": "^19.1.0-rc.2",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.5.2",
|
||||
"eslint-plugin-security": "^4.0.0",
|
||||
"eslint-plugin-sonarjs": "^4.0.1",
|
||||
"eslint-plugin-testing-library": "^7.16.0",
|
||||
"eslint-plugin-unicorn": "^63.0.0",
|
||||
"eslint-plugin-unused-imports": "^4.4.1",
|
||||
"eslint-plugin-vitest": "^0.5.4",
|
||||
"jsdom": "28.1.0",
|
||||
"knip": "^5.86.0",
|
||||
"postcss": "^8.5.8",
|
||||
|
||||
@@ -239,7 +239,7 @@ export function AccessListForm({ initialData, onSubmit, onCancel, onDelete, isLo
|
||||
</select>
|
||||
{(formData.type === 'blacklist' || formData.type === 'geo_blacklist') && (
|
||||
<div className="mt-2 flex items-start gap-2 p-3 bg-blue-900/20 border border-blue-700/50 rounded-lg">
|
||||
<Info className="h-4 w-4 text-blue-400 mt-0.5 flex-shrink-0" />
|
||||
<Info className="h-4 w-4 text-blue-400 mt-0.5 shrink-0" />
|
||||
<p className="text-xs text-blue-300">
|
||||
<strong>Recommended:</strong> Block lists are safer than allow lists. They block known bad actors while allowing everyone else access, preventing lockouts.
|
||||
</p>
|
||||
@@ -302,7 +302,7 @@ export function AccessListForm({ initialData, onSubmit, onCancel, onDelete, isLo
|
||||
</div>
|
||||
{preset.warning && (
|
||||
<div className="flex items-start gap-1 mt-2 text-xs text-orange-400">
|
||||
<AlertTriangle className="h-3 w-3 mt-0.5 flex-shrink-0" />
|
||||
<AlertTriangle className="h-3 w-3 mt-0.5 shrink-0" />
|
||||
<span>{preset.warning}</span>
|
||||
</div>
|
||||
)}
|
||||
@@ -352,7 +352,7 @@ export function AccessListForm({ initialData, onSubmit, onCancel, onDelete, isLo
|
||||
</div>
|
||||
{preset.warning && (
|
||||
<div className="flex items-start gap-1 mt-2 text-xs text-orange-400">
|
||||
<AlertTriangle className="h-3 w-3 mt-0.5 flex-shrink-0" />
|
||||
<AlertTriangle className="h-3 w-3 mt-0.5 shrink-0" />
|
||||
<span>{preset.warning}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -91,7 +91,7 @@ export function CrowdSecKeyWarning() {
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<AlertTriangle className="h-5 w-5 text-warning flex-shrink-0" />
|
||||
<AlertTriangle className="h-5 w-5 text-warning shrink-0" />
|
||||
<h4 className="font-semibold text-content-primary">
|
||||
{t('security.crowdsec.keyWarning.title')}
|
||||
</h4>
|
||||
@@ -122,7 +122,7 @@ export function CrowdSecKeyWarning() {
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setShowKey(!showKey)}
|
||||
className="flex-shrink-0"
|
||||
className="shrink-0"
|
||||
title={showKey ? 'Hide key' : 'Show key'}
|
||||
>
|
||||
{showKey ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
|
||||
@@ -132,7 +132,7 @@ export function CrowdSecKeyWarning() {
|
||||
size="sm"
|
||||
onClick={handleCopy}
|
||||
disabled={copied}
|
||||
className="flex-shrink-0"
|
||||
className="shrink-0"
|
||||
>
|
||||
{copied ? (
|
||||
<>
|
||||
|
||||
@@ -296,7 +296,7 @@ export default function Layout({ children }: LayoutProps) {
|
||||
})}
|
||||
</nav>
|
||||
|
||||
<div className={`mt-2 border-t border-gray-200 dark:border-gray-800 pt-4 flex-shrink-0 ${isCollapsed ? 'hidden' : ''}`}>
|
||||
<div className={`mt-2 border-t border-gray-200 dark:border-gray-800 pt-4 shrink-0 ${isCollapsed ? 'hidden' : ''}`}>
|
||||
<div className="text-xs text-gray-500 dark:text-gray-500 text-center mb-2 flex flex-col gap-0.5">
|
||||
<span>Version {health?.version || 'dev'}</span>
|
||||
{health?.git_commit && health.git_commit !== 'unknown' && (
|
||||
@@ -319,7 +319,7 @@ export default function Layout({ children }: LayoutProps) {
|
||||
|
||||
{/* Collapsed Logout */}
|
||||
{isCollapsed && (
|
||||
<div className="mt-2 border-t border-gray-200 dark:border-gray-800 pt-4 pb-4 flex-shrink-0">
|
||||
<div className="mt-2 border-t border-gray-200 dark:border-gray-800 pt-4 pb-4 shrink-0">
|
||||
<button
|
||||
onClick={() => {
|
||||
setMobileSidebarOpen(false)
|
||||
|
||||
@@ -90,7 +90,7 @@ const NotificationCenter: FC = () => {
|
||||
{/* Update Notification */}
|
||||
{updateInfo?.available && (
|
||||
<div className="flex items-start px-4 py-3 border-b dark:border-gray-700 bg-yellow-50 dark:bg-yellow-900/10 hover:bg-yellow-100 dark:hover:bg-yellow-900/20">
|
||||
<div className="flex-shrink-0 mt-0.5">
|
||||
<div className="shrink-0 mt-0.5">
|
||||
<AlertCircle className="w-5 h-5 text-yellow-500" />
|
||||
</div>
|
||||
<div className="ml-3 w-0 flex-1">
|
||||
@@ -119,7 +119,7 @@ const NotificationCenter: FC = () => {
|
||||
key={notification.id}
|
||||
className="flex items-start px-4 py-3 border-b dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
>
|
||||
<div className="flex-shrink-0 mt-0.5">
|
||||
<div className="shrink-0 mt-0.5">
|
||||
{getIcon(notification.type)}
|
||||
</div>
|
||||
<div className="ml-3 w-0 flex-1">
|
||||
@@ -133,7 +133,7 @@ const NotificationCenter: FC = () => {
|
||||
{new Date(notification.created_at).toLocaleString()}
|
||||
</p>
|
||||
</div>
|
||||
<div className="ml-4 flex-shrink-0 flex">
|
||||
<div className="ml-4 shrink-0 flex">
|
||||
<button
|
||||
onClick={() => markReadMutation.mutate(notification.id)}
|
||||
className="bg-white dark:bg-gray-800 rounded-md inline-flex text-gray-400 hover:text-gray-500 focus:outline-none"
|
||||
|
||||
@@ -225,7 +225,7 @@ export function PermissionsPolicyBuilder({ value, onChange }: PermissionsPolicyB
|
||||
) : (
|
||||
policies.map((policy) => (
|
||||
<div key={policy.feature} className="flex items-center gap-3 p-3 bg-gray-50 dark:bg-gray-800 rounded-lg">
|
||||
<span className="font-mono text-sm font-semibold text-gray-900 dark:text-white flex-shrink-0">
|
||||
<span className="font-mono text-sm font-semibold text-gray-900 dark:text-white shrink-0">
|
||||
{policy.feature}
|
||||
</span>
|
||||
<div className="flex-1">
|
||||
|
||||
@@ -87,7 +87,7 @@ export function SecurityScoreDisplay({
|
||||
<Card className="p-4">
|
||||
<div className="flex items-start gap-4">
|
||||
{/* Circular Score Display */}
|
||||
<div className="flex-shrink-0">
|
||||
<div className="shrink-0">
|
||||
<div
|
||||
className={`${sizeClasses[size]} rounded-full ${getScoreBgColor()} flex flex-col items-center justify-center font-bold ${getScoreColor()}`}
|
||||
>
|
||||
@@ -177,7 +177,7 @@ export function SecurityScoreDisplay({
|
||||
<ul className="mt-3 space-y-2 pl-6">
|
||||
{suggestions.map((suggestion, index) => (
|
||||
<li key={index} className="flex items-start gap-2 text-sm text-gray-600 dark:text-gray-400">
|
||||
<AlertCircle className="w-4 h-4 text-yellow-500 flex-shrink-0 mt-0.5" />
|
||||
<AlertCircle className="w-4 h-4 text-yellow-500 shrink-0 mt-0.5" />
|
||||
<span>{suggestion}</span>
|
||||
</li>
|
||||
))}
|
||||
|
||||
@@ -33,7 +33,7 @@ export default function CertificateCleanupDialog({
|
||||
>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="flex items-start gap-3 mb-4">
|
||||
<div className="flex-shrink-0 w-10 h-10 rounded-full bg-orange-900/30 flex items-center justify-center">
|
||||
<div className="shrink-0 w-10 h-10 rounded-full bg-orange-900/30 flex items-center justify-center">
|
||||
<AlertTriangle className="h-5 w-5 text-orange-400" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
|
||||
@@ -32,7 +32,7 @@ export default function ImportSuccessModal({
|
||||
<div className="relative bg-dark-card rounded-lg p-6 w-[500px] max-w-full mx-4 border border-gray-800">
|
||||
{/* Header */}
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="flex-shrink-0 w-12 h-12 rounded-full bg-green-900/30 flex items-center justify-center">
|
||||
<div className="shrink-0 w-12 h-12 rounded-full bg-green-900/30 flex items-center justify-center">
|
||||
<CheckCircle className="h-6 w-6 text-green-400" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -101,7 +101,7 @@ export default function ImportSuccessModal({
|
||||
{created > 0 && (
|
||||
<div className="bg-blue-900/20 border border-blue-800/50 rounded-lg p-4 mb-6">
|
||||
<div className="flex items-start gap-3">
|
||||
<Info className="h-4 w-4 text-blue-400 mt-0.5 flex-shrink-0" />
|
||||
<Info className="h-4 w-4 text-blue-400 mt-0.5 shrink-0" />
|
||||
<div>
|
||||
<p className="text-sm font-medium text-blue-300">Certificate Provisioning</p>
|
||||
<p className="text-xs text-gray-400 mt-1">
|
||||
|
||||
@@ -306,7 +306,7 @@ export default function ManualDNSChallenge({
|
||||
size="sm"
|
||||
onClick={() => handleCopy('name', challenge.fqdn)}
|
||||
aria-label={t('dnsProvider.manual.copyRecordName')}
|
||||
className="flex-shrink-0"
|
||||
className="shrink-0"
|
||||
>
|
||||
{copiedField === 'name' ? (
|
||||
<Check className="h-4 w-4 text-success" aria-hidden="true" />
|
||||
@@ -343,7 +343,7 @@ export default function ManualDNSChallenge({
|
||||
size="sm"
|
||||
onClick={() => handleCopy('value', challenge.value)}
|
||||
aria-label={t('dnsProvider.manual.copyRecordValue')}
|
||||
className="flex-shrink-0"
|
||||
className="shrink-0"
|
||||
>
|
||||
{copiedField === 'value' ? (
|
||||
<Check className="h-4 w-4 text-success" aria-hidden="true" />
|
||||
@@ -433,7 +433,7 @@ export default function ManualDNSChallenge({
|
||||
>
|
||||
<div className="flex items-start gap-3">
|
||||
<StatusIcon
|
||||
className={`h-5 w-5 flex-shrink-0 ${statusConfig.colorClass} ${
|
||||
className={`h-5 w-5 shrink-0 ${statusConfig.colorClass} ${
|
||||
currentStatus === 'verifying' ? 'animate-spin' : ''
|
||||
}`}
|
||||
aria-hidden="true"
|
||||
|
||||
@@ -81,7 +81,7 @@ export function Alert({
|
||||
className={cn(alertVariants({ variant }), className)}
|
||||
{...props}
|
||||
>
|
||||
<IconComponent className={cn('h-5 w-5 flex-shrink-0 mt-0.5', iconColor)} />
|
||||
<IconComponent className={cn('h-5 w-5 shrink-0 mt-0.5', iconColor)} />
|
||||
<div className="flex-1 min-w-0">
|
||||
{title && (
|
||||
<h5 className="font-semibold text-sm mb-1">{title}</h5>
|
||||
@@ -92,7 +92,7 @@ export function Alert({
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleDismiss}
|
||||
className="flex-shrink-0 p-1 rounded-md text-content-muted hover:text-content-primary hover:bg-surface-muted transition-colors duration-fast"
|
||||
className="shrink-0 p-1 rounded-md text-content-muted hover:text-content-primary hover:bg-surface-muted transition-colors duration-fast"
|
||||
aria-label="Dismiss alert"
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
|
||||
@@ -35,7 +35,7 @@ const SelectTrigger = React.forwardRef<
|
||||
>
|
||||
{children}
|
||||
<SelectPrimitive.Icon asChild>
|
||||
<ChevronDown className="h-4 w-4 text-content-muted flex-shrink-0" />
|
||||
<ChevronDown className="h-4 w-4 text-content-muted shrink-0" />
|
||||
</SelectPrimitive.Icon>
|
||||
</SelectPrimitive.Trigger>
|
||||
))
|
||||
|
||||
@@ -129,7 +129,7 @@ export function SkeletonList({
|
||||
{Array.from({ length: items }).map((_, i) => (
|
||||
<div key={i} className="flex items-center gap-4">
|
||||
{showAvatar && (
|
||||
<Skeleton variant="circular" className="h-10 w-10 flex-shrink-0" />
|
||||
<Skeleton variant="circular" className="h-10 w-10 shrink-0" />
|
||||
)}
|
||||
<div className="flex-1 space-y-2">
|
||||
<Skeleton className="h-4 w-1/3" />
|
||||
|
||||
@@ -580,7 +580,7 @@ export default function CrowdSecConfig() {
|
||||
{/* Yellow warning: Process running but LAPI initializing */}
|
||||
{lapiStatusQuery.data && lapiStatusQuery.data.running && !lapiStatusQuery.data.lapi_ready && initialCheckComplete && (
|
||||
<div className="flex items-start gap-3 p-4 bg-yellow-900/20 border border-yellow-700/50 rounded-lg" data-testid="lapi-warning">
|
||||
<AlertTriangle className="w-5 h-5 text-yellow-400 flex-shrink-0 mt-0.5" />
|
||||
<AlertTriangle className="w-5 h-5 text-yellow-400 shrink-0 mt-0.5" />
|
||||
<div className="flex-1">
|
||||
<p className="text-sm text-yellow-200 font-medium mb-2">
|
||||
{t('crowdsecConfig.lapiInitializing')}
|
||||
@@ -606,7 +606,7 @@ export default function CrowdSecConfig() {
|
||||
{/* Red warning: Process not running at all */}
|
||||
{lapiStatusQuery.data && !lapiStatusQuery.data.running && initialCheckComplete && (
|
||||
<div className="flex items-start gap-3 p-4 bg-red-900/20 border border-red-700/50 rounded-lg" data-testid="lapi-not-running-warning">
|
||||
<AlertTriangle className="w-5 h-5 text-red-400 flex-shrink-0 mt-0.5" />
|
||||
<AlertTriangle className="w-5 h-5 text-red-400 shrink-0 mt-0.5" />
|
||||
<div className="flex-1">
|
||||
<p className="text-sm text-red-200 font-medium mb-2">
|
||||
{t('crowdsecConfig.notRunning')}
|
||||
|
||||
@@ -94,7 +94,7 @@ const Logs: FC = () => {
|
||||
: 'hover:bg-surface-muted text-content-secondary'
|
||||
}`}
|
||||
>
|
||||
<FileText className="w-4 h-4 mr-2 flex-shrink-0" />
|
||||
<FileText className="w-4 h-4 mr-2 shrink-0" />
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="font-medium truncate">{log.name}</div>
|
||||
<div className="text-xs text-content-muted">{(log.size / 1024 / 1024).toFixed(2)} MB</div>
|
||||
|
||||
@@ -175,7 +175,7 @@ export default function Plugins() {
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-3">
|
||||
<Package className="w-5 h-5 text-content-secondary flex-shrink-0" />
|
||||
<Package className="w-5 h-5 text-content-secondary shrink-0" />
|
||||
<div className="flex-1 min-w-0">
|
||||
<h3 className="text-base font-medium text-content-primary truncate">
|
||||
{plugin.name}
|
||||
@@ -228,7 +228,7 @@ export default function Plugins() {
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-3">
|
||||
<Package className="w-5 h-5 text-brand-500 flex-shrink-0" />
|
||||
<Package className="w-5 h-5 text-brand-500 shrink-0" />
|
||||
<div className="flex-1 min-w-0">
|
||||
<h3 className="text-base font-medium text-content-primary truncate">
|
||||
{plugin.name}
|
||||
|
||||
@@ -438,7 +438,7 @@ export default function ProxyHosts() {
|
||||
style={{ maxWidth: '100%' }}
|
||||
>
|
||||
<span className="truncate max-w-[30ch]">{d}</span>
|
||||
<ExternalLink size={12} className="opacity-50 flex-shrink-0" />
|
||||
<ExternalLink size={12} className="opacity-50 shrink-0" />
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
@@ -1101,7 +1101,7 @@ export default function ProxyHosts() {
|
||||
<DialogContent className="max-w-lg">
|
||||
<DialogHeader>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="flex-shrink-0 w-10 h-10 rounded-full bg-error/10 flex items-center justify-center">
|
||||
<div className="shrink-0 w-10 h-10 rounded-full bg-error/10 flex items-center justify-center">
|
||||
<AlertTriangle className="h-5 w-5 text-error" />
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -90,7 +90,7 @@ export default function RateLimiting() {
|
||||
{/* Info Banner */}
|
||||
<div className="bg-blue-900/20 border border-blue-800/50 rounded-lg p-4">
|
||||
<div className="flex items-start gap-3">
|
||||
<Info className="h-5 w-5 text-blue-400 flex-shrink-0 mt-0.5" />
|
||||
<Info className="h-5 w-5 text-blue-400 shrink-0 mt-0.5" />
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold text-blue-300 mb-1">
|
||||
{t('rateLimiting.aboutTitle')}
|
||||
|
||||
@@ -452,9 +452,9 @@ export default function SystemSettings() {
|
||||
/>
|
||||
{publicURLValid !== null && (
|
||||
publicURLValid ? (
|
||||
<CheckCircle2 className="h-5 w-5 text-green-500 self-center flex-shrink-0" />
|
||||
<CheckCircle2 className="h-5 w-5 text-green-500 self-center shrink-0" />
|
||||
) : (
|
||||
<XCircle className="h-5 w-5 text-red-500 self-center flex-shrink-0" />
|
||||
<XCircle className="h-5 w-5 text-red-500 self-center shrink-0" />
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -371,7 +371,7 @@ export default function WafConfig() {
|
||||
{/* Info Banner */}
|
||||
<div className="bg-blue-900/20 border border-blue-800/50 rounded-lg p-4">
|
||||
<div className="flex items-start gap-3">
|
||||
<FileCode2 className="h-5 w-5 text-blue-400 flex-shrink-0 mt-0.5" />
|
||||
<FileCode2 className="h-5 w-5 text-blue-400 shrink-0 mt-0.5" />
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold text-blue-300 mb-1">
|
||||
{t('wafConfig.aboutTitle')}
|
||||
|
||||
Reference in New Issue
Block a user