feat(modal): add edit mode with anchored dropdowns and keyboard workflow
- Add TaskDetailModal edit mode with form validation, tags + annotations editing, and SaveEdits event - Anchor dropdown/suggestion menus using deferred/anchored overlay to avoid clipping - Add modal-specific keymap contexts (ModalInput/ModalDropdown) for Esc/Ctrl+Enter/Tab navigation - Refresh modal project suggestions from tasks; improve project child filtering boundary match - Small UI polish (toast styling, layout spacing) and update shortcuts docs
This commit is contained in:
@@ -6,6 +6,8 @@ pub enum ContextId {
|
||||
SidebarProjects,
|
||||
SidebarTags,
|
||||
Modal,
|
||||
ModalInput,
|
||||
ModalDropdown,
|
||||
FilterBar,
|
||||
TextInput,
|
||||
}
|
||||
@@ -19,6 +21,8 @@ impl ContextId {
|
||||
"sidebarprojects" | "SidebarProjects" => Some(Self::SidebarProjects),
|
||||
"sidebartags" | "SidebarTags" => Some(Self::SidebarTags),
|
||||
"modal" | "Modal" => Some(Self::Modal),
|
||||
"modalinput" | "ModalInput" => Some(Self::ModalInput),
|
||||
"modaldropdown" | "ModalDropdown" => Some(Self::ModalDropdown),
|
||||
"filterbar" | "FilterBar" => Some(Self::FilterBar),
|
||||
"textinput" | "TextInput" => Some(Self::TextInput),
|
||||
_ => None,
|
||||
@@ -33,6 +37,8 @@ impl ContextId {
|
||||
Self::SidebarProjects => "SidebarProjects",
|
||||
Self::SidebarTags => "SidebarTags",
|
||||
Self::Modal => "Modal",
|
||||
Self::ModalInput => "ModalInput",
|
||||
Self::ModalDropdown => "ModalDropdown",
|
||||
Self::FilterBar => "FilterBar",
|
||||
Self::TextInput => "TextInput",
|
||||
}
|
||||
|
||||
@@ -429,5 +429,77 @@ pub fn build_default_keymap() -> KeymapLayer {
|
||||
Command::SaveModal,
|
||||
);
|
||||
|
||||
layer.bind(
|
||||
ContextId::ModalInput,
|
||||
KeyChord::new(Key::Escape, Mods::none()),
|
||||
Command::CloseModal,
|
||||
);
|
||||
layer.bind(
|
||||
ContextId::ModalInput,
|
||||
KeyChord::new(Key::Enter, Mods::ctrl()),
|
||||
Command::SaveModal,
|
||||
);
|
||||
layer.bind(
|
||||
ContextId::ModalInput,
|
||||
KeyChord::new(Key::Tab, Mods::none()),
|
||||
Command::FocusFilterNext,
|
||||
);
|
||||
layer.bind(
|
||||
ContextId::ModalInput,
|
||||
KeyChord::new(Key::Tab, Mods::shift()),
|
||||
Command::FocusFilterPrev,
|
||||
);
|
||||
|
||||
layer.bind(
|
||||
ContextId::ModalDropdown,
|
||||
KeyChord::new(Key::Escape, Mods::none()),
|
||||
Command::CloseModal,
|
||||
);
|
||||
layer.bind(
|
||||
ContextId::ModalDropdown,
|
||||
KeyChord::new(Key::Enter, Mods::ctrl()),
|
||||
Command::SaveModal,
|
||||
);
|
||||
layer.bind(
|
||||
ContextId::ModalDropdown,
|
||||
KeyChord::new(Key::Enter, Mods::none()),
|
||||
Command::ToggleDropdown,
|
||||
);
|
||||
layer.bind(
|
||||
ContextId::ModalDropdown,
|
||||
KeyChord::new(Key::Space, Mods::none()),
|
||||
Command::ToggleDropdown,
|
||||
);
|
||||
layer.bind(
|
||||
ContextId::ModalDropdown,
|
||||
KeyChord::new(Key::Char('j'), Mods::none()),
|
||||
Command::SelectNextOption,
|
||||
);
|
||||
layer.bind(
|
||||
ContextId::ModalDropdown,
|
||||
KeyChord::new(Key::Char('k'), Mods::none()),
|
||||
Command::SelectPrevOption,
|
||||
);
|
||||
layer.bind(
|
||||
ContextId::ModalDropdown,
|
||||
KeyChord::new(Key::ArrowDown, Mods::none()),
|
||||
Command::SelectNextOption,
|
||||
);
|
||||
layer.bind(
|
||||
ContextId::ModalDropdown,
|
||||
KeyChord::new(Key::ArrowUp, Mods::none()),
|
||||
Command::SelectPrevOption,
|
||||
);
|
||||
layer.bind(
|
||||
ContextId::ModalDropdown,
|
||||
KeyChord::new(Key::Tab, Mods::none()),
|
||||
Command::FocusFilterNext,
|
||||
);
|
||||
layer.bind(
|
||||
ContextId::ModalDropdown,
|
||||
KeyChord::new(Key::Tab, Mods::shift()),
|
||||
Command::FocusFilterPrev,
|
||||
);
|
||||
|
||||
layer
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user