feat(FN-3587): make agent error modal mobile-safe

- Update AgentErrorDetailsModal styles to improve mobile layout and avoid viewport overflow
- Add mobile regression tests for agent modal behavior in agent-modals-mobile coverage
- Extend core modal mobile test suite with AgentErrorDetailsModal safeguards

Fusion-Task-Id: FN-3587
This commit is contained in:
Fusion
2026-05-06 08:51:21 -07:00
committed by gsxdsm
parent d16af28bbd
commit d9a3241f19
3 changed files with 53 additions and 9 deletions

View File

@@ -23,10 +23,14 @@
.agent-error-modal {
max-width: min(calc(var(--space-2xl) * 20), 100%);
min-height: 0;
}
.agent-error-modal__content {
padding: 0 var(--space-lg) var(--space-md);
flex: 1 1 auto;
min-height: 0;
overflow: hidden;
}
.agent-error-modal__error {
@@ -45,20 +49,17 @@
}
@media (max-width: 768px) {
.modal-overlay:has(.agent-error-modal) {
padding-top: var(--space-md);
align-items: stretch;
}
.agent-error-modal {
width: calc(100% - var(--space-lg));
max-height: calc(100vh - var(--space-lg) * 2);
width: 100%;
max-width: 100%;
height: 100vh;
height: 100dvh;
max-height: 100vh;
max-height: 100dvh;
flex: 1 1 auto;
}
.agent-error-modal__content {
flex: 1 1 auto;
min-height: 0;
display: flex;
}
@@ -67,5 +68,6 @@
max-height: none;
min-height: 0;
width: 100%;
-webkit-overflow-scrolling: touch;
}
}

View File

@@ -393,6 +393,30 @@ describe("agent modal mobile CSS structure", () => {
});
});
describe("AgentErrorDetailsModal", () => {
it("mobile rules constrain modal to viewport height", () => {
const styles = readStyles();
const modalRuleMatch = styles.match(/@media \(max-width: 768px\)[\s\S]*?\.agent-error-modal\s*\{[^}]+\}/);
expect(modalRuleMatch).toBeTruthy();
const modalRule = modalRuleMatch![0];
expect(modalRule).toContain("height: 100dvh");
expect(modalRule).toContain("max-height: 100dvh");
expect(modalRule).toContain("width: 100%");
expect(modalRule).toContain("max-width: 100%");
});
it("keeps the error log as the scrollable surface on mobile", () => {
const styles = readStyles();
const contentRuleMatch = styles.match(/\.agent-error-modal__content\s*\{[^}]+\}/);
expect(contentRuleMatch).toBeTruthy();
expect(contentRuleMatch![0]).toContain("overflow: hidden");
expect(styles).toMatch(/@media \(max-width: 768px\)[\s\S]*?\.agent-error-modal__error\s*\{[^}]*max-height:\s*none;[^}]*\}/);
expect(styles).toMatch(/@media \(max-width: 768px\)[\s\S]*?\.agent-error-modal__error\s*\{[^}]*-webkit-overflow-scrolling:\s*touch;[^}]*\}/);
});
});
describe("Cross-cutting mobile CSS", () => {
it("agent-dialog mobile rules include safe-area inset handling", () => {
const styles = readStyles();

View File

@@ -267,6 +267,24 @@ describe("core modals mobile css coverage", () => {
expect(fullscreenBlockMatch![0]).toContain("max-height: unset");
});
it("AgentErrorDetailsModal: mobile uses viewport-sized modal with inner scrolling log region", () => {
const css = loadAllAppCss();
const mobileBlock = getMainMobileBlock(css);
const modalRuleMatch = mobileBlock.match(/\.agent-error-modal\s*\{[^}]+\}/s);
expect(modalRuleMatch).not.toBeNull();
expect(modalRuleMatch![0]).toContain("height: 100dvh");
expect(modalRuleMatch![0]).toContain("max-height: 100dvh");
const contentRuleMatch = css.match(/\.agent-error-modal__content\s*\{[^}]+\}/s);
expect(contentRuleMatch).not.toBeNull();
expect(contentRuleMatch![0]).toContain("overflow: hidden");
const errorRuleMatch = mobileBlock.match(/\.agent-error-modal__error\s*\{[^}]+\}/s);
expect(errorRuleMatch).not.toBeNull();
expect(errorRuleMatch![0]).toContain("-webkit-overflow-scrolling: touch");
});
it("NewTaskModal: quick fields buttons meet 36px touch target on mobile", () => {
const css = loadAllAppCss();
const mobileBlock = getMainMobileBlock(css);