fix(skill): use Dialog initialFocus to focus input on modal open

Expose initialFocus prop on Modal component (passthrough to Headless
UI Dialog) so the create blank skill modal reliably focuses the name
input when opened, replacing the ineffective autoFocus attribute.
This commit is contained in:
yyh 2026-01-30 16:07:15 +08:00
parent 5c0023b788
commit 4338632a78
No known key found for this signature in database
2 changed files with 7 additions and 2 deletions

View File

@ -19,6 +19,7 @@ type IModal = {
highPriority?: boolean // For modals that need to appear above dropdowns
overlayOpacity?: boolean // For semi-transparent overlay instead of default
clickOutsideNotClose?: boolean // Prevent closing when clicking outside modal
initialFocus?: React.RefObject<HTMLElement | null>
}
export default function Modal({
@ -35,10 +36,11 @@ export default function Modal({
highPriority = false,
overlayOpacity = false,
clickOutsideNotClose = false,
initialFocus,
}: IModal) {
return (
<Transition appear show={isShow} as={Fragment}>
<Dialog as="div" className={cn('relative', highPriority ? 'z-[1100]' : 'z-[60]', wrapperClassName)} onClose={clickOutsideNotClose ? noop : onClose}>
<Dialog as="div" className={cn('relative', highPriority ? 'z-[1100]' : 'z-[60]', wrapperClassName)} onClose={clickOutsideNotClose ? noop : onClose} initialFocus={initialFocus}>
<TransitionChild>
<div className={cn('fixed inset-0', overlayOpacity ? 'bg-workflow-canvas-canvas-overlay' : 'bg-background-overlay', 'duration-300 ease-in data-[closed]:opacity-0', 'data-[enter]:opacity-100', 'data-[leave]:opacity-0')} />
</TransitionChild>

View File

@ -46,6 +46,8 @@ const CreateBlankSkillModal = ({ isOpen, onClose }: CreateBlankSkillModalProps)
const { data: existingNames } = useExistingSkillNames()
const inputRef = useRef<HTMLInputElement>(null)
const trimmedName = skillName.trim()
const isDuplicate = !!trimmedName && (existingNames?.has(trimmedName) ?? false)
const canCreate = !!trimmedName && !isDuplicate && !isCreating
@ -116,18 +118,19 @@ const CreateBlankSkillModal = ({ isOpen, onClose }: CreateBlankSkillModalProps)
title={t('skill.startTab.createModal.title', { ns: 'workflow' })}
closable={!isCreating}
clickOutsideNotClose={isCreating}
initialFocus={inputRef}
>
<div className="mt-6 flex flex-col gap-1">
<label className="system-sm-semibold text-text-secondary">
{t('skill.startTab.createModal.nameLabel', { ns: 'workflow' })}
</label>
<Input
ref={inputRef}
value={skillName}
onChange={e => setSkillName(e.target.value)}
placeholder={t('skill.startTab.createModal.namePlaceholder', { ns: 'workflow' }) || ''}
destructive={isDuplicate}
disabled={isCreating}
autoFocus
onKeyDown={(e) => {
if (e.key === 'Enter' && canCreate)
handleCreate()