Hello, I noticed that a lot of developers struggle to compete with modern UI standards or certain UI styles, especially slick themes, glass architecture, interactive UI, etc. This is why here at Starlight Solutions, Inc. we decided to release a framework to make it easier for developers to have a variation of interactive & customizable UI presets. We may update this in the feature as it does not have many features yet, but here is the current module.
--[[
⠀⠀⠀⢸⣦⡀⠀⠀⠀⠀⢀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⢸⣏⠻⣶⣤⡶⢾⡿⠁⠀⢠⣄⡀⢀⣴⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⣀⣼⠷⠀⠀⠁⢀⣿⠃⠀⠀⢀⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠴⣾⣯⣅⣀⠀⠀⠀⠈⢻⣦⡀⠒⠻⠿⣿⡿⠿⠓⠂⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠉⢻⡇⣤⣾⣿⣷⣿⣿⣤⠀⠀⣿⠁⠀⠀⠀⢀⣴⣿⣿⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠸⣿⡿⠏⠀⢀⠀⠀⠿⣶⣤⣤⣤⣄⣀⣴⣿⡿⢻⣿⡆⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠟⠁⠀⢀⣼⠀⠀⠀⠹⣿⣟⠿⠿⠿⡿⠋⠀⠘⣿⣇⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⢳⣶⣶⣿⣿⣇⣀⠀⠀⠙⣿⣆⠀⠀⠀⠀⠀⠀⠛⠿⣿⣦⣤⣀⠀⠀
⠀⠀⠀⠀⠀⠀⣹⣿⣿⣿⣿⠿⠋⠁⠀⣹⣿⠳⠀⠀⠀⠀⠀⠀⢀⣠⣽⣿⡿⠟⠃
⠀⠀⠀⠀⠀⢰⠿⠛⠻⢿⡇⠀⠀⠀⣰⣿⠏⠀⠀⢀⠀⠀⠀⣾⣿⠟⠋⠁⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠀⠀⣰⣿⣿⣾⣿⠿⢿⣷⣀⢀⣿⡇⠁⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠉⠁⠀⠀⠀⠀⠙⢿⣿⣿⠇⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀
Starlight Solutions, Inc.
Project: Stargaze UI
Author: festiveicing (@SirJolly)
]]
local ColorTable = {}
ColorTable.HexVals = {
"#121212",
"#1A1A1A",
"#03000D",
}
ColorTable.States = {}
ColorTable.Lighting = {}
ColorTable.Effects = {}
local BLACK = Color3.new()
local WHITE = Color3.new(1, 1, 1)
local function Clamp(Value)
if typeof(Value) ~= "number" then
error(("Expected number, got %s."):format(typeof(Value)), 3)
end
return math.clamp(Value, 0, 1)
end
local function NormalizeHex(Hex)
if typeof(Hex) ~= "string" then
error(("Expected hex string, got %s."):format(typeof(Hex)), 3)
end
local Value = Hex:gsub("^#", ""):upper()
if #Value == 3 then
Value = Value:gsub(".", "%1%1")
end
if #Value ~= 6 or not Value:match("^[%x]+$") then
error("Invalid hex color.", 3)
end
return "#" .. Value
end
local function ParseHex(Hex)
local Normalized = NormalizeHex(Hex)
local Value = Normalized:sub(2)
local R = tonumber(Value:sub(1, 2), 16)
local G = tonumber(Value:sub(3, 4), 16)
local B = tonumber(Value:sub(5, 6), 16)
if not R or not G or not B then
error("Failed to parse hex color.", 3)
end
return R, G, B
end
local function ResolveColor(Color)
local ColorType = typeof(Color)
if ColorType == "Color3" then
return Color
end
if ColorType == "string" then
return Color3.fromRGB(ParseHex(Color))
end
error(("Expected Color3 or hex string, got %s."):format(ColorType), 3)
end
local function ToByte(Value)
return math.clamp(math.round(Value * 255), 0, 255)
end
local function ToChannel(Value)
if typeof(Value) ~= "number" then
error(("Expected number, got %s."):format(typeof(Value)), 3)
end
return math.clamp(math.round(Value), 0, 255)
end
for Index, Hex in ipairs(ColorTable.HexVals) do
ColorTable.HexVals[Index] = NormalizeHex(Hex)
end
function ColorTable.IsHex(Hex)
local Success = pcall(NormalizeHex, Hex)
return Success
end
function ColorTable.NormalizeHex(Hex)
return NormalizeHex(Hex)
end
function ColorTable.Resolve(Color)
return ResolveColor(Color)
end
function ColorTable.FromRGB(R, G, B)
return Color3.fromRGB(
ToChannel(R),
ToChannel(G),
ToChannel(B)
)
end
function ColorTable.ToRGB(Color)
if typeof(Color) == "Color3" then
return ToByte(Color.R), ToByte(Color.G), ToByte(Color.B)
end
return ParseHex(Color)
end
function ColorTable.ToColor3(Color)
return ResolveColor(Color)
end
function ColorTable.ToHex(Color)
if typeof(Color) == "string" then
return NormalizeHex(Color)
end
local Resolved = ResolveColor(Color)
return string.format(
"#%02X%02X%02X",
ToByte(Resolved.R),
ToByte(Resolved.G),
ToByte(Resolved.B)
)
end
function ColorTable.Blend(ColorA, ColorB, Alpha)
return ResolveColor(ColorA):Lerp(ResolveColor(ColorB), Clamp(Alpha))
end
function ColorTable.Tint(Color, Tint, Alpha)
return ResolveColor(Color):Lerp(ResolveColor(Tint), Clamp(Alpha))
end
function ColorTable.Lighten(Color, Amount)
return ResolveColor(Color):Lerp(WHITE, Clamp(Amount))
end
function ColorTable.Darken(Color, Amount)
return ResolveColor(Color):Lerp(BLACK, Clamp(Amount))
end
function ColorTable.Desaturate(Color, Amount)
local H, S, V = ResolveColor(Color):ToHSV()
return Color3.fromHSV(H, Clamp(S * (1 - Amount)), V)
end
function ColorTable.Saturate(Color, Amount)
local H, S, V = ResolveColor(Color):ToHSV()
return Color3.fromHSV(H, Clamp(S * (1 + Amount)), V)
end
function ColorTable.ShiftHue(Color, Degrees)
if typeof(Degrees) ~= "number" then
error(("Expected number, got %s."):format(typeof(Degrees)), 2)
end
local H, S, V = ResolveColor(Color):ToHSV()
H = (H + (Degrees / 360)) % 1
return Color3.fromHSV(H, S, V)
end
function ColorTable.WithOpacity(Color, Opacity)
return {
Color = ResolveColor(Color),
Transparency = 1 - Clamp(Opacity),
}
end
function ColorTable.States.Default(Color)
return ResolveColor(Color)
end
function ColorTable.States.Hover(Color)
return ColorTable.Lighten(
ColorTable.Desaturate(Color, 0.08),
0.05
)
end
function ColorTable.States.Active(Color)
return ColorTable.Lighten(Color, 0.10)
end
function ColorTable.States.Pressed(Color)
return ColorTable.Darken(Color, 0.12)
end
function ColorTable.States.Selected(Color)
return ColorTable.Tint(Color, WHITE, 0.08)
end
function ColorTable.States.Focus(Color)
return ColorTable.Lighten(
ColorTable.Saturate(Color, 0.05),
0.08
)
end
function ColorTable.States.Disabled(Color)
return ColorTable.Desaturate(
ColorTable.Darken(Color, 0.30),
0.80
)
end
function ColorTable.States.Drag(Color)
return ColorTable.Lighten(
ColorTable.Saturate(Color, 0.08),
0.12
)
end
function ColorTable.States.DropTarget(Color)
return ColorTable.Tint(
Color,
Color3.fromRGB(96, 174, 255),
0.15
)
end
function ColorTable.States.Success(Color)
return ColorTable.Tint(
Color,
Color3.fromRGB(90, 220, 120),
0.12
)
end
function ColorTable.States.Warning(Color)
return ColorTable.Tint(
Color,
Color3.fromRGB(255, 196, 64),
0.15
)
end
function ColorTable.States.Error(Color)
return ColorTable.Tint(
Color,
Color3.fromRGB(255, 92, 92),
0.18
)
end
function ColorTable.Lighting.Glow(Color)
local H, S, V = ResolveColor(Color):ToHSV()
return Color3.fromHSV(
H,
Clamp(S * 0.85),
Clamp(V * 1.15)
)
end
function ColorTable.Lighting.Highlight(Color)
return ColorTable.Tint(Color, WHITE, 0.12)
end
function ColorTable.Lighting.Shadow(Color)
return ColorTable.Darken(Color, 0.25)
end
function ColorTable.Lighting.Overlay(Color)
return ColorTable.Tint(Color, WHITE, 0.08)
end
function ColorTable.Lighting.Backdrop(Color)
return ColorTable.Desaturate(
ColorTable.Darken(Color, 0.15),
0.20
)
end
function ColorTable.Effects.Surface(Color)
return ColorTable.Desaturate(Color, 0.12)
end
function ColorTable.Effects.Muted(Color)
return ColorTable.Desaturate(Color, 0.35)
end
function ColorTable.Effects.Elevated(Color)
return ColorTable.Lighten(Color, 0.04)
end
function ColorTable.Effects.Recessed(Color)
return ColorTable.Darken(Color, 0.08)
end
function ColorTable.Effects.Border(Color)
return ColorTable.Lighten(
ColorTable.Desaturate(Color, 0.10),
0.10
)
end
function ColorTable.Effects.Accent(Color)
return ColorTable.Saturate(
ColorTable.Lighten(Color, 0.03),
0.08
)
end
function ColorTable.Effects.Glass(Color)
return {
Color = ColorTable.Desaturate(Color, 0.45),
Transparency = 0.35,
}
end
return ColorTable