Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/freddi301/idris-2-ui
Declarative UI in Idris 2!
https://github.com/freddi301/idris-2-ui
Last synced: 14 days ago
JSON representation
Declarative UI in Idris 2!
- Host: GitHub
- URL: https://github.com/freddi301/idris-2-ui
- Owner: freddi301
- License: mit
- Created: 2024-05-11T16:20:11.000Z (9 months ago)
- Default Branch: master
- Last Pushed: 2024-07-16T05:41:03.000Z (7 months ago)
- Last Synced: 2024-07-16T08:04:16.850Z (7 months ago)
- Language: Idris
- Size: 121 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# Idris 2 UI
Make declaritve UIs in Idris 2!
This library aims to provide the developer experience inspired by react native.
# ROADMAP
- [x] basic web devolpment
- [x] recompile on save (manual reload in browser is still needed)
- [ ] inspector
- [ ] basic mobile development**⚠️ DISCLAIMER ⚠️**
This project is meant for inspiring production-ready packages and as a testing ground for iterations to reach the best developer experience possible.
Iterations code is all kept, in separate packages.
# TODO APP
| [try it online](https://freddi301.github.io/idris-2-ui/src/Demo25/doc/todo.html) | [source](src/Demo25/TodoApp.idr) |
| -------------------------------------------------------------------------------- | -------------------------------- |![screenshot](src/Demo25/doc/todo.png)
# Usage
- clone this repository
- [dev machine setup](DEV-MACHINE-SETUP.md)
- run `./watch-build.sh`
- edit [source file](src/Demo25/Usage.idr) and save
- open [output file](build/exec/index.html), reload after save (wait for compiler to finish)```idris
module Demo25.Usageimport Demo25.UI.View
import Demo25.UI.Browser.Viewimport Demo25.TodoApp
--- Hello world
HelloWorldApp = Text "Hello World"
--- Component instances
Counter : { default 1 step : Int } -> View
Counter = do
(count, setCount) <- useState $ the Int 0
Flex { style = s{ direction = Row } } [
Text "\{show count}",
Text { press = [setCount $ count + step] } "+\{show step}"
]ComponentInstancesApp = Flex { style = s{ direction = Col } } [
Counter,
Counter { step = 2 }
]--- Naive Routing
namespace NaiveRouting
data Route = HomeRoute | AboutRoute
HomeScreen = Text "Home"
AboutScreen = Text "About"
matchRoute : Route -> View
matchRoute HomeRoute = HomeScreen
matchRoute AboutRoute = AboutScreenexport
NaiveRoutingApp : View
NaiveRoutingApp = do
(currentRoute, setCurrentRoute) <- useState HomeRoute
Flex { style = s{ direction = Col } } [
Flex { style = s{ direction = Row } } [
Text { press = [setCurrentRoute HomeRoute] } "Home",
Text { press = [setCurrentRoute AboutRoute] } "About"
],
matchRoute currentRoute
]--- Simple todos
SimpleTodosApp = do
(text, setText) <- useState $ the String ""
(todos, setTodos) <- useState $ the (List String) []
let addTodo = [
setTodos (text :: todos),
setText ""
]
Flex { style = s{ direction = Col } } [
Flex { style = s{ direction = Row } } [
Input { value = text, change = (\text => [setText text]) },
Text { press = addTodo } "add"
],
Flex { style = s{ direction = Col } } $ (flip map) todos $ \todo => Text todo
]--- Routing
namespace Routing
interface Route where view : View
navigateContext = createContext (Route -> List StateUpdate)
routeContext = createContext RouteLink : (to : Route) -> (content : String) -> View
Link to content = do
navigate <- navigateContext
Text { press = navigate to } contentRouter : (initial : Route) -> (render: (outlet : View) -> View) -> View
Router initial render = do
(currentRoute, setCurrentRoute) <- useState initial
let navigate = \to => [setCurrentRoute to]
let contextProviders = (Provider navigateContext navigate) . (Provider routeContext currentRoute)
contextProviders (render (view @{currentRoute}))---
[Home] Route where
view = Text "HOME"[About] Route where
view = Text "ABOUT"[Product] {id : String} -> Route where
view = Text "PRODUCT \{id}"[Counters] Route where
view = Flex { style = s{ direction = Col } } [
Counter,
Counter { step = 3 }
]export
RoutingApp : View
RoutingApp = Router Home $ \outlet =>
Flex { style = s{ direction = Col } } [
Text "RoutingApp",
Flex { style = s{ direction = Row } } [
Link Home "Home",
Link About "About",
Link (Product { id = "1" }) "Product (1)",
Link (Product { id = "2" }) "Product (2)",
Link Counters "Counters"
],
outlet
]--- Styling
StyledApp = Flex [
Input {
style = s{
color = rgba 200 200 200 0.5
},
value = "",
change = \value => []
},
Text {
style = s{
font = s{
family = "Roboto",
size = 32,
weight = 800,
style = Italic
},
color = rgb 255 0 0,
align = Center,
lineHeight = 2
}
} "Hello\nworld",
Flex {
style = s{
direction = Row,
margin = s{ all = 1, vertical = 2, horizontal = 3, top = 4, right = 5, bottom = 6, left = 7 },
padding = s{ all = 1, vertical = 2, horizontal = 3, top = 4, right = 5, bottom = 6, left = 7 },
border = s{
width = s{ all = 1, vertical = 2, horizontal = 3, top = 4, right = 5, bottom = 6, left = 7 },
radius = s{
all = 1,
top = 2,
left = 3,
bottom = 4,
right = 5,
topLeft = 6,
topRight = 7,
bottomRight = 8,
bottomLeft = 9
},
color = s{
all = rgba 10 0 0 0.5,
vertical = rgba 20 0 0 0.5,
horizontal = rgba 30 0 0 0.5,
top = rgba 40 0 0 0.5,
right = rgba 50 0 0 0.5,
bottom = rgba 60 0 0 0.5,
left = rgba 70 0 0 0.5
}
},
background = rgb 0 255 0,
gap = s{ all = 1, col = 2, row = 3 }, -- aka css flex-gap
wrap = True, -- aka css flex-wrap
justify = Center, -- aka css justify-content
align = End, -- aka css self-align
grow = 2, -- aka css flex-grow
width = s{ min = psf 0.2, max = psf 0.3 }, -- parent size fraction aka css percentage / 100
height = dip 200 -- density indipendent pixels aka css pixels
}
} []
]--- render
main : IO ()
main = do
root <- Root.create
root.render [
TodoApp,
HelloWorldApp,
NaiveRoutingApp,
ComponentInstancesApp,
SimpleTodosApp,
RoutingApp,
StyledApp
]```