Skip to content

Commit

Permalink
Iris.TabBar, Iris.Tab
Browse files Browse the repository at this point in the history
# TabBar and Tab
Adds a new TabBar and Tab item similar to how the MenuBar and MenuItem work, but for tabs. Tabs can be closed from view using a state and only one Tab can be active at a time.

## Additions
- New TabBar and Tab widgets.
- Demo window examples

## Changes
- Changed style demo window to use Tabs

## Fixes
- Fixed wrong spacing in Group widget
  • Loading branch information
SirMallard authored Oct 19, 2024
1 parent ead4efc commit 22ed03c
Show file tree
Hide file tree
Showing 13 changed files with 535 additions and 13 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
bin/
build/
.vscode/

Expand Down
70 changes: 69 additions & 1 deletion lib/API.lua
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,6 @@ return function(Iris: Types.Iris)
[SECTION] Image Widget API
----------------------------------
]]

--[=[
@class Image
Image Widget API
Expand Down Expand Up @@ -695,6 +694,75 @@ return function(Iris: Types.Iris)
]=]
Iris.CollapsingHeader = wrapper("CollapsingHeader")

--[[
--------------------------------
[SECTION] Tab Widget API
--------------------------------
]]
--[=[
@class Tab
Tab Widget API
]=]

--[=[
@within Tab
@prop TabBar Iris.TabBar
@tag Widget
@tag HasChildren
@tag HasState
Creates a TabBar for putting tabs under. This does not create the tabs but just the container for them to be in.
The index state is used to control the current tab and is based on an index starting from 1 rather than the
text provided to a Tab. The TabBar will replicate the index to the Tab children .
```lua
hasChildren: true
hasState: true
Arguments = {}
Events = {}
State = {
index: State<number>? -- whether the widget is collapsed.
}
```
]=]
Iris.TabBar = wrapper("TabBar")

--[=[
@within Tab
@prop Tab Iris.Tab
@tag Widget
@tag HasChildren
@tag HasState
The tab item for use under a TabBar. The TabBar must be the parent and determines the index value. You cannot
provide a state for this tab. The optional Hideable argument determines if a tab can be closed, which is
controlled by the isOpened state.
A tab will take up the full horizontal width of the parent and hide any other tabs in the TabBar.
```lua
hasChildren: true
hasState: true
Arguments = {
Text: string,
Hideable: boolean? = nil -- determines whether a tab can be closed/hidden
}
Events = {
clicked: () -> boolean,
hovered: () -> boolean
selected: () -> boolean
unselected: () -> boolean
active: () -> boolean
opened: () -> boolean
closed: () -> boolean
}
State = {
isOpened: State<boolean>?
}
```
]=]
Iris.Tab = wrapper("Tab")

--[[
----------------------------------
[SECTION] Input Widget API
Expand Down
2 changes: 2 additions & 0 deletions lib/PubTypes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export type Image = Types.Image
export type ImageButton = Types.ImageButton
export type Tree = Types.Tree
export type CollapsingHeader = Types.CollapsingHeader
export type TabBar = Types.TabBar
export type Tab = Types.Tab
export type Input<T> = Types.Input<T>
export type InputColor3 = Types.InputColor3
export type InputColor4 = Types.InputColor4
Expand Down
15 changes: 15 additions & 0 deletions lib/Types.lua
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export type Image = WidgetTypes.Image
export type ImageButton = WidgetTypes.ImageButton
export type Tree = WidgetTypes.Tree
export type CollapsingHeader = WidgetTypes.CollapsingHeader
export type TabBar = WidgetTypes.TabBar
export type Tab = WidgetTypes.Tab
export type Input<T> = WidgetTypes.Input<T>
export type InputColor3 = WidgetTypes.InputColor3
export type InputColor4 = WidgetTypes.InputColor4
Expand Down Expand Up @@ -180,6 +182,8 @@ export type WidgetClass = {
ChildDiscarded: (thisWidget: Widget, thisChild: Widget) -> (),
}

-- Iris

export type Internal = {
--[[
--------------
Expand Down Expand Up @@ -393,6 +397,13 @@ export type Config = {
HeaderActiveColor: Color3,
HeaderActiveTransparency: number,

TabColor: Color3,
TabTransparency: number,
TabHoveredColor: Color3,
TabHoveredTransparency: number,
TabActiveColor: Color3,
TabActiveTransparency: number,

SelectionImageObjectColor: Color3,
SelectionImageObjectTransparency: number,
SelectionImageObjectBorderColor: Color3,
Expand Down Expand Up @@ -512,6 +523,10 @@ export type Iris = {
Tree: WidgetCall<Tree, WidgetArguments, WidgetStates?>,
CollapsingHeader: WidgetCall<CollapsingHeader, WidgetArguments, WidgetStates?>,

-- Tab Widget API
TabBar: WidgetCall<TabBar, WidgetArguments?, WidgetStates?>,
Tab: WidgetCall<Tab, WidgetArguments, WidgetStates?>,

-- Input Widget API
InputNum: WidgetCall<Input<number>, WidgetArguments, WidgetStates?>,
InputVector2: WidgetCall<Input<Vector2>, WidgetArguments, WidgetStates?>,
Expand Down
26 changes: 26 additions & 0 deletions lib/WidgetTypes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,32 @@ export type CollapsingHeader = ParentWidget & {
},
} & Collapsed & Uncollapsed & Hovered

-- Tabs

export type TabBar = ParentWidget & {
Tabs: { Tab },

state: {
index: State<number>,
},
}

export type Tab = ParentWidget & {
parentWidget: TabBar,
Index: number,
ButtonColors: { [string]: Color3 | number },

arguments: {
Text: string,
Hideable: boolean,
},

state: {
index: State<number>,
isOpened: State<boolean>,
},
} & Clicked & Opened & Selected & Unselected & Active & Closed & Hovered

-- Input
export type Input<T> = Widget & {
lastClickedTime: number,
Expand Down
14 changes: 14 additions & 0 deletions lib/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ local TemplateConfig = {
HeaderActiveColor = Color3.fromRGB(66, 150, 250),
HeaderActiveTransparency = 0,

TabColor = Color3.fromRGB(46, 89, 148),
TabTransparency = 0.14,
TabHoveredColor = Color3.fromRGB(66, 150, 250),
TabHoveredTransparency = 0.2,
TabActiveColor = Color3.fromRGB(51, 105, 173),
TabActiveTransparency = 0,

SelectionImageObjectColor = Color3.fromRGB(255, 255, 255),
SelectionImageObjectTransparency = 0.8,
SelectionImageObjectBorderColor = Color3.fromRGB(255, 255, 255),
Expand Down Expand Up @@ -150,6 +157,13 @@ local TemplateConfig = {
HeaderActiveColor = Color3.fromRGB(66, 150, 250),
HeaderActiveTransparency = 0,

TabColor = Color3.fromRGB(195, 203, 213),
TabTransparency = 0.07,
TabHoveredColor = Color3.fromRGB(66, 150, 250),
TabHoveredTransparency = 0.2,
TabActiveColor = Color3.fromRGB(152, 186, 255),
TabActiveTransparency = 0,

SliderGrabColor = Color3.fromRGB(61, 133, 224),
SliderGrabTransparency = 0,
SliderGrabActiveColor = Color3.fromRGB(66, 150, 250),
Expand Down
89 changes: 82 additions & 7 deletions lib/demoWindow.lua
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,81 @@ return function(Iris: Types.Iris)
Iris.End()
end,

Tab = function()
Iris.Tree({ "Tabs" })
do
Iris.Tree({ "Simple" })
do
Iris.TabBar()
do
Iris.Tab({ "Apples" })
do
Iris.Text({ "Who loves apples?" })
end
Iris.End()
Iris.Tab({ "Broccoli" })
do
Iris.Text({ "And what about broccoli?" })
end
Iris.End()
Iris.Tab({ "Carrots" })
do
Iris.Text({ "But carrots are the best." })
end
Iris.End()
end
Iris.End()
Iris.Separator()
Iris.Text({ "Very important questions." })
end
Iris.End()

Iris.Tree({ "Closable" })
do
local a = Iris.State(true)
local b = Iris.State(true)
local c = Iris.State(true)

Iris.TabBar()
do
Iris.Tab({ "🍎", true }, { isOpened = a })
do
Iris.Text({ "Who loves apples?" })
if Iris.Button({ "I don't like apples." }).clicked() then
a:set(false)
end
end
Iris.End()
Iris.Tab({ "🥦", true }, { isOpened = b })
do
Iris.Text({ "And what about broccoli?" })
if Iris.Button({ "Not for me." }).clicked() then
b:set(false)
end
end
Iris.End()
Iris.Tab({ "🥕", true }, { isOpened = c })
do
Iris.Text({ "But carrots are the best." })
if Iris.Button({ "I disagree with you." }).clicked() then
c:set(false)
end
end
Iris.End()
end
Iris.End()
Iris.Separator()
if Iris.Button({ "Actually, let me reconsider it." }).clicked() then
a:set(true)
b:set(true)
c:set(true)
end
end
Iris.End()
end
Iris.End()
end,

Indent = function()
Iris.Tree({ "Indents" })
Iris.Text({ "Not Indented" })
Expand Down Expand Up @@ -502,7 +577,7 @@ return function(Iris: Types.Iris)
Iris.End()
end,
}
local widgetDemosOrder = { "Basic", "Image", "Selectable", "Combo", "Tree", "CollapsingHeader", "Group", "Indent", "Input", "MultiInput", "InputText", "Tooltip", "Plotting" }
local widgetDemosOrder = { "Basic", "Image", "Selectable", "Combo", "Tree", "CollapsingHeader", "Group", "Tab", "Indent", "Input", "MultiInput", "InputText", "Tooltip", "Plotting" }

local function recursiveTree()
local theTree = Iris.Tree({ "Recursive Tree" })
Expand Down Expand Up @@ -744,8 +819,6 @@ return function(Iris: Types.Iris)
local styleEditor
do
styleEditor = function()
local selectedPanel = Iris.State(1)

local styleList = {
{
"Sizing",
Expand Down Expand Up @@ -979,17 +1052,19 @@ return function(Iris: Types.Iris)
end
Iris.End()

Iris.SameLine()
Iris.TabBar()
do
for i, v in ipairs(styleList) do
Iris.RadioButton({ v[1], i }, { index = selectedPanel })
Iris.Tab({ v[1] })
do
styleList[i][2]()
end
Iris.End()
end
end
Iris.End()

Iris.Separator()

styleList[selectedPanel:get()][2]()
end
Iris.End()
end
Expand Down
2 changes: 1 addition & 1 deletion lib/widgets/Format.lua
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ return function(Iris: Types.Internal, widgets: Types.WidgetUtility)
Group.LayoutOrder = thisWidget.ZIndex
Group.ClipsDescendants = false

widgets.UIListLayout(Group, Enum.FillDirection.Vertical, UDim.new(0, Iris._config.ItemSpacing.X))
widgets.UIListLayout(Group, Enum.FillDirection.Vertical, UDim.new(0, Iris._config.ItemSpacing.Y))

return Group
end,
Expand Down
4 changes: 2 additions & 2 deletions lib/widgets/Menu.lua
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ return function(Iris: Types.Internal, widgets: Types.WidgetUtility)
Events = {},
Generate = function(thisWidget: Types.MenuBar)
local MenuBar: Frame = Instance.new("Frame")
MenuBar.Name = "MenuBar"
MenuBar.Name = "Iris_MenuBar"
MenuBar.Size = UDim2.fromScale(1, 0)
MenuBar.AutomaticSize = Enum.AutomaticSize.Y
MenuBar.BackgroundColor3 = Iris._config.MenubarBgColor
Expand All @@ -121,7 +121,7 @@ return function(Iris: Types.Internal, widgets: Types.WidgetUtility)

return MenuBar
end,
Update = function()
Update = function(_thisWidget: Types.Widget)

end,
ChildAdded = function(thisWidget: Types.MenuBar, _thisChild: Types.Widget)
Expand Down
Loading

0 comments on commit 22ed03c

Please sign in to comment.