abstr2ctUI | a style-based ui framework


a lightweight and simple ui framework for applying styles and functionality to gui objects
Created and maintained by Chromatype

Take the model here!

Documentation

Documentation can be found inside the module, but I’ll leave a copy of what is contained there here.

--[[

functions

	abstr2ctUI.createClass(string className, dictionary defaults)
		className: name of the class
		defaults: default properties, events and children
		
			EXAMPLE:
				abstr2ctUI.createClass("frame", {
					properties = {
						BackgroundColor3 = Color3.fromRGB(67,67,67)
					};
					children ={
						UICorner = {
							CornerRadius = UDim.new(0.1,0)
						}
					};
					events = {
						MouseEnter = function(guiObject, class)
							print("Player's mouse entered " .. guiObject.Name .. "!")
						end
					}
				})
				
	abstr2ctUI.applyClass(string className, GuiObject guiObject, dictionary deviations)
		className: name of the class to apply
		guiObject: guiobject to apply the class onto
		deviations: a dictionary of changes to properties, events, or children
		note that if a deviation has the same key as something in the base class,
		the deviation will take priority and overwrite the value.
		
			Example:
				abstr2ctUI.applyClass("frame", menu, {
					properties = {
						BackgroundColor3 = Color3.fromRGB(255,255,255);
						frameName = "BEST FRAME EVER"
					};
					events = {
						MouseEnter = function(guiObject, class)
							print("Player's mouse entered " .. class.properties.frameName .. "!")
						end
					}
				})
		
		applyClass will return a new class with all deviations applied on it, this is also
		passed into any event along side guiObject so that you can use deviations in the properties
		to do different things on different guiObjects.
		
		class:inherit(string className, array thingsToInherit)
			className: name of the class to inherit from
			thingsToInherit: an array containing keys to dictionaries in the parent class
			
			Example:
				abstr2ctUI.createClass("button", {
					children = {
						UIStroke = {
							Thickness = 2
						}
					}
				})
			
				newClass:inherit("button", {"children"})
			this will only take the children from the class 'button' and apply it onto the guiObject
			attached to newClass
			
global values
	properties
		GuiObject guiObject
		the guiObject attached to the class
		
	events
		function onApplication
		an event that is fired when the class has been fully applied
		
		function onInherit
		an event that is fired when :inherit is called on the class
		
misc notes
	-classes can be accessed via abstr2ctUI.classes
	-there is a util module that currently only contains 1 function, util.tableCopy()
	this can be accessed via abstr2ctUI.util
	- i know that roact is probably better in every single usecase, but i made this for myself
	and thought i might publish it.
]]
Tutorial

First insert the module into ReplicatedStorage or wherever you feel like it.
Obviously then we require the module.

local abstr2ctUI = require(game.ReplicatedStorage.abstr2ctUI)

Now we can’t do anything quite yet, so we need to create a class using abstr2ctUI.createClass(), let’s call the class reallyAwesomeFrame

local abstr2ctUI = require(game.ReplicatedStorage.abstr2ctUI)
absctr2ctUI.createClass("reallyAwesomeFrame")

end

This class doesn’t contain any style or functionality, so lets back the background darker, add a UICorner to it, and make it print something when the player’s mouse enters the frame.

abstr2ctUI.createClass("reallyAwesomeFrame", {
	properties = {
		BackgroundColor3 = Color3.fromRGB(75,75,75)
	}; children = {
		UICorner = {
			CornerRadius = UDim.new(0,4)
		}
	};
	events = {
		MouseEnter = function(guiObject)
			print("Mouse entered ", guiObject, "!")
		end,
	}
})

createClass has 2 parameters className and defaults
defaults that contain any combination of 3 separate dictionaries, properties, children and events

properties = { 
		--Key is the property name, Value is the property's, well, value.
		BackgroundColor3 = Color3.fromRGB(75,75,75)
};

If a key is not a valid property in the GuiObject that the class is applied to, it will still save to the properties dictionary for further use.

children = {
		-- Key is the instance's class and the Value is a dictionary of properties.
		UICorner = {
			CornerRadius = UDim.new(0,4)
		}
	};

If the key is an instance that does not exist, an error will throw.

events = {
		-- Key = you get the idea now
		MouseEnter = function(guiObject)
			print("Mouse entered ", guiObject, "!")
		end,
	}
})

If a key is not a valid connection in the GuiObject that the class is applied to, it will still save to the events dictionary for further use
additionally, if a key is equal to onApplication it will be called when the class is fully applied to the GuiObject and if a key is equal to onInherit it will be called when :inherit() is called, but we’ll get to that later.

Now that we have created our class, we have to apply it to a GuiObject. Create a frame in StarterGui that looks something like this:
image
Then, call abstr2ctUI.applyClass() to it

abstr2ctUI.applyClass("reallyAwesomeFrame", script.Parent.reallyAwesomeFrame)

abstr2ctUI.applyClass() has 3 parameters, className, guiObject, and deviations
Both className and guiObject are pretty simple, but `deviations deserves an explanation.

Deviations allow you to modify any property, event, or child of a class, and only for whatever GuiObject you apply it to. Because of this applyClass returns newClass which is essentially a copy of the class you used but with the deviations apply. Even if there are no deviations it will still return newClass

Let’s use deviations to change the color from 75,75,75 to 255,0,0

abstr2ctUI.applyClass("reallyAwesomeFrame", script.Parent.reallyAwesomeFrame, {
   properties = {
      BackgroundColor3 = Color3.fromRGB(255,0,0)
   }
})

Lastly, newClass has 1 method, :inherit(). It has 2 parameters className and thingsToInherit
className is the name of the class to inherit from, and thingsToInherit is a dictionary of well, things yo inherit
Let’s say we have 2 classes, closeButton and openButton. closeButton has a UICorner in it’s children and openButton does not, we can call :inherit("closeButton", {"children"}) to grab the UICorner from the class closeButton

abstr2ctUI.applyClass("openButton", script.Parent.open, {
	properties = {
		frameToOPen = script.Parent.reallyAwesomeFrame
	}
}):inherit("closeButton", {"children"})

That’s about it, have fun using :heart:
If you have any bugs, feedback, or questions make sure to let me know.

1 Like

This is really awesome and the documentation is well put and clear, but … really? This is the fifth UI library I’ve seen on here and I dont understand why more are being made.

I wont say much because I haven’t tried this yet and this is probably your personal UI library you want to share which I fully respect.

But there isn’t alot this offers over something like Roact but im sure this will find use.

Yep, spot on guess. This was a personal UI library that I thought I might post. The reason its extremely bare bones is because the main goal was to be a UI library in <100 lines because I saw Roact and said to myself “I don’t need this much, stuff”. As for the amount amount of UI libraries, no clue to be honest.

I was kind of hoping for it to be more of a ‘expand-it-yourself’ type thing but I might have to do more to make that easier.

2 Likes

Oh I see where you were coming from. Roact is pretty hefty and I can see myself expanding on this easily. Ill definitely try it out!

1 Like

This looks cool, I have one irrelevant question though: How did you make the text that is used in the header?

Text to ASCII Art Generator (TAAG) using the font ‘Big Money-nw’. Then I just used a photo editor to make it into an image.

Thank you very much for the quick response!

I’m not seeing the font you’re referencing, however.

Text to ASCII Art Generator (TAAG) Should be it.

Nevermind, I got it. Thanks so much for your time!

1 Like