Skip to content

Commit

Permalink
Setup tech specs
Browse files Browse the repository at this point in the history
  • Loading branch information
vocksel committed Nov 2, 2024
1 parent 65e5a41 commit 3ca0357
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 5 deletions.
10 changes: 5 additions & 5 deletions docs/docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@ sidebar_position: 5

# Contributing

# Onboarding
## Onboarding

# Building
## Building

```lua
lune run build
```

# Running tests
## Running tests

```lua
lune run test
```

# Adding new renderers
## Adding new renderers

[Story Renderer Spec](https://www.notion.so/Story-Renderer-Spec-4260feeab4574ad68f87006dee57cf75?pvs=21)

# Creating releases
## Creating releases

Create GitHub release with tag

Expand Down
1 change: 1 addition & 0 deletions docs/docs/tech-specs/intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Tech Specs
144 changes: 144 additions & 0 deletions docs/docs/tech-specs/story-renderers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# Story Renderers Spec

The render API allows any UI library to be supported as the renderer for a Storyteller story.

For each renderer, Storyteller provides a mounting point, context, and lifecycle hooks to handle rendering, lifetime, and cleanup.

## Supported renderers

| **Name** | **Format** |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| React | Result of `React.createElement` or a function that takes `props` as the first argument and creates an element |
| Roact | Result of `Roact.createElement` or a function that takes `props` as the first argument and creates an element |
| Fusion | Result of `Fusion.New` or a function that takes `props` as the first argument and creates an Instance |
| Manual | A function that takes `props` as the first argument and returns an Instance |
| Functional (Legacy) | A function that takes `target` as the first argument, `props` as the second, and optionally returns a function for manually cleaning up |
| Hoarcekat (Legacy) | Same as `Functional (Legacy)` but the story file itself is represented by a function |

Future:
- [Vide](https://centau.github.io/vide/)
- [Blend](https://quenty.github.io/NevermoreEngine/api/Blend/)
- Developer Storybook (Roblox internal)

## Implementing a renderer

All renderers live here: https://github.com/flipbook-labs/storyteller/tree/main/src/renderers.

When writing tests for a renderer, the `render` function must be used to ensure each renderer behaves properly with lifecycles.

When adding a new renderer, use the existing ones as reference and use the below API docs to hook up all necessary behavior for your UI library.

## API

### Props

#### theme

`theme: "Dark" | "Light"`

The name of the current Roblox Studio theme.

#### container

`container: Instance`

The location where GuiObjects will be rendered to.

#### story

`story: Story`

Reference to the Story that is being rendered.

#### storybook

`storybook: Storybook`

Reference to the Storybook that the Story is a part of.

#### controls

`controls: { [string]: any }`

All the values provided by the story controls. The contents of this vary based on the story being rendered.

### Renderer

```lua
export type Renderer = {
mount: (container: Instance, element: unknown, context: Context) -> GuiObject | Folder,
update: ((controls: StoryControls<T>) -> ())?,

transformArgs: ((args: Args, context: Context) -> Args)?,
shouldUpdate: ((context: Context, prevContext: Context?) -> boolean)?,
unmount: ((context: Context) -> ())?,
}
```

#### mount

`mount(container: Instance, element: unknown, context: RenderContext)`

This function handles the initial mounting of a UI element to the container.

The first two arguments `container` and `element` are provided for convenience and are identical to `context.container` and `context.story.story`, respectively.

#### update

`update(context: RenderContext, prevContext: RenderContext)`

Called any time something changes to RenderContext and determines if the story should re-render, and how.

This is a general purpose function for handling any context change. For example, by comparing `context` and `prevContext` a renderer can choose how it wants to re-render a story when controls change. In the case of Roact new GuiObjects are created, whereas Fusion relies on stable identities and instead relies on `transformContext` to

#### unmount

`unmount()`

Called when a story is closed. This function handles cleanup for the `mount` function so there are no lingering UI elements between stories.

#### transformContext

`transformContext(context: RenderContext, prevContext: RenderContext?): RenderContext`

This function is always called before `mount` and `update` in order to transform the RenderContext object provided to them.

For the Fusion renderer, `context.controls` has each of its values mapped to `Fusion.Value`, and if `prevContext` is supplied then each Value has `:set()` called on it. This ensures the rendered GuiObjects maintain stable identities, while still updating from changes to controls.

## Usage

### React

```lua
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local React = require(ReplicatedStorage.Packages.React)
local ReactRoblox = require(ReplicatedStorage.Packages.ReactRoblox)

return {
storyRoots = {
script.Parent.Components,
},
packages = {
React = React,
ReactRoblox = ReactRoblox,
},
}
```

### Fusion

```lua
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Fusion = require(ReplicatedStorage.Packages.Fusion)

return {
storyRoots = {
script.Parent.Components,
},
packages = {
Fusion = Fusion,
},
}
```
6 changes: 6 additions & 0 deletions docs/docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ const config: Config = {
{
to: "/api/",
label: "API",
position: "left"
},
{
type: 'docSidebar',
sidebarId: 'specs',
label: "Specs",
position: "left"
},
{
Expand Down
6 changes: 6 additions & 0 deletions docs/sidebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ const sidebars: SidebarsConfig = {
"migration-guide",
"contributing",
],
specs: [
{
type: 'autogenerated',
dirName: 'tech-specs',
},
],
// But you can create a sidebar manually
/*
tutorialSidebar: [
Expand Down

0 comments on commit 3ca0357

Please sign in to comment.