字号调整
This commit is contained in:
1 parent
0c5938a5a3
commit
fa41d620fd
6 files changed
+68
-28
No files matched your search
@@ -6,8 +6,10 @@ import { useLocalSettings } from "@/core/settings";
|
||||
|
||||
/**
|
||||
* 基准字号 = 16px,对应《深蓝色 UI 规范》§2.1.2 后台系统正文字号(16px Regular)。
|
||||
* 用户在「外观 → 字号」里选择的倍数作用于 <html> 根元素的 font-size;由于 Tailwind
|
||||
* 的字号 / 间距基于 rem,整套界面会随之按比例放大 / 缩小。`fontScale === 1` 即默认 16px。
|
||||
* 用户在「外观 → 字号」里选择的倍数通过 CSS 变量 `--ui-font-scale` 生效:globals.css
|
||||
* 只把 Tailwind 的 `--text-*` 字号 token 乘以该倍数,**不动间距 token**,所以放大 / 缩小
|
||||
* 的只有文字本身,padding / margin / 宽高等布局尺寸保持不变,不会把页面挤错位。
|
||||
* `fontScale === 1` 即默认 16px。
|
||||
*/
|
||||
export const BASE_FONT_PX = 16;
|
||||
|
||||
@@ -20,7 +22,8 @@ export const FONT_SCALE_OPTIONS: { value: number; label: string; px: number }[]
|
||||
];
|
||||
|
||||
/**
|
||||
* 将用户选择的字号倍数应用到 <html> 根元素。挂在应用根部,保证刷新后即时生效、全局统一。
|
||||
* 把用户选择的字号倍数写到 <html> 的 `--ui-font-scale` CSS 变量。挂在应用根部,
|
||||
* 保证刷新后即时生效、全局统一。只设变量、不直接改 font-size,因此布局不受影响。
|
||||
* 不渲染任何 DOM。
|
||||
*/
|
||||
export function FontScaleApplier() {
|
||||
@@ -32,7 +35,10 @@ export function FontScaleApplier() {
|
||||
typeof fontScale === "number" && Number.isFinite(fontScale) && fontScale > 0
|
||||
? fontScale
|
||||
: 1;
|
||||
document.documentElement.style.fontSize = `${BASE_FONT_PX * scale}px`;
|
||||
const root = document.documentElement;
|
||||
root.style.setProperty("--ui-font-scale", String(scale));
|
||||
// 清掉旧实现可能残留的根级 font-size 内联样式(旧版用它做整页缩放)。
|
||||
root.style.removeProperty("font-size");
|
||||
}, [fontScale]);
|
||||
|
||||
return null;
|
||||
|
||||
@@ -56,12 +56,12 @@ export function MessageBubble({
|
||||
{senderName}
|
||||
</span>
|
||||
{badge && (
|
||||
<span className="text-[9px] font-mono font-black uppercase text-[var(--brand-900)] bg-[var(--brand-200)] border border-red-200 px-1.5 py-0.2 rounded">
|
||||
<span className="text-[calc(9px*var(--ui-font-scale,1))] font-mono font-black uppercase text-[var(--brand-900)] bg-[var(--brand-200)] border border-red-200 px-1.5 py-0.2 rounded">
|
||||
{badge}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<span className="text-[10px] text-slate-400 font-mono font-medium shrink-0">{time}</span>
|
||||
<span className="text-[calc(10px*var(--ui-font-scale,1))] text-slate-400 font-mono font-medium shrink-0">{time}</span>
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
@@ -139,13 +139,13 @@ export const sharedMarkdownComponents = {
|
||||
const isBlock = /language-/.test(className ?? "");
|
||||
if (isBlock) {
|
||||
return (
|
||||
<pre className="bg-slate-100 text-slate-800 rounded-md p-2 my-1 overflow-x-auto text-[11px] font-mono">
|
||||
<pre className="bg-slate-100 text-slate-800 rounded-md p-2 my-1 overflow-x-auto text-[calc(11px*var(--ui-font-scale,1))] font-mono">
|
||||
<code>{children}</code>
|
||||
</pre>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<code className="bg-slate-100 text-slate-800 rounded px-1 py-0.5 text-[11px] font-mono">
|
||||
<code className="bg-slate-100 text-slate-800 rounded px-1 py-0.5 text-[calc(11px*var(--ui-font-scale,1))] font-mono">
|
||||
{children}
|
||||
</code>
|
||||
);
|
||||
@@ -161,7 +161,7 @@ export const sharedMarkdownComponents = {
|
||||
</a>
|
||||
),
|
||||
table: ({ children }: { children?: React.ReactNode }) => (
|
||||
<table className="my-1 border-collapse text-[11px]">{children}</table>
|
||||
<table className="my-1 border-collapse text-[calc(11px*var(--ui-font-scale,1))]">{children}</table>
|
||||
),
|
||||
th: ({ children }: { children?: React.ReactNode }) => (
|
||||
<th className="border border-slate-300 px-1.5 py-0.5 bg-slate-50 font-bold text-left">
|
||||
@@ -254,7 +254,7 @@ export function ReasoningBlock({
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleToggle}
|
||||
className="inline-flex items-center gap-1.5 text-[11.5px] text-slate-500 hover:text-slate-700 transition-colors cursor-pointer"
|
||||
className="inline-flex items-center gap-1.5 text-[calc(11.5px*var(--ui-font-scale,1))] text-slate-500 hover:text-slate-700 transition-colors cursor-pointer"
|
||||
>
|
||||
<BrainIcon className={cn("size-3.5", streaming && "text-primary animate-pulse")} />
|
||||
<span className={cn(streaming && "animate-pulse")}>{headerLabel}</span>
|
||||
@@ -265,7 +265,7 @@ export function ReasoningBlock({
|
||||
{open && (
|
||||
<div
|
||||
className={cn(
|
||||
"rounded-md border border-slate-200 bg-slate-50/60 px-3 py-2 text-[11.5px] text-slate-600 leading-relaxed",
|
||||
"rounded-md border border-slate-200 bg-slate-50/60 px-3 py-2 text-[calc(11.5px*var(--ui-font-scale,1))] text-slate-600 leading-relaxed",
|
||||
contentClassName,
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -86,10 +86,10 @@ export function MessageStepsCard({
|
||||
const display = getStepDisplay(lastReasoning.key, lastReasoning.label, lastReasoning.args);
|
||||
const Icon = display.icon;
|
||||
return (
|
||||
<div className={cn("flex items-center gap-2 text-[11.5px] text-slate-500 py-0.5", className)}>
|
||||
<div className={cn("flex items-center gap-2 text-[calc(11.5px*var(--ui-font-scale,1))] text-slate-500 py-0.5", className)}>
|
||||
<Icon className="size-3.5 text-slate-400" />
|
||||
<span>{display.label}</span>
|
||||
<span className="text-[10px] text-slate-400 font-mono">{lastReasoning.ts}</span>
|
||||
<span className="text-[calc(10px*var(--ui-font-scale,1))] text-slate-400 font-mono">{lastReasoning.ts}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -108,7 +108,7 @@ export function MessageStepsCard({
|
||||
>
|
||||
<ChainOfThoughtStep
|
||||
label={
|
||||
<span className="text-[11.5px] opacity-60">
|
||||
<span className="text-[calc(11.5px*var(--ui-font-scale,1))] opacity-60">
|
||||
{showAbove ? "隐藏步骤" : `查看其他 ${priorToolSteps.length} 个步骤`}
|
||||
</span>
|
||||
}
|
||||
@@ -189,9 +189,9 @@ function ToolStep({
|
||||
: undefined
|
||||
}
|
||||
label={
|
||||
<span className="text-[12px] text-slate-700">
|
||||
<span className="text-[calc(12px*var(--ui-font-scale,1))] text-slate-700">
|
||||
<span className="font-medium">{display.label}</span>
|
||||
<span className="ml-2 text-[10px] text-slate-400 font-mono">{step.ts}</span>
|
||||
<span className="ml-2 text-[calc(10px*var(--ui-font-scale,1))] text-slate-400 font-mono">{step.ts}</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
@@ -204,10 +204,10 @@ function ReasoningStep({ step, streaming }: { step: BubbleStep; streaming: boole
|
||||
const display = getStepDisplay(step.key, step.label, step.args);
|
||||
const Icon = display.icon;
|
||||
return (
|
||||
<div className="flex items-center gap-2 text-[11.5px] text-slate-500">
|
||||
<div className="flex items-center gap-2 text-[calc(11.5px*var(--ui-font-scale,1))] text-slate-500">
|
||||
<Icon className={cn("size-3.5", streaming ? "text-primary animate-pulse" : "text-slate-400")} />
|
||||
<span>{display.label}</span>
|
||||
<span className="text-[10px] text-slate-400 font-mono">{step.ts}</span>
|
||||
<span className="text-[calc(10px*var(--ui-font-scale,1))] text-slate-400 font-mono">{step.ts}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -167,7 +167,7 @@ export function Step2Panel(props: Step2PanelProps) {
|
||||
<Cpu className="w-5 h-5 text-primary" strokeWidth={2.5} />
|
||||
<div>
|
||||
<h3 className="text-sm font-extrabold text-slate-900">多智能体圆桌会商中心</h3>
|
||||
<p className="text-[10px] text-slate-400 font-medium">
|
||||
<p className="text-[calc(10px*var(--ui-font-scale,1))] text-slate-400 font-medium">
|
||||
分布式领域专家实时动态博弈与纳什协商收敛中
|
||||
</p>
|
||||
</div>
|
||||
@@ -202,7 +202,7 @@ export function Step2Panel(props: Step2PanelProps) {
|
||||
<button
|
||||
type="button"
|
||||
onClick={onResumeRoundtable}
|
||||
className={`bg-emerald-100 hover:bg-emerald-200 text-emerald-800 text-[10px] font-bold px-2.5 py-1 rounded-xl flex items-center gap-1 transition border border-emerald-200/40 shadow-sm ${
|
||||
className={`bg-emerald-100 hover:bg-emerald-200 text-emerald-800 text-[calc(10px*var(--ui-font-scale,1))] font-bold px-2.5 py-1 rounded-xl flex items-center gap-1 transition border border-emerald-200/40 shadow-sm ${
|
||||
pauseFlash
|
||||
? "ring-2 ring-emerald-400 ring-offset-1 animate-pulse"
|
||||
: ""
|
||||
@@ -215,7 +215,7 @@ export function Step2Panel(props: Step2PanelProps) {
|
||||
<button
|
||||
type="button"
|
||||
onClick={onPauseRoundtable}
|
||||
className="bg-amber-100 hover:bg-amber-200 text-amber-800 text-[10px] font-bold px-2.5 py-1 rounded-xl flex items-center gap-1 transition border border-amber-200/40 shadow-sm"
|
||||
className="bg-amber-100 hover:bg-amber-200 text-amber-800 text-[calc(10px*var(--ui-font-scale,1))] font-bold px-2.5 py-1 rounded-xl flex items-center gap-1 transition border border-amber-200/40 shadow-sm"
|
||||
>
|
||||
<Pause className="w-3.5 h-3.5" />
|
||||
暂停会商
|
||||
@@ -279,13 +279,13 @@ export function Step2Panel(props: Step2PanelProps) {
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs font-extrabold text-amber-900">总控协调需要澄清</span>
|
||||
{pendingClarification.clarificationType && (
|
||||
<span className="text-[9px] font-mono font-black uppercase text-amber-900 bg-amber-200 border border-amber-300 px-1.5 py-0.2 rounded">
|
||||
<span className="text-[calc(9px*var(--ui-font-scale,1))] font-mono font-black uppercase text-amber-900 bg-amber-200 border border-amber-300 px-1.5 py-0.2 rounded">
|
||||
{pendingClarification.clarificationType}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{pendingClarification.context && (
|
||||
<p className="text-[11px] text-amber-800 italic">{pendingClarification.context}</p>
|
||||
<p className="text-[calc(11px*var(--ui-font-scale,1))] text-amber-800 italic">{pendingClarification.context}</p>
|
||||
)}
|
||||
<p className="text-xs text-slate-800 leading-relaxed font-medium whitespace-pre-wrap break-words">
|
||||
{pendingClarification.question}
|
||||
@@ -306,7 +306,7 @@ export function Step2Panel(props: Step2PanelProps) {
|
||||
key={`${idx}-${label}`}
|
||||
type="button"
|
||||
onClick={() => onSubmitClarification(label)}
|
||||
className="text-[11px] font-bold px-3 py-1.5 rounded-full bg-white border border-amber-300 text-amber-900 hover:bg-amber-100 transition active:scale-95 cursor-pointer"
|
||||
className="text-[calc(11px*var(--ui-font-scale,1))] font-bold px-3 py-1.5 rounded-full bg-white border border-amber-300 text-amber-900 hover:bg-amber-100 transition active:scale-95 cursor-pointer"
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
@@ -580,17 +580,17 @@ function PresentFileCard({
|
||||
<div className="flex items-start gap-2">
|
||||
<FileIcon className="mt-0.5 size-4 shrink-0 text-slate-400" />
|
||||
<span
|
||||
className="truncate text-[12px] font-medium text-slate-700"
|
||||
className="truncate text-[calc(12px*var(--ui-font-scale,1))] font-medium text-slate-700"
|
||||
title={filename}
|
||||
>
|
||||
{filename}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<span className="rounded bg-slate-100 px-1.5 py-0.5 text-[10px] font-mono font-semibold text-slate-500">
|
||||
<span className="rounded bg-slate-100 px-1.5 py-0.5 text-[calc(10px*var(--ui-font-scale,1))] font-mono font-semibold text-slate-500">
|
||||
{typeLabel}
|
||||
</span>
|
||||
<span className="text-[10px] text-slate-400">点击预览</span>
|
||||
<span className="text-[calc(10px*var(--ui-font-scale,1))] text-slate-400">点击预览</span>
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
@import "tailwindcss";
|
||||
/* 注意:不要在这里 `@import "tailwindcss"`。Tailwind 已由全局 globals.css 引入,
|
||||
* 本文件被打进同一份样式表,再次 import 会把整套 theme/utilities 重复发一遍
|
||||
* (CSS 体积翻倍,且重复发出的 --text-* 等主题变量会和全局覆盖打架)。
|
||||
* 本文件只写圆桌页自己的作用域规则即可。 */
|
||||
|
||||
/* 圆桌规划 — 浅色红色主题(对齐 docs/浅红色ui修改.md) */
|
||||
.roundtable-planning {
|
||||
|
||||
@@ -820,3 +820,34 @@
|
||||
border-color: var(--border);
|
||||
outline-color: var(--ring);
|
||||
}
|
||||
|
||||
/* ─── 全局字号缩放(只改字号,不动布局)──────────────────────────────────
|
||||
* 用户在「设置 → 外观 → 字号」里选的倍数由 FontScaleApplier 写到
|
||||
* <html> 的 `--ui-font-scale`(默认 1)。这里只把 Tailwind 的 `--text-*`
|
||||
* 字号 token 乘以该倍数 —— 间距 token(--spacing)原样不动,所以 padding /
|
||||
* margin / gap / 宽高这些布局尺寸不随字号变化,避免放大字体把页面挤错位。
|
||||
* 行高用 Tailwind 默认的无单位比值,会跟随字号等比变化(文字不会重叠)。
|
||||
* 不在 @layer 内,优先级高于 Tailwind 的主题层变量,确保覆盖生效。 */
|
||||
:root {
|
||||
--ui-font-scale: 1;
|
||||
|
||||
--text-xs: calc(0.75rem * var(--ui-font-scale, 1));
|
||||
--text-sm: calc(0.875rem * var(--ui-font-scale, 1));
|
||||
--text-base: calc(1rem * var(--ui-font-scale, 1));
|
||||
--text-lg: calc(1.125rem * var(--ui-font-scale, 1));
|
||||
--text-xl: calc(1.25rem * var(--ui-font-scale, 1));
|
||||
--text-2xl: calc(1.5rem * var(--ui-font-scale, 1));
|
||||
--text-3xl: calc(1.875rem * var(--ui-font-scale, 1));
|
||||
--text-4xl: calc(2.25rem * var(--ui-font-scale, 1));
|
||||
--text-5xl: calc(3rem * var(--ui-font-scale, 1));
|
||||
--text-6xl: calc(3.75rem * var(--ui-font-scale, 1));
|
||||
--text-7xl: calc(4.5rem * var(--ui-font-scale, 1));
|
||||
--text-8xl: calc(6rem * var(--ui-font-scale, 1));
|
||||
--text-9xl: calc(8rem * var(--ui-font-scale, 1));
|
||||
}
|
||||
|
||||
/* 没有显式 text-* 类的元素(继承自 body 的默认正文)也跟随缩放。
|
||||
* 只设 font-size,不影响任何盒模型尺寸。 */
|
||||
body {
|
||||
font-size: calc(1rem * var(--ui-font-scale, 1));
|
||||
}
|
||||
Reference in new issue
Block a user