diff --git a/plugin/src/components/App.luau b/plugin/src/components/App.luau index 3d10465..cb3b2c5 100644 --- a/plugin/src/components/App.luau +++ b/plugin/src/components/App.luau @@ -2,6 +2,7 @@ local React = require("@pkg/React") local types = require("@root/types") local HomeWrapper = require("./HomeWrapper") local ThemeDetailsWrapper = require("./ThemeDetailsWrapper") +local NavBar = require("./NavBar") local useCallback = React.useCallback local useState = React.useState @@ -9,14 +10,17 @@ local useState = React.useState type PublishedExtension = types.PublishedExtension type ExtensionTheme = types.ExtensionTheme -export type View = "Home" | "ThemeDetails" - export type Props = { plugin: Plugin, } +local VIEWS: { types.View } = { + "Home", + "History", +} + local function App(_props: Props) - local view, setView = useState("Home" :: View) + local view: types.View, setView = useState("Home" :: types.View) local extension, setExtension = useState(nil :: PublishedExtension?) local searchTerm, setSearchTerm = useState(nil :: string?) @@ -34,6 +38,15 @@ local function App(_props: Props) Size = UDim2.fromScale(1, 1), BackgroundTransparency = 1, }, { + Layout = React.createElement("UIListLayout", { + SortOrder = Enum.SortOrder.LayoutOrder, + }), + + NavBar = React.createElement(NavBar, { + views = VIEWS, + onNavigate = setView, + }), + Home = if view == "Home" then React.createElement(HomeWrapper, { onSearch = setSearchTerm, diff --git a/plugin/src/components/NavBar.luau b/plugin/src/components/NavBar.luau new file mode 100644 index 0000000..60ab018 --- /dev/null +++ b/plugin/src/components/NavBar.luau @@ -0,0 +1,37 @@ +local React = require("@pkg/React") +local getLayoutOrder = require("./getLayoutOrder") +local TabButton = require("./TabButton") +local types = require("@root/types") + +export type Props = { + views: { types.View }, + onNavigate: (view: types.View) -> (), +} + +local function NavBar(props: Props) + local children = { + Layout = React.createElement("UIListLayout", { + SortOrder = Enum.SortOrder.LayoutOrder, + FillDirection = Enum.FillDirection.Horizontal, + }), + } + + for _, view in props.views do + children[view] = React.createElement(TabButton, { + LayoutOrder = getLayoutOrder(), + text = view, + width = UDim.new(1 / #props.views), + onActivated = function() + props.onNavigate(view) + end, + }) + end + + return React.createElement("Frame", { + Size = UDim2.fromScale(1, 0), + AutomaticSize = Enum.AutomaticSize.Y, + BackgroundTransparency = 1, + }, children) +end + +return NavBar diff --git a/plugin/src/components/NavBar.story.luau b/plugin/src/components/NavBar.story.luau new file mode 100644 index 0000000..6ae692b --- /dev/null +++ b/plugin/src/components/NavBar.story.luau @@ -0,0 +1,11 @@ +local React = require("@pkg/React") +local NavBar = require("./NavBar") + +return { + story = function() + return React.createElement(NavBar, { + views = { "Home", "History", "Settings", "About" }, + onNavigate = print, + }) + end, +} diff --git a/plugin/src/components/TabButton.luau b/plugin/src/components/TabButton.luau new file mode 100644 index 0000000..257c01d --- /dev/null +++ b/plugin/src/components/TabButton.luau @@ -0,0 +1,57 @@ +local React = require("@pkg/React") +local Sift = require("@pkg/Sift") + +local TEXT_SIZE = 16 +local PADDING = 8 +local BUTTON_TEXT_COLOR = Color3.fromRGB(0, 0, 0) +local BUTTON_COLOR = Color3.fromRGB(150, 150, 150) +local BUTTON_HOVER_COLOR = Color3.fromRGB(200, 200, 200) + +local defaultProps = { + width = UDim.new(1, 0), +} + +export type Props = { + text: string, + width: UDim?, + onActivated: (() -> ())?, + LayoutOrder: number?, +} + +type InternalProps = typeof(defaultProps) & Props + +local function TabButton(providedProps: Props) + local props: InternalProps = Sift.Dictionary.join(defaultProps, providedProps) + local isHovered, setIsHovered = React.useState(false) + + local onMouseEnter = React.useCallback(function() + setIsHovered(true) + end, {}) + + local onMouseLeave = React.useCallback(function() + setIsHovered(false) + end, {}) + + return React.createElement("TextButton", { + LayoutOrder = props.LayoutOrder, + Text = props.text, + TextColor3 = BUTTON_TEXT_COLOR, + AutoButtonColor = false, + TextSize = TEXT_SIZE, + Font = Enum.Font.GothamMedium, + Size = UDim2.new(props.width, UDim.new()), + AutomaticSize = Enum.AutomaticSize.Y, + BackgroundColor3 = if isHovered then BUTTON_HOVER_COLOR else BUTTON_COLOR, + BorderSizePixel = 0, + [React.Event.MouseEnter] = onMouseEnter, + [React.Event.MouseLeave] = onMouseLeave, + [React.Event.Activated] = props.onActivated, + }, { + Padding = React.createElement("UIPadding", { + PaddingTop = UDim.new(0, PADDING), + PaddingBottom = UDim.new(0, PADDING), + }), + }) +end + +return TabButton diff --git a/plugin/src/components/TabButton.story.luau b/plugin/src/components/TabButton.story.luau new file mode 100644 index 0000000..e7e43c1 --- /dev/null +++ b/plugin/src/components/TabButton.story.luau @@ -0,0 +1,11 @@ +local React = require("@pkg/React") +local TabButton = require("./TabButton") + +return { + story = function() + return React.createElement(TabButton, { + views = { "Home", "History", "Settings", "About" }, + onNavigate = print, + }) + end, +} diff --git a/plugin/src/types.luau b/plugin/src/types.luau index 4760e12..7c3366a 100644 --- a/plugin/src/types.luau +++ b/plugin/src/types.luau @@ -1,3 +1,5 @@ +export type View = "Home" | "ThemeDetails" | "History" | "Settings" | "About" + type ArtifactFileAssetType = "Microsoft.VisualStudio.Code.Manifest" | "Microsoft.VisualStudio.Services.Content.Changelog"