-- [Credits]: www.flaticon.com [For the notification icons] --
-- SERVICES --
local RS = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local TS = game:GetService("TweenService")
local Remotes = RS.Remotes
-- EVENTS --
local Notification_RE = Remotes.Notification_RE
local Notification_BE = Remotes.Notification_BE
local function buttonHoverFX(Button)
local Data = {
Size = Button.Size,
HoverSize = UDim2.fromScale(Button.Size.X.Scale * 1.1, Button.Size.Y.Scale * 1.1),
ClickSize = UDim2.fromScale(Button.Size.X.Scale * 0.95, Button.Size.Y.Scale * 0.95),
State = false
}
Button.MouseEnter:Connect(function()
Data.State = true
Button:TweenSize(Data.HoverSize, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.175, true)
end)
Button.MouseLeave:Connect(function()
Data.State = false
Button:TweenSize(Data.Size, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.175, true)
end)
Button.MouseButton1Click:Connect(function()
Button:TweenSize(Data.ClickSize, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.175, true, function()
if Data.State == true then
Button:TweenSize(Data.HoverSize, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.175, true)
else
Button:TweenSize(Data.Size, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.175, true)
end
end)
end)
end
local module = {}
module.__index = module
local Bubble_Task = nil
function module.Init()
local self = setmetatable({}, module)
self.Screen_Gui = script.Notifications:Clone()
self.Screen_Gui.Enabled = true
self.Screen_Gui.Parent = Players.LocalPlayer:WaitForChild("PlayerGui")
self.State = true
self.Debounce = false
self.Active_Outer = {}
self.Active_Notifications = {}
self.Amount = 0
self.Outer_Timeout = 5
local Frame = self.Screen_Gui.Frame
Frame.Visible = true
self:Toggle_Frame()
buttonHoverFX(Frame.Icon)
buttonHoverFX(Frame.Header.Close)
buttonHoverFX(Frame.List.Template)
Frame.Icon.MouseButton1Click:Connect(function()
self:Toggle_Frame()
end)
Frame.Header.Close.MouseButton1Click:Connect(function()
self:Toggle_Frame()
end)
Notification_BE.Event:Connect(function(Notification_Data : {Text : string?, Type : string?, Custom_ID : string?})
if not Notification_Data then return end
self:Notify(Notification_Data)
end)
Notification_RE.OnClientEvent:Connect(function(Notification_Data : {Text : string?, Type : string?, Custom_ID : string?})
if not Notification_Data then return end
self:Notify(Notification_Data)
end)
return self
end
function module:Toggle_Frame()
if self.Debounce then return end
self.Debounce = true
local Frame = self.Screen_Gui.Frame
if self.State then
self.State = false
-- Close Anim
TS:Create(Frame.BG, TweenInfo.new(0.35, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {
BackgroundTransparency = 1
}):Play()
TS:Create(Frame.UICorner, TweenInfo.new(0.35), {
CornerRadius = UDim.new(1, 0)
}):Play()
Frame.Header.Visible = false
self.Screen_Gui.Outer_List.Visible = true
task.spawn(function()
for _, Slot in ipairs(Frame.List:GetChildren()) do
if not Slot:IsA("TextButton") then continue end
if Slot.Name == "Template" then continue end
Slot:TweenSize(UDim2.fromScale(0, 0), Enum.EasingDirection.In, Enum.EasingStyle.Back, 0.35, true)
end
Frame.List.Visible = false
end)
Frame:TweenSize(Frame:GetAttribute("Hidden_Size"), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.35, true)
task.delay(0.35, function()
if self.Amount >= 1 then
Frame.Bubble.Size = UDim2.fromScale(0, 0)
Frame.Bubble.Visible = true
Frame.Bubble:TweenSize(UDim2.fromScale(0.57, 0.57), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.35, true)
end
Frame.Icon.Size = UDim2.fromScale(0, 0)
Frame.Icon.Visible = true
Frame.Icon:TweenSize(UDim2.fromScale(0.6, 0.6), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.35, true)
task.wait(0.35)
self.Debounce = false
end)
else
self.State = true
-- Open Anim
Frame.Icon.Visible = false
Frame.Bubble.Visible = false
Frame:TweenSize(Frame:GetAttribute("Expanded_Size"), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.35, true)
TS:Create(Frame.UICorner, TweenInfo.new(0.35), {
CornerRadius = UDim.new(0.03, 0)
}):Play()
task.spawn(function()
for ID, Outer_Slot in pairs(self.Active_Outer) do
self.Active_Outer[ID] = nil
Outer_Slot:TweenSize(UDim2.fromScale(0, 0), Enum.EasingDirection.In, Enum.EasingStyle.Back, 0.35, true)
task.delay(0.35, function()
Outer_Slot:Destroy()
end)
end
self.Screen_Gui.Outer_List.Visible = false
end)
task.delay(0.35, function()
TS:Create(Frame.BG, TweenInfo.new(0.35, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {
BackgroundTransparency = 0
}):Play()
Frame.Header.Visible = true
Frame.List.Visible = true
task.spawn(function()
for _, Slot in ipairs(Frame.List:GetChildren()) do
if not Slot:IsA("TextButton") then continue end
if Slot.Name == "Template" then continue end
Slot:TweenSize(Frame.List.Template.Size, Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.35, true)
end
self.Debounce = false
end)
end)
end
end
function module:Outer_Notify(Notification_Data)
if not Notification_Data then return end
local List = self.Screen_Gui.Outer_List
local Notification_Slot = List.Template:Clone()
Notification_Slot.Name = tostring(Notification_Data.ID)
Notification_Slot.Icon.Image = self.Type_Dictionary[Notification_Data.Type]
Notification_Slot.TextLabel.Text = Notification_Data.Text
Notification_Slot.Size = UDim2.fromScale(0, 0)
Notification_Slot.LayoutOrder = Notification_Data.ID
Notification_Slot.Timing.Size = UDim2.fromScale(0, 1)
Notification_Slot.Visible = true
Notification_Slot.Parent = List
Notification_Slot:TweenSize(List.Template.Size, Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.35, true)
-- EVENT HANDLING --
Notification_Slot.MouseEnter:Connect(function()
Notification_Slot.Dismiss.Visible = true
end)
Notification_Slot.MouseLeave:Connect(function()
Notification_Slot.Dismiss.Visible = false
end)
Notification_Slot.MouseButton1Click:Connect(function()
self:Dismiss(Notification_Data.ID)
end)
self.Active_Outer[Notification_Data.ID] = Notification_Slot
Notification_Slot.Timing:TweenSize(UDim2.fromScale(1, 1), Enum.EasingDirection.In, Enum.EasingStyle.Linear, self.Outer_Timeout, true, function()
if not Notification_Slot then return end
self.Active_Outer[Notification_Data.ID] = nil
Notification_Slot:TweenSize(UDim2.fromScale(0, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.35, true, function()
Notification_Slot:Destroy()
end)
end)
end
function module:Notify(Data : {
Text : string?,
Type : string?,
Custom_ID : string?
})
local Notification_Data = {
Text = Data.Text or "Text has not been provided.",
Type = Data.Type or "Normal",
ID = next(self.Active_Notifications) and #self.Active_Notifications + 1 or 1
}
self.Type_Dictionary = {
["Normal"] = "rbxassetid://12884354993",
["Error"] = "rbxassetid://12897714117",
["Warning"] = "rbxassetid://12897730803",
["Award"] = "rbxassetid://12897682557",
["Tip"] = "rbxassetid://12897696888",
["Died"] = "rbxassetid://12897762812",
["Custom"] = Data.Custom_ID or "rbxassetid://12884354993"
}
if not self.Type_Dictionary[Notification_Data.Type] then return end
if self.State == false then self:Outer_Notify(Notification_Data) end
local Frame = self.Screen_Gui.Frame
local List = Frame.List
local Notification_Slot = List.Template:Clone()
Notification_Slot.Name = tostring(Notification_Data.ID)
Notification_Slot.Icon.Image = self.Type_Dictionary[Notification_Data.Type]
Notification_Slot.TextLabel.Text = Notification_Data.Text
Notification_Slot.Size = UDim2.fromScale(0, 0)
Notification_Slot.LayoutOrder = -Notification_Data.ID
Notification_Slot.Visible = true
Notification_Slot.Parent = List
Notification_Slot:TweenSize(List.Template.Size, Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.35)
-- EVENT HANDLING --
Notification_Slot.MouseEnter:Connect(function()
Notification_Slot.Dismiss.Visible = true
end)
Notification_Slot.MouseLeave:Connect(function()
Notification_Slot.Dismiss.Visible = false
end)
Notification_Slot.MouseButton1Click:Connect(function()
self:Dismiss(Notification_Data.ID)
end)
self.Active_Notifications[Notification_Data.ID] = Notification_Slot
self.Amount += 1
self:Update_Bubble()
end
function module:Update_Bubble()
local Frame = self.Screen_Gui.Frame
local Bubble = Frame.Bubble
local Amount_Text = Bubble.TextLabel
if Bubble_Task ~= nil then task.cancel(Bubble_Task) Bubble_Task = nil end
if self.Amount >= 1 then
if self.State == false then
if Bubble.Visible then
Bubble:TweenSize(UDim2.fromScale(0.65, 0.65), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.15, true, function()
Bubble:TweenSize(UDim2.fromScale(0.57, 0.57), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.1, true)
end)
else
Bubble.Visible = true
Bubble:TweenSize(UDim2.fromScale(0.57, 0.57), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.25, true)
end
end
Amount_Text.Text = tostring(self.Amount)
else
if self.State == false then
if Bubble.Visible then
Bubble:TweenSize(UDim2.fromScale(0, 0), Enum.EasingDirection.In, Enum.EasingStyle.Back, 0.35, true)
Bubble_Task = task.delay(0.35, function()
if not Bubble.Visible then return end
Bubble.Visible = false
end)
end
end
Amount_Text.Text = tostring(self.Amount)
end
end
function module:Dismiss(ID)
if not self.Active_Notifications[ID] then return end
local Slot = self.Active_Notifications[ID]
self.Active_Notifications[ID] = nil
if self.Amount >= 1 then
self.Amount -= 1
end
if self.Active_Outer[ID] ~= nil then
local Outer_Slot = self.Active_Outer[ID]
self.Active_Outer[ID] = nil
Outer_Slot:TweenSize(UDim2.fromScale(0, 0), Enum.EasingDirection.In, Enum.EasingStyle.Back, 0.35, true)
task.delay(0.35, function()
Outer_Slot:Destroy()
end)
end
Slot:TweenSize(UDim2.fromScale(0, 0), Enum.EasingDirection.In, Enum.EasingStyle.Back, 0.35, true)
task.delay(0.35, function()
Slot:Destroy()
self:Update_Bubble()
end)
end
return module
Here you go fixed the bugs for you and the methods work now
Very nice system though.