mirror of
https://github.com/leonvanzyl/autocoder.git
synced 2026-02-01 23:13:36 +00:00
fix: hide AssistantFAB during spec creation mode
The Chat AI Assistant button (AssistantFAB) was appearing on top of the full-screen spec creation chat overlay, causing a visual bug where the button would overlap with the Send input area. Changes: - Add onStepChange callback prop to NewProjectModal to notify parent when the modal step changes - Add onSpecCreatingChange callback prop to ProjectSelector to propagate spec creation state up to App.tsx - Add isSpecCreating state to App.tsx to track when spec creation chat is active - Update AssistantFAB render condition to include !isSpecCreating - Disable 'A' keyboard shortcut during spec creation mode The fix propagates the spec creation state through the component hierarchy: NewProjectModal -> ProjectSelector -> App.tsx, allowing the FAB to be hidden when step === 'chat' in the new project modal. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,7 @@ function App() {
|
|||||||
const [debugPanelHeight, setDebugPanelHeight] = useState(288) // Default height
|
const [debugPanelHeight, setDebugPanelHeight] = useState(288) // Default height
|
||||||
const [assistantOpen, setAssistantOpen] = useState(false)
|
const [assistantOpen, setAssistantOpen] = useState(false)
|
||||||
const [showSettings, setShowSettings] = useState(false)
|
const [showSettings, setShowSettings] = useState(false)
|
||||||
|
const [isSpecCreating, setIsSpecCreating] = useState(false)
|
||||||
|
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const { data: projects, isLoading: projectsLoading } = useProjects()
|
const { data: projects, isLoading: projectsLoading } = useProjects()
|
||||||
@@ -100,8 +101,8 @@ function App() {
|
|||||||
setShowExpandProject(true)
|
setShowExpandProject(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A : Toggle assistant panel (when project selected)
|
// A : Toggle assistant panel (when project selected and not in spec creation)
|
||||||
if ((e.key === 'a' || e.key === 'A') && selectedProject) {
|
if ((e.key === 'a' || e.key === 'A') && selectedProject && !isSpecCreating) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
setAssistantOpen(prev => !prev)
|
setAssistantOpen(prev => !prev)
|
||||||
}
|
}
|
||||||
@@ -132,7 +133,7 @@ function App() {
|
|||||||
|
|
||||||
window.addEventListener('keydown', handleKeyDown)
|
window.addEventListener('keydown', handleKeyDown)
|
||||||
return () => window.removeEventListener('keydown', handleKeyDown)
|
return () => window.removeEventListener('keydown', handleKeyDown)
|
||||||
}, [selectedProject, showAddFeature, showExpandProject, selectedFeature, debugOpen, assistantOpen, features, showSettings])
|
}, [selectedProject, showAddFeature, showExpandProject, selectedFeature, debugOpen, assistantOpen, features, showSettings, isSpecCreating])
|
||||||
|
|
||||||
// Combine WebSocket progress with feature data
|
// Combine WebSocket progress with feature data
|
||||||
const progress = wsState.progress.total > 0 ? wsState.progress : {
|
const progress = wsState.progress.total > 0 ? wsState.progress : {
|
||||||
@@ -167,6 +168,7 @@ function App() {
|
|||||||
selectedProject={selectedProject}
|
selectedProject={selectedProject}
|
||||||
onSelectProject={handleSelectProject}
|
onSelectProject={handleSelectProject}
|
||||||
isLoading={projectsLoading}
|
isLoading={projectsLoading}
|
||||||
|
onSpecCreatingChange={setIsSpecCreating}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{selectedProject && (
|
{selectedProject && (
|
||||||
@@ -290,8 +292,8 @@ function App() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Assistant FAB and Panel - hide FAB when expand modal is open */}
|
{/* Assistant FAB and Panel - hide when expand modal or spec creation is open */}
|
||||||
{selectedProject && !showExpandProject && (
|
{selectedProject && !showExpandProject && !isSpecCreating && (
|
||||||
<>
|
<>
|
||||||
<AssistantFAB
|
<AssistantFAB
|
||||||
onClick={() => setAssistantOpen(!assistantOpen)}
|
onClick={() => setAssistantOpen(!assistantOpen)}
|
||||||
|
|||||||
@@ -25,12 +25,14 @@ interface NewProjectModalProps {
|
|||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
onProjectCreated: (projectName: string) => void
|
onProjectCreated: (projectName: string) => void
|
||||||
|
onStepChange?: (step: Step) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NewProjectModal({
|
export function NewProjectModal({
|
||||||
isOpen,
|
isOpen,
|
||||||
onClose,
|
onClose,
|
||||||
onProjectCreated,
|
onProjectCreated,
|
||||||
|
onStepChange,
|
||||||
}: NewProjectModalProps) {
|
}: NewProjectModalProps) {
|
||||||
const [step, setStep] = useState<Step>('name')
|
const [step, setStep] = useState<Step>('name')
|
||||||
const [projectName, setProjectName] = useState('')
|
const [projectName, setProjectName] = useState('')
|
||||||
@@ -46,6 +48,12 @@ export function NewProjectModal({
|
|||||||
|
|
||||||
const createProject = useCreateProject()
|
const createProject = useCreateProject()
|
||||||
|
|
||||||
|
// Wrapper to notify parent of step changes
|
||||||
|
const changeStep = (newStep: Step) => {
|
||||||
|
setStep(newStep)
|
||||||
|
onStepChange?.(newStep)
|
||||||
|
}
|
||||||
|
|
||||||
if (!isOpen) return null
|
if (!isOpen) return null
|
||||||
|
|
||||||
const handleNameSubmit = (e: React.FormEvent) => {
|
const handleNameSubmit = (e: React.FormEvent) => {
|
||||||
@@ -63,18 +71,18 @@ export function NewProjectModal({
|
|||||||
}
|
}
|
||||||
|
|
||||||
setError(null)
|
setError(null)
|
||||||
setStep('folder')
|
changeStep('folder')
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleFolderSelect = (path: string) => {
|
const handleFolderSelect = (path: string) => {
|
||||||
// Append project name to the selected path
|
// Append project name to the selected path
|
||||||
const fullPath = path.endsWith('/') ? `${path}${projectName.trim()}` : `${path}/${projectName.trim()}`
|
const fullPath = path.endsWith('/') ? `${path}${projectName.trim()}` : `${path}/${projectName.trim()}`
|
||||||
setProjectPath(fullPath)
|
setProjectPath(fullPath)
|
||||||
setStep('method')
|
changeStep('method')
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleFolderCancel = () => {
|
const handleFolderCancel = () => {
|
||||||
setStep('name')
|
changeStep('name')
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleMethodSelect = async (method: SpecMethod) => {
|
const handleMethodSelect = async (method: SpecMethod) => {
|
||||||
@@ -82,7 +90,7 @@ export function NewProjectModal({
|
|||||||
|
|
||||||
if (!projectPath) {
|
if (!projectPath) {
|
||||||
setError('Please select a project folder first')
|
setError('Please select a project folder first')
|
||||||
setStep('folder')
|
changeStep('folder')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +102,7 @@ export function NewProjectModal({
|
|||||||
path: projectPath,
|
path: projectPath,
|
||||||
specMethod: 'manual',
|
specMethod: 'manual',
|
||||||
})
|
})
|
||||||
setStep('complete')
|
changeStep('complete')
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
onProjectCreated(project.name)
|
onProjectCreated(project.name)
|
||||||
handleClose()
|
handleClose()
|
||||||
@@ -110,7 +118,7 @@ export function NewProjectModal({
|
|||||||
path: projectPath,
|
path: projectPath,
|
||||||
specMethod: 'claude',
|
specMethod: 'claude',
|
||||||
})
|
})
|
||||||
setStep('chat')
|
changeStep('chat')
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
setError(err instanceof Error ? err.message : 'Failed to create project')
|
setError(err instanceof Error ? err.message : 'Failed to create project')
|
||||||
}
|
}
|
||||||
@@ -125,7 +133,7 @@ export function NewProjectModal({
|
|||||||
try {
|
try {
|
||||||
await startAgent(projectName.trim(), yoloMode)
|
await startAgent(projectName.trim(), yoloMode)
|
||||||
// Success - navigate to project
|
// Success - navigate to project
|
||||||
setStep('complete')
|
changeStep('complete')
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
onProjectCreated(projectName.trim())
|
onProjectCreated(projectName.trim())
|
||||||
handleClose()
|
handleClose()
|
||||||
@@ -144,7 +152,7 @@ export function NewProjectModal({
|
|||||||
|
|
||||||
const handleChatCancel = () => {
|
const handleChatCancel = () => {
|
||||||
// Go back to method selection but keep the project
|
// Go back to method selection but keep the project
|
||||||
setStep('method')
|
changeStep('method')
|
||||||
setSpecMethod(null)
|
setSpecMethod(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +163,7 @@ export function NewProjectModal({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
setStep('name')
|
changeStep('name')
|
||||||
setProjectName('')
|
setProjectName('')
|
||||||
setProjectPath(null)
|
setProjectPath(null)
|
||||||
setSpecMethod(null)
|
setSpecMethod(null)
|
||||||
@@ -168,10 +176,10 @@ export function NewProjectModal({
|
|||||||
|
|
||||||
const handleBack = () => {
|
const handleBack = () => {
|
||||||
if (step === 'method') {
|
if (step === 'method') {
|
||||||
setStep('folder')
|
changeStep('folder')
|
||||||
setSpecMethod(null)
|
setSpecMethod(null)
|
||||||
} else if (step === 'folder') {
|
} else if (step === 'folder') {
|
||||||
setStep('name')
|
changeStep('name')
|
||||||
setProjectPath(null)
|
setProjectPath(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ interface ProjectSelectorProps {
|
|||||||
selectedProject: string | null
|
selectedProject: string | null
|
||||||
onSelectProject: (name: string | null) => void
|
onSelectProject: (name: string | null) => void
|
||||||
isLoading: boolean
|
isLoading: boolean
|
||||||
|
onSpecCreatingChange?: (isCreating: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ProjectSelector({
|
export function ProjectSelector({
|
||||||
@@ -17,6 +18,7 @@ export function ProjectSelector({
|
|||||||
selectedProject,
|
selectedProject,
|
||||||
onSelectProject,
|
onSelectProject,
|
||||||
isLoading,
|
isLoading,
|
||||||
|
onSpecCreatingChange,
|
||||||
}: ProjectSelectorProps) {
|
}: ProjectSelectorProps) {
|
||||||
const [isOpen, setIsOpen] = useState(false)
|
const [isOpen, setIsOpen] = useState(false)
|
||||||
const [showNewProjectModal, setShowNewProjectModal] = useState(false)
|
const [showNewProjectModal, setShowNewProjectModal] = useState(false)
|
||||||
@@ -166,6 +168,7 @@ export function ProjectSelector({
|
|||||||
isOpen={showNewProjectModal}
|
isOpen={showNewProjectModal}
|
||||||
onClose={() => setShowNewProjectModal(false)}
|
onClose={() => setShowNewProjectModal(false)}
|
||||||
onProjectCreated={handleProjectCreated}
|
onProjectCreated={handleProjectCreated}
|
||||||
|
onStepChange={(step) => onSpecCreatingChange?.(step === 'chat')}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Delete Confirmation Dialog */}
|
{/* Delete Confirmation Dialog */}
|
||||||
|
|||||||
Reference in New Issue
Block a user