FN-7703: fix search icon overlapping text in file browser search input
Fixes the search icon overlapping placeholder/typed text in the Files — Project search input under the compact spacing theme. - Anchor .file-browser-search-input padding-left to the icon's own --space-sm offset + 16px icon width + a real gap, instead of the unrelated calc(--space-lg + --space-md) formula that collided exactly with the icon's occupied width under compact spacing - Add FNXC:FileBrowser comment documenting the collision math and why the padding is now theme-invariant - Add a regression test asserting padding-left exceeds icon offset + width against the compact spacing scale - Add a patch changeset for @runfusion/fusion Files changed: .changeset/fn-7703-search-icon-overlap.md | 7 +++ packages/dashboard/app/components/FileBrowser.css | 11 ++++- .../app/components/__tests__/FileBrowser.test.tsx | 52 ++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) Fusion-Task-Id: FN-7703 Fusion-Task-Lineage: d7de7f82-f0e7-4086-a8ef-2fed2b4704ec Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
7
.changeset/fn-7703-search-icon-overlap.md
Normal file
7
.changeset/fn-7703-search-icon-overlap.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
summary: Fix the search icon overlapping typed/placeholder text in the Files — Project search input.
|
||||
category: fix
|
||||
dev: `.file-browser-search-input` `padding-left` was `calc(var(--space-lg) + var(--space-md))`, which collided exactly with the leading `.file-browser-search-icon`'s occupied width (`var(--space-sm)` offset + 16px icon) under the compact spacing theme. Padding is now anchored to the same `--space-sm` offset the icon uses, plus the icon's box width, plus a real gap, so clearance holds across all spacing scales for both the FileBrowser view and modal.
|
||||
@@ -209,10 +209,19 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/*
|
||||
FNXC:FileBrowser 2026-07-08-00:00:
|
||||
Search input left padding must exceed the leading icon's offset + width so the
|
||||
magnifier never overlaps placeholder/typed text. The prior calc(--space-lg + --space-md)
|
||||
collided exactly with the icon's right edge (--space-sm offset + 16px icon) under the
|
||||
compact spacing theme (space-sm:4px, space-md:8px, space-lg:12px -> 12+8=20 == 4+16),
|
||||
leaving zero gap. Anchor the padding to the same --space-sm offset the icon uses, plus
|
||||
the icon's box width, plus a visible gap, so the relationship stays theme-invariant.
|
||||
*/
|
||||
.file-browser-search-input {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
padding-left: calc(var(--space-lg) + var(--space-md));
|
||||
padding-left: calc(var(--space-sm) + 16px + var(--space-sm));
|
||||
}
|
||||
|
||||
.file-browser-create-button {
|
||||
|
||||
@@ -611,6 +611,58 @@ describe("FileBrowser", () => {
|
||||
expect(css).toMatch(/\.file-browser-context-menu__item\s*\{[^}]*min-height:\s*36px;/);
|
||||
});
|
||||
|
||||
// FN-7703: the leading magnifier icon in the "Search project files" input
|
||||
// was overlapping the placeholder/typed text because the input's
|
||||
// padding-left did not reserve enough clearance for the absolutely
|
||||
// positioned icon. Under the compact spacing theme (--space-sm: 4px),
|
||||
// the old formula calc(var(--space-lg) + var(--space-md)) == 12px + 8px
|
||||
// == 20px collided exactly with the icon's occupied width
|
||||
// (--space-sm offset 4px + 16px icon == 20px), leaving zero gap. This
|
||||
// test encodes the invariant directly against the declared CSS formulas
|
||||
// (rather than jsdom computed styles, which do not resolve calc()/var())
|
||||
// so it fails against the pre-fix rule and passes once padding-left is
|
||||
// anchored to the icon's own offset + width + a real gap.
|
||||
it("reserves search input padding-left beyond the leading icon's offset + width under the compact spacing theme", () => {
|
||||
const css = loadAllAppCss();
|
||||
|
||||
const iconRuleMatch = css.match(/\.file-browser-search-icon\s*\{([^}]*)\}/);
|
||||
const inputRuleMatch = css.match(/\.file-browser-search-input\s*\{([^}]*)\}/);
|
||||
expect(iconRuleMatch).toBeTruthy();
|
||||
expect(inputRuleMatch).toBeTruthy();
|
||||
|
||||
const iconLeftMatch = iconRuleMatch![1].match(/left:\s*([^;]+);/);
|
||||
const paddingLeftMatch = inputRuleMatch![1].match(/padding-left:\s*([^;]+);/);
|
||||
expect(iconLeftMatch).toBeTruthy();
|
||||
expect(paddingLeftMatch).toBeTruthy();
|
||||
|
||||
// Compact spacing scale from public/theme-data.css (the failing case).
|
||||
const compactSpaceTokens: Record<string, number> = {
|
||||
"--space-sm": 4,
|
||||
"--space-md": 8,
|
||||
"--space-lg": 12,
|
||||
};
|
||||
|
||||
function resolvePx(expr: string): number {
|
||||
let normalized = expr.trim();
|
||||
if (normalized.startsWith("calc(") && normalized.endsWith(")")) {
|
||||
normalized = normalized.slice(5, -1);
|
||||
}
|
||||
for (const [token, value] of Object.entries(compactSpaceTokens)) {
|
||||
normalized = normalized.split(`var(${token})`).join(String(value));
|
||||
}
|
||||
normalized = normalized.replace(/px/g, "");
|
||||
expect(normalized).toMatch(/^[0-9+\-*/.\s]+$/);
|
||||
return Function(`"use strict"; return (${normalized});`)();
|
||||
}
|
||||
|
||||
const iconLeftPx = resolvePx(iconLeftMatch![1]);
|
||||
const paddingLeftPx = resolvePx(paddingLeftMatch![1]);
|
||||
const iconWidthPx = 16; // Search size={16} in FileBrowser.tsx
|
||||
|
||||
// The regression: text must clear the icon's full occupied width, not just its offset.
|
||||
expect(paddingLeftPx).toBeGreaterThan(iconLeftPx + iconWidthPx);
|
||||
});
|
||||
|
||||
// ── Download Actions ────────────────────────────────────────────────
|
||||
|
||||
it("opens download URL for file when Download is clicked", () => {
|
||||
|
||||
Reference in New Issue
Block a user