Simple Menu User Interface - What kind of improvements could I make code wise? Struggling to see what I can improve in terms of this script

Hello there, I have been trying to create a simple menu interface. I do not really know what I could improve code wise, if anything. I am trying to see what I could make in terms of improvements within the code base or if I am using any modules (like Maid) the wrong way.

Could you take a look and tell me if anything looks odd to you?

Overview of the codebase for this simple menu user interface:

This is the module script for the code:

local Menu = {
	Events = {
		OnClosed = nil,
		Submitted = nil,
		OnItemSelected = nil
	},
	Close = nil,
	SubmitCoolDown = 3
}

local uiColors = {
	red = Color3.new(0.666667, 0, 0),
	black = Color3.new(0, 0, 0)
}

local private = {
	userInterface = nil,
	templateItem = nil, 
	items = {},
	currentItemSelectedIdx = 1,
	colorOnSelect = uiColors.red,
	colorOnNotSelected = uiColors.black,
	functions = {
		submit = nil, clickedOn = nil, moveUp = nil, moveDown = nil, getCurrentItemSelected = nil
	},
	maid = nil
}

local UserInputService = game:GetService("UserInputService")
local Signal = require(game.ReplicatedStorage.Signal)
local Maid = require(game.ReplicatedStorage.Maid)
local bin = game.StarterGui.Bin
local localPlayer = game.Players.LocalPlayer

private.maid = Maid.new()
Menu.Events.OnClosed = Signal.new()
Menu.Events.Submitted = Signal.new()
Menu.Events.OnItemSelected = Signal.new()
private.maid:GiveTask(Menu.Events.OnClosed)
private.maid:GiveTask(Menu.Events.Submitted)
private.maid:GiveTask(Menu.Events.OnItemSelected)

Menu.Close = function()
	private.maid:Destroy()
end

local submitting = false
private.functions.submit = function(item)
	if not (submitting) then
		submitting = true
		
		Menu.Events.Submitted:Fire(item.Name) 
		wait(Menu.SubmitCoolDown)
		submitting = false
	end
end

private.functions.getCurrentItemSelected = function()
	local getItem = private.items[private.currentItemSelectedIdx]
	return getItem
end

local doubleClickDetectionIsOn = false
private.functions.clickedOn = function(item)
	local getItemClickedIdx = item:GetAttribute("ItemIdx")
	local itemIsNotAlreadySelected = (private.currentItemSelectedIdx ~= getItemClickedIdx)
	
	if (itemIsNotAlreadySelected) then
		item.BackgroundColor3 = private.colorOnSelect
		
		private.items[private.currentItemSelectedIdx].BackgroundColor3 = private.colorOnNotSelected
		
		private.currentItemSelectedIdx = getItemClickedIdx
		Menu.Events.OnItemSelected:Fire(item.name.." has been selected.")
	end
	
	if not (doubleClickDetectionIsOn) then
		doubleClickDetectionIsOn = true
		wait(2)
		doubleClickDetectionIsOn = false
	else
		private.functions.submit(item)
	end
end

private.functions.moveDown = function()
	local lastMenuItemIdx = #private.items
	if  (private.currentItemSelectedIdx ~= lastMenuItemIdx) then
		local moveSelectedIdxDown = private.currentItemSelectedIdx + 1 -- This goes down in the gui.
		
		local nextItem = private.items[moveSelectedIdxDown]
		nextItem.BackgroundColor3 = private.colorOnSelect
		
		local currentItemBeforeMovingDown = private.items[private.currentItemSelectedIdx]
		currentItemBeforeMovingDown.BackgroundColor3 = private.colorOnNotSelected
		
		private.currentItemSelectedIdx = moveSelectedIdxDown
		local getItem = private.functions.getCurrentItemSelected()
		Menu.Events.OnItemSelected:Fire(getItem.Name)
	end
end

private.functions.moveUp = function()
	local atBeginning = 1 
	if (private.currentItemSelectedIdx ~= atBeginning) then
		local moveSelectedIdxUp = private.currentItemSelectedIdx -  1
		
		local prevItem = private.items[moveSelectedIdxUp]
		prevItem.BackgroundColor3 = private.colorOnSelect
		
		local currentItemBeforeMovingUp = private.items[private.currentItemSelectedIdx]
		currentItemBeforeMovingUp.BackgroundColor3 = private.colorOnNotSelected
		
		private.currentItemSelectedIdx = moveSelectedIdxUp
		local getItem = private.functions.getCurrentItemSelected()
		Menu.Events.OnItemSelected:Fire(getItem.Name)
	end
end

function Menu.insert(options)
	if type(options) == "table" then
		for i = 1, #options do
			local newItem = private.templateItem:Clone()
			newItem.Name = options[i]
			newItem.Text = options[i]
			newItem.Parent = private.userInterface.Frame.BodyFrame.ScrollingFrame
			
			local function attachEventsToItem()
				newItem.MouseButton1Click:Connect(function()
					private.functions.clickedOn(newItem)
				end)
			end
			attachEventsToItem()
			
			local appendItemToEndOfItems = #private.items + 1 
			private.items[appendItemToEndOfItems] = newItem
			newItem:SetAttribute("ItemIdx", #private.items)
			private.templateItem.BackgroundColor3 = private.colorOnNotSelected -- Makes sure that the templateItem's background color when not selected is the 
																			-- color that is designated for not selected every new insertion!
		end
	else
		warn("[Menu] Wrong input format when using insert. Must be a table.")
	end
end

function Menu.create()
	-- Create default state/environment:
	private.userInterface = bin.Menu:Clone()
	private.userInterface.Parent = localPlayer.PlayerGui
	-- Make the place holder item a template item for cloning purposes:
	local placeHolderItem = private.userInterface.Frame.BodyFrame.ScrollingFrame.PlaceholderItem
	private.templateItem = placeHolderItem:Clone()
	placeHolderItem:Destroy()
	
	private.maid:GiveTask(private.userInterface)
	private.maid:GiveTask(private.templateItem)
	-- Event listeners for the menu itself:
	private.maid:GiveTask(UserInputService.InputBegan:Connect(function(input, _gameProcessed)
		if (input.KeyCode == Enum.KeyCode.W) then
			private.functions.moveUp()
		elseif (input.KeyCode == Enum.KeyCode.S) then
			private.functions.moveDown()
		elseif (input.KeyCode == Enum.KeyCode.Backspace) then
			Menu.Events.OnClosed:Fire()
		elseif (input.KeyCode == Enum.KeyCode.Return) then
			local getItem = private.functions.getCurrentItemSelected()
			private.functions.submit(getItem)
		end
	end))
	private.userInterface.Frame.ButtonFrame.FirstButton.MouseButton1Click:Connect(function()
		Menu.Events.OnClosed:Fire()
		Menu.Close()
	end)
	private.userInterface.Frame.ButtonFrame.SecondButton.MouseButton1Click:Connect(function()
		local getItem = private.functions.getCurrentItemSelected()
		private.functions.submit(getItem)
	end)
	-- Enable the menu:
	private.userInterface.Enabled = true
end

return Menu

And here is the code being used in a local script simply:

repeat wait() until game.ContentProvider.RequestQueueSize == 0 -- Wait until the game has completely loaded in for the player.
local Maid = require(game.ReplicatedStorage.Maid)
local Menu = require(game.ReplicatedStorage.Menu)

Menu.create()
Menu.insert({"Menu Item Button One", "Panda Express"})
local maid = Maid.new()

maid:GiveTask(Menu.Events.OnItemSelected:Connect(function(itemName)
	print(itemName.." was selected.")
end))
maid:GiveTask(Menu.Events.Submitted:Connect(function(itemName)
	print(itemName.." was submitted.")
end))
maid:GiveTask(Menu.Events.OnClosed:Connect(function(itemName)
	maid:Destroy()
end))