[object Object]

← back to Exo

fix(app): tighten Share Bug Report prompt layout (#2008)

fb12b403ea77ad219a7d81b78d1246171454378a · 2026-04-30 15:10:26 +0100 · Alex Cheema

## Summary

Follow-ups to #2003 based on feedback that the Share Bug Report window
felt visually weighty: too much padding above and below, and a
description editor that invited an essay rather than a one-liner.

## Changes (one file)

`app/EXO/EXO/Views/BugReportWindowController.swift`:

- **Auto-size the window to its content.** Switched from `NSHostingView`
+ fixed `contentRect: 480x380` + SwiftUI `frame(minHeight: 320)` to
`NSHostingController` with `sizingOptions = [.preferredContentSize,
.minSize]`. The fixed-min combo was centering the form in dead vertical
space.
- **Smaller, lower-pressure editor.** Field is now labeled `Description
(optional)` with a placeholder hint (`What were you doing when it
broke?`) inside the editor. Editor height fixed at 72pt (was 120pt min).
Replaced the long lead-in paragraph and headline with a single one-line
caption between field and buttons: `Diagnostic logs will be uploaded
with your report.`
- **Tighter spacing.** Outer padding 20 -> 16, root spacing 16 -> 12,
prompting-section spacing 12 -> 8.
- **Remove em dash from copy.**

`BugReportService` and the menu wiring are unchanged.

## Test plan

- [ ] Click `Share Bug Report...` from the menu bar.
- [ ] The window opens centered and sized to its content (no big empty
bands top/bottom).
- [ ] Description editor is visibly compact, with the placeholder hint
showing when empty.
- [ ] The optional-ness is conveyed by the field label (no separate help
paragraph).
- [ ] Caption `Diagnostic logs will be uploaded with your report.`
appears in `.caption` style under the editor, above the buttons.
- [ ] Resize the window: persists across re-opens (frame autosave still
works).
- [ ] Send/Cancel/Try Again/Done flows behave the same as before.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit fb12b403ea77ad219a7d81b78d1246171454378a
Author: Alex Cheema <41707476+AlexCheema@users.noreply.github.com>
Date:   Thu Apr 30 15:10:26 2026 +0100

    fix(app): tighten Share Bug Report prompt layout (#2008)
    
    ## Summary
    
    Follow-ups to #2003 based on feedback that the Share Bug Report window
    felt visually weighty: too much padding above and below, and a
    description editor that invited an essay rather than a one-liner.
    
    ## Changes (one file)
    
    `app/EXO/EXO/Views/BugReportWindowController.swift`:
    
    - **Auto-size the window to its content.** Switched from `NSHostingView`
    + fixed `contentRect: 480x380` + SwiftUI `frame(minHeight: 320)` to
    `NSHostingController` with `sizingOptions = [.preferredContentSize,
    .minSize]`. The fixed-min combo was centering the form in dead vertical
    space.
    - **Smaller, lower-pressure editor.** Field is now labeled `Description
    (optional)` with a placeholder hint (`What were you doing when it
    broke?`) inside the editor. Editor height fixed at 72pt (was 120pt min).
    Replaced the long lead-in paragraph and headline with a single one-line
    caption between field and buttons: `Diagnostic logs will be uploaded
    with your report.`
    - **Tighter spacing.** Outer padding 20 -> 16, root spacing 16 -> 12,
    prompting-section spacing 12 -> 8.
    - **Remove em dash from copy.**
    
    `BugReportService` and the menu wiring are unchanged.
    
    ## Test plan
    
    - [ ] Click `Share Bug Report...` from the menu bar.
    - [ ] The window opens centered and sized to its content (no big empty
    bands top/bottom).
    - [ ] Description editor is visibly compact, with the placeholder hint
    showing when empty.
    - [ ] The optional-ness is conveyed by the field label (no separate help
    paragraph).
    - [ ] Caption `Diagnostic logs will be uploaded with your report.`
    appears in `.caption` style under the editor, above the buttons.
    - [ ] Resize the window: persists across re-opens (frame autosave still
    works).
    - [ ] Send/Cancel/Try Again/Done flows behave the same as before.
    
    🤖 Generated with [Claude Code](https://claude.com/claude-code)
    
    ---------
    
    Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 app/EXO/EXO/Views/BugReportWindowController.swift | 72 ++++++++++++-----------
 1 file changed, 37 insertions(+), 35 deletions(-)

diff --git a/app/EXO/EXO/Views/BugReportWindowController.swift b/app/EXO/EXO/Views/BugReportWindowController.swift
index 853976c0..1e1c9604 100644
--- a/app/EXO/EXO/Views/BugReportWindowController.swift
+++ b/app/EXO/EXO/Views/BugReportWindowController.swift
@@ -18,17 +18,12 @@ final class BugReportWindowController: ObservableObject {
             self?.window?.close()
         })
 
-        let hostingView = NSHostingView(rootView: view)
-
-        let newWindow = NSWindow(
-            contentRect: NSRect(x: 0, y: 0, width: 480, height: 380),
-            styleMask: [.titled, .closable, .resizable],
-            backing: .buffered,
-            defer: false
-        )
+        let hostingController = NSHostingController(rootView: view)
+        hostingController.sizingOptions = [.preferredContentSize, .minSize]
+
+        let newWindow = NSWindow(contentViewController: hostingController)
+        newWindow.styleMask = [.titled, .closable, .resizable]
         newWindow.title = "Send a Bug Report"
-        newWindow.contentView = hostingView
-        newWindow.contentMinSize = NSSize(width: 420, height: 320)
         newWindow.center()
         newWindow.setFrameAutosaveName("ExoBugReportWindow")
         newWindow.isReleasedWhenClosed = false
@@ -54,7 +49,7 @@ private struct BugReportView: View {
     @FocusState private var descriptionFocused: Bool
 
     var body: some View {
-        VStack(alignment: .leading, spacing: 16) {
+        VStack(alignment: .leading, spacing: 12) {
             switch phase {
             case .prompting:
                 promptingView
@@ -66,39 +61,45 @@ private struct BugReportView: View {
                 failureView(message: message)
             }
         }
-        .padding(20)
-        .frame(minWidth: 420, minHeight: 320)
+        .padding(16)
+        .frame(minWidth: 380)
         .animation(.easeInOut(duration: 0.2), value: phase)
         .onAppear { descriptionFocused = true }
     }
 
     private var promptingView: some View {
-        VStack(alignment: .leading, spacing: 12) {
-            VStack(alignment: .leading, spacing: 4) {
-                Text("Tell us what went wrong")
-                    .font(.headline)
-                Text(
-                    "A short description of what you were doing and what happened helps us track down the bug. This is optional — diagnostic logs will be sent either way."
-                )
+        VStack(alignment: .leading, spacing: 8) {
+            Text("Description (optional)")
                 .font(.subheadline)
                 .foregroundColor(.secondary)
-                .fixedSize(horizontal: false, vertical: true)
+            ZStack(alignment: .topLeading) {
+                if userDescription.isEmpty {
+                    Text("What were you doing when it broke?")
+                        .font(.body)
+                        .foregroundColor(Color(nsColor: .placeholderTextColor))
+                        .padding(.horizontal, 10)
+                        .padding(.vertical, 8)
+                        .allowsHitTesting(false)
+                }
+                TextEditor(text: $userDescription)
+                    .font(.body)
+                    .scrollContentBackground(.hidden)
+                    .padding(4)
+                    .frame(height: 72)
+                    .focused($descriptionFocused)
             }
+            .background(
+                RoundedRectangle(cornerRadius: 6)
+                    .fill(Color(nsColor: .textBackgroundColor))
+            )
+            .overlay(
+                RoundedRectangle(cornerRadius: 6)
+                    .strokeBorder(Color(nsColor: .separatorColor), lineWidth: 1)
+            )
 
-            TextEditor(text: $userDescription)
-                .font(.body)
-                .scrollContentBackground(.hidden)
-                .padding(6)
-                .frame(minHeight: 120)
-                .background(
-                    RoundedRectangle(cornerRadius: 6)
-                        .fill(Color(nsColor: .textBackgroundColor))
-                )
-                .overlay(
-                    RoundedRectangle(cornerRadius: 6)
-                        .strokeBorder(Color(nsColor: .separatorColor), lineWidth: 1)
-                )
-                .focused($descriptionFocused)
+            Text("Diagnostic logs will be uploaded with your report.")
+                .font(.caption)
+                .foregroundColor(.secondary)
 
             HStack {
                 Spacer()
@@ -109,6 +110,7 @@ private struct BugReportView: View {
                 }
                 .keyboardShortcut(.defaultAction)
             }
+            .padding(.top, 4)
         }
     }
 

← 1606e638 feat(app): open Share Bug Report in a dedicated window (#200  ·  back to Exo  ·  A few targeted tweaks to address HF rate limits (#2009) 8dae3ecb →