From 3107b1b21b22b66329f02bfc68eeac4f89a2d46c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 8 Mar 2020 18:32:42 -0700 Subject: [PATCH] Dynamic theming. Closes #241. Upgrades to Roact master and introduces dynamic theme switching. We branch on the theme name in order to try to use Rojo's brand colors instead of Studio's. I kind of winged it with these colors and we might want to choose slightly nicer dark theme colors in the future. I also took the opportunity to reorganize the color naming scheme since it didn't really work for dark theme. --- plugin/modules/roact | 2 +- plugin/src/Components/App.lua | 9 +- plugin/src/Components/ConnectPanel.lua | 220 +++++++++--------- plugin/src/Components/ConnectingPanel.lua | 37 +-- .../src/Components/ConnectionActivePanel.lua | 53 ++--- plugin/src/Components/ErrorPanel.lua | 89 +++---- plugin/src/Components/FormButton.lua | 74 +++--- plugin/src/Components/FormTextInput.lua | 80 +++---- plugin/src/Components/Panel.lua | 32 +-- plugin/src/Components/RojoFooter.lua | 85 +++---- plugin/src/Components/Theme.lua | 104 +++++++++ plugin/src/Theme.lua | 14 -- plugin/src/init.server.lua | 2 +- 13 files changed, 455 insertions(+), 346 deletions(-) create mode 100644 plugin/src/Components/Theme.lua delete mode 100644 plugin/src/Theme.lua diff --git a/plugin/modules/roact b/plugin/modules/roact index b1db3f82..f7d2f1ce 160000 --- a/plugin/modules/roact +++ b/plugin/modules/roact @@ -1 +1 @@ -Subproject commit b1db3f82a2510c4e5e5b2bdc2c47298ea02dabd8 +Subproject commit f7d2f1ce1dd69120f457c2f8032bb184eb8f0c29 diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 9fbb3c0a..3617b2fd 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -13,6 +13,7 @@ local Version = require(Plugin.Version) local preloadAssets = require(Plugin.preloadAssets) local strict = require(Plugin.strict) +local Theme = require(Plugin.Components.Theme) local ConnectPanel = require(Plugin.Components.ConnectPanel) local ConnectingPanel = require(Plugin.Components.ConnectingPanel) local ConnectionActivePanel = require(Plugin.Components.ConnectionActivePanel) @@ -199,9 +200,11 @@ function App:render() } end - return Roact.createElement(Roact.Portal, { - target = self.dockWidget, - }, children) + return Roact.createElement(Theme.StudioProvider, nil, { + UI = Roact.createElement(Roact.Portal, { + target = self.dockWidget, + }, children), + }) end function App:didMount() diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index 8dd092d1..7c89efe4 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -4,8 +4,8 @@ local Plugin = Rojo.Plugin local Roact = require(Rojo.Roact) local Config = require(Plugin.Config) -local Theme = require(Plugin.Theme) +local Theme = require(Plugin.Components.Theme) local Panel = require(Plugin.Components.Panel) local FitList = require(Plugin.Components.FitList) local FitText = require(Plugin.Components.FitText) @@ -26,136 +26,138 @@ end function ConnectPanel:render() local startSession = self.props.startSession - return e(Panel, nil, { - Layout = e("UIListLayout", { - SortOrder = Enum.SortOrder.LayoutOrder, - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - }), + return Theme.with(function(theme) + return e(Panel, nil, { + Layout = e("UIListLayout", { + SortOrder = Enum.SortOrder.LayoutOrder, + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + }), - Inputs = e(FitList, { - containerProps = { - BackgroundTransparency = 1, - LayoutOrder = 1, - }, - layoutProps = { - FillDirection = Enum.FillDirection.Horizontal, - Padding = UDim.new(0, 8), - }, - paddingProps = { - PaddingTop = UDim.new(0, 20), - PaddingBottom = UDim.new(0, 10), - PaddingLeft = UDim.new(0, 24), - PaddingRight = UDim.new(0, 24), - }, - }, { - Address = e(FitList, { + Inputs = e(FitList, { containerProps = { - LayoutOrder = 1, BackgroundTransparency = 1, + LayoutOrder = 1, }, layoutProps = { - Padding = UDim.new(0, 4), + FillDirection = Enum.FillDirection.Horizontal, + Padding = UDim.new(0, 8), + }, + paddingProps = { + PaddingTop = UDim.new(0, 20), + PaddingBottom = UDim.new(0, 10), + PaddingLeft = UDim.new(0, 24), + PaddingRight = UDim.new(0, 24), }, }, { - Label = e(FitText, { - Kind = "TextLabel", - LayoutOrder = 1, - BackgroundTransparency = 1, - TextXAlignment = Enum.TextXAlignment.Left, - Font = Theme.TitleFont, - TextSize = 20, - Text = "Address", - TextColor3 = Theme.PrimaryColor, + Address = e(FitList, { + containerProps = { + LayoutOrder = 1, + BackgroundTransparency = 1, + }, + layoutProps = { + Padding = UDim.new(0, 4), + }, + }, { + Label = e(FitText, { + Kind = "TextLabel", + LayoutOrder = 1, + BackgroundTransparency = 1, + TextXAlignment = Enum.TextXAlignment.Left, + Font = theme.TitleFont, + TextSize = 20, + Text = "Address", + TextColor3 = theme.Text1, + }), + + Input = e(FormTextInput, { + layoutOrder = 2, + width = UDim.new(0, 220), + value = self.state.address, + placeholderValue = Config.defaultHost, + onValueChange = function(newValue) + self:setState({ + address = newValue, + }) + end, + }), }), - Input = e(FormTextInput, { - layoutOrder = 2, - width = UDim.new(0, 220), - value = self.state.address, - placeholderValue = Config.defaultHost, - onValueChange = function(newValue) - self:setState({ - address = newValue, - }) - end, + Port = e(FitList, { + containerProps = { + LayoutOrder = 2, + BackgroundTransparency = 1, + }, + layoutProps = { + Padding = UDim.new(0, 4), + }, + }, { + Label = e(FitText, { + Kind = "TextLabel", + LayoutOrder = 1, + BackgroundTransparency = 1, + TextXAlignment = Enum.TextXAlignment.Left, + Font = theme.TitleFont, + TextSize = 20, + Text = "Port", + TextColor3 = theme.Text1, + }), + + Input = e(FormTextInput, { + layoutOrder = 2, + width = UDim.new(0, 80), + value = self.state.port, + placeholderValue = Config.defaultPort, + onValueChange = function(newValue) + self:setState({ + port = newValue, + }) + end, + }), }), }), - Port = e(FitList, { + Buttons = e(FitList, { + fitAxes = "Y", containerProps = { + BackgroundTransparency = 1, LayoutOrder = 2, - BackgroundTransparency = 1, + Size = UDim2.new(1, 0, 0, 0), }, layoutProps = { - Padding = UDim.new(0, 4), + FillDirection = Enum.FillDirection.Horizontal, + HorizontalAlignment = Enum.HorizontalAlignment.Right, + Padding = UDim.new(0, 8), + }, + paddingProps = { + PaddingTop = UDim.new(0, 0), + PaddingBottom = UDim.new(0, 20), + PaddingLeft = UDim.new(0, 24), + PaddingRight = UDim.new(0, 24), }, }, { - Label = e(FitText, { - Kind = "TextLabel", - LayoutOrder = 1, - BackgroundTransparency = 1, - TextXAlignment = Enum.TextXAlignment.Left, - Font = Theme.TitleFont, - TextSize = 20, - Text = "Port", - TextColor3 = Theme.PrimaryColor, - }), - - Input = e(FormTextInput, { + e(FormButton, { layoutOrder = 2, - width = UDim.new(0, 80), - value = self.state.port, - placeholderValue = Config.defaultPort, - onValueChange = function(newValue) - self:setState({ - port = newValue, - }) + text = "Connect", + onClick = function() + if startSession ~= nil then + local address = self.state.address + if address:len() == 0 then + address = Config.defaultHost + end + + local port = self.state.port + if port:len() == 0 then + port = Config.defaultPort + end + + startSession(address, port) + end end, }), }), - }), - - Buttons = e(FitList, { - fitAxes = "Y", - containerProps = { - BackgroundTransparency = 1, - LayoutOrder = 2, - Size = UDim2.new(1, 0, 0, 0), - }, - layoutProps = { - FillDirection = Enum.FillDirection.Horizontal, - HorizontalAlignment = Enum.HorizontalAlignment.Right, - Padding = UDim.new(0, 8), - }, - paddingProps = { - PaddingTop = UDim.new(0, 0), - PaddingBottom = UDim.new(0, 20), - PaddingLeft = UDim.new(0, 24), - PaddingRight = UDim.new(0, 24), - }, - }, { - e(FormButton, { - layoutOrder = 2, - text = "Connect", - onClick = function() - if startSession ~= nil then - local address = self.state.address - if address:len() == 0 then - address = Config.defaultHost - end - - local port = self.state.port - if port:len() == 0 then - port = Config.defaultPort - end - - startSession(address, port) - end - end, - }), - }), - }) + }) + end) end return ConnectPanel \ No newline at end of file diff --git a/plugin/src/Components/ConnectingPanel.lua b/plugin/src/Components/ConnectingPanel.lua index c28d6880..9dd0c126 100644 --- a/plugin/src/Components/ConnectingPanel.lua +++ b/plugin/src/Components/ConnectingPanel.lua @@ -2,8 +2,7 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) local Plugin = script:FindFirstAncestor("Plugin") -local Theme = require(Plugin.Theme) - +local Theme = require(Plugin.Components.Theme) local Panel = require(Plugin.Components.Panel) local FitText = require(Plugin.Components.FitText) @@ -12,23 +11,25 @@ local e = Roact.createElement local ConnectingPanel = Roact.Component:extend("ConnectingPanel") function ConnectingPanel:render() - return e(Panel, nil, { - Layout = Roact.createElement("UIListLayout", { - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 8), - }), + return Theme.with(function(theme) + return e(Panel, nil, { + Layout = Roact.createElement("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 8), + }), - Text = e(FitText, { - Padding = Vector2.new(12, 6), - Font = Theme.ButtonFont, - TextSize = 18, - Text = "Connecting...", - TextColor3 = Theme.PrimaryColor, - BackgroundTransparency = 1, - }), - }) + Text = e(FitText, { + Padding = Vector2.new(12, 6), + Font = theme.ButtonFont, + TextSize = 18, + Text = "Connecting...", + TextColor3 = theme.Text1, + BackgroundTransparency = 1, + }), + }) + end) end return ConnectingPanel \ No newline at end of file diff --git a/plugin/src/Components/ConnectionActivePanel.lua b/plugin/src/Components/ConnectionActivePanel.lua index 47cb1aa5..437589a9 100644 --- a/plugin/src/Components/ConnectionActivePanel.lua +++ b/plugin/src/Components/ConnectionActivePanel.lua @@ -2,8 +2,7 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) local Plugin = script:FindFirstAncestor("Plugin") -local Theme = require(Plugin.Theme) - +local Theme = require(Plugin.Components.Theme) local Panel = require(Plugin.Components.Panel) local FitText = require(Plugin.Components.FitText) local FormButton = require(Plugin.Components.FormButton) @@ -15,32 +14,34 @@ local ConnectionActivePanel = Roact.Component:extend("ConnectionActivePanel") function ConnectionActivePanel:render() local stopSession = self.props.stopSession - return e(Panel, nil, { - Layout = Roact.createElement("UIListLayout", { - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 8), - }), + return Theme.with(function(theme) + return e(Panel, nil, { + Layout = Roact.createElement("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 8), + }), - Text = e(FitText, { - Padding = Vector2.new(12, 6), - Font = Theme.ButtonFont, - TextSize = 18, - Text = "Connected to Live-Sync Server", - TextColor3 = Theme.PrimaryColor, - BackgroundTransparency = 1, - }), + Text = e(FitText, { + Padding = Vector2.new(12, 6), + Font = theme.ButtonFont, + TextSize = 18, + Text = "Connected to Live-Sync Server", + TextColor3 = theme.Text1, + BackgroundTransparency = 1, + }), - DisconnectButton = e(FormButton, { - layoutOrder = 2, - text = "Disconnect", - secondary = true, - onClick = function() - stopSession() - end, - }), - }) + DisconnectButton = e(FormButton, { + layoutOrder = 2, + text = "Disconnect", + secondary = true, + onClick = function() + stopSession() + end, + }), + }) + end) end return ConnectionActivePanel \ No newline at end of file diff --git a/plugin/src/Components/ErrorPanel.lua b/plugin/src/Components/ErrorPanel.lua index 97b16929..e541e0d8 100644 --- a/plugin/src/Components/ErrorPanel.lua +++ b/plugin/src/Components/ErrorPanel.lua @@ -2,8 +2,7 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) local Plugin = script:FindFirstAncestor("Plugin") -local Theme = require(Plugin.Theme) - +local Theme = require(Plugin.Components.Theme) local Panel = require(Plugin.Components.Panel) local FitText = require(Plugin.Components.FitText) local FitScrollingFrame = require(Plugin.Components.FitScrollingFrame) @@ -20,50 +19,52 @@ function ErrorPanel:render() local errorMessage = self.props.errorMessage local onDismiss = self.props.onDismiss - return e(Panel, nil, { - Layout = Roact.createElement("UIListLayout", { - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 8), - }), - - ErrorContainer = e(FitScrollingFrame, { - containerProps = { - BackgroundTransparency = 1, - BorderSizePixel = 0, - Size = UDim2.new(1, -HOR_PADDING * 2, 1, -BUTTON_HEIGHT), - Position = UDim2.new(0, HOR_PADDING, 0, 0), - ScrollBarImageColor3 = Theme.PrimaryColor, - VerticalScrollBarInset = Enum.ScrollBarInset.ScrollBar, - ScrollingDirection = Enum.ScrollingDirection.Y, - }, - }, { - Text = e(FitText, { - Size = UDim2.new(1, 0, 0, 0), - - LayoutOrder = 1, - TextXAlignment = Enum.TextXAlignment.Left, - TextYAlignment = Enum.TextYAlignment.Top, - FitAxis = "Y", - Font = Theme.ButtonFont, - TextSize = 18, - Text = errorMessage, - TextWrap = true, - TextColor3 = Theme.PrimaryColor, - BackgroundTransparency = 1, + return Theme.with(function(theme) + return e(Panel, nil, { + Layout = Roact.createElement("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 8), }), - }), - DismissButton = e(FormButton, { - layoutOrder = 2, - text = "Dismiss", - secondary = true, - onClick = function() - onDismiss() - end, - }), - }) + ErrorContainer = e(FitScrollingFrame, { + containerProps = { + BackgroundTransparency = 1, + BorderSizePixel = 0, + Size = UDim2.new(1, -HOR_PADDING * 2, 1, -BUTTON_HEIGHT), + Position = UDim2.new(0, HOR_PADDING, 0, 0), + ScrollBarImageColor3 = theme.Text1, + VerticalScrollBarInset = Enum.ScrollBarInset.ScrollBar, + ScrollingDirection = Enum.ScrollingDirection.Y, + }, + }, { + Text = e(FitText, { + Size = UDim2.new(1, 0, 0, 0), + + LayoutOrder = 1, + TextXAlignment = Enum.TextXAlignment.Left, + TextYAlignment = Enum.TextYAlignment.Top, + FitAxis = "Y", + Font = theme.ButtonFont, + TextSize = 18, + Text = errorMessage, + TextWrap = true, + TextColor3 = theme.Text1, + BackgroundTransparency = 1, + }), + }), + + DismissButton = e(FormButton, { + layoutOrder = 2, + text = "Dismiss", + secondary = true, + onClick = function() + onDismiss() + end, + }), + }) + end) end return ErrorPanel \ No newline at end of file diff --git a/plugin/src/Components/FormButton.lua b/plugin/src/Components/FormButton.lua index 94ffba5e..7451395a 100644 --- a/plugin/src/Components/FormButton.lua +++ b/plugin/src/Components/FormButton.lua @@ -4,7 +4,7 @@ local Plugin = Rojo.Plugin local Roact = require(Rojo.Roact) local Assets = require(Plugin.Assets) -local Theme = require(Plugin.Theme) +local Theme = require(Plugin.Components.Theme) local FitList = require(Plugin.Components.FitList) local FitText = require(Plugin.Components.FitText) @@ -20,43 +20,45 @@ local function FormButton(props) local textColor local backgroundColor - if props.secondary then - textColor = Theme.AccentColor - backgroundColor = Theme.SecondaryColor - else - textColor = Theme.SecondaryColor - backgroundColor = Theme.AccentColor - end + return Theme.with(function(theme) + if props.secondary then + textColor = theme.Brand1 + backgroundColor = theme.Background2 + else + textColor = theme.TextOnAccent + backgroundColor = theme.Brand1 + end - return e(FitList, { - containerKind = "ImageButton", - containerProps = { - LayoutOrder = layoutOrder, - BackgroundTransparency = 1, - Image = RoundBox.asset, - ImageRectOffset = RoundBox.offset, - ImageRectSize = RoundBox.size, - SliceCenter = RoundBox.center, - ScaleType = Enum.ScaleType.Slice, - ImageColor3 = backgroundColor, + return e(FitList, { + containerKind = "ImageButton", + containerProps = { + LayoutOrder = layoutOrder, + BackgroundTransparency = 1, + Image = RoundBox.asset, + ImageRectOffset = RoundBox.offset, + ImageRectSize = RoundBox.size, + SliceCenter = RoundBox.center, + ScaleType = Enum.ScaleType.Slice, + ImageColor3 = backgroundColor, - [Roact.Event.Activated] = function() - if onClick ~= nil then - onClick() - end - end, - }, - }, { - Text = e(FitText, { - Kind = "TextLabel", - Text = text, - TextSize = 18, - TextColor3 = textColor, - Font = Theme.ButtonFont, - Padding = Vector2.new(16, 8), - BackgroundTransparency = 1, - }), - }) + [Roact.Event.Activated] = function() + if onClick ~= nil then + onClick() + end + end, + }, + }, { + Text = e(FitText, { + Kind = "TextLabel", + Text = text, + TextSize = 18, + TextColor3 = textColor, + Font = theme.ButtonFont, + Padding = Vector2.new(16, 8), + BackgroundTransparency = 1, + }), + }) + end) end return FormButton \ No newline at end of file diff --git a/plugin/src/Components/FormTextInput.lua b/plugin/src/Components/FormTextInput.lua index 22748c4b..f1f4625f 100644 --- a/plugin/src/Components/FormTextInput.lua +++ b/plugin/src/Components/FormTextInput.lua @@ -4,7 +4,7 @@ local Plugin = Rojo.Plugin local Roact = require(Rojo.Roact) local Assets = require(Plugin.Assets) -local Theme = require(Plugin.Theme) +local Theme = require(Plugin.Components.Theme) local e = Roact.createElement @@ -35,46 +35,48 @@ function FormTextInput:render() shownPlaceholder = placeholderValue end - return e("ImageLabel", { - LayoutOrder = layoutOrder, - Image = RoundBox.asset, - ImageRectOffset = RoundBox.offset, - ImageRectSize = RoundBox.size, - ScaleType = Enum.ScaleType.Slice, - SliceCenter = RoundBox.center, - ImageColor3 = Theme.SecondaryColor, - Size = UDim2.new(width.Scale, width.Offset, 0, TEXT_SIZE + PADDING * 2), - BackgroundTransparency = 1, - }, { - InputInner = e("TextBox", { + return Theme.with(function(theme) + return e("ImageLabel", { + LayoutOrder = layoutOrder, + Image = RoundBox.asset, + ImageRectOffset = RoundBox.offset, + ImageRectSize = RoundBox.size, + ScaleType = Enum.ScaleType.Slice, + SliceCenter = RoundBox.center, + ImageColor3 = theme.Background2, + Size = UDim2.new(width.Scale, width.Offset, 0, TEXT_SIZE + PADDING * 2), BackgroundTransparency = 1, - Size = UDim2.new(1, -PADDING * 2, 1, -PADDING * 2), - Position = UDim2.new(0.5, 0, 0.5, 0), - AnchorPoint = Vector2.new(0.5, 0.5), - Font = Theme.InputFont, - ClearTextOnFocus = false, - TextXAlignment = Enum.TextXAlignment.Center, - TextSize = TEXT_SIZE, - Text = value, - PlaceholderText = shownPlaceholder, - PlaceholderColor3 = Theme.LightTextColor, - TextColor3 = Theme.PrimaryColor, + }, { + InputInner = e("TextBox", { + BackgroundTransparency = 1, + Size = UDim2.new(1, -PADDING * 2, 1, -PADDING * 2), + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + Font = theme.InputFont, + ClearTextOnFocus = false, + TextXAlignment = Enum.TextXAlignment.Center, + TextSize = TEXT_SIZE, + Text = value, + PlaceholderText = shownPlaceholder, + PlaceholderColor3 = theme.Text2, + TextColor3 = theme.Text1, - [Roact.Change.Text] = function(rbx) - onValueChange(rbx.Text) - end, - [Roact.Event.Focused] = function() - self:setState({ - focused = true, - }) - end, - [Roact.Event.FocusLost] = function() - self:setState({ - focused = false, - }) - end, - }), - }) + [Roact.Change.Text] = function(rbx) + onValueChange(rbx.Text) + end, + [Roact.Event.Focused] = function() + self:setState({ + focused = true, + }) + end, + [Roact.Event.FocusLost] = function() + self:setState({ + focused = false, + }) + end, + }), + }) + end) end return FormTextInput \ No newline at end of file diff --git a/plugin/src/Components/Panel.lua b/plugin/src/Components/Panel.lua index 5ae1e874..9a19ecfc 100644 --- a/plugin/src/Components/Panel.lua +++ b/plugin/src/Components/Panel.lua @@ -3,6 +3,7 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) local Plugin = script:FindFirstAncestor("Plugin") local RojoFooter = require(Plugin.Components.RojoFooter) +local Theme = require(Plugin.Components.Theme) local e = Roact.createElement @@ -13,22 +14,25 @@ function Panel:init() end function Panel:render() - return e("Frame", { - Size = UDim2.new(1, 0, 1, 0), - BackgroundTransparency = 1, - }, { - Layout = Roact.createElement("UIListLayout", { - HorizontalAlignment = Enum.HorizontalAlignment.Center, - SortOrder = Enum.SortOrder.LayoutOrder, - }), - - Body = e("Frame", { - Size = UDim2.new(0, 360, 1, -32), + return Theme.with(function(theme) + return e("Frame", { + Size = UDim2.new(1, 0, 1, 0), BackgroundTransparency = 1, - }, self.props[Roact.Children]), + }, { + Layout = Roact.createElement("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + }), - Footer = e(RojoFooter), - }) + Body = e("Frame", { + Size = UDim2.new(0, 360, 1, -32), + BackgroundColor3 = theme.Background1, + BorderSizePixel = 0, + }, self.props[Roact.Children]), + + Footer = e(RojoFooter), + }) + end) end return Panel \ No newline at end of file diff --git a/plugin/src/Components/RojoFooter.lua b/plugin/src/Components/RojoFooter.lua index babc1a78..3a32c610 100644 --- a/plugin/src/Components/RojoFooter.lua +++ b/plugin/src/Components/RojoFooter.lua @@ -6,7 +6,7 @@ local Roact = require(Rojo.Roact) local Config = require(Plugin.Config) local Version = require(Plugin.Version) local Assets = require(Plugin.Assets) -local Theme = require(Plugin.Theme) +local Theme = require(Plugin.Components.Theme) local e = Roact.createElement @@ -18,50 +18,53 @@ function RojoFooter:init() end function RojoFooter:render() - return e("Frame", { - LayoutOrder = 3, - Size = UDim2.new(1, 0, 0, 32), - BackgroundColor3 = Theme.SecondaryColor, - BorderSizePixel = 0, - }, { - Padding = e("UIPadding", { - PaddingTop = UDim.new(0, 4), - PaddingBottom = UDim.new(0, 4), - PaddingLeft = UDim.new(0, 8), - PaddingRight = UDim.new(0, 8), - }), - - LogoContainer = e("Frame", { - BackgroundTransparency = 1, - - Size = UDim2.new(0, 0, 0, 32), + return Theme.with(function(theme) + return e("Frame", { + LayoutOrder = 3, + Size = UDim2.new(1, 0, 0, 32), + BackgroundColor3 = theme.Background2, + BorderSizePixel = 0, + ZIndex = 2, }, { - Logo = e("ImageLabel", { - Image = Assets.Images.Logo, - Size = UDim2.new(0, 80, 0, 40), - ScaleType = Enum.ScaleType.Fit, - BackgroundTransparency = 1, - Position = UDim2.new(0, 0, 1, -10), - AnchorPoint = Vector2.new(0, 1), + Padding = e("UIPadding", { + PaddingTop = UDim.new(0, 4), + PaddingBottom = UDim.new(0, 4), + PaddingLeft = UDim.new(0, 8), + PaddingRight = UDim.new(0, 8), }), - }), - Version = e("TextLabel", { - Position = UDim2.new(1, 0, 0, 0), - Size = UDim2.new(0, 0, 1, 0), - AnchorPoint = Vector2.new(1, 0), - Font = Theme.TitleFont, - TextSize = 18, - Text = Version.display(Config.version), - TextXAlignment = Enum.TextXAlignment.Right, - TextColor3 = Theme.LightTextColor, - BackgroundTransparency = 1, + LogoContainer = e("Frame", { + BackgroundTransparency = 1, - [Roact.Change.AbsoluteSize] = function(rbx) - self.setFooterVersionSize(rbx.AbsoluteSize) - end, - }), - }) + Size = UDim2.new(0, 0, 0, 32), + }, { + Logo = e("ImageLabel", { + Image = Assets.Images.Logo, + Size = UDim2.new(0, 80, 0, 40), + ScaleType = Enum.ScaleType.Fit, + BackgroundTransparency = 1, + Position = UDim2.new(0, 0, 1, -10), + AnchorPoint = Vector2.new(0, 1), + }), + }), + + Version = e("TextLabel", { + Position = UDim2.new(1, 0, 0, 0), + Size = UDim2.new(0, 0, 1, 0), + AnchorPoint = Vector2.new(1, 0), + Font = theme.TitleFont, + TextSize = 18, + Text = Version.display(Config.version), + TextXAlignment = Enum.TextXAlignment.Right, + TextColor3 = theme.Text2, + BackgroundTransparency = 1, + + [Roact.Change.AbsoluteSize] = function(rbx) + self.setFooterVersionSize(rbx.AbsoluteSize) + end, + }), + }) + end) end return RojoFooter \ No newline at end of file diff --git a/plugin/src/Components/Theme.lua b/plugin/src/Components/Theme.lua new file mode 100644 index 00000000..ebd46015 --- /dev/null +++ b/plugin/src/Components/Theme.lua @@ -0,0 +1,104 @@ +--[[ + Theming system taking advantage of Roact's new context API. + + Doesn't use colors provided by Studio and instead just branches on theme + name. This isn't exactly best practice. +]] + +local Studio = settings():GetService("Studio") + +local Rojo = script:FindFirstAncestor("Rojo") + +local Roact = require(Rojo.Roact) +local Log = require(Rojo.Log) + +local strict = require(script.Parent.Parent.strict) + +local lightTheme = strict("Theme", { + ButtonFont = Enum.Font.GothamSemibold, + InputFont = Enum.Font.Code, + TitleFont = Enum.Font.GothamBold, + MainFont = Enum.Font.Gotham, + + Brand1 = Color3.fromRGB(225, 56, 53), + + Text1 = Color3.fromRGB(64, 64, 64), + Text2 = Color3.fromRGB(160, 160, 160), + TextOnAccent = Color3.fromRGB(235, 235, 235), + + Background1 = Color3.fromRGB(255, 255, 255), + Background2 = Color3.fromRGB(235, 235, 235), +}) + +local darkTheme = strict("Theme", { + ButtonFont = Enum.Font.GothamSemibold, + InputFont = Enum.Font.Code, + TitleFont = Enum.Font.GothamBold, + MainFont = Enum.Font.Gotham, + + Brand1 = Color3.fromRGB(225, 56, 53), + + Text1 = Color3.fromRGB(235, 235, 235), + Text2 = Color3.fromRGB(200, 200, 200), + TextOnAccent = Color3.fromRGB(235, 235, 235), + + Background1 = Color3.fromRGB(48, 48, 48), + Background2 = Color3.fromRGB(64, 64, 64), +}) + +local Context = Roact.createContext(lightTheme) + +local StudioProvider = Roact.Component:extend("StudioProvider") + +-- Pull the current theme from Roblox Studio and update state with it. +function StudioProvider:updateTheme() + local studioTheme = Studio.Theme + + if studioTheme.Name == "Light" then + self:setState({ + theme = lightTheme, + }) + elseif studioTheme.Name == "Dark" then + self:setState({ + theme = darkTheme, + }) + else + Log.warn("Unexpected theme '{}'' -- falling back to light theme!", studioTheme.Name) + + self:setState({ + theme = lightTheme, + }) + end +end + +function StudioProvider:init() + self:updateTheme() +end + +function StudioProvider:render() + return Roact.createElement(Context.Provider, { + value = self.state.theme, + }, self.props[Roact.Children]) +end + +function StudioProvider:didMount() + self.connection = Studio.ThemeChanged:Connect(function() + self:updateTheme() + end) +end + +function StudioProvider:willUnmount() + self.connection:Disconnect() +end + +local function with(callback) + return Roact.createElement(Context.Consumer, { + render = callback, + }) +end + +return { + StudioProvider = StudioProvider, + Consumer = Context.Consumer, + with = with, +} \ No newline at end of file diff --git a/plugin/src/Theme.lua b/plugin/src/Theme.lua deleted file mode 100644 index 0307c287..00000000 --- a/plugin/src/Theme.lua +++ /dev/null @@ -1,14 +0,0 @@ -local strict = require(script.Parent.strict) - -return strict("Theme", { - ButtonFont = Enum.Font.GothamSemibold, - InputFont = Enum.Font.Code, - TitleFont = Enum.Font.GothamBold, - MainFont = Enum.Font.Gotham, - - AccentColor = Color3.fromRGB(225, 56, 53), - AccentLightColor = Color3.fromRGB(255, 146, 145), - PrimaryColor = Color3.fromRGB(64, 64, 64), - SecondaryColor = Color3.fromRGB(235, 235, 235), - LightTextColor = Color3.fromRGB(160, 160, 160), -}) \ No newline at end of file diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index c249171b..2aaf4514 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -19,7 +19,7 @@ local app = Roact.createElement(App, { plugin = plugin, }) -local tree = Roact.mount(app, game:GetService("CoreGui"), "Rojo UI") +local tree = Roact.mount(app, nil, "Rojo UI") plugin.Unloading:Connect(function() Roact.unmount(tree)