Skip to content

Commit 32e4f05

Browse files
EgoMoosesircfenner
andauthored
Add spritesheet icon support (#50)
* Add spritesheet icon support * refactor baseicon * update changelog * fix storybook for luau-analyze * fix doc comments * fix dropdown item icon alignment --------- Co-authored-by: sircfenner <sircfenner@users.noreply.github.com>
1 parent 4ed1141 commit 32e4f05

File tree

9 files changed

+114
-37
lines changed

9 files changed

+114
-37
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
- Added RectSize, RectOffset, and ResampleMode to icon props available in Button, MainButton, and Dropdown
6+
37
## 1.1.0
48

59
- Fixed image links in documentation

src/Components/Button.luau

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ local BaseButton = require("./Foundation/BaseButton")
4646
@field Color Color3?
4747
@field UseThemeColor boolean?
4848
@field Alignment HorizontalAlignment?
49+
@field ResampleMode Enum.ResamplerMode?
50+
@field RectOffset Vector2?
51+
@field RectSize Vector2?
4952
5053
The `Alignment` prop is used to configure which side of any text the icon
5154
appears on. Left-alignment is the default and center-alignment is not supported.

src/Components/Dropdown/DropdownItem.luau

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ local React = require("@pkg/@jsdotlua/react")
33
local Constants = require("../../Constants")
44
local useTheme = require("../../Hooks/useTheme")
55

6+
local BaseIcon = require("../Foundation/BaseIcon")
7+
68
local DropdownTypes = require("./Types")
79

810
type DropdownItemProps = {
@@ -27,13 +29,24 @@ local function DropdownItem(props: DropdownItemProps)
2729
modifier = Enum.StudioStyleGuideModifier.Hover
2830
end
2931

30-
local iconColor = Color3.fromRGB(255, 255, 255)
32+
local iconNode: React.Node?
3133
if props.Icon then
34+
local iconColor = Color3.fromRGB(255, 255, 255)
3235
if props.Icon.UseThemeColor then
3336
iconColor = theme:GetColor(Enum.StudioStyleGuideColor.MainText)
3437
elseif props.Icon.Color then
3538
iconColor = props.Icon.Color
3639
end
40+
41+
local iconProps = (table.clone(props.Icon) :: any) :: BaseIcon.BaseIconProps
42+
iconProps.Color = iconColor
43+
iconProps.AnchorPoint = Vector2.new(0, 0.5)
44+
iconProps.Position = UDim2.fromScale(0, 0.5)
45+
iconProps.Size = UDim2.fromOffset(props.Icon.Size.X, props.Icon.Size.Y)
46+
iconProps.Disabled = nil
47+
iconProps.LayoutOrder = nil
48+
49+
iconNode = React.createElement(BaseIcon, iconProps)
3750
end
3851

3952
return React.createElement("Frame", {
@@ -66,15 +79,7 @@ local function DropdownItem(props: DropdownItemProps)
6679
PaddingLeft = UDim.new(0, props.TextInset),
6780
PaddingBottom = UDim.new(0, 2),
6881
}),
69-
Icon = props.Icon and React.createElement("ImageLabel", {
70-
AnchorPoint = Vector2.new(0, 0.5),
71-
Position = UDim2.fromScale(0, 0.5),
72-
Size = UDim2.fromOffset(props.Icon.Size.X, props.Icon.Size.Y),
73-
BackgroundTransparency = 1,
74-
Image = props.Icon.Image,
75-
ImageTransparency = props.Icon.Transparency or 0,
76-
ImageColor3 = iconColor,
77-
}),
82+
Icon = iconNode,
7883
Label = React.createElement("TextLabel", {
7984
BackgroundTransparency = 1,
8085
AnchorPoint = Vector2.new(1, 0),

src/Components/Dropdown/Types.luau

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,19 @@ export type DropdownItemDetail = {
2929
@field Transparency number?
3030
@field Color Color3?
3131
@field UseThemeColor boolean?
32+
@field ResampleMode Enum.ResamplerMode?
33+
@field RectOffset Vector2?
34+
@field RectSize Vector2?
3235
]=]
3336

3437
export type DropdownItemIcon = {
3538
Image: string,
3639
Size: Vector2,
3740
Transparency: number?,
3841
Color: Color3?,
42+
ResampleMode: Enum.ResamplerMode?,
43+
RectOffset: Vector2?,
44+
RectSize: Vector2?,
3945
UseThemeColor: boolean?,
4046
}
4147

src/Components/Foundation/BaseButton.luau

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,31 @@ local Constants = require("../../Constants")
66
local getTextSize = require("../../getTextSize")
77
local useTheme = require("../../Hooks/useTheme")
88

9+
local BaseIcon = require("./BaseIcon")
10+
911
local PADDING_X = 8
1012
local PADDING_Y = 4
1113
local DEFAULT_HEIGHT = Constants.DefaultButtonHeight
1214

15+
export type BaseButtonIconProps = {
16+
Image: string,
17+
Size: Vector2,
18+
Transparency: number?,
19+
Color: Color3?,
20+
ResampleMode: Enum.ResamplerMode?,
21+
RectOffset: Vector2?,
22+
RectSize: Vector2?,
23+
UseThemeColor: boolean?,
24+
Alignment: Enum.HorizontalAlignment?,
25+
}
26+
1327
export type BaseButtonConsumerProps = CommonProps.T & {
1428
AutomaticSize: Enum.AutomaticSize?,
1529
OnActivated: (() -> ())?,
1630
Selected: boolean?,
1731
Text: string?,
1832
TextTransparency: number?,
19-
Icon: {
20-
Image: string,
21-
Size: Vector2,
22-
Transparency: number?,
23-
Color: Color3?,
24-
UseThemeColor: boolean?,
25-
Alignment: Enum.HorizontalAlignment?,
26-
}?,
33+
Icon: BaseButtonIconProps?,
2734
}
2835

2936
export type BaseButtonProps = BaseButtonConsumerProps & {
@@ -78,6 +85,17 @@ local function BaseButton(props: BaseButtonProps)
7885
size = UDim2.new(size.Width, UDim.new(0, math.max(DEFAULT_HEIGHT, contentHeight + PADDING_Y * 2)))
7986
end
8087

88+
local iconNode: React.Node?
89+
if props.Icon then
90+
local iconProps = (table.clone(props.Icon) :: any) :: BaseIcon.BaseIconProps
91+
iconProps.Disabled = props.Disabled
92+
iconProps.Color = iconProps.Color or if props.Icon.UseThemeColor then textColor else nil
93+
iconProps.LayoutOrder = if props.Icon.Alignment == Enum.HorizontalAlignment.Right then 3 else 1
94+
iconProps.Size = UDim2.fromOffset(props.Icon.Size.X, props.Icon.Size.Y)
95+
96+
iconNode = React.createElement(BaseIcon, iconProps)
97+
end
98+
8199
return React.createElement("TextButton", {
82100
AutoButtonColor = false,
83101
AnchorPoint = props.AnchorPoint,
@@ -115,17 +133,7 @@ local function BaseButton(props: BaseButtonProps)
115133
HorizontalAlignment = Enum.HorizontalAlignment.Center,
116134
VerticalAlignment = Enum.VerticalAlignment.Center,
117135
}),
118-
Icon = props.Icon and React.createElement("ImageLabel", {
119-
Image = props.Icon.Image,
120-
Size = UDim2.fromOffset(props.Icon.Size.X, props.Icon.Size.Y),
121-
LayoutOrder = if props.Icon.Alignment == Enum.HorizontalAlignment.Right then 3 else 1,
122-
BackgroundTransparency = 1,
123-
ImageColor3 = if props.Icon.Color
124-
then props.Icon.Color
125-
elseif props.Icon.UseThemeColor then textColor
126-
else nil,
127-
ImageTransparency = 1 - (1 - (props.Icon.Transparency or 0)) * (1 - if props.Disabled then 0.2 else 0),
128-
}),
136+
Icon = iconNode,
129137
Label = props.Text and React.createElement("TextLabel", {
130138
TextColor3 = textColor,
131139
Font = Constants.DefaultFont,
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
local React = require("@pkg/@jsdotlua/react")
2+
3+
local CommonProps = require("../../CommonProps")
4+
5+
export type BaseIconConsumerProps = CommonProps.T & {
6+
Image: string,
7+
Transparency: number?,
8+
Color: Color3?,
9+
ResampleMode: Enum.ResamplerMode?,
10+
RectOffset: Vector2?,
11+
RectSize: Vector2?,
12+
}
13+
14+
export type BaseIconProps = BaseIconConsumerProps
15+
16+
local function BaseIcon(props: BaseIconProps)
17+
return React.createElement("ImageLabel", {
18+
Size = props.Size,
19+
Position = props.Position,
20+
AnchorPoint = props.AnchorPoint,
21+
LayoutOrder = props.LayoutOrder,
22+
ZIndex = props.ZIndex,
23+
BackgroundTransparency = 1,
24+
Image = props.Image,
25+
ImageColor3 = props.Color,
26+
ImageTransparency = 1 - (1 - (props.Transparency or 0)) * (1 - if props.Disabled then 0.2 else 0),
27+
ImageRectOffset = props.RectOffset,
28+
ImageRectSize = props.RectSize,
29+
ResampleMode = props.ResampleMode,
30+
})
31+
end
32+
33+
return BaseIcon

src/Components/MainButton.luau

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ local BaseButton = require("./Foundation/BaseButton")
2525
@field Color Color3?
2626
@field UseThemeColor boolean?
2727
@field Alignment HorizontalAlignment?
28+
@field ResampleMode Enum.ResamplerMode?
29+
@field RectOffset Vector2?
30+
@field RectSize Vector2?
2831
]=]
2932

3033
--[=[

src/Stories/Button.story.luau

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ local function StoryButton(props: {
1010
})
1111
return React.createElement(Button, {
1212
LayoutOrder = if props.Disabled then 2 else 1,
13-
Icon = if props.HasIcon
14-
then {
15-
Image = "rbxasset://studio_svg_textures/Shared/InsertableObjects/Dark/Standard/Part.png",
16-
Size = Vector2.one * 16,
17-
UseThemeColor = true,
18-
Alignment = Enum.HorizontalAlignment.Left,
19-
}
20-
else nil,
13+
Icon = props.HasIcon and {
14+
Image = "rbxassetid://18786011824",
15+
UseThemeColor = true,
16+
Size = Vector2.new(16, 16),
17+
Alignment = Enum.HorizontalAlignment.Left,
18+
RectOffset = Vector2.new(1000, 0),
19+
RectSize = Vector2.new(16, 16),
20+
} :: any,
2121
Text = props.Text,
2222
OnActivated = if not props.Disabled then function() end else nil,
2323
Disabled = props.Disabled,
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--!nocheck
2+
3+
local React = require("@pkg/@jsdotlua/react")
4+
local ReactRoblox = require("@pkg/@jsdotlua/react-roblox")
5+
6+
return {
7+
name = "StudioComponents",
8+
storyRoots = {
9+
script.Parent.Parent,
10+
},
11+
packages = {
12+
React = React,
13+
ReactRoblox = ReactRoblox,
14+
},
15+
}

0 commit comments

Comments
 (0)