Skip to content

Commit

Permalink
Display unavailable storybooks
Browse files Browse the repository at this point in the history
  • Loading branch information
vocksel committed Dec 19, 2024
1 parent a1b51d9 commit ea6048b
Show file tree
Hide file tree
Showing 11 changed files with 345 additions and 41 deletions.
Binary file added img/Alert.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
79 changes: 79 additions & 0 deletions src/Common/CodeBlock.luau
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
local React = require("@pkg/React")
local Sift = require("@pkg/Sift")

local SelectableTextLabel = require("@root/Forms/SelectableTextLabel")
local nextLayoutOrder = require("@root/Common/nextLayoutOrder")
local useTheme = require("@root/Common/useTheme")

local useMemo = React.useMemo

local function getLineNumbers(str: string): string
return Sift.List.reduce(str:split("\n"), function(accumulator, _item, index)
return if index == 1 then tostring(index) else `{accumulator}\n{index}`
end, "")
end

export type Props = {
source: string,
sourceColor: Color3?,
layoutOrder: number?,
}

local function StoryError(props: Props)
local theme = useTheme()

local sourceColor = useMemo(function()
return if props.sourceColor then props.sourceColor else theme.text
end, { props.sourceColor })

return React.createElement("Frame", {
AutomaticSize = Enum.AutomaticSize.XY,
BackgroundTransparency = 0.5,
BorderSizePixel = 0,
BackgroundColor3 = theme.sidebar,
LayoutOrder = props.layoutOrder,
}, {
Layout = React.createElement("UIListLayout", {
SortOrder = Enum.SortOrder.LayoutOrder,
FillDirection = Enum.FillDirection.Horizontal,
Padding = theme.padding,
}),

BorderRadius = React.createElement("UICorner", {
CornerRadius = theme.corner,
}),

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

LineNumbers = React.createElement("TextLabel", {
LayoutOrder = nextLayoutOrder(),
AutomaticSize = Enum.AutomaticSize.XY,
Text = getLineNumbers(props.source),
TextSize = theme.textSize,
LineHeight = 1,
BackgroundTransparency = 1,
Font = Enum.Font.RobotoMono,
TextColor3 = theme.textFaded,
TextXAlignment = Enum.TextXAlignment.Right,
}),

SourceCode = React.createElement(SelectableTextLabel, {
LayoutOrder = nextLayoutOrder(),
Size = UDim2.fromScale(1, 0),
AutomaticSize = Enum.AutomaticSize.Y,
Text = props.source,
TextColor3 = sourceColor,
TextSize = theme.textSize,
TextWrapped = false,
LineHeight = 1,
Font = Enum.Font.RobotoMono,
}),
})
end

return StoryError
9 changes: 5 additions & 4 deletions src/Navigation/Screen.luau
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
local ModuleLoader = require("@pkg/ModuleLoader")
local React = require("@pkg/React")
local Storyteller = require("@pkg/Storyteller")

Expand All @@ -7,14 +6,13 @@ local NavigationContext = require("@root/Navigation/NavigationContext")
local NoStorySelected = require("@root/Storybook/NoStorySelected")
local SettingsView = require("@root/UserSettings/SettingsView")
local StoryCanvas = require("@root/Storybook/StoryCanvas")
local StorybookError = require("@root/Storybook/StorybookError")

local useMemo = React.useMemo

type ModuleLoader = ModuleLoader.ModuleLoader
type LoadedStorybook = Storyteller.LoadedStorybook

export type Props = {
loader: ModuleLoader,
story: ModuleScript?,
storybook: LoadedStorybook?,
}
Expand All @@ -27,10 +25,13 @@ local function Screen(props: Props)
if currentScreen == "Home" then
if props.story and props.storybook then
return React.createElement(StoryCanvas, {
loader = props.loader,
story = props.story,
storybook = props.storybook,
})
elseif props.unavailableStorybook then
return React.createElement(StorybookError, {
unavailableStorybook = props.unavailableStorybook,
})
else
return React.createElement(NoStorySelected)
end
Expand Down
8 changes: 7 additions & 1 deletion src/Panels/Sidebar.luau
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ local StorybookTreeView = require("@root/Storybook/StorybookTreeView")
local useTheme = require("@root/Common/useTheme")

type LoadedStorybook = Storyteller.LoadedStorybook
type UnavailableStorybook = Storyteller.UnavailableStorybook

local e = React.createElement

type Props = {
layoutOrder: number?,
onStoryChanged: (storyModule: ModuleScript?, storybook: LoadedStorybook?) -> (),
storybooks: { LoadedStorybook },
onShowErrorPage: (unavailableStorybook: UnavailableStorybook) -> (),
storybooks: {
avialable: { LoadedStorybook },
unavailable: { UnavailableStorybook },
},
}

local function Sidebar(props: Props)
Expand Down Expand Up @@ -82,6 +87,7 @@ local function Sidebar(props: Props)
searchTerm = search,
storybooks = props.storybooks,
onStoryChanged = props.onStoryChanged,
onShowErrorPage = props.onShowErrorPage,
}),
}),
})
Expand Down
20 changes: 13 additions & 7 deletions src/Plugin/PluginApp.luau
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
local ModuleLoader = require("@pkg/ModuleLoader")
local React = require("@pkg/React")
local Storyteller = require("@pkg/Storyteller")

Expand All @@ -15,6 +14,7 @@ local useTheme = require("@root/Common/useTheme")
local TOPBAR_HEIGHT_PX = 32

type LoadedStorybook = Storyteller.LoadedStorybook
type UnavailableStorybook = Storyteller.UnavailableStorybook

export type Props = {
loader: ModuleLoader.ModuleLoader,
Expand All @@ -26,20 +26,25 @@ local function App(props: Props)
local storybooks = Storyteller.useStorybooks(game, props.loader)
local storyModule: ModuleScript?, setStoryModule = React.useState(nil :: ModuleScript?)
local storybook, setStorybook = React.useState(nil :: LoadedStorybook?)
local unavailableStorybook, setUnavailableStorybook = React.useState(nil :: LoadedStorybook?)
local initialSidebarWidth = settingsContext.getSetting("sidebarWidth")
local sidebarWidth, setSidebarWidth = React.useState(initialSidebarWidth)
local navigation = NavigationContext.use()

local onStoryChanged = React.useCallback(function(newStoryModule: ModuleScript?, newStorybook: LoadedStorybook?)
navigation.navigateTo("Home")

setStoryModule(function(prev: ModuleScript?)
return if prev ~= newStoryModule then newStoryModule else nil
end)

setUnavailableStorybook(nil)
setStoryModule(newStoryModule)
setStorybook(newStorybook)
end, { navigation.navigateTo } :: { unknown })

local onShowErrorPage = React.useCallback(function(newUnavailableStorybook: UnavailableStorybook)
setStoryModule(nil)
setStorybook(nil)
setUnavailableStorybook(newUnavailableStorybook)
end, {})

local onSidebarResized = React.useCallback(function(newSize: Vector2)
setSidebarWidth(newSize.X)
end, {})
Expand Down Expand Up @@ -67,7 +72,8 @@ local function App(props: Props)
}, {
Sidebar = React.createElement(Sidebar, {
onStoryChanged = onStoryChanged,
storybooks = storybooks.available,
onShowErrorPage = onShowErrorPage,
storybooks = storybooks,
}),
}),

Expand All @@ -91,9 +97,9 @@ local function App(props: Props)
BackgroundTransparency = 1,
}, {
Screen = React.createElement(Screen, {
loader = props.loader,
story = storyModule,
storybook = storybook,
unavailableStorybook = unavailableStorybook,
}),
}),
}),
Expand Down
27 changes: 23 additions & 4 deletions src/Storybook/StoryError.luau
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
local React = require("@pkg/React")
local SelectableTextLabel = require("@root/Forms/SelectableTextLabel")

local CodeBlock = require("@root/Common/CodeBlock")
local ScrollingFrame = require("@root/Common/ScrollingFrame")
local useTheme = require("@root/Common/useTheme")

export type Props = {
Expand All @@ -10,10 +12,27 @@ export type Props = {
local function StoryError(props: Props)
local theme = useTheme()

return React.createElement(SelectableTextLabel, {
return React.createElement(ScrollingFrame, {
ScrollingDirection = Enum.ScrollingDirection.XY,
LayoutOrder = props.layoutOrder,
Text = props.err,
TextColor3 = theme.alert,
}, {
Layout = React.createElement("UIListLayout", {
SortOrder = Enum.SortOrder.LayoutOrder,
FillDirection = Enum.FillDirection.Horizontal,
Padding = theme.padding,
}),

Padding = React.createElement("UIPadding", {
PaddingTop = theme.paddingSmall,
PaddingRight = theme.paddingSmall,
PaddingBottom = theme.paddingSmall,
PaddingLeft = theme.paddingSmall,
}),

CodeBlock = React.createElement(CodeBlock, {
source = props.err,
sourceColor = theme.alert,
}),
})
end

Expand Down
112 changes: 112 additions & 0 deletions src/Storybook/StorybookError.luau
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
local React = require("@pkg/React")
local Sift = require("@pkg/Sift")
local Storyteller = require("@pkg/Storyteller")

local CodeBlock = require("@root/Common/CodeBlock")
local ScrollingFrame = require("@root/Common/ScrollingFrame")
local nextLayoutOrder = require("@root/Common/nextLayoutOrder")
local useTheme = require("@root/Common/useTheme")

type UnavailableStorybook = Storyteller.UnavailableStorybook

export type Props = {
unavailableStorybook: UnavailableStorybook,
layoutOrder: number?,
}

local function StoryError(props: Props)
local theme = useTheme()

local storybookSource = props.unavailableStorybook.storybook.source.Source

return React.createElement(ScrollingFrame, {
ScrollingDirection = Enum.ScrollingDirection.XY,
LayoutOrder = props.layoutOrder,
}, {
Layout = React.createElement("UIListLayout", {
SortOrder = Enum.SortOrder.LayoutOrder,
FillDirection = Enum.FillDirection.Vertical,
Padding = theme.paddingLarge,
}),

Padding = React.createElement("UIPadding", {
PaddingTop = theme.paddingLarge,
PaddingRight = theme.paddingLarge,
PaddingBottom = theme.paddingLarge,
PaddingLeft = theme.paddingLarge,
}),

MainText = React.createElement("TextLabel", {
LayoutOrder = nextLayoutOrder(),
Text = `Failed to load {props.unavailableStorybook.storybook.name}`,
AutomaticSize = Enum.AutomaticSize.XY,
BackgroundTransparency = 1,
Font = theme.font,
TextColor3 = theme.text,
TextSize = theme.textSize,
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Center,
}),

Problem = React.createElement("Frame", {
AutomaticSize = Enum.AutomaticSize.XY,
BackgroundTransparency = 1,
LayoutOrder = nextLayoutOrder(),
}, {
Layout = React.createElement("UIListLayout", {
SortOrder = Enum.SortOrder.LayoutOrder,
FillDirection = Enum.FillDirection.Vertical,
Padding = theme.padding,
}),

Title = React.createElement("TextLabel", {
LayoutOrder = nextLayoutOrder(),
Text = "Error",
AutomaticSize = Enum.AutomaticSize.XY,
BackgroundTransparency = 1,
Font = theme.headerFont,
TextColor3 = theme.text,
TextSize = theme.headerTextSize,
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Center,
}),

CodeBlock = React.createElement(CodeBlock, {
source = props.unavailableStorybook.problem,
sourceColor = theme.alert,
layoutOrder = nextLayoutOrder(),
}),
}),

StorybookSource = React.createElement("Frame", {
AutomaticSize = Enum.AutomaticSize.XY,
BackgroundTransparency = 1,
LayoutOrder = nextLayoutOrder(),
}, {
Layout = React.createElement("UIListLayout", {
SortOrder = Enum.SortOrder.LayoutOrder,
FillDirection = Enum.FillDirection.Vertical,
Padding = theme.padding,
}),

Title = React.createElement("TextLabel", {
LayoutOrder = nextLayoutOrder(),
Text = "Storybook Source",
AutomaticSize = Enum.AutomaticSize.XY,
BackgroundTransparency = 1,
Font = theme.headerFont,
TextColor3 = theme.text,
TextSize = theme.headerTextSize,
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Center,
}),

CodeBlock = React.createElement(CodeBlock, {
source = storybookSource,
layoutOrder = nextLayoutOrder(),
}),
}),
})
end

return StoryError
31 changes: 31 additions & 0 deletions src/Storybook/StorybookError.story.luau
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
local React = require("@pkg/React")
local Storyteller = require("@pkg/Storyteller")

local ContextProviders = require("@root/Common/ContextProviders")
local MockPlugin = require("@root/Testing/MockPlugin")
local StorybookError = require("@root/Storybook/StorybookError")

type UnavailableStorybook = Storyteller.UnavailableStorybook

return {
summary = "Component for displaying error messages to the user",
story = function()
local storybookModule = script.Parent.Parent["init.storybook"]
local unavailableStorybook: UnavailableStorybook = {
problem = "Something went wrong!",
storybook = {
name = storybookModule.Name,
source = storybookModule,
loader = {} :: any,
},
}

return React.createElement(ContextProviders, {
plugin = MockPlugin.new() :: any,
}, {
StorybookError = React.createElement(StorybookError, {
unavailableStorybook = unavailableStorybook,
}),
})
end,
}
Loading

0 comments on commit ea6048b

Please sign in to comment.