8000 style(web): unify design tokens and polish desktop and mobile UI craft by InfinityPacer · Pull Request #82 · InfinityPacer/meterleaf · GitHub
[go: up one dir, main page]

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 19 additions & 18 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,24 @@ Meterleaf 是看账的工具,界面安静、密度适中,数字是主角。
`border-border`),不写十六进制色值。图表画在 canvas 里读不到 CSS 变量,由
`src/web/lib/theme-colors.ts` 取出当前主题的颜色。

| 令牌 | 浅色 / 深色 | 用在 |
| ------------------------------------- | ------------------------------------------------------------- | ----------------------------------------------------------- |
| `canvas` | `#f7f7f8` / `#0f0f11` | 页面底 |
| `surface` / `soft` / `elevated` | `#ffffff` `#f0f0f2` `#ffffff` / `#17171a` `#1f1f23` `#2e2e33` | 卡片与面板、弱一级的底(筛选、分段控件)、浮层 |
| `sidebar` | `#fbfbfc` / `#131316` | 桌面侧栏 |
| `ink` / `muted` / `faint` | `#18181b` `#5f5f68` `#8e8e97` / `#f2f2f3` `#a1a1aa` `#71717a` | 正文与数字、说明与次要数字、最弱的提示 |
| `line` / `line-soft` / `control-line` | `#e4e4e7` `#ededf0` `#d4d4d8` / `#2a2a2f` `#212125` `#3f3f46` | 分隔线、表格内的弱分隔、输入框与控件边框 |
| `track` | `#e9e9ec` / `#27272b` | 额度进度条的底槽 |
| `accent` / `accent-ink` | 翠绿 `#0e8a55` `#ffffff` / `#3ccb8a` `#07130d` | 进度、选中、焦点环、主要操作,`accent-ink` 是强调色上的文字 |
| `accent-soft` / `accent-line` | 强调色 8% / 12% 与 30% / 36% | 选中项与套餐徽标的底和边 |
| `warn` | `#c2410c` / `#f08a5d` | 额度用尽或接近用尽(`quota-alert` 是它的别名) |
| `danger` | `#c8323f` / `#f2798a` | 失败与破坏性操作 |
| `radius` | `6px` | 控件圆角基准,卡片用 8px,大面板用 12px,头像与状态点是圆形 |
| `shadow` | 极轻的 1px 投影 / 无 | 浅色下浮起的卡片,深色不用投影,靠 `elevated` 区分层次 |

靛蓝配色的强调色是 `#4f46e5` / `#8b8cf6`,黑白配色是 `#18181b` / `#f2f2f3`。`teal`、`blue`、`tint`
是旧名,都指向强调色,新代码不再使用。
| 令牌 | 浅色 / 深色 | 用在 |
| ----------------------------------------------------- | --------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `canvas` | `#f7f7f8` / `#0f0f11` | 页面画布底色,与 `index.html` 首屏色保持一致 |
| `surface` / `soft` / `soft-hover` / `elevated` | `#ffffff` `#f1f2f4` `#e8eaee` `#ffffff` / `#161619` `#1f1f24` `#27272e` `#2b2b33` | 卡片与面板、次级控件底、悬停反馈底、分段控件滑块与浮起层 |
| `sidebar` | `#fbfbfc` / `#121215` | 桌面侧栏与移动端侧栏抽屉 |
| `ink` / `muted` / `faint` | `#18181b` `#5b5c66` `#8b8d98` / `#f2f2f3` `#a0a1ab` `#6e707a` | 正文与主数字、标签与说明、次级弱提示 |
| `line` / `line-soft` / `control-line` | `#e4e5e9` `#eff0f3` `#d4d6dc` / `#27272d` `#1f1f24` `#383842` | 卡片与区块细线、表内弱分隔线、输入与下拉触发器描边 |
| `track` | `#e8e9ed` / `#26262c` | 额度进度条与构成条底槽 |
| `accent` / `accent-ink` | 翠绿 `#0e8a55` `#ffffff` / `#3ccb8a` `#07130d` | 进度、选中、焦点环、主要状态,`accent-ink` 是强调色实底上的文字 |
| `accent-soft` / `accent-line` | 强调色 8% / 12% 与 28% / 34% | 选中弱底与二档套餐徽标描边 |
| `warn` / `danger` | `#c2410c` `#c8323f` / `#f08a5d` `#f2798a` | 额度预警或环比升高、失败与破坏性操作 |
| `radius-xs` / `radius-sm` / `radius-md` / `radius-lg` | `6px` / `8px` / `12px` / `16px` | 徽标与内滑块、按钮与筛选控件、桌面面板卡片与菜单弹层、移动端卡片 |
| `shadow-card` | 浅色细微接触投影 / 深色顶边 3% 高光内描边 | 所有桌面与移动端主卡片统一层次 |
| `shadow-control` / `shadow-float` | 控件微投影 / 浮层柔和投影 | 分段滑块与按钮微层次、下拉弹层与对话框 |
| `control-height` | 桌面 `38px` / 移动端 `44px` | 筛选栏内日期、下拉、分段切换与搜索框严格等高对齐 |
| `ease-out` / `duration-fast` | `cubic-bezier(0.16, 1, 0.3, 1)` / `150ms` | 悬停、弹层与状态过渡曲线 |

靛蓝配色的强调色是 `#4f46e5` / `#8b8cf6`,黑白配色是 `#18181b` / `#f2f2f3`。`teal`、`blue`、`tint`、`radius`、`shadow` 保留为兼容别名。

## 字体与数字

Expand All @@ -44,7 +45,7 @@ Meterleaf 是看账的工具,界面安静、密度适中,数字是主角。
- 字重以 400、500、600 为主,强调用 600,不用粗体堆层次。
- 金额、百分比、Tokens 与次数一律用等宽数字(`font-variant-numeric: tabular-nums`),上下行对齐,
数字变化时不跳动。
- 字间距保持 0,只有套餐徽标略放宽。
- 正文字间距保持 0,大号展示数字略收紧(`-0.015em` 到 `-0.028em`),套餐徽标略放宽。

## 布局

Expand Down
57 changes: 41 additions & 16 deletions src/web/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2128,9 +2128,13 @@ export function App() {
)}
<dt>推理强度</dt>
<dd>
{selected.details.requestedReasoningEffort ??
selected.details.reasoningEffort ??
"N/A"}
{(selected.details.requestedReasoningEffort ??
selected.details.reasoningEffort) ? (
(selected.details.requestedReasoningEffort ??
selected.details.reasoningEffort)
) : (
<span className="faint-na">N/A</span>
)}
</dd>
{selected.details.requestedReasoningEffort &&
selected.details.reasoningEffort &&
Expand All @@ -2143,7 +2147,7 @@ export function App() {
)}
{selected.details.firstTokenMs !== null && (
<>
<dt>首 token 延迟</dt>
<dt>首 Token 延迟</dt>
<dd>
{selected.details.firstTokenMs.toLocaleString()} ms
</dd>
Expand All @@ -2161,22 +2165,42 @@ export function App() {
)}
<dt>速度档</dt>
<dd>
{selected.tier === "unknown"
? "N/A"
: selected.tier === "priority"
? "Priority"
: selected.tier === "flex"
? "Flex"
: "Standard"}
{selected.tier === "unknown" ? (
<span className="faint-na">N/A</span>
) : selected.tier === "priority" ? (
"Priority"
) : selected.tier === "flex" ? (
"Flex"
) : (
"Standard"
)}
</dd>
<dt>来源 ID</dt>
<dd>{selected.sourceId || "N/A"}</dd>
<dd>
{selected.sourceId || <span className="faint-na">N/A</span>}
</dd>
<dt>源记录 ID</dt>
<dd>{selected.sourceRecordId || "N/A"}</dd>
<dd>
{selected.sourceRecordId || (
<span className="faint-na">N/A</span>
)}
</dd>
<dt>网关成本</dt>
<dd>{formatUsd(selected.gatewayCost ?? null)}</dd>
<dd>
{selected.gatewayCost == null ? (
<span className="faint-na">N/A</span>
) : (
formatUsd(selected.gatewayCost)
)}
</dd>
<dt>网关计费</dt>
<dd>{formatUsd(selected.gatewayBilled ?? null)}</dd>
<dd>
{selected.gatewayBilled == null ? (
<span className="faint-na">N/A</span>
) : (
formatUsd(selected.gatewayBilled)
)}
</dd>
</dl>
<h3>Token 拆分</h3>
<dl className="details-list tokens-list">
Expand Down Expand Up @@ -2256,7 +2280,7 @@ export function App() {
label={
key === "sevenDayFable"
? "Fable 周额度"
: `${label}窗口`
: `${label} 窗口`
}
asOf={quotaAsOf}
waiting={waiting}
Expand Down Expand Up @@ -2488,6 +2512,7 @@ export function App() {
)}
<Button
variant="outline"
className="detail-action-button"
=> {
openAccountRequests(selectedAccount.id);
setSelectedAccount(null);
Expand Down
9 changes: 8 additions & 1 deletion src/web/components/LedgerTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,14 @@ export function LedgerTable({
id: "reasoningEffort",
header: "推理强度",
accessorFn: requestReasoningEffort,
cell: (info) => info.getValue<string | null>() ?? "N/A",
cell: (info) => {
const effort = info.getValue<string | null>();
return effort ? (
<span className="effort-badge">{effort}</span>
) : (
<span className="faint-na">N/A</span>
);
},
enableSorting: false,
},
{
Expand Down
22 changes: 11 additions & 11 deletions src/web/components/ModelDistribution.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -322,17 +322,17 @@ export function ModelDistribution({
<p className="mobile-model-empty muted">暂无可展示的占比</p>
)}
</div>
</div>
<div className="mobile-distribution-unit">
<Segmented
label="手机模型分布指标"
value={unit}
>
options={[
{ value: "tokens", label: "Tokens" },
{ value: "usd", label: "费用" },
]}
/>
<div className="mobile-distribution-unit">
<Segmented
label="手机模型分布指标"
value={unit}
>}
options={[
{ value: "tokens", label: "Tokens" },
{ value: "usd", label: "费用" },
]}
/>
</div>
</div>
</section>
);
Expand Down
14 changes: 14 additions & 0 deletions src/web/components/ReportTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,20 @@ export function ReportTable({
</details>
);
})}
{data.length > 1 &&
(() => {
const totals = totalRow(data);
return (
<div className="mobile-report-total">
<span>合计</span>
<span>{totals.requests.toLocaleString()}</span>
<span>{compact(totals.tokens)}</span>
<span className="mobile-report-usd">
<strong>{amount(totals.usd, "usd")}</strong>
</span>
</div>
);
})()}
</div>
{!data.length ? (
<div className="empty-state">
Expand Down
17 changes: 10 additions & 7 deletions src/web/components/UsageChart.tsx
6871
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ export function UsageChart({
renderMode: "richText",
backgroundColor: colors.surface,
borderColor: colors.line,
textStyle: { color: colors.ink, fontSize: 13 },
borderWidth: 1,
padding: [8, 10],
textStyle: { color: colors.ink, fontSize: 12.5 },
formatter: (params: unknown) => {
const values = params as { dataIndex: number }[];
const point = data[values[0]?.dataIndex ?? 0];
Expand Down Expand Up @@ -154,7 +156,7 @@ export function UsageChart({
unit === "usd" ? `$${compactAxis(v)}` : compactAxis(v),
},
splitLine: {
lineStyle: { color: colors.lineSoft },
lineStyle: { color: colors.lineSoft, type: "dashed" },
},
},
series: [
Expand All @@ -174,17 +176,17 @@ export function UsageChart({
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: colors.accentAlpha(0.22) },
{ offset: 1, color: colors.accentAlpha(0.02) },
{ offset: 0, color: colors.accentAlpha(0.18) },
{ offset: 1, color: colors.accentAlpha(0.01) },
],
},
}
: undefined,
data: data.map((point) => point.value),
barMaxWidth: 42,
barMaxWidth: 36,
itemStyle: {
color: colors.accent,
borderRadius: [3, 3, 0, 0],
borderRadius: [4, 4, 0, 0],
},
emphasis: { itemStyle: { color: colors.accent } },
},
Expand Down Expand Up @@ -232,7 +234,7 @@ export function UsageChart({
series: [
{
type: "pie",
radius: donut ? ["58%", "90%"] : "68%",
radius: donut ? ["64%", "88%"] : "68%",
center: donut ? ["50%", "50%"] : ["50%", "43%"],
stillShowZeroSum: false,
label: {
Expand All @@ -247,6 +249,7 @@ export function UsageChart({
itemStyle: {
borderColor: colors.surface,
borderWidth: 2,
borderRadius: donut ? 3 : 0,
},
data: pieData,
},
Expand Down
Loading
Loading
0