diff --git a/pages/Base64Converter/FileMode.tsx b/pages/Base64Converter/FileMode.tsx index 1713b51..25b61b4 100644 --- a/pages/Base64Converter/FileMode.tsx +++ b/pages/Base64Converter/FileMode.tsx @@ -1,18 +1,7 @@ import { useCallback, useMemo, useRef, useState } from 'react'; -import { - Alert, - alpha, - Box, - Button, - CircularProgress, - Paper, - Stack, - Typography, -} from '@mui/material'; +import { Upload, Trash2 } from 'lucide-react'; import TextInputArea from '@/components/TextInputArea'; import type { ToolbarAction } from '@/components/TextInputArea'; -import UploadFileIcon from '@mui/icons-material/UploadFile'; -import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline'; import { useTranslation } from 'react-i18next'; import CopyButton from '@/components/CopyButton'; import DecodeResultPaper from '@/components/DecodeResultPaper'; @@ -183,34 +172,18 @@ export default function FileMode() { {direction === 'encode' && ( <> - fileInputRef.current?.click()} - sx={{ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - minHeight: 180, - border: '2px dashed', - borderColor: isDragging ? 'info.main' : info ? 'info.main' : 'divider', - borderRadius: 3, - p: 4, - bgcolor: (theme) => - isDragging - ? alpha(theme.palette.info.main, 0.08) - : info - ? alpha(theme.palette.info.main, 0.04) - : 'action.hover', - cursor: 'pointer', - transition: 'all 0.2s', - '&:hover': { - borderColor: 'info.main', - bgcolor: (theme) => alpha(theme.palette.info.main, 0.04), - }, - }} + className={`flex flex-col items-center justify-center min-h-[180px] border-2 border-dashed rounded-xl p-8 cursor-pointer transition-all duration-200 ${ + isDragging + ? 'border-blue-500 bg-blue-50' + : info + ? 'border-blue-500 bg-blue-50/50' + : 'border-gray-300 bg-gray-50 hover:border-blue-500 hover:bg-blue-50/50' + }`} > {isLoading ? ( - +
) : info ? ( - - - - {info.name} - - +
+ + {info.name} + {formatFileSize(info.size)} · {info.type} - - - {t('clickOrDropToReplace')} - - + + {t('clickOrDropToReplace')} +
) : ( - - - +
+ + {t('clickOrDropToFile')} - - + + {t('maxFileSize', { max: `${MAX_FILE_SIZE / 1024 / 1024} MB` })} - - + +
)} - +
- {error && {error}} + {error && ( +
+ {error} +
+ )} {result && ( - alpha(theme.palette.info.main, 0.04), - border: '1px solid', - borderColor: (theme) => alpha(theme.palette.info.main, 0.15), - }} - > - - - {t('base64Output')} - - +
+
+ {t('base64Output')} +
- - +
+
- - +
+ {t('originalSize')}: {formatFileSize(result.originalBytes)} - - + + {t('encodedSize')}: {formatFileSize(result.outputBytes)} - - - - - + +
+
)} {info && !result && ( - + )} )} diff --git a/pages/Base64Converter/ImageMode.tsx b/pages/Base64Converter/ImageMode.tsx index 95d17e3..0ae654d 100644 --- a/pages/Base64Converter/ImageMode.tsx +++ b/pages/Base64Converter/ImageMode.tsx @@ -1,17 +1,6 @@ import { useCallback, useMemo, useRef, useState } from 'react'; -import { - Alert, - alpha, - Box, - Button, - CircularProgress, - Paper, - Stack, - Typography, -} from '@mui/material'; +import { Image, Trash2 } from 'lucide-react'; import TextInputArea, { type ToolbarAction } from '@/components/TextInputArea'; -import ImageIcon from '@mui/icons-material/Image'; -import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline'; import { useTranslation } from 'react-i18next'; import CopyButton from '@/components/CopyButton'; import DecodeResultPaper from '@/components/DecodeResultPaper'; @@ -189,34 +178,18 @@ export default function ImageMode() { {direction === 'encode' && ( <> - imageInputRef.current?.click()} - sx={{ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - minHeight: 180, - border: '2px dashed', - borderColor: isDragging ? 'info.main' : info ? 'info.main' : 'divider', - borderRadius: 3, - p: 4, - bgcolor: (theme) => - isDragging - ? alpha(theme.palette.info.main, 0.08) - : info - ? alpha(theme.palette.info.main, 0.04) - : 'action.hover', - cursor: 'pointer', - transition: 'all 0.2s', - '&:hover': { - borderColor: 'info.main', - bgcolor: (theme) => alpha(theme.palette.info.main, 0.04), - }, - }} + className={`flex flex-col items-center justify-center min-h-[180px] border-2 border-dashed rounded-xl p-8 cursor-pointer transition-all duration-200 ${ + isDragging + ? 'border-blue-500 bg-blue-50' + : info + ? 'border-blue-500 bg-blue-50/50' + : 'border-gray-300 bg-gray-50 hover:border-blue-500 hover:bg-blue-50/50' + }`} > {isLoading ? ( - +
) : info ? ( - +
{result && ( - )} - - {info.name} - - + {info.name} + {formatFileSize(info.size)} · {info.type} - - - {t('clickOrDropToReplace')} - - + + {t('clickOrDropToReplace')} +
) : ( - - - +
+ + {t('clickOrDropToImage')} - - - {t('supportedFormats')} - - + + {t('supportedFormats')} +
)} - +
- {error && {error}} + {error && ( +
+ {error} +
+ )} {result && ( - alpha(theme.palette.info.main, 0.04), - border: '1px solid', - borderColor: (theme) => alpha(theme.palette.info.main, 0.15), - }} - > - - - {t('base64Output')} - - +
+
+ {t('base64Output')} +
- - - +
+
+
{result.output.length > 2000 ? `${result.output.substring(0, 2000)}...` : result.output} - - - +
+
+ {t('originalSize')}: {formatFileSize(result.originalBytes)} - - + + {t('encodedSize')}: {formatFileSize(result.outputBytes)} - - - + +
+
)} {info && ( - + )} )} @@ -361,17 +302,10 @@ export default function ImageMode() { onFileNameChange={setDecodedFileName} onDownload={handleDownload} > - )} diff --git a/pages/Base64Converter/TextMode.tsx b/pages/Base64Converter/TextMode.tsx index 4400141..95354eb 100644 --- a/pages/Base64Converter/TextMode.tsx +++ b/pages/Base64Converter/TextMode.tsx @@ -1,7 +1,6 @@ import { useCallback, useMemo, useState } from 'react'; -import { Alert, alpha, Button, Paper, Stack, Typography } from '@mui/material'; +import { ArrowLeftRight } from 'lucide-react'; import TextInputArea, { type ToolbarAction } from '@/components/TextInputArea'; -import SwapHorizIcon from '@mui/icons-material/SwapHoriz'; import { useTranslation } from 'react-i18next'; import CopyButton from '@/components/CopyButton'; import { textToBase64, base64ToText } from '@/utils/base64Converter'; @@ -71,7 +70,7 @@ export default function TextMode({ onSwitchToImageMode }: TextModeProps = {}) { { key: 'convert', label: actionLabel, - icon: , + icon: , type: 'primary', position: 'bottom', disabled: (value: string) => !value.trim(), @@ -121,42 +120,31 @@ export default function TextMode({ onSwitchToImageMode }: TextModeProps = {}) { /> {showImageHint && ( - - {t('switchToImageMode')} - - } - > - {t('imageDataUriHint')} - +
+ {t('imageDataUriHint')} + +
)} {output && ( - alpha(theme.palette.info.main, 0.04), - border: '1px solid', - borderColor: (theme) => alpha(theme.palette.info.main, 0.15), - }} - > - - - {outputLabel} - +
+
+ {outputLabel} - +
2000 ? `${output.substring(0, 2000)}...` : output} showClear={false} showCount /> - +
)} ); diff --git a/pages/Base64Converter/index.tsx b/pages/Base64Converter/index.tsx index 66e7d66..0a943dc 100644 --- a/pages/Base64Converter/index.tsx +++ b/pages/Base64Converter/index.tsx @@ -1,7 +1,4 @@ -import { Box, Container, Stack } from '@mui/material'; -import TextFieldsIcon from '@mui/icons-material/TextFields'; -import UploadFileIcon from '@mui/icons-material/UploadFile'; -import ImageIcon from '@mui/icons-material/Image'; +import { Type, Upload, Image } from 'lucide-react'; import { useLazyTranslation } from '@/utils/useLazyTranslation'; import PageHeader from '@/components/PageHeader'; import { base64ConverterPageStyles } from '@/config/pageTheme'; @@ -28,14 +25,14 @@ export default function Index() { ); const modeIcon: Record = { - text: , - file: , - image: , + text: , + file: , + image: , }; return ( - - +
+
- +
setPageMode('image')} />} {pageMode === 'file' && } {pageMode === 'image' && } - - - +
+
+
); }