mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-26 09:02:11 +03:00
fix(ui): wrap quota card footer action buttons to prevent clipping Refresh button on narrow cards (#11464)
Validated in a combined sub-batch worktree off release/v3.8.51 tip. This PR's branch carried ~100 already-merged commits from a stale rebase (phantom-diff — every commit but the last matches history already on the release tip); cherry-picked only the genuine value commit (the flex-wrap fix itself) and pushed that to this branch. - Focused tests: quota-card-expanded-footer-flex-wrap.test.ts, quota-card-expanded-sort-collapse.test.ts, quota-card-grid-mobile-7072.test.ts — part of sub-batch's 165/165 node:test run - typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK - Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff Thanks for the clear root cause (extra View credits button + missing flex-wrap on the footer + overflow-hidden on the outer Card clipping the trailing Refresh now button).
This commit is contained in:
1
changelog.d/fixes/quota-card-footer-flex-wrap.md
Normal file
1
changelog.d/fixes/quota-card-footer-flex-wrap.md
Normal file
@@ -0,0 +1 @@
|
||||
- fix(ui): wrap quota card footer action buttons to prevent clipping Refresh button on narrow cards — when extra action buttons such as `View credits` are present on Codex cards, allow the footer row to flex-wrap with `shrink-0` buttons so `Refresh now` remains visible and clickable across all responsive card widths
|
||||
@@ -418,10 +418,10 @@ export default function QuotaCardExpanded({
|
||||
</button>
|
||||
)}
|
||||
|
||||
<div className="flex items-center justify-between gap-2 pt-1.5 border-t border-border/40">
|
||||
<div className="flex flex-wrap items-center justify-between gap-1.5 pt-1.5 border-t border-border/40">
|
||||
{refreshedLabel && (
|
||||
<span
|
||||
className={`text-[10px] tabular-nums ${
|
||||
className={`text-[10px] tabular-nums shrink-0 ${
|
||||
hasStaleData ? "text-amber-500" : "text-text-muted"
|
||||
}`}
|
||||
title={
|
||||
@@ -433,7 +433,7 @@ export default function QuotaCardExpanded({
|
||||
{tr("updatedShort", "Updated")} {refreshedLabel}
|
||||
</span>
|
||||
)}
|
||||
<div className="flex items-center gap-1.5 ml-auto">
|
||||
<div className="flex flex-wrap items-center justify-end gap-1.5 ml-auto">
|
||||
{canRedeemResetCredit && (
|
||||
<button
|
||||
type="button"
|
||||
@@ -442,7 +442,7 @@ export default function QuotaCardExpanded({
|
||||
e.stopPropagation();
|
||||
onOpenResetCredits?.();
|
||||
}}
|
||||
className="inline-flex items-center gap-1 text-[11px] font-medium px-2 py-1 rounded-md border border-primary/40 text-primary bg-bg-subtle hover:bg-black/[0.04] dark:hover:bg-white/[0.04] disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer"
|
||||
className="inline-flex shrink-0 items-center gap-1 text-[11px] font-medium px-2 py-1 rounded-md border border-primary/40 text-primary bg-bg-subtle hover:bg-black/[0.04] dark:hover:bg-white/[0.04] disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer"
|
||||
>
|
||||
<span
|
||||
className={`material-symbols-outlined text-[12px] ${
|
||||
@@ -461,7 +461,7 @@ export default function QuotaCardExpanded({
|
||||
e.stopPropagation();
|
||||
onOpenCutoff();
|
||||
}}
|
||||
className={`inline-flex items-center gap-1 text-[11px] font-medium px-2 py-1 rounded-md border bg-bg-subtle hover:bg-black/[0.04] dark:hover:bg-white/[0.04] disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer ${
|
||||
className={`inline-flex shrink-0 items-center gap-1 text-[11px] font-medium px-2 py-1 rounded-md border bg-bg-subtle hover:bg-black/[0.04] dark:hover:bg-white/[0.04] disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer ${
|
||||
hasCutoffOverrides ? "border-primary/40 text-primary" : "border-border"
|
||||
}`}
|
||||
>
|
||||
@@ -474,7 +474,7 @@ export default function QuotaCardExpanded({
|
||||
e.stopPropagation();
|
||||
onOpenCost();
|
||||
}}
|
||||
className="inline-flex items-center gap-1 text-[11px] font-medium px-2 py-1 rounded-md border border-border bg-bg-subtle hover:bg-black/[0.04] dark:hover:bg-white/[0.04] cursor-pointer"
|
||||
className="inline-flex shrink-0 items-center gap-1 text-[11px] font-medium px-2 py-1 rounded-md border border-border bg-bg-subtle hover:bg-black/[0.04] dark:hover:bg-white/[0.04] cursor-pointer"
|
||||
>
|
||||
<span className="material-symbols-outlined text-[12px]">bar_chart</span>
|
||||
{t("usdCost")}
|
||||
@@ -486,7 +486,7 @@ export default function QuotaCardExpanded({
|
||||
e.stopPropagation();
|
||||
onRefresh();
|
||||
}}
|
||||
className="inline-flex items-center gap-1 text-[11px] font-medium px-2 py-1 rounded-md border border-border bg-bg-subtle hover:bg-black/[0.04] dark:hover:bg-white/[0.04] disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer"
|
||||
className="inline-flex shrink-0 items-center gap-1 text-[11px] font-medium px-2 py-1 rounded-md border border-border bg-bg-subtle hover:bg-black/[0.04] dark:hover:bg-white/[0.04] disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer"
|
||||
>
|
||||
<span
|
||||
className={`material-symbols-outlined text-[12px] ${loading ? "animate-spin" : ""}`}
|
||||
|
||||
35
tests/unit/quota-card-expanded-footer-flex-wrap.test.ts
Normal file
35
tests/unit/quota-card-expanded-footer-flex-wrap.test.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const COMPONENT_PATH = path.resolve(
|
||||
path.dirname(fileURLToPath(import.meta.url)),
|
||||
"../../src/app/(dashboard)/dashboard/usage/components/ProviderLimits/parts/QuotaCardExpanded.tsx"
|
||||
);
|
||||
|
||||
test("QuotaCardExpanded footer enables flex-wrap to prevent action button clipping", () => {
|
||||
const content = fs.readFileSync(COMPONENT_PATH, "utf8");
|
||||
|
||||
// Assert footer container has flex-wrap and border-t
|
||||
assert.match(
|
||||
content,
|
||||
/className="[^"]*flex\s+flex-wrap[^"]*border-t[^"]*"/,
|
||||
"Footer container must include flex-wrap to allow wrapping on narrow cards"
|
||||
);
|
||||
|
||||
// Assert buttons container has flex-wrap
|
||||
assert.match(
|
||||
content,
|
||||
/className="[^"]*flex\s+flex-wrap[^"]*ml-auto[^"]*"/,
|
||||
"Action buttons container must include flex-wrap to prevent pushing Refresh now button off-screen"
|
||||
);
|
||||
|
||||
// Assert Refresh now button has shrink-0
|
||||
assert.ok(
|
||||
content.includes("inline-flex shrink-0 items-center gap-1 text-[11px] font-medium") &&
|
||||
content.includes('tr("forceRefresh", "Refresh now")'),
|
||||
"Action buttons must include shrink-0 to prevent compression"
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user