1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
require "pro_tacts/admin/phlex"

require "pro_tacts/admin/search_field"

module ProTacts
  module Admin
    # The search on a wide screen: a popover the header's button opens
    # (Layout) over whatever screen it is on, holding the search
    # (SearchField). A phone goes to the search page instead
    # (SearchPage); why the two differ, and why a dialog at all, is
    # docs/plans/2026-09-30-live-search.md.
    #
    # The Popover API does the opening and closing — the button, Esc,
    # a click outside — and `autofocus` lands in the input each time
    # it opens. `/` opens it from anywhere a key is not already typing
    # into something (docs/DESIGN.md, "The core idea"). What was typed
    # stays when it closes, so reopening lands on the same answer;
    # opened blank, it lists the recently updated contacts, the search
    # page's own list before a word is typed.
    class SearchDialog < Phlex::HTML
      ID = "search" #: String

      # `/` opens the dialog unless it is being typed into a field —
      # the dialog's own input among them — or the dialog is already
      # open, where showPopover would throw.
      SLASH = "if (!$el.matches(':popover-open') && " \
              "!$event.target.closest('input, textarea, select, [contenteditable]')) " \
              "{ $event.preventDefault(); $el.showPopover() }" #: String
      private_constant :SLASH

      def view_template
        dialog(id: ID, popover: "auto", class: "search-dialog", x_data: true,
               "@keydown.slash.window": SLASH) do
          render SearchField.new
        end
      end
    end
  end
end