How to trigger menus from operators in Python?
Okay, so it took me a little while (and a lot of searching online), but it was this link (https://wiki.blender.org/index.php/Dev:Py/Scripts/Cookbook/Code_snippets/Interface#A_popup_dialog) that showed me what I needed.

What I have done is definitely a hack, and there are more elegant solutions, but if you are just looking for a way that works, then this will help a lot.
(Warning: Lots of code)

So it works by having three classes, which call each other in turn.

The "Clicked On" Operator

The first is an operator that simply exists to invoke the dialog box when clicked in the "search menu".

class slowClick(bpy.types.Operator):
bl_idname = "slowclick.move_operator"
bl_label = "Slow"

def execute(self, context):
    # Default can be used since I only have a single dialog
    bpy.ops.object.dialog_operator('INVOKE_DEFAULT')

    return {'FINISHED'}


The Dialog Box

The second is the dialog box itself. This is invoked in the line bpy.ops.object.dialog_operator('INVOKE_DEFAULT'), and then displayed.

The actual dialog box is built somewhat counter-intuitively. Rather than putting in sliders using the standard layout.row().prop, all you actually do is define the variables, and on creation they can be changed. In my program that looked like this:

# create the sliders (and checkbox) in the dialog box so the user can change where the slo-mo starts and ends
firstSlowFrameP = bpy.props.IntProperty(
    name="First Slow Frame:",  # as you want it to appear on the slider
    default=40,  # optional
    description="This is the first frame that will be in slow motion"
)

globalSelect = bpy.props.BoolProperty(
    name="Global",  # affect all objects in scene
    default=False,
    description="If true, all available objects will be affected"
)


As with normal panels, how you define the property defines what kind of item it will be (e.g. slider for 'Int' and checkbox for 'Bool'), and at the bottom it has an "OK" button.

def execute(self, context):
    # first thing is to globalise the variables needed, and yes I know this isn't the best way
    global firstSlowFrame, globalSelect

    # reassign the variables based on the user's input on the sliders
    firstSlowFrame = self.firstSlowFrameP
    globalSelect = self.globalSelect

    # this actually calls the operator that does the editing
    bpy.ops.slow.move_operator()
    return {'FINISHED'}

def invoke(self, context, event):
    # call itself and run
    wm = context.window_manager
    return wm.invoke_props_dialog(self)


So the def execute() details what happens when the "OK" button is pressed. It globalises all the variables that were changed in the slider, so they can be accessed by the main and final function.

(The def invoke() just describes its creation when invoked)

The Main Function

Finally we get to the actual function. I won't put the main code here (If you want the addon go to How can I slow down or animate time?), but this is just your standard operator:

class Slow(bpy.types.Operator):
    bl_idname = "slow.move_operator"
    bl_label = "OK"

    # get the global variables since this is in a class
    global firstSlowFrame, globalSelect

    #PROGRAM


All you have to do is get the variables that were changed by the sliders, and it all works nicely.

(Technically, if you press "space" and type "OK" you will get this and it will probably not work since the variables don't exist yet, so at the very beginning of the program I would define a "default" value for each that will be used if the user accidentally bypasses the whole dialog box.)

Example

This is a template that can be used, feel free to use it, modify it, I doubt I invented this hack so I mean credit me if you want but I'm really not fussed, just hope this can help someone.

import bpy
import math
from bpy.props import *

scn = bpy.context.scene

# initialising the variables that will be in the dialog
intVariable = 10
strVariable = "Hello"
boolVariable = True


# This is the operator that is clicked by the user, triggering the dialog box
class ToBeClicked(bpy.types.Operator):
    bl_idname = "toBeClicked.move_operator"
    bl_label = "WHATEVER YOU WANT YOUR USER TO TYPE IN"

    def execute(self, context):
        # Default can be used since I only have a single dialog
        bpy.ops.object.dialog_operator('INVOKE_DEFAULT')

        return {'FINISHED'}


class DialogOperator(bpy.types.Operator):
    bl_idname = "object.dialog_operator"
    bl_label = "Dialog Operator"

    # create the sliders (and checkbox) in the dialog box 
    intVariableProperty = bpy.props.IntProperty(
        name="Integer Variable:",  # as you want it to appear on the slider
        default=10,  # optional
        description="This is an integer"  # what you get when you hover over
    )

    strVariableProperty = bpy.props.StringProperty(
        name="String Variable:",  # as you want it to appear on the bar
        default="Hello",  # optional
        description="This is a string"  # what you get when you hover over
    )

    boolVariableProperty = bpy.props.BoolProperty(
        name="Boolean Variable:",  # as you want it to appear on the checkbox
        default=True,
        description="This is a boolean checkbox"  # what you get when you hover over
    )

    # This is what happens when "OK is pressed
    def execute(self, context):
        # first thing is to globalise the variables needed, and yes I know this isn't the best way
        global intVariable, strVariable, boolVariable

        # this is just for troubleshooting
        print("Dialog Runs")
        print(self.intVariableProperty, self.strVariableProperty, self.boolVariableProperty)

        # reassign the variables based on the user's input on the sliders
        intVariable = self.intVariableProperty
        strVariable = self.strVariableProperty
        boolVariable = self.boolVariableProperty

        # this actually calls the operator that does the editing
        bpy.ops.slow.move_operator()
        return {'FINISHED'}

    # This is just saying that when it is invoked, how to display it
    def invoke(self, context, event):
        # call itself and run
        wm = context.window_manager
        return wm.invoke_props_dialog(self)


# This is the actual program that does something with the variables
class Main(bpy.types.Operator):
    bl_idname = "main.move_operator"
    bl_label = "OK"

    # get the global variables since this is in a class
    global intVariable, strVariable, boolVariable

    # This just makes sure that everything can be applied
    # if (CONDITION):
    # PROGRAM


    return {'FINISHED'}

    # This can give an error if you want certain conditions met
    # else:
    # self.report({'ERROR'}, 'There is no animation')
    # return {'CANCELLED'}


# registers everything
def register():
    bpy.utils.register_class(Main)
    bpy.utils.register_class(ToBeClicked)
    bpy.utils.register_class(DialogOperator)


if __name__ == "__main__":
    register()


I know this is really very long, in answer to a very unimportant question, but it took me a while to solve this and I'm pretty pleased with it, so I hope other people can find it just as useful.

Feel free to add corrections in the comments!