style(usage): compact overview stat cards and fit 6 cards in a single row

This commit is contained in:
lzt404 committed 2026-09-21 21:58:01 +08:00
1 parent ae18553e1d
commit 07c6d79b81
3 files changed
+60 -32

No files matched your search

+2 -5
View File
@@ -1028,7 +1028,7 @@ function OverviewView({ overview, range }: { overview: UsageOverview; range?: Pi
},
{
label: t('usage.stat.tps'),
value: overview.tpsSampleCount > 0 ? `${overview.tps.toFixed(1)} TPS` : '—',
value: overview.tpsSampleCount > 0 ? overview.tps.toFixed(1) : '—',
meta: t('usage.stat.performanceMeta', {
samples: compactNumber(overview.tpsSampleCount),
rpm: overview.rpm.toFixed(2),
@@ -1073,12 +1073,9 @@ function OverviewView({ overview, range }: { overview: UsageOverview; range?: Pi
<div className="usage-overview-layout">
<div className="usage-stat-grid">
{cards.map(({ label, value, meta, metaTitle }) => (
<article className="panel usage-stat-card" key={label}>
<article className="panel usage-stat-card" key={label} title={metaTitle ?? meta}>
<span className="usage-stat-card-label">{label}</span>
<strong className="usage-stat-card-value">{value}</strong>
<small className="usage-stat-card-meta" title={metaTitle ?? meta}>
{meta}
</small>
</article>
))}
</div>
+33 -25
View File
@@ -8439,47 +8439,53 @@ textarea:focus-visible {
.usage-stat-grid {
grid-column: 1 / -1;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 12px;
grid-template-columns: repeat(6, minmax(0, 1fr));
gap: 10px;
}
.usage-stat-card {
display: grid;
gap: 8px;
padding: 14px 16px;
display: flex;
flex-direction: column;
justify-content: center;
gap: 5px;
padding: 10px 12px;
border: 1px solid var(--theme-e3e1db);
border-radius: 9px;
border-radius: 8px;
background: var(--theme-fffdf8);
min-width: 0;
transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}
.usage-stat-card:hover {
border-color: var(--theme-d5d2cb);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
transform: translateY(-1px);
}
.usage-stat-card-label {
color: var(--theme-7a746c);
font-size: var(--font-size-meta);
font-weight: var(--font-weight-semibold);
font-size: var(--font-size-caption);
font-weight: var(--font-weight-medium);
line-height: 1.25;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.usage-stat-card-value {
color: var(--theme-2d2a26);
font-size: var(--font-size-metric-compact);
font-size: 20px;
font-weight: var(--font-weight-semibold);
font-variant-numeric: tabular-nums;
line-height: 1.15;
line-height: 1.2;
letter-spacing: -0.01em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.usage-stat-card-meta {
color: var(--theme-8a847c);
font-size: var(--font-size-caption);
line-height: 1.3;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: none;
}
/* Trend Panel */
@@ -10851,10 +10857,6 @@ body.table-col-resizing * {
grid-template-columns: 200px minmax(0, 1fr);
}
.usage-stat-grid {
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
}
.control-panel,
.version-panel {
grid-column: auto;
@@ -11321,7 +11323,7 @@ body.table-col-resizing * {
}
.usage-stat-grid {
grid-template-columns: 1fr;
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.usage-custom-range {
@@ -14554,13 +14556,13 @@ body.table-col-resizing * {
.agent-workbench {
grid-template-columns: 200px minmax(0, 1fr);
}
.usage-stat-grid {
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
}
}
@container workspace (max-width: 760px) {
.usage-stat-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.config-network-grid,
.config-tls-fields,
.config-management-form,
@@ -14725,6 +14727,12 @@ body.table-col-resizing * {
}
}
@container workspace (max-width: 480px) {
.usage-stat-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@container workspace (max-width: 540px) {
.usage-data-management-heading,
.usage-data-management-action,
+25 -2
View File
@@ -6,11 +6,34 @@ const base = 'http://127.0.0.1:1421';
(async () => {
const browser = await chromium.launch({ channel: 'msedge', headless: true, args: ['--no-proxy-server'] });
try {
const page = await browser.newPage({ viewport: { width: 1100, height: 600 } });
const page = await browser.newPage({ viewport: { width: 1213, height: 600 } });
await page.route('**/*', (route) => route.request().url().startsWith(`${base}/`) ? route.continue() : route.abort());
await page.goto(`${base}/tests/fixtures/usage-layout.html`, { waitUntil: 'domcontentloaded' });
await page.locator('.usage-trend-x-axis').waitFor();
const statInfo1213 = await page.evaluate(() => {
const cards = Array.from(document.querySelectorAll('.usage-stat-card'));
const metas = Array.from(document.querySelectorAll('.usage-stat-card-meta'));
const tpsCard = cards.find((card) => card.querySelector('.usage-stat-card-label')?.textContent?.trim() === 'TPS');
const tpsValue = tpsCard?.querySelector('.usage-stat-card-value')?.textContent?.trim() ?? '';
return {
cardCount: cards.length,
metaCount: metas.length,
cardRows: new Set(cards.map((card) => Math.round(card.getBoundingClientRect().top))).size,
tpsValue,
};
});
assert.equal(statInfo1213.cardCount, 6, 'There are 6 stat cards');
assert.equal(statInfo1213.cardRows, 1, 'At 1213px width, all 6 cards fit into a single row');
assert.equal(statInfo1213.metaCount, 0, 'Stat cards have no meta subtext displayed');
assert.ok(!statInfo1213.tpsValue.includes('TPS'), `TPS value should not contain TPS unit: ${statInfo1213.tpsValue}`);
assert.ok(/^\d+(\.\d+)?$/.test(statInfo1213.tpsValue), `TPS value should be numeric: ${statInfo1213.tpsValue}`);
// Now test constrained width where cards wrap and ensure vertical scrolling is preserved
await page.setViewportSize({ width: 750, height: 600 });
await page.waitForTimeout(100);
const geometry = await page.evaluate(() => {
const layout = document.querySelector('.usage-overview-layout');
const panel = document.querySelector('.usage-trend-panel');
@@ -45,7 +68,7 @@ const base = 'http://127.0.0.1:1421';
return axis.getBoundingClientRect().bottom <= layout.getBoundingClientRect().bottom + 1;
}), 'The complete X axis is reachable by scrolling the overview');
console.log('PASS: wrapped usage cards preserve the full trend chart and use vertical overview scrolling.');
console.log('PASS: 1213px single row stat cards and constrained wrapped overview scrolling passed.');
} finally {
await browser.close();
}