feat(FN-3343): add Escape key keyboard handling to modals
This merge delivers v0.17.2 and ships FN-3343 keyboard handling across four dashboard modals (NewTaskModal, SubtaskBreakdownModal, MilestoneSliceInterviewModal, SettingsModal) with mobile CSS overrides, plus keyboard style regression tests for each modal and a minor test alignment for the onboarding Fusion-Task-Id: FN-3343
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState, useCallback, useEffect, useMemo, useRef } from "react";
|
||||
import { useState, useCallback, useEffect, useMemo, useRef, type CSSProperties } from "react";
|
||||
import type { PlanningQuestion } from "@fusion/core";
|
||||
import { getErrorMessage } from "@fusion/core";
|
||||
import {
|
||||
@@ -29,7 +29,9 @@ import {
|
||||
import { ConversationHistory } from "./ConversationHistory";
|
||||
import { useSessionLock } from "../hooks/useSessionLock";
|
||||
import { useAiSessionSync } from "../hooks/useAiSessionSync";
|
||||
import { useMobileKeyboard } from "../hooks/useMobileKeyboard";
|
||||
import { useMobileScrollLock } from "../hooks/useMobileScrollLock";
|
||||
import { useViewportMode } from "../hooks/useViewportMode";
|
||||
import { getSessionTabId } from "../utils/getSessionTabId";
|
||||
|
||||
interface MilestoneSliceInterviewModalProps {
|
||||
@@ -74,7 +76,18 @@ export function MilestoneSliceInterviewModal({
|
||||
projectId,
|
||||
resumeSessionId,
|
||||
}: MilestoneSliceInterviewModalProps) {
|
||||
const viewportMode = useViewportMode();
|
||||
useMobileScrollLock(isOpen);
|
||||
const { keyboardOverlap, viewportHeight, viewportOffsetTop, keyboardOpen } = useMobileKeyboard({
|
||||
enabled: viewportMode === "mobile",
|
||||
});
|
||||
const keyboardStyle: CSSProperties = keyboardOpen
|
||||
? ({
|
||||
"--keyboard-overlap": `${keyboardOverlap}px`,
|
||||
"--vv-offset-top": `${viewportOffsetTop}px`,
|
||||
...(viewportHeight !== null ? { "--vv-height": `${viewportHeight}px` } : {}),
|
||||
} as CSSProperties)
|
||||
: {};
|
||||
const [view, setView] = useState<ViewState>({ type: "initial" });
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [responseHistory, setResponseHistory] = useState<QuestionResponse[]>([]);
|
||||
@@ -451,7 +464,7 @@ export function MilestoneSliceInterviewModal({
|
||||
aria-modal="true"
|
||||
data-testid="milestone-slice-interview-modal"
|
||||
>
|
||||
<div className="modal modal-lg planning-modal">
|
||||
<div className="modal modal-lg planning-modal" style={keyboardStyle}>
|
||||
<div className="modal-header">
|
||||
<div className="detail-title-row">
|
||||
<Sparkles size={20} className="icon-triage" />
|
||||
|
||||
Reference in New Issue
Block a user