From 551a2a3c1eea0466152d6e6cf5abe8cc95a41190 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Wed, 15 Jul 2026 23:22:33 -0700 Subject: [PATCH] fix(dashboard): align import detail header and show translated titles in its title bar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GitHub/GitLab import detail panel had no inset of its own, so it sat flush against the window's left edge while FN-8015's resize gutter left a gap on the right only — "Preview" was clipped and the whole header read as misaligned on both the desktop window and the mobile sheet. Give the panel a symmetric inset, letting that existing gutter supply the right side rather than overriding it (which would push the inner scrollbar back into the resize hot zone the gutter protects). Also in the header: `space-between` spread three children apart and flung "Close issue" into the middle, so the label now takes the free space and the two actions stay grouped as a pair. Both actions size from one rule instead of each inheriting its own .btn defaults, at a 40px touch target on mobile where Import is the sheet's primary action. "Preview" becomes a muted eyebrow matching the existing ISSUE #NNNN label. Fix title truncation while here: `.floating-window__title` declared text-overflow: ellipsis but was display:flex, which made the text an anonymous flex item that text-overflow cannot act on, so titles hard-cut mid-word. Every caller passes a plain string, so a block box makes the existing declaration work as written. Finally, the detail title bar kept the raw upstream title while the card below showed the translation — one item displaying two different titles at once. Both now read importTranslation.display.title, gated on activeTab to match translateSelection so an item's number is never paired with the other tab's title. The existing translation test now asserts both surfaces in both directions; it fails without this change. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../github-import-detail-header-polish.md | 7 ++ .../app/components/FloatingWindow.css | 10 ++- .../app/components/GitHubImportModal.css | 67 +++++++++++++------ .../app/components/GitHubImportModal.tsx | 16 ++++- .../__tests__/GitHubImportModal.test.tsx | 10 +++ 5 files changed, 84 insertions(+), 26 deletions(-) create mode 100644 .changeset/github-import-detail-header-polish.md diff --git a/.changeset/github-import-detail-header-polish.md b/.changeset/github-import-detail-header-polish.md new file mode 100644 index 0000000000..2cee13b0d0 --- /dev/null +++ b/.changeset/github-import-detail-header-polish.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": patch +--- + +summary: Fix cramped GitHub/GitLab import detail header and show translated titles in its title bar. +category: fix +dev: Detail panel now owns a symmetric inset (right side still supplied by the FN-8015 `.floating-window__body` resize gutter — do not override that margin). Header uses a label + right-aligned action cluster instead of `space-between`, and both actions size from one rule (30px desktop / 40px mobile touch target). `.floating-window__title` switched from `display:flex` to `block` so its already-declared `text-overflow: ellipsis` actually applies — every caller passes a string title. Detail window titles read `importTranslation.display.title`, gated on `activeTab` to match `translateSelection`. diff --git a/packages/dashboard/app/components/FloatingWindow.css b/packages/dashboard/app/components/FloatingWindow.css index a956cbd28e..87cb2939de 100644 --- a/packages/dashboard/app/components/FloatingWindow.css +++ b/packages/dashboard/app/components/FloatingWindow.css @@ -178,11 +178,15 @@ On mobile/narrow app viewports, opening Quick Chat should present the full Chat } } +/* +FNXC:FloatingWindow 2026-07-15-18:20: +Long titles (e.g. the GitHub import detail's "#2159 — ") must truncate with an ellipsis rather than hard-cut mid-word against the close button. +display MUST stay block, not flex: every caller passes a plain string, so under flex the text became an anonymous flex item, which text-overflow cannot act on — the ellipsis declared here silently never rendered. A block box makes the existing overflow/text-overflow/white-space trio work as written. +Reintroducing flex here (e.g. to lay out an element title) re-breaks truncation for all callers; give the title an inner element instead. +*/ .floating-window__title { - display: flex; + display: block; flex: 1; - align-items: center; - gap: var(--space-sm); min-width: 0; overflow: hidden; font-weight: 600; diff --git a/packages/dashboard/app/components/GitHubImportModal.css b/packages/dashboard/app/components/GitHubImportModal.css index ca1a5cc309..6f88c28ef8 100644 --- a/packages/dashboard/app/components/GitHubImportModal.css +++ b/packages/dashboard/app/components/GitHubImportModal.css @@ -146,54 +146,69 @@ overflow: hidden; } +/* +FNXC:GitHubImport 2026-07-15-18:20: +The detail panel is the FloatingWindow's only child and owns its own inset — without one the Preview header rendered flush against the window's left edge while FN-8015's resize gutter left a lone gap on the right, so the header read as mis-aligned on both the desktop window and the mobile sheet. +padding-inline-end is deliberately 0: FN-8015 already reserves var(--space-lg) of inline-end margin on the shared .floating-window__body to hold a hosted scrollbar clear of the east/north-east/south-east resize hot zones, and that gutter supplies this panel's right inset. Matching padding-inline-start to the same token makes the inset symmetric without overriding the shared body (which would push the inner scroller back into the hot zone). +If that body gutter ever changes token, change padding-inline-start with it. +Padding lives on the panel rather than the pane content so header, toast, and scrolling body share one inset and the header divider is inset with them. +*/ .github-import-detail-panel { display: flex; flex: 1; flex-direction: column; min-width: 0; min-height: 0; + padding: var(--space-lg); + padding-inline-end: 0; overflow: hidden; } +/* +FNXC:GitHubImport 2026-07-15-18:20: +Header is one label + a right-aligned action cluster. The label takes the free space (margin-inline-end:auto) rather than the container using space-between, so Close issue and Import stay grouped as a pair at the end instead of Close issue being flung into the middle whenever both actions render. +*/ .github-import-pane-header { display: flex; align-items: center; - justify-content: space-between; gap: var(--space-sm); padding-bottom: var(--space-sm); - margin-bottom: var(--space-sm); + margin-bottom: var(--space-md); border-bottom: 1px solid var(--border); } +/* +FNXC:GitHubImport 2026-07-15-18:20: +"Preview" / "Issues" is a section label, not a peer of the issue title inside the card. The muted uppercase eyebrow matches .preview-meta so the two read as one type system, and it stops the label competing with the primary Import action for emphasis. +*/ .github-import-pane-header h4 { - font-size: 13px; + margin-inline-end: auto; + min-width: 0; + overflow: hidden; + color: var(--text-muted); + font-size: 12px; font-weight: 600; - letter-spacing: 0.01em; - color: var(--text); + letter-spacing: 0.06em; + text-transform: uppercase; + text-overflow: ellipsis; + white-space: nowrap; } /* -FNXC:GitHubImport 2026-06-23-02:00: -Top import action sits at the end of the non-scrolling preview-pane header (space-between pushes it opposite the Preview title / Back button). -margin-left:auto keeps it pinned right even when the mobile Back button is absent. The button height stays compact so the header does not grow taller than the prior single-line heading. +FNXC:GitHubImport 2026-07-15-18:20: +Both header actions size from one rule so the secondary Close issue and the primary Import share a baseline and an identical height — previously each inherited only .btn/.btn-primary defaults and rendered visibly mismatched. min-height keeps the pair a comfortable target without growing the header past the single-line label. */ -.github-import-action-top { - margin-left: auto; - flex-shrink: 0; - display: inline-flex; - align-items: center; - gap: var(--space-xs); -} - -/* -FNXC:GitHubImport 2026-06-23-03:15: -Close-issue action sits just left of the top Import action in the preview header. It is the lighter (non-primary) button; flex-shrink:0 keeps it on one line next to Import even on a narrow preview pane. -*/ -.github-import-issue-close-top { +.github-import-pane-header .btn { flex-shrink: 0; display: inline-flex; align-items: center; + justify-content: center; gap: var(--space-xs); + min-height: 30px; + padding: 0 var(--space-md); + font-size: 12px; + line-height: 1; + white-space: nowrap; } /* @@ -1396,4 +1411,14 @@ Import Tasks embedded header now adopts the canonical ViewHeader chrome — edge .github-import-gitlab__workspace { grid-template-columns: 1fr; } + + /* + FNXC:GitHubImport 2026-07-15-18:20: + This is the breakpoint where the detail FloatingWindow becomes a full-screen sheet. The panel's var(--space-lg) inset already reads as a conventional mobile gutter, so only the actions change: they grow to a 40px touch target because the desktop 30px pair is a mouse-sized hit area and Import is the sheet's primary action. + */ + .github-import-pane-header .btn { + min-height: 40px; + padding: 0 var(--space-md); + font-size: 13px; + } } diff --git a/packages/dashboard/app/components/GitHubImportModal.tsx b/packages/dashboard/app/components/GitHubImportModal.tsx index 296668462d..977c90f07c 100644 --- a/packages/dashboard/app/components/GitHubImportModal.tsx +++ b/packages/dashboard/app/components/GitHubImportModal.tsx @@ -1544,7 +1544,18 @@ export function GitHubImportModal({ isOpen, onClose, onImport, tasks, projectId, {(selectedIssue || selectedPull) && ( { setSelectedIssueNumber(null); setSelectedPullNumber(null); }} defaultSize={{ width: 760, height: 680 }} minSize={{ width: 420, height: 360 }} @@ -1826,7 +1837,8 @@ export function GitHubImportModal({ isOpen, onClose, onImport, tasks, projectId, {selectedGitlabItem && ( setSelectedGitlabKey(null)} defaultSize={{ width: 760, height: 680 }} minSize={{ width: 420, height: 360 }} diff --git a/packages/dashboard/app/components/__tests__/GitHubImportModal.test.tsx b/packages/dashboard/app/components/__tests__/GitHubImportModal.test.tsx index 2c9bd2bc18..84ed1c961d 100644 --- a/packages/dashboard/app/components/__tests__/GitHubImportModal.test.tsx +++ b/packages/dashboard/app/components/__tests__/GitHubImportModal.test.tsx @@ -429,6 +429,9 @@ describe("GitHubImportModal", () => { /* FNXC:GitHubImportTranslate 2026-07-14-12:00: When selected issue prose is not the dashboard language, the preview must offer Translate / Dismiss and swap title+body after a successful AI translation without changing import provenance. + + FNXC:GitHubImportTranslate 2026-07-15-18:40: + The swap must cover EVERY surface showing the title, not just the preview card: the detail window's title bar reads from the same translated source, so one item can never display the translated title in the card and the raw upstream title in the bar at the same time. Both surfaces are asserted in both directions (translated, then toggled back). */ it("offers translation when selected issue content is not the dashboard language", async () => { const frenchBody = @@ -468,10 +471,17 @@ describe("GitHubImportModal", () => { expect(screen.getByText("Import preview problem")).toBeTruthy(); }); + // The detail window's title bar swaps with the card, keeping the issue number paired with the title it belongs to. + const titleBar = screen.getByTestId("floating-window-drag-handle-github-import-detail"); + expect(titleBar.textContent).toContain("#7 — Import preview problem"); + expect(titleBar.textContent).not.toContain("Problème d'aperçu d'importation"); + expect(screen.getByTestId("github-import-translate-toggle")).toBeTruthy(); fireEvent.click(screen.getByTestId("github-import-translate-toggle")); const previewCard = screen.getByTestId("github-import-preview-card"); expect(within(previewCard).getByText(/Problème d'aperçu d'importation/)).toBeTruthy(); + // Toggling back to the original must revert the bar too, not strand it on the translation. + expect(titleBar.textContent).toContain("#7 — Problème d'aperçu d'importation"); }); it("does not show translate controls for English content when dashboard language is English", async () => {