style(usage): compact overview stat cards and fit 6 cards in a single row
This commit is contained in:
1 parent
ae18553e1d
commit
07c6d79b81
3 files changed
+60
-32
No files matched your search
@@ -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
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user