CustomActionObject (CAO) v1.3.0 | A simple way to create custom designs mobile button


:floppy_disk: GitHub

CustomActionObject (CAO) is a lightweight module designed to give developers full control over the visual style of mobile buttons created by ContextActionService.
Since Roblox hasn’t updated the look of mobile buttons in a long time, I created this module to make it easier to customize and restyle them the way you want.
https://create.roblox.com/store/asset/117099778644311/CustomActionObject

:package: Examples


Without module


:package: Template for Custom Buttons

Templates

Roblox default design template


Custom template

:wrench: Basic Usage

local ContextActionService = game:GetService("ContextActionService")
local CAO = require(game.ReplicatedStorage.CustomActionObject)

-- Bind your mobile action
ContextActionService:BindAction("Sprint", function() end, true)
ContextActionService:SetPosition("Sprint", UDim2.new(.7, 0, -0.2, 0))
ContextActionService:SetTitle("Sprint", "Sprint")

-- Apply default style to the button
CAO.default(ContextActionService:GetButton("Sprint"))

:page_facing_up: API Reference

Functions

.default(button)

CAO.default(ContextActionService:GetButton("Button"))

Apply the default button style

.custom(…)

CAO.custom(ContextActionService:GetButton("Button"), 
	ContextImage:AssetID,
	ContextTransparency: number,
	ContextColor3: Color3,
	ActionTransparency: number,
	ActionColor3: Color3, 
	TextFont: Font)

Fully customizable context button styling

.SetProfile(…)

CAO.SetProfile(ContextActionService:GetButton("Button"), 
	Profile: ModuleScript,)

Using custom profiles/presets

.legacy(button)

CAO.default(ContextActionService:GetButton("Button"))

Apply legacy default use two image button design

.custom_legacy(…)

CAO.custom_legacy((ContextActionService:GetButton("Button"), 
	ContextImageDefault:AssetID, 
	ContextImagePressed:AssetID,
	ContextTransparency: number,
	ContextColor3: Color3,
	ActionTransparency: number,
	ActionColor3: Color3, 
	TextFont: Font)

Mix of legacy behavior with full customization

Methods

:SetButtonSize(number)

local default = CAO.default(ContextActionService:GetButton("Button"))
default:SetButtonSize(number)

Set button size in pixel

:SetContextColor(Color3)

local default = CAO.default(ContextActionService:GetButton("Button"))
default:SetContextColor(Color3)

Set the background (context) color of the button

:SetContextTransparency(number)

local default = CAO.default(ContextActionService:GetButton("Button"))
default:SetContextTransparency(number)

Set transparency of the button

:SetFont(font)

local default = CAO.default(ContextActionService:GetButton("Button"))
default:SetFont(font)

Set the font for the button’s text

:SetTextSize(number)

local default = CAO.default(ContextActionService:GetButton("Button"))
default:SetTextSize(number)

Set the text size in pixel for the button’s text

:SetActionColor(Color3)

local default = CAO.default(ContextActionService:GetButton("Button"))
default:SetActionColor(color)

Set the color of the button’s text and icon

:SetActionTransparency(number)

local default = CAO.default(ContextActionService:GetButton("Button"))
default:SetActionTransparency(number)

Set transparency for icon and text label

:SetEnabled(value:boolean)

local default = CAO.default(ContextActionService:GetButton("Button"))
default:SetEnabled(value:boolean)

You can disable or enable the button

:Destroy()

local default = CAO.default(ContextActionService:GetButton("Button"))
default:Destroy()

Just removes the button lol

:memo: License

This module is released under the Mozilla Public License Version 2.0 (MPL-2.0). You’re free to use it in any project, including commercial ones. The only requirement is that if you modify the source code of this module, you must publish your changes under the same license and give credit to the original author.
This way, improvements stay open for the community, and original authorship is respected.


:light_bulb:Feedback

This is my first ever module script and the first version of the module itself, so go easy on me :sweat_smile:
I’m open to feedback, ideas, or bug reports — feel free to share! :wink:

:speech_balloon: Credits

Created by MBAID
Inspired to create this module by M100 (Micamaster100) — whose work and ideas sparked the original motivation.
Also influenced by TopBarPlus for its clean API and modular structure.

25 Likes

this looks very nice ill use it for my games

2 Likes

Im surprised how easy it is to use, good stuff bro

1 Like

This module is very good, thank you, it was very useful and will be useful in my future projects.

1 Like

Hi MBAID, great module. I’m currently trying the custom_legacy but it seems like it’s not showing anything? Would be great if you will be able to help me out. Here’s my code:

local function styleMobileActionButtons()
	CAO.custom_legacy(
		ContextActionService:GetButton(Constants.ACTION_CRAWL),
		"135718474056000",
		"79674412901283",
		1,
		Color3.new(1, 1, 1),
		1,
		Color3.new(1, 1, 1))
	ContextActionService:SetPosition(Constants.ACTION_CRAWL, UDim2.new(.7, 0, -0.2, 0))
end

And here’s the result. Don’t mind the other button showing in the image, that’s unrelated on this.


If I inspect the PlayerGui > ContextActionGui. The button is there. I’m not sure why it’s not rendering the button with the provided asset id’s.

EDIT:
Sorry, I was setting the Transparency to 1 when it should be set to 0. Already working properly.

local function styleMobileActionButtons()
	CAO.custom_legacy(
		ContextActionService:GetButton(Constants.ACTION_CRAWL),
		"rbxassetid://135718474056000",
		"rbxassetid://79674412901283",
		1,
		Color3.new(1, 1, 1),
		1,
		Color3.new(1, 1, 1))
	ContextActionService:SetPosition(Constants.ACTION_CRAWL, UDim2.new(.7, 0, -0.2, 0))
end

I guess the problem is that you just wrote 135718474056000, without rbxassetid://

I recommend you use .custom
since I posted a template for it. It’s better to use it.

1 Like

Can I still use an Icon with the custom() like so?

1 Like


you can edit this template

or the original Roblox

However, if you do not intend to change the button shape itself, you do not need .custom at all.
You can simply use ContextActionService as usual, but apply .default from the module.
Example:

local ContextActionService = game:GetService("ContextActionService")
local CAO = require(game.ReplicatedStorage.CustomActionObject)

-- Bind your mobile action
ContextActionService:BindAction("Sprint", function() end, true)
ContextActionService:SetPosition("Sprint", UDim2.new(.7, 0, -0.2, 0))
ContextActionService:SetImage("Sprint", id)

-- Apply default style to the button
CAO.default(ContextActionService:GetButton("Sprint"))
1 Like

I see, this is much simpler than the method I used. Thank you so much!

1 Like

CAO Update v1.3.0

https://create.roblox.com/store/asset/117099778644311/CustomActionObject

RobloxStudioBeta_8q6QauRihp

Now creating your own mobile buttons has become even more flexible, because now you can script them yourself! By creating your own profile/preset for the CAO module

Example:

Module script (Profile/Preset)

Profile 1

-- Template for a profile

return function (self)
	self.ContextButton.ImageTransparency = 1
	
	local context = Instance.new("ImageButton")
	context.Size = UDim2.new(1,0,1,0)
	context.AnchorPoint = Vector2.new(.5,.5)
	context.Position = UDim2.new(.5,0,.5,0)
	context.BackgroundTransparency = 1
	context.Image = "http://www.roblox.com/asset/?id=107327556584650"
	context.ImageTransparency = 0
	context.ZIndex = 0

	context.ImageRectOffset = Vector2.new(1, 146)
	context.ImageRectSize = Vector2.new(144, 144)

	context.Parent = self.ContextButton

	self.label.ImageTransparency = .5

	self.text_label.TextTransparency = .5
	self.text_label.TextStrokeTransparency = 1
	
	self.label.ImageColor3 = self:GetColor()
	self.text_label.TextColor3 = self:GetColor()
	
	
	-- Hover button
	self.ContextButton.MouseEnter:Connect(function()
		context.ImageRectOffset = Vector2.new(146, 146)
		context.ImageRectSize = Vector2.new(144, 144)
		
		self.label.ImageColor3 = Color3.fromHSV(0,0,0)
		self.text_label.TextColor3 = Color3.fromHSV(0,0,0)
	end)
	-- Unhover button
	self.ContextButton.MouseLeave:Connect(function()
		context.ImageRectOffset = Vector2.new(1, 146)
		context.ImageRectSize = Vector2.new(144, 144)
		
		self.label.ImageColor3 = self:GetColor()
		self.text_label.TextColor3 = self:GetColor()
	end)
end

This is the recommended template for editing and creating your own template for this. But there is also this template (not recommended).

Profile 2

-- Template for a profile

local TweenService = game:GetService("TweenService")


return function (self)
	self.ContextButton.ImageTransparency = 1
	
	local context = Instance.new("ImageButton")
	context.Size = UDim2.new(1,0,1,0)
	context.AnchorPoint = Vector2.new(.5,.5)
	context.Position = UDim2.new(.5,0,.5,0)
	context.BackgroundTransparency = 1
	context.Image = "http://www.roblox.com/asset/?id=107327556584650"
	context.ImageTransparency = 0
	context.ZIndex = 0

	context.ImageRectOffset = Vector2.new(1, 146)
	context.ImageRectSize = Vector2.new(144, 144)

	context.Parent = self.ContextButton

	self.label.ImageTransparency = .5

	self.text_label.TextTransparency = .5
	self.text_label.TextStrokeTransparency = 1
	
	--self.label.ImageColor3 = self:GetColor()
	--self.text_label.TextColor3 = self:GetColor()
	

	
	local Tweenlabel = TweenService:Create(self.label, TweenInfo.new(.25, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {ImageColor3 = Color3.fromHSV(0,0,0)})
	local TweenText = TweenService:Create(self.text_label, TweenInfo.new(.25, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {TextColor3 = Color3.fromHSV(0,0,0)})
	
	local Tweenlabel2 = TweenService:Create(self.label, TweenInfo.new(.25, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {ImageColor3 = self:GetColor()})
	local TweenText2 = TweenService:Create(self.text_label, TweenInfo.new(.25, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {TextColor3 = self:GetColor()})
	
	local TweenContext = TweenService:Create(context, TweenInfo.new(.25, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {ImageColor3 = Color3.fromHSV(0,0,0)})
	local TweenContext2 = TweenService:Create(context, TweenInfo.new(.25, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {ImageColor3 = self:GetColor()})
	
	Tweenlabel2:Play()
	TweenText2:Play()
	TweenContext:Play()
	
	context.ImageRectOffset = Vector2.new(146, 146)
	context.ImageRectSize = Vector2.new(144, 144)
	
	-- Hover button
	self.ContextButton.MouseEnter:Connect(function()

		
		--self.label.ImageColor3 = Color3.fromHSV(0,0,0)
		--self.text_label.TextColor3 = Color3.fromHSV(0,0,0)
		
		Tweenlabel:Play()
		TweenText:Play()
		TweenContext2:Play()
	end)
	-- Unhover button
	self.ContextButton.MouseLeave:Connect(function()
		--context.ImageRectOffset = Vector2.new(1, 146)
		--context.ImageRectSize = Vector2.new(144, 144)
		
		Tweenlabel2:Play()
		TweenText2:Play()
		TweenContext:Play()
		
		--self.label.ImageColor3 = self:GetColor()
		--self.text_label.TextColor3 = self:GetColor()
	end)
end

Example of using a profile in a local script

local ContextActionService = game:GetService("ContextActionService")
local CAO = require(game.ReplicatedStorage.CustomActionObject)

ContextActionService:BindAction("SprintMobile16", SprintMobile, true)
ContextActionService:SetPosition("SprintMobile16", UDim2.new(.3,0,-.4,0))
ContextActionService:SetTitle("SprintMobile16", "G")

local profile = CAO.SetProfile(ContextActionService:GetButton("SprintMobile16"),
game.ReplicatedStorage.Profile1)

.SetProfile(ContextButton, Profile: ModuleScript) - Now you can create a fully customized button for yourself by scripting your profile for it.

  • Added new methods:
    :SetEnabled(value:boolean) - You can disable or enable the button
    :Destroy() - removes the button
  • Optimized script
1 Like