@@ -283,6 +283,10 @@ function M.push(location, opts)
283283 if stack .hidden then
284284 M .toggle (stack .root_winid )
285285 end
286+ -- Clear zoom before pushing so the new top popup gets normal layout
287+ if stack .zoomed_id then
288+ stack .zoomed_id = nil
289+ end
286290 local model = popup .create (location , create_opts )
287291 if not model then
288292 return nil
325329local function close_stack_item (stack , idx , item )
326330 local current_win = vim .api .nvim_get_current_win ()
327331 local should_restore_focus = item .winid == current_win and vim .w [current_win ].peekstack_popup_id ~= nil
332+ -- Clear zoom if the zoomed popup is being closed
333+ if stack .zoomed_id == item .id then
334+ stack .zoomed_id = nil
335+ end
328336 -- Remove from popups BEFORE closing the window to prevent
329337 -- WinClosed autocmd from re-entering and processing the same popup.
330338 table.remove (stack .popups , idx )
@@ -650,6 +658,9 @@ function M.handle_win_closed(winid)
650658 if stack .focused_id == item .id then
651659 focused_removed = true
652660 end
661+ if stack .zoomed_id == item .id then
662+ stack .zoomed_id = nil
663+ end
653664 emit_popup_event (" PeekstackClose" , item , root_winid )
654665 feedback .highlight_origin (item .origin )
655666 table.remove (stack .popups , idx )
@@ -719,6 +730,9 @@ function M.handle_buf_wipeout(bufnr)
719730 for idx = # stack .popups , 1 , - 1 do
720731 local item = stack .popups [idx ]
721732 if item .bufnr == bufnr then
733+ if stack .zoomed_id == item .id then
734+ stack .zoomed_id = nil
735+ end
722736 unindex_popup (item )
723737 table.remove (stack .popups , idx )
724738 end
@@ -795,6 +809,9 @@ function M.handle_origin_wipeout(bufnr)
795809 for idx = # stack .popups , 1 , - 1 do
796810 local item = stack .popups [idx ]
797811 if should_close_for_origin (item ) then
812+ if stack .zoomed_id == item .id then
813+ stack .zoomed_id = nil
814+ end
798815 popup .close (item )
799816 unindex_popup (item )
800817 table.remove (stack .popups , idx )
@@ -855,6 +872,8 @@ function M.toggle(winid)
855872 end
856873
857874 if not stack .hidden then
875+ -- Clear zoom state before hiding
876+ stack .zoomed_id = nil
858877 -- Move focus back to root window before hiding
859878 if vim .api .nvim_win_is_valid (stack .root_winid ) then
860879 vim .api .nvim_set_current_win (stack .root_winid )
@@ -897,11 +916,41 @@ function M.is_hidden(winid)
897916 return stack .hidden == true
898917end
899918
919+ --- Toggle zoom on the top popup. When zoomed, the popup fills the
920+ --- entire editor. Calling again restores the normal layout.
921+ --- @param winid ? integer
922+ --- @return boolean
923+ function M .toggle_zoom (winid )
924+ deps ()
925+ local stack = ensure_stack (winid )
926+ if # stack .popups == 0 or stack .hidden then
927+ return false
928+ end
929+
930+ local top = stack .popups [# stack .popups ]
931+ if stack .zoomed_id == top .id then
932+ stack .zoomed_id = nil
933+ else
934+ stack .zoomed_id = top .id
935+ end
936+ layout .reflow (stack )
937+ return true
938+ end
939+
940+ --- Check whether the current stack has a zoomed popup.
941+ --- @param winid ? integer
942+ --- @return boolean
943+ function M .is_zoomed (winid )
944+ local stack = ensure_stack (winid )
945+ return stack .zoomed_id ~= nil
946+ end
947+
900948--- Close all popups in the current (or given) window's stack.
901949--- @param winid ? integer
902950function M .close_all (winid )
903951 deps ()
904952 local stack = ensure_stack (winid )
953+ stack .zoomed_id = nil
905954 -- When hidden, windows are already closed; just clear hidden state
906955 -- and record history for each popup.
907956 if stack .hidden then
0 commit comments