Skip to content

Commit

Permalink
Controls panel QOL improvements (#259)
Browse files Browse the repository at this point in the history
# Problem

Story controls need some sprucing up

# Solution

Before:

<img width="756" alt="Screenshot 2024-08-11 at 6 57 49 PM"
src="https://github.com/user-attachments/assets/7b1ac93b-3cb6-4cc9-abda-9510133690d8">

After:

<img width="734" alt="Screenshot 2024-08-11 at 6 57 30 PM"
src="https://github.com/user-attachments/assets/22155904-a446-4721-9547-ea6c505f7af7">


Fixes #253

# Checklist

- [x] Ran `lune run test` locally before merging
  • Loading branch information
vocksel authored Nov 3, 2024
1 parent efe83a7 commit eb289ed
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 39 deletions.
2 changes: 1 addition & 1 deletion foreman.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ selene = { source = "Kampfkarren/selene", version = "0.27.1" }
stylua = { source = "JohnnyMorganz/StyLua", version = "0.20.0" }
tarmac = { source = "Roblox/tarmac", version = "0.7.0" }
wally = { source = "UpliftGames/wally", version = "0.3.2" }
luau-lsp = { source = "JohnnyMorganz/luau-lsp", version = "1.32.3" }
luau-lsp = { source = "JohnnyMorganz/luau-lsp", version = "1.34.0" }
wally-package-types = { source = "JohnnyMorganz/wally-package-types", version = "1.3.2" }
8 changes: 6 additions & 2 deletions src/Forms/InputField.luau
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ local function InputField(providedProps: Props)

local ref = React.useRef(nil :: TextBox?)
local text, setText = React.useState("")
local isValid, setIsValid = React.useState(false)
local isValid, setIsValid = React.useState(true)
local theme = useTheme()

local onFocusLost = React.useCallback(
Expand All @@ -41,15 +41,19 @@ local function InputField(providedProps: Props)
end
end,
{
text,
isValid,
props.onFocusLost,
props.onSubmit,
} :: { unknown }
)

local onTextChanged = React.useCallback(function(rbx: TextBox)
local newText = rbx.Text

if newText == text and newText ~= "" then
newText = newText:gsub("$%s+", ""):gsub("%s+^", "")

if newText == text or newText == "" then
return
end

Expand Down
108 changes: 83 additions & 25 deletions src/Storybook/StoryControls.luau
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
local React = require("@pkg/React")
local Sift = require("@pkg/Sift")

local Checkbox = require("@root/Forms/Checkbox")
local Dropdown = require("@root/Forms/Dropdown")
local InputField = require("@root/Forms/InputField")
local useTheme = require("@root/Common/useTheme")

local useMemo = React.useMemo
local e = React.createElement

type Props = {
Expand All @@ -16,72 +18,131 @@ type Props = {
local function StoryControls(props: Props)
local theme = useTheme()

local controls: { [string]: React.Node } = {}
for key, value in props.controls do
local sortedControls: { { name: string, value: any } } = useMemo(function()
local result = {}

for _, entry in Sift.Dictionary.entries(props.controls) do
table.insert(result, {
name = entry[1],
value = entry[2],
})
end

return Sift.List.sort(result, function(a, b)
return a.name < b.name
end)
end, { props.controls })

local controlElements: { [string]: React.Node } = {}
for index, control in sortedControls do
local function setControl(newValue: any)
props.setControl(key, newValue)
local newValueAsNum = tonumber(newValue)
if newValueAsNum then
newValue = newValueAsNum
end

props.setControl(control.name, newValue)
end

local controlType = typeof(control.value)
local option: React.Node
if typeof(value) == "boolean" then
if controlType == "boolean" then
option = React.createElement(Checkbox, {
initialState = value,
initialState = control.value,
onStateChange = setControl,
})
elseif typeof(value) == "table" then
elseif controlType == "table" then
option = React.createElement(Dropdown, {
default = value[1],
options = value,
default = control.value[1],
options = control.value,
onOptionChange = setControl,
})
else
elseif controlType == "number" or controlType == "string" then
option = React.createElement(InputField, {
placeholder = value,
onTextChange = setControl,
placeholder = control.value,
onSubmit = setControl,
})
else
option = React.createElement("TextLabel", {
Text = `ERR: Controls of type "{controlType}" are unsupported`,
AutomaticSize = Enum.AutomaticSize.XY,
BackgroundTransparency = 1,
Font = theme.font,
TextColor3 = theme.alert,
TextSize = theme.textSize,
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Center,
TextTruncate = Enum.TextTruncate.AtEnd,
})
end

controls[key] = e("Frame", {
BackgroundTransparency = 1,
controlElements[control.name] = e("Frame", {
LayoutOrder = index,
BackgroundColor3 = theme.background,
BackgroundTransparency = if index % 2 == 0 then 1 else 0,
BorderSizePixel = 0,
Size = UDim2.fromScale(1, 0),
AutomaticSize = Enum.AutomaticSize.Y,
}, {
Layout = React.createElement("UIListLayout", {
FillDirection = Enum.FillDirection.Horizontal,
SortOrder = Enum.SortOrder.LayoutOrder,
Padding = theme.padding,
}),

Padding = e("UIPadding", {
PaddingTop = theme.padding,
PaddingRight = theme.padding,
PaddingBottom = theme.padding,
PaddingLeft = theme.padding,
}),

Name = e("TextLabel", {
Text = key,
Size = UDim2.fromScale(1 / 2, 0),
LayoutOrder = 1,
Text = control.name,
Size = UDim2.fromScale(1 / 4, 0),
AutomaticSize = Enum.AutomaticSize.Y,
BackgroundTransparency = 1,
Font = theme.font,
TextColor3 = theme.text,
TextSize = theme.textSize,
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Top,
TextYAlignment = Enum.TextYAlignment.Center,
TextTruncate = Enum.TextTruncate.AtEnd,
}),

Option = e("Frame", {
LayoutOrder = 2,
BackgroundTransparency = 1,
Size = UDim2.fromScale(1 / 2, 0),
Size = UDim2.fromScale(1, 0),
AutomaticSize = Enum.AutomaticSize.Y,
}, {
Flex = e("UIFlexItem", {
FlexMode = Enum.UIFlexMode.Shrink,
}),
}, option),
})
end

return e("Frame", {
BackgroundTransparency = 1,
BackgroundTransparency = 0.4,
BackgroundColor3 = theme.sidebar,
BorderSizePixel = 0,
LayoutOrder = props.layoutOrder,
Size = UDim2.fromScale(1, 0),
AutomaticSize = Enum.AutomaticSize.Y,
Size = UDim2.fromScale(1, 1),
}, {
Layout = e("UIListLayout", {
SortOrder = Enum.SortOrder.LayoutOrder,
Padding = theme.padding,
}),

Padding = e("UIPadding", {
PaddingTop = theme.padding,
PaddingRight = theme.padding,
PaddingBottom = theme.padding,
PaddingLeft = theme.padding,
}),

Title = e("TextLabel", {
LayoutOrder = 1,
Text = "Controls",
Expand All @@ -101,12 +162,9 @@ local function StoryControls(props: Props)
BackgroundTransparency = 1,
}, {
Layout = e("UIListLayout", {
SortOrder = Enum.SortOrder.Name,
Padding = theme.padding,
SortOrder = Enum.SortOrder.LayoutOrder,
}),

ControlsFragment = React.createElement(React.Fragment, nil, controls),
}),
}, controlElements),
})
end

Expand Down
2 changes: 2 additions & 0 deletions src/Storybook/StoryControls.story.luau
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ return {
"Option 2",
"Option 3",
},
onlyTwentyCharacters = "OnlyTwentyCharacters",
badControlType = function() end,
},
setControl = function() end,
}),
Expand Down
5 changes: 3 additions & 2 deletions src/Storybook/StoryPreview.luau
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ local defaultProps = {
}

export type Props = {
layoutOrder: number,
story: types.Story,
ref: any,
controls: { [string]: any },
storyModule: ModuleScript,

ref: any,
layoutOrder: number?,
}

type InternalProps = Props & typeof(defaultProps)
Expand Down
10 changes: 1 addition & 9 deletions src/Storybook/StoryView.luau
Original file line number Diff line number Diff line change
Expand Up @@ -183,17 +183,9 @@ local function StoryView(props: Props)
onResize = onControlsResized,
}, {
ScrollingFrame = e(ScrollingFrame, {
LayoutOrder = 2,
BackgroundTransparency = 0.4,
BackgroundTransparency = 1,
BackgroundColor3 = theme.sidebar,
}, {
Padding = e("UIPadding", {
PaddingTop = theme.padding,
PaddingRight = theme.padding,
PaddingBottom = theme.padding,
PaddingLeft = theme.padding,
}),

StoryControls = e(StoryControls, {
controls = controls,
setControl = setControl,
Expand Down

0 comments on commit eb289ed

Please sign in to comment.