Currently popup windows can open in a way that most of the window is outside the monitor border. Make sure that no part of the window is outside the monitor borders. Code: class Header:
    """Class for handling header UI."""
    DATA_TYPE_OPTIONS = ["string", "integer", "float", "boolean"]

    def __init__(self, root: tk.Tk, app: 'TableApp'):
        self.root = root
        self.app = app
        self.style = app.style
        self.colors = app.colors
        self.fonts = app.fonts
        self.dimensions = app.dimensions
        self.table_name_label = None
        self.lower_header_frame = None
        self.result = None
        self._setup_header()
        self.dropdown = None
        self.popup_bindings = {}

    def _setup_header(self) -> None:
        header_frame = self._setup_main_frame()
        self._setup_upper_section(header_frame)
        self._setup_lower_section(header_frame)

    def _setup_main_frame(self) -> tk.Frame:
        header_frame = create_frame(parent=self.root, width=None, bg=self.colors["background"])
        header_frame.grid(row=0, column=1, columnspan=2, sticky="ew")
        header_frame.config(height=self.dimensions["header_height"])
        header_frame.grid_propagate(False)
        header_frame.grid_rowconfigure(0, weight=0)
        header_frame.grid_rowconfigure(1, weight=0)
        for i in range(5):
            header_frame.grid_columnconfigure(i, weight=1 if i == 4 else 0)
        return header_frame

    def _setup_upper_section(self, parent: tk.Frame) -> None:
        upper_frame = create_frame(parent=parent, width=None, bg=self.colors["background"])
        upper_frame.grid(row=0, column=0, columnspan=6, sticky="ew", pady=(0, 10))
        upper_frame.grid_columnconfigure(5, weight=1)
        self._add_upper_content(upper_frame)

    def _add_upper_content(self, frame: tk.Frame) -> None:
        tk.Label(
            frame, text="Data > ", bg=self.colors["background"], fg=self.colors["header_info"], font=self.fonts["header_info"]
        ).grid(row=0, column=0, padx=22, pady=(22, 0), sticky="nw")
        self.table_name_label = tk.Label(
            frame, text=self.app.current_table_name or "No Table Selected", bg=self.colors["background"], fg=self.colors["text"], font=self.fonts["header_info"]
        )
        self.table_name_label.grid(row=0, column=0, padx=(88, 10), pady=(22, 0), sticky="nw")
        self._setup_settings_section(frame)

    def _setup_settings_section(self, frame: tk.Frame) -> None:
        settings_container = tk.Frame(frame, bg=self.colors["background"])
        settings_container.grid(row=0, column=5, padx=(0, 40), pady=(22, 0), sticky="ne")
        common_label_options = {
            'bg': self.colors["background"],
            'fg': self.colors["text"],
            'font': self.fonts["text"],
            'cursor': "hand2",
            'width': 2,
            'height': 1
        }
        buttons_frame = tk.Frame(settings_container, bg=self.colors["background"])
        buttons_frame.pack(side=tk.LEFT)
        labels = ['S', 'I', 'E', 'D']
        actions = [self.show_stats, self.app.table_io.import_file, self.app.table_io.export_table, self.show_datatype_dialog]
        for label_text, action in zip(labels, actions):
            label = tk.Label(buttons_frame, text=label_text, **common_label_options)
            label.pack(side=tk.LEFT)
            label.bind("<Button-1>", lambda e, act=action: act())
            label.bind("<Enter>", lambda e, lbl=label: lbl.config(bg=self.colors["button_selected"]))
            label.bind("<Leave>", lambda e, lbl=label: lbl.config(bg=self.colors["background"]))

    def _setup_lower_section(self, parent: tk.Frame) -> None:
        self.lower_header_frame = create_frame(parent=parent, width=None, bg=self.colors["background"])
        self.lower_header_frame.grid(row=1, column=0, columnspan=5, sticky="ew")

    def create_styled_popup(self, popup_attr_name='popup_window', extra_widgets=None):
        """Creates a styled popup window and handles closing events."""
        if extra_widgets is None:
            extra_widgets = []

        if hasattr(self, popup_attr_name) and getattr(self, popup_attr_name).winfo_exists():
            getattr(self, popup_attr_name).destroy()

        popup = tk.Toplevel(self.root)
        popup.overrideredirect(True)
        setattr(self, popup_attr_name, popup)

        border_frame = tk.Frame(popup, bg=self.colors["frame_border"])
        border_frame.pack(padx=0, pady=0, expand=True, fill=tk.BOTH)
        content_frame = tk.Frame(border_frame, bg=self.colors["background"])
        content_frame.pack(padx=1, pady=1, expand=True, fill=tk.BOTH)
        inner_frame = tk.Frame(content_frame, bg=self.colors["background"])
        inner_frame.pack(padx=10, pady=10, expand=True, fill=tk.BOTH)

        popup.update_idletasks()
        popup_width = popup.winfo_width()
        popup_height = popup.winfo_height()
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        menu_x = self.root.winfo_pointerx()
        menu_y = self.root.winfo_pointery()
        padding = 10
        if menu_x + popup_width > screen_width - padding:
            menu_x = screen_width - popup_width - padding
        if menu_y + popup_height > screen_height - padding:
            menu_y = screen_height - popup_height - padding
        menu_x = max(padding, menu_x)
        menu_y = max(padding, menu_y)
        popup.geometry(f"+{menu_x}+{menu_y}")

        def close_popup(event=None):
            if popup.winfo_exists():
                popup.destroy()
            self._unbind_popup_events(popup_attr_name)

        def click_outside(event):
            ancestors = [popup] + extra_widgets
            if not self._is_descendant(event.widget, ancestors):
                close_popup()

        def window_resized(event):
            close_popup()

        self.popup_bindings[popup_attr_name] = {
            "click_outside": self.root.bind("<Button-1>", click_outside),
            "window_resized": self.root.bind("<Configure>", window_resized)
        }
        popup.bind("<Escape>", close_popup)
        popup.focus_force()

        return inner_frame

    def _unbind_popup_events(self, popup_attr_name):
        """Unbinds the popup events."""
        bindings = self.popup_bindings.get(popup_attr_name, {})
        if "click_outside" in bindings:
            self.root.unbind("<Button-1>", bindings["click_outside"])
        if "window_resized" in bindings:
            self.root.unbind("<Configure>", bindings["window_resized"])
        if popup_attr_name in self.popup_bindings:
            del self.popup_bindings[popup_attr_name]

    def _is_descendant(self, widget, ancestors):
        """Checks if a widget is a descendant of any in a list of ancestors."""
        while widget:
            if widget in ancestors:
                return True
            widget = widget.master
        return False

    def show_stats(self):
        """Display stats about the boolean columns in a menu-like popup with a table."""
        table_name = self.app.current_table_name
        if not table_name:
            messagebox.showwarning("No Table Selected", "Please select a table to view stats.")
            return
        if not self.app.current_sheet:
            messagebox.showwarning("No Data", "No data available to show stats.")
            return
        data = self.app.current_sheet.get_sheet_data()
        current_headers = self.app.current_sheet.headers()
        data_types = self.app.data_manager.tables_data[table_name].get("data_types", [])
        while len(data_types) < len(current_headers):
            data_types.append('string')
        total_rows = len(data)
        boolean_columns = []
        for col_idx, dtype in enumerate(data_types):
            if dtype == 'boolean':
                header = current_headers[col_idx]
                column_data = [bool(row[col_idx]) if row[col_idx] is not None else False for row in data]
                true_count = sum(1 for val in column_data if val is True)
                false_count = sum(1 for val in column_data if val is False)
                boolean_columns.append((header, true_count, false_count))

        inner_frame = self.create_styled_popup(popup_attr_name='stats_popup')

        total_label = tk.Label(
            inner_frame, text=f"Number of Rows: {total_rows}", bg=self.colors["background"], fg=self.colors["text"], font=self.fonts["menu"]
        )
        total_label.pack(pady=(0, 5), anchor='center')
        separator = tk.Frame(inner_frame, bg=self.colors["separator_menu"], height=1)
        separator.pack(fill=tk.X, pady=(0, 5))
        if boolean_columns:
            table_frame = tk.Frame(inner_frame, bg=self.colors["background"])
            table_frame.pack()
            headers = ["Column", "True", "False"]
            for col_num, header_text in enumerate(headers):
                header_label = tk.Label(
                    table_frame, text=header_text, bg=self.colors["background"], fg=self.colors["text"], font=self.fonts["menu"]
                )
                header_label.grid(row=0, column=col_num, padx=10, pady=2, sticky='w')
            for row_num, (header, true_count, false_count) in enumerate(boolean_columns, start=1):
                header_label = tk.Label(
                    table_frame, text=header, bg=self.colors["background"], fg=self.colors["header_info"], font=self.fonts["menu"]
                )
                header_label.grid(row=row_num, column=0, padx=10, pady=2, sticky='w')
                true_label = tk.Label(
                    table_frame, text=str(true_count), bg=self.colors["background"], fg=self.colors["header_info"], font=self.fonts["menu"]
                )
                true_label.grid(row=row_num, column=1, padx=10, pady=2, sticky='w')
                false_label = tk.Label(
                    table_frame, text=str(false_count), bg=self.colors["background"], fg=self.colors["header_info"], font=self.fonts["menu"]
                )
                false_label.grid(row=row_num, column=2, padx=10, pady=2, sticky='w')
            for col_num in range(3):
                table_frame.grid_columnconfigure(col_num, weight=1)
        else:
            no_data_label = tk.Label(
                inner_frame, text="No boolean columns to display.", bg=self.colors["background"], fg=self.colors["text"], font=self.fonts["menu"]
            )
            no_data_label.pack(pady=10)

    def show_datatype_dialog(self) -> None:
        """Show custom popup window for changing column data types."""
        table_name = self.app.current_table_name
        if not table_name:
            messagebox.showwarning("No Table Selected", "Please select a table to change datatypes.")
            return
        current_headers = self.app.current_sheet.headers() if self.app.current_sheet else []
        self.app.data_manager.headers[table_name] = current_headers
        self.data_types = self.app.data_manager.tables_data[table_name].get("data_types", []).copy()
        while len(self.data_types) < len(current_headers):
            self.data_types.append('string')
        self.datatype_vars = {}

        inner_frame = self.create_styled_popup(popup_attr_name='datatype_popup')

        for header_index, header in enumerate(current_headers):
            current_type = self.data_types[header_index]
            frame = tk.Frame(inner_frame, bg=self.colors["background"])
            frame.pack(fill=tk.X, pady=0)
            header_label = tk.Label(
                frame, text=f"{header}:", bg=self.colors["background"], fg=self.colors["text"], font=self.fonts["menu"]
            )
            header_label.pack(side=tk.LEFT, padx=(0, 10))
            var = tk.StringVar(value=current_type)
            dropdown_button = tk.Label(
                frame, textvariable=var, bg=self.colors["background"], fg=self.colors["header_info"], font=self.fonts["menu"], cursor="hand2", width=6, anchor='w'
            )
            dropdown_button.pack(side=tk.RIGHT)

            def on_enter(e, btn=dropdown_button):
                btn.config(bg=self.colors["button_selected"])

            def on_leave(e, btn=dropdown_button):
                btn.config(bg=self.colors["background"])

            dropdown_button.bind("<Enter>", on_enter)
            dropdown_button.bind("<Leave>", on_leave)

            def create_dropdown(event, var=var, button=dropdown_button):
                if self.dropdown is not None and self.dropdown.winfo_exists():
                    self.dropdown.destroy()
                self.dropdown = None
                x = button.winfo_rootx()
                y = button.winfo_rooty() + button.winfo_height()
                dropdown = tk.Toplevel(self.datatype_popup)
                self.dropdown = dropdown
                dropdown.overrideredirect(True)
                dropdown.geometry(f"+{x}+{y}")
                border_frame = tk.Frame(dropdown, bg=self.colors["frame_border"])
                border_frame.pack(padx=0, pady=0, expand=True, fill=tk.BOTH)
                inner_dropdown_frame = tk.Frame(border_frame, bg=self.colors["background"])
                inner_dropdown_frame.pack(padx=1, pady=1, expand=True, fill=tk.BOTH)
                for option in self.DATA_TYPE_OPTIONS:
                    option_label = tk.Label(
                        inner_dropdown_frame, text=option, bg=self.colors["background"], fg=self.colors["header_info"], font=self.fonts["menu"], anchor='w', width=6
                    )
                    option_label.pack(fill=tk.X)

                    def on_option_enter(e, lbl=option_label):
                        lbl.config(bg=self.colors["button_selected"])

                    def on_option_leave(e, lbl=option_label):
                        lbl.config(bg=self.colors["background"])

                    option_label.bind("<Enter>", on_option_enter)
                    option_label.bind("<Leave>", on_option_leave)

                    def on_option_select(e, opt=option):
                        var.set(opt)
                        dropdown.destroy()
                        self.dropdown = None
                        return "break"

                    option_label.bind("<Button-1>", on_option_select)
                dropdown.bind("<Button-1>", lambda e: "break")
                dropdown.focus_force()

                def close_dropdown(event):
                    if not self._is_descendant(event.widget, [dropdown]):
                        if dropdown.winfo_exists():
                            dropdown.destroy()
                            self.dropdown = None
                        self.root.unbind("<Button-1>", click_outside_dropdown)

                click_outside_dropdown = self.root.bind("<Button-1>", close_dropdown)
                return "break"

            dropdown_button.bind("<Button-1>", create_dropdown)
            dropdown_button.bind("<Button-1>", lambda e: "break", add="+")

            self.datatype_vars[header] = var

        separator = tk.Frame(inner_frame, bg=self.colors["separator_menu"], height=1)
        separator.pack(fill=tk.X, pady=(5, 5))
        apply_container = tk.Frame(
            inner_frame, bg=self.colors["background"], cursor="hand2"
        )
        apply_container.pack(fill=tk.X, pady=(5, 0))
        apply_label = tk.Label(
            apply_container, text="Apply Changes", bg=self.colors["background"], fg=self.colors["text"], font=self.fonts["menu"], cursor="hand2"
        )
        apply_label.pack(expand=True, fill=tk.BOTH, pady=0)

        def on_hover_enter(event):
            apply_container.config(bg=self.colors["button_selected"])
            apply_label.config(bg=self.colors["button_selected"])

        def on_hover_leave(event):
            apply_container.config(bg=self.colors["background"])
            apply_label.config(bg=self.colors["background"])

        apply_container.bind("<Enter>", on_hover_enter)
        apply_container.bind("<Leave>", on_hover_leave)
        apply_label.bind("<Enter>", on_hover_enter)
        apply_label.bind("<Leave>", on_hover_leave)
        apply_container.bind("<Button-1>", lambda e: self._apply_changes())
        apply_label.bind("<Button-1>", lambda e: self._apply_changes())

    def _apply_changes(self) -> None:
        """Apply the datatype changes and update the table."""
        table_name = self.app.current_table_name
        current_headers = self.app.current_sheet.headers() if self.app.current_sheet else []
        self.data_types = []
        for header in current_headers:
            dtype = self.datatype_vars[header].get()
            self.data_types.append(dtype)
        self.app.data_manager.tables_data[table_name]["data_types"] = self.data_types
        self.app.data_manager.save_data()
        self.app.table_display.apply_column_data_types(self.data_types)
        self.app.table_display.process_and_save_current_sheet_data()
        self.app.refresh_table()
        if hasattr(self, 'datatype_popup') and self.datatype_popup.winfo_exists():
            self.datatype_popup.destroy()
            self._unbind_popup_events('datatype_popup')