mirror of
https://github.com/centau/vide.git
synced 2026-08-20 14:41:37 +00:00
Initial commit
This commit is contained in:
commit
cb002f4f27
50 changed files with 4666 additions and 0 deletions
23
docs/tut/crash-course/1-introduction.md
Normal file
23
docs/tut/crash-course/1-introduction.md
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# Introduction
|
||||
|
||||
This is a brief tutorial designed to give you a quick run through the usage of
|
||||
Vide.
|
||||
|
||||
Vide is largely inspired by other UI libraries such as Solid and Fusion.
|
||||
|
||||
## Why Vide?
|
||||
|
||||
Creating UI is a slow and tedious process. The purpose of Vide is to make UI
|
||||
declarative and concise, making it faster to create and more importantly easier
|
||||
to maintain. Vide achieves this using a reactive style of programming which
|
||||
allows you to focus on the flow of data through your application without
|
||||
worrying about manually updating UI instances.
|
||||
|
||||
Some of the main focuses behind Vide's design choices:
|
||||
|
||||
- Concise syntax to reduce verbosity as much as possible.
|
||||
- Reducing the amount of imports needed for usage by using Luau's syntax and
|
||||
semantics.
|
||||
- Being completely typecheckable.
|
||||
- Flexibility, particularly with integrating other libraries and allowing users
|
||||
to use their own patterns.
|
||||
60
docs/tut/crash-course/2-creation.md
Normal file
60
docs/tut/crash-course/2-creation.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# Creating UI Elements
|
||||
|
||||
Instances are created using [`create()`](../../api/creation.md#create).
|
||||
|
||||
```lua
|
||||
local vide = require(path_to_vide)
|
||||
local create = vide.create
|
||||
```
|
||||
|
||||
`create()` returns a constructor for a given class which then takes a table of
|
||||
properties to assign when creating a new instance for that class.
|
||||
|
||||
```lua
|
||||
local frame = create "Frame" {
|
||||
Name = "Background",
|
||||
Position = UDim2.fromScale(0.5, 0.5)
|
||||
}
|
||||
```
|
||||
|
||||
String keys are assigned as properties and integer keys are assigned as child
|
||||
instances.
|
||||
|
||||
```lua
|
||||
create "ScreenGui" {
|
||||
Parent = game.StarterGui,
|
||||
|
||||
create "Frame" {
|
||||
AnchorPoint = Vector2.new(0.5, 0.5),
|
||||
Position = UDim2.fromScale(0.5, 0.5),
|
||||
Size = UDim2.fromScale(0.4, 0.7),
|
||||
|
||||
create "TextLabel" {
|
||||
Text = "hi"
|
||||
},
|
||||
|
||||
create"TextLabel" {
|
||||
Text = "bye"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To connect to an event, just set the event property name to a function.
|
||||
|
||||
All event arguments are passed into the function.
|
||||
|
||||
```lua
|
||||
create "TextButton" {
|
||||
Activated = function()
|
||||
print "clicked!"
|
||||
end
|
||||
}
|
||||
```
|
||||
|
||||
In short:
|
||||
|
||||
- String keys = properties
|
||||
- Function values = events
|
||||
- Non-function values = property values
|
||||
- Numeric keys = children
|
||||
47
docs/tut/crash-course/3-components.md
Normal file
47
docs/tut/crash-course/3-components.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# Components
|
||||
|
||||
Components are custom-made reusable pieces of UI made from other pieces of UI.
|
||||
|
||||
Using components you make your application more modular and better organized.
|
||||
|
||||
Components leverage functions to create self-contained UI that can even have
|
||||
its own state and behavior.
|
||||
|
||||
```lua
|
||||
local function Button(props: {
|
||||
Position: UDim2,
|
||||
Text: string,
|
||||
Callback: () -> ()
|
||||
})
|
||||
return create "TextButton" {
|
||||
BackgroundColor3 = Color3.fromRGB(50, 50, 50),
|
||||
Size = UDim2.fromOffset(400, 250),
|
||||
|
||||
Position = props.Position,
|
||||
Text = props.Text,
|
||||
Callback = props.Callback
|
||||
}
|
||||
end
|
||||
|
||||
local button = Button {
|
||||
Position = UDim2.new(),
|
||||
Text = "Click me!",
|
||||
|
||||
Callback = function()
|
||||
print "clicked"
|
||||
end
|
||||
}
|
||||
```
|
||||
|
||||
Above is a simple example of a button component with its background color set to
|
||||
a dark grey and with a fixed size.
|
||||
|
||||
A single parameter `props` is used to pass properties to the component.
|
||||
|
||||
Components allow you to *encapsulate* behavior. You can only modify the
|
||||
component in ways that you allow in the component.
|
||||
|
||||
This also promotes code reusability. Anytime you want a new button all you do
|
||||
is call `Button {}` instead of creating and setting every property each time.
|
||||
|
||||
This can be extended to much more complicated UI.
|
||||
56
docs/tut/crash-course/4-state.md
Normal file
56
docs/tut/crash-course/4-state.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# State
|
||||
|
||||
State in Vide are the core of reactivity in Vide.
|
||||
|
||||
State contain values that can change, and when they do change, automatically
|
||||
update anything that is using it.
|
||||
|
||||
A state object in Vide can be created using
|
||||
[`source()`](../../api/reactivity-core.md#source).
|
||||
|
||||
```lua
|
||||
local source = vide.source
|
||||
```
|
||||
|
||||
```lua
|
||||
local count = source(0)
|
||||
```
|
||||
|
||||
The value of a state can be set by calling it with an argument, and can be read
|
||||
by calling it with no arguments.
|
||||
|
||||
```lua
|
||||
count(count() + 1) -- increment count state by 1
|
||||
```
|
||||
|
||||
Below is an example of a counter component that has state.
|
||||
|
||||
```lua
|
||||
local function Counter()
|
||||
local count = source(0)
|
||||
|
||||
return create "TextButton" {
|
||||
Text = count,
|
||||
|
||||
Activated = function()
|
||||
count(count() + 1)
|
||||
end
|
||||
}
|
||||
end
|
||||
```
|
||||
|
||||
Any time the source value is set, anything depending on it will automatically be
|
||||
updated using the new value.
|
||||
|
||||
Vide detects when you assign a function to a property. This is known
|
||||
as *binding* and doing so will cause the property to *automatically* update
|
||||
whenever a state in that function is updated, by rerunning the function and
|
||||
assigning its return value. You can only bind non-event
|
||||
properties, otherwise the function is connected as the event callback.
|
||||
|
||||
You as the programmer do not have to worry about manually updating variables or
|
||||
UI instances, you can just focus on defining how the data maps to UI and
|
||||
everything will update when changes occur.
|
||||
|
||||
Each call of `Counter {}` will create a new counter element, each with their own
|
||||
independent count state.
|
||||
58
docs/tut/crash-course/5-derived-state.md
Normal file
58
docs/tut/crash-course/5-derived-state.md
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# Derived State
|
||||
|
||||
You can create new state from existing states. This is known as *deriving
|
||||
state*.
|
||||
|
||||
A function that wraps a state effectively becomes a state. If a state used
|
||||
inside a function is updated, the whole function can be re-ran to recompute
|
||||
its value.
|
||||
|
||||
```lua
|
||||
local count = source(0)
|
||||
|
||||
local function text()
|
||||
return "count: " .. count()
|
||||
end
|
||||
|
||||
create "TextLabel" {
|
||||
Text = text
|
||||
}
|
||||
```
|
||||
|
||||
Sometimes when using expensive computations to derive state, you only want to
|
||||
recalculate it once when a source state has changed
|
||||
|
||||
If you wrap a source state with a regular function, its value will be recomputed
|
||||
every time you call that function.
|
||||
[`derive()`](../../api/reactivity-core.md#derive) accepts a functions whose
|
||||
return value will be cached, so that subsequent calls of this derived state
|
||||
will return the same cached value until one of its source states have changed.
|
||||
|
||||
```lua
|
||||
local derive = vide.derive
|
||||
```
|
||||
|
||||
```lua
|
||||
local count = source(0)
|
||||
|
||||
local factorial = derive(function()
|
||||
local n = 1
|
||||
for i = 2, count() do
|
||||
n *= i
|
||||
end
|
||||
return n
|
||||
end)
|
||||
```
|
||||
|
||||
This can improve performance for expensive calculations.
|
||||
|
||||
```lua
|
||||
create "TextLabel" {
|
||||
Text = function()
|
||||
return "factorial squared: " .. factorial() * factorial()
|
||||
end
|
||||
}
|
||||
|
||||
count(3) -- displays "factorial squared: 36"
|
||||
count(4) -- displays "factorial squared: 576"
|
||||
```
|
||||
35
docs/tut/crash-course/6-table-state.md
Normal file
35
docs/tut/crash-course/6-table-state.md
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Table State
|
||||
|
||||
Vide has functions for dealing with table states.
|
||||
|
||||
Below is an example using the above `List` class.
|
||||
|
||||
```lua
|
||||
type Item = {
|
||||
Name: string,
|
||||
Icon: number
|
||||
}
|
||||
|
||||
local items = source({} :: Array<Item>)
|
||||
|
||||
List {
|
||||
Children = indexes(items, function(item, i)
|
||||
return create "ImageLabel" {
|
||||
Image = function()
|
||||
return "rbxassetid://" .. item().Icon
|
||||
end,
|
||||
|
||||
LayoutOrder = i
|
||||
}
|
||||
end)
|
||||
}
|
||||
```
|
||||
|
||||
Here we map each element in `items` to a value returned by a callback.
|
||||
|
||||
The callback is called only *once* per key. The first argument given to the
|
||||
callback is a state that has the value of the table key's value.
|
||||
|
||||
Anytime the value of the corresponding table key changes, the state value
|
||||
changes too. This saves us from having to recreate a UI element any time a
|
||||
table index changes.
|
||||
98
docs/tut/crash-course/7-property-groups.md
Normal file
98
docs/tut/crash-course/7-property-groups.md
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
# Property Groups
|
||||
|
||||
Often when creating components from existing components, you can find yourself
|
||||
repetitively passing through properties such as size or position.
|
||||
|
||||
```lua
|
||||
function Background(props: {
|
||||
Color: Color3,
|
||||
AnchorPoint: UDim2,
|
||||
Position: UDim2,
|
||||
Size: UDim2
|
||||
})
|
||||
return create "Frame" {
|
||||
Color = props.Color
|
||||
AnchorPoint = props.AnchorPoint,
|
||||
Position = props.Position,
|
||||
Size = props.Size
|
||||
}
|
||||
end
|
||||
|
||||
function Menu(props: {
|
||||
Color = props.Color
|
||||
AnchorPoint: UDim2,
|
||||
Position: UDim2,
|
||||
Size: UDim2
|
||||
})
|
||||
return Background {
|
||||
Color = props.COlor,
|
||||
AnchorPoint = props.AnchorPoint,
|
||||
Position = props.Position,
|
||||
Size = props.Size
|
||||
}
|
||||
end
|
||||
```
|
||||
|
||||
One way this can be avoided is by using *property nesting*. In Vide, passign a
|
||||
table value inside `props` has special semantics. Any key with a table value is
|
||||
not assigned like a property, instead the table is iterated and processed just
|
||||
like the outer table is. Any properties in the nested table will be assigned
|
||||
to the instance just the same.
|
||||
|
||||
Below is an example of how you can use this to pass groups of similar properties
|
||||
together such as position and size, while also using typechecking.
|
||||
|
||||
```lua
|
||||
type Layout = {
|
||||
Layout = {
|
||||
Position: UDim2?,
|
||||
Size: UDim2?,
|
||||
AnchorPoint: Vector2?
|
||||
}
|
||||
}
|
||||
|
||||
function Background(props: Layout & { Color: Color3 })
|
||||
return create "Frame" {
|
||||
Color = props.Color,
|
||||
props.Layout
|
||||
}
|
||||
end
|
||||
|
||||
function Menu(props: Layout & { Color: Color3 })
|
||||
return Background {
|
||||
Color = props.Color,
|
||||
Layout = props.Layout
|
||||
}
|
||||
end
|
||||
```
|
||||
|
||||
Here we created a nested group with the key `Layout` that can accept
|
||||
layout-related properties. Any name could be chosen for the key.
|
||||
This allows us to write much more concise syntax that is also typecheckable.
|
||||
|
||||
The same can be done for properties such as children to pass table of instances.
|
||||
|
||||
```lua
|
||||
type Children = {
|
||||
Children = Array<Instance>
|
||||
}
|
||||
|
||||
local function List(props: Children & Layout)
|
||||
return create "Frame" {
|
||||
props.Layout,
|
||||
props.Children,
|
||||
create "UIListLayout" {}
|
||||
}
|
||||
end
|
||||
|
||||
List {
|
||||
Layout = {
|
||||
Position = UDim2.new()
|
||||
},
|
||||
|
||||
Children = {
|
||||
create "TextLabel" { Text = "1" },
|
||||
create "TextLabel" { Text = "2" }
|
||||
}
|
||||
}
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue