This commit is contained in:
Justin Blake 2026-05-26 16:03:24 -04:00
commit 22ae65c92f
No known key found for this signature in database
GPG key ID: E70CAC45C816AAEA
8 changed files with 188 additions and 0 deletions

8
src/Desktop.gren Normal file
View file

@ -0,0 +1,8 @@
module Desktop exposing (Desktop)
{-| Phantom-type tag for desktop-specific UI elements and views.
-}
type Desktop
= Desktop

8
src/Mobile.gren Normal file
View file

@ -0,0 +1,8 @@
module Mobile exposing (Mobile)
{-| Phantom-type tag for mobile-specific UI elements and views.
-}
type Mobile
= Mobile

33
src/Skog.gren Normal file
View file

@ -0,0 +1,33 @@
module Skog exposing (Program, program)
{-| Define a multi-platform Skog program.
The app provides shared `init`, `update`, and `subscriptions` along with
separate `mobileView` and `desktopView` functions. Bridges (SwiftUI,
Compose, DOM) consume the views; this stub just wires up a Platform.worker.
-}
import Desktop exposing (Desktop)
import Mobile exposing (Mobile)
import Platform
import UI
type alias Program model msg =
Platform.Program {} model msg
program :
{ init : { model : model, command : Cmd msg }
, update : msg -> model -> { model : model, command : Cmd msg }
, subscriptions : model -> Sub msg
, mobileView : model -> UI.Element Mobile msg
, desktopView : model -> UI.Element Desktop msg
}
-> Program model msg
program config =
Platform.worker
{ init = \_ -> config.init
, update = config.update
, subscriptions = config.subscriptions
}

82
src/UI.gren Normal file
View file

@ -0,0 +1,82 @@
module UI exposing
( Element
, text
, column
, row
, button
, image
)
{-| Cross-platform UI primitives.
The `platform` type parameter stays polymorphic for elements that work
everywhere. Platform-specific elements live in the `Mobile` and `Desktop`
modules and constrain the parameter.
-}
import UI.Attribute exposing (Attribute)
type Element platform msg
= Text
{ attributes : Array (Attribute platform msg)
, content : String
}
| Column
{ attributes : Array (Attribute platform msg)
, children : Array (Element platform msg)
}
| Row
{ attributes : Array (Attribute platform msg)
, children : Array (Element platform msg)
}
| Button
{ attributes : Array (Attribute platform msg)
, onPress : msg
, label : Element platform msg
}
| Image
{ attributes : Array (Attribute platform msg)
, source : String
}
text : Array (Attribute platform msg) -> String -> Element platform msg
text attributes content =
Text { attributes = attributes, content = content }
column :
Array (Attribute platform msg)
-> Array (Element platform msg)
-> Element platform msg
column attributes children =
Column { attributes = attributes, children = children }
row :
Array (Attribute platform msg)
-> Array (Element platform msg)
-> Element platform msg
row attributes children =
Row { attributes = attributes, children = children }
button :
Array (Attribute platform msg)
-> { onPress : msg, label : Element platform msg }
-> Element platform msg
button attributes config =
Button
{ attributes = attributes
, onPress = config.onPress
, label = config.label
}
image :
Array (Attribute platform msg)
-> String
-> Element platform msg
image attributes source =
Image { attributes = attributes, source = source }

19
src/UI/Attribute.gren Normal file
View file

@ -0,0 +1,19 @@
module UI.Attribute exposing (Attribute, padding, backgroundColor)
{-| Styling attributes for UI elements.
-}
type Attribute platform msg
= Padding Int
| BackgroundColor String
padding : Int -> Attribute platform msg
padding amount =
Padding amount
backgroundColor : String -> Attribute platform msg
backgroundColor color =
BackgroundColor color