style(qrcode): 优化预览态布局适配popup窗口
- 调整文本预览区域高度,单行显示截断文本 - 缩小二维码图片尺寸(56x56 -> 48x48) - 减少内边距和间距,更紧凑的布局 - 确保完整显示在popup窗口中无需滚动
This commit is contained in:
@@ -46,34 +46,34 @@ const QrCodePreview = ({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex flex-col justify-center items-center min-h-[200px] border border-input rounded-xl p-6 bg-muted/40',
|
'flex flex-col justify-center items-center border border-input rounded-xl p-4 bg-muted/40',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col items-center w-full max-w-xs">
|
<div className="flex flex-col items-center w-full max-w-xs">
|
||||||
{/*
|
{/*
|
||||||
2. 二维码容器适配:
|
二维码容器适配:
|
||||||
在暗黑模式下,纯黑白的二维码如果直接暴露在暗色背景下,会导致手机摄像头极难识别。
|
在暗黑模式下,纯黑白的二维码如果直接暴露在暗色背景下,会导致手机摄像头极难识别。
|
||||||
通过裹一层 bg-white 和 p-3,确保黑白对比度绝对安全,同时加入 shadow 增强卡片感。
|
通过裹一层 bg-white 和 p-2,确保黑白对比度绝对安全,同时加入 shadow 增强卡片感。
|
||||||
*/}
|
*/}
|
||||||
<div className="p-3 bg-white rounded-lg shadow-sm border border-border/40">
|
<div className="p-2 bg-white rounded-lg shadow-sm border border-border/40">
|
||||||
<img
|
<img
|
||||||
src={qrCodeDataUrl}
|
src={qrCodeDataUrl}
|
||||||
alt="QR Code Preview"
|
alt="QR Code Preview"
|
||||||
className="w-56 h-56 max-w-full object-contain block animate-in fade-in duration-300"
|
className="w-48 h-48 max-w-full object-contain block animate-in fade-in duration-300"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex w-full gap-2 mt-5">
|
<div className="flex w-full gap-2 mt-3">
|
||||||
<Button variant="outline" size="sm" onClick={onDownload} className="flex-1">
|
<Button variant="outline" size="sm" onClick={onDownload} className="flex-1 h-8">
|
||||||
<Download className="w-4 h-4 text-muted-foreground" />
|
<Download className="w-3.5 h-3.5 text-muted-foreground" />
|
||||||
<span className="truncate">{t('qrCode:downloadButton')}</span>
|
<span className="truncate text-xs">{t('qrCode:downloadButton')}</span>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button variant="default" size="sm" onClick={onCopy} className="flex-1">
|
<Button variant="default" size="sm" onClick={onCopy} className="flex-1 h-8">
|
||||||
<Copy className="w-4 h-4" />
|
<Copy className="w-3.5 h-3.5" />
|
||||||
<span className="truncate">{t('qrCode:copyQrButton')}</span>
|
<span className="truncate text-xs">{t('qrCode:copyQrButton')}</span>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -133,8 +133,8 @@ describe('QrCodePage', () => {
|
|||||||
// 点击生成按钮
|
// 点击生成按钮
|
||||||
fireEvent.click(screen.getByText('生成二维码'));
|
fireEvent.click(screen.getByText('生成二维码'));
|
||||||
|
|
||||||
// 验证显示截断的文本(100字符 + "...")
|
// 验证显示截断的文本(80字符 + "...")
|
||||||
const truncatedText = longText.slice(0, 100) + '...';
|
const truncatedText = longText.slice(0, 80) + '...';
|
||||||
expect(screen.getByText(truncatedText)).toBeInTheDocument();
|
expect(screen.getByText(truncatedText)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { Label } from '@/components/ui/label';
|
|||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
/** 文本预览的最大显示字符数 */
|
/** 文本预览的最大显示字符数 */
|
||||||
const TEXT_PREVIEW_MAX_LENGTH = 100;
|
const TEXT_PREVIEW_MAX_LENGTH = 80;
|
||||||
|
|
||||||
export default function GeneratePanel() {
|
export default function GeneratePanel() {
|
||||||
const { t } = useI18n('qrCode');
|
const { t } = useI18n('qrCode');
|
||||||
@@ -81,29 +81,29 @@ export default function GeneratePanel() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 预览态:显示文本预览 + 二维码
|
// 预览态:显示文本预览 + 二维码(紧凑布局,适配popup窗口)
|
||||||
return (
|
return (
|
||||||
<div className="w-full select-none p-0.5 space-y-4">
|
<div className="w-full select-none p-0.5 flex flex-col">
|
||||||
{/* 文本预览区域 */}
|
{/* 文本预览区域(固定高度,单行显示) */}
|
||||||
<div className="border border-border rounded-xl bg-card text-card-foreground shadow-sm p-4">
|
<div className="border border-border rounded-xl bg-card text-card-foreground shadow-sm p-3 mb-3">
|
||||||
<div className="flex items-center justify-between mb-2">
|
<div className="flex items-center justify-between mb-1.5">
|
||||||
<Label className="text-[10px] font-bold text-muted-foreground/90 uppercase tracking-wider select-none pl-0.5">
|
<Label className="text-[10px] font-bold text-muted-foreground/90 uppercase tracking-wider select-none pl-0.5">
|
||||||
{t('qrCode:textPreviewLabel')}
|
{t('qrCode:textPreviewLabel')}
|
||||||
</Label>
|
</Label>
|
||||||
<Button variant="ghost" size="sm" onClick={backToEdit} className="h-7 px-2 text-xs">
|
<Button variant="ghost" size="sm" onClick={backToEdit} className="h-6 px-2 text-xs">
|
||||||
<Pencil className="w-3 h-3 mr-1" />
|
<Pencil className="w-3 h-3 mr-1" />
|
||||||
{t('qrCode:editButton')}
|
{t('qrCode:editButton')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="text-sm text-foreground bg-muted/50 rounded-md p-3 cursor-default"
|
className="text-sm text-foreground bg-muted/50 rounded-md px-3 py-2 cursor-default line-clamp-1"
|
||||||
title={generatorState.savedText}
|
title={generatorState.savedText}
|
||||||
>
|
>
|
||||||
{getTruncatedText(generatorState.savedText)}
|
{getTruncatedText(generatorState.savedText)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 二维码预览区域 */}
|
{/* 二维码预览区域(自适应剩余空间) */}
|
||||||
<QrCodePreview
|
<QrCodePreview
|
||||||
qrCodeDataUrl={generatorState.qrCodeDataUrl}
|
qrCodeDataUrl={generatorState.qrCodeDataUrl}
|
||||||
onDownload={downloadQrCode}
|
onDownload={downloadQrCode}
|
||||||
|
|||||||
Reference in New Issue
Block a user