mirror of
https://github.com/ryan-haskell/elm-spa.git
synced 2024-11-25 18:56:16 +03:00
im really happy with this thing 😭
This commit is contained in:
parent
2c9d529f84
commit
fb0e01a083
4
examples/docs/.gitignore
vendored
Normal file
4
examples/docs/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
elm-stuff
|
||||
dist
|
24
examples/docs/README.md
Normal file
24
examples/docs/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# your elm-spa
|
||||
> learn more at [https://elm-spa.dev](https://elm-spa.dev)
|
||||
|
||||
### local development
|
||||
|
||||
```
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## folder structure
|
||||
|
||||
```elm
|
||||
README.md -- this file you're reading 👀
|
||||
elm.json -- has project dependencies
|
||||
src/
|
||||
Main.elm -- the entrypoint to the app
|
||||
Global.elm -- share state across pages
|
||||
Transitions.elm -- smoothly animate between pages
|
||||
Ports.elm -- communicate with JS
|
||||
Pages/ -- where all your pages go
|
||||
Layouts/ -- reusable views around pages
|
||||
Components/ -- views shared across the site
|
||||
Utils/ -- a place for helper functions
|
||||
```
|
31
examples/docs/elm.json
Normal file
31
examples/docs/elm.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"type": "application",
|
||||
"source-directories": [
|
||||
"src",
|
||||
"elm-stuff/.elm-spa"
|
||||
],
|
||||
"elm-version": "0.19.1",
|
||||
"dependencies": {
|
||||
"direct": {
|
||||
"elm/core": "1.0.2",
|
||||
"elm/html": "1.0.0",
|
||||
"elm/json": "1.1.3",
|
||||
"elm/url": "1.0.0",
|
||||
"elm-explorations/markdown": "1.0.0",
|
||||
"mdgriffith/elm-ui": "1.1.5",
|
||||
"ryannhg/elm-spa": "2.0.0"
|
||||
},
|
||||
"indirect": {
|
||||
"elm/browser": "1.0.2",
|
||||
"elm/time": "1.0.0",
|
||||
"elm/virtual-dom": "1.0.2"
|
||||
}
|
||||
},
|
||||
"test-dependencies": {
|
||||
"direct": {},
|
||||
"indirect": {}
|
||||
},
|
||||
"elm-spa": {
|
||||
"ui": "Element"
|
||||
}
|
||||
}
|
1457
examples/docs/package-lock.json
generated
Normal file
1457
examples/docs/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
24
examples/docs/package.json
Normal file
24
examples/docs/package.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "my-elm-spa-project",
|
||||
"version": "1.0.0",
|
||||
"description": "learn more at https://elm-spa.dev",
|
||||
"scripts": {
|
||||
"start": "npm install && npm run dev",
|
||||
"dev": "npm run elm:spa:build && npm run elm:spa:watch & npm run elm:live",
|
||||
"build": "npm run elm:spa:build && npm run elm:compile",
|
||||
"elm:compile": "elm make src/Main.elm --output=public/dist/elm.compiled.js --optimize",
|
||||
"elm:live": "elm-live src/Main.elm --dir=public --start-page=index.html --open --pushstate --port=1234 -- --output=public/dist/elm.compiled.js --debug",
|
||||
"elm:spa:build": "elm-spa build .",
|
||||
"elm:spa:watch": "SHELL=/bin/bash chokidar 'src/Pages' -c 'npm run elm:spa:build'"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"chokidar-cli": "2.1.0",
|
||||
"elm": "0.19.1-3",
|
||||
"elm-live": "4.0.1",
|
||||
"elm-spa": "2.0.4"
|
||||
}
|
||||
}
|
BIN
examples/docs/public/favicon.png
Normal file
BIN
examples/docs/public/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
25
examples/docs/public/index.html
Normal file
25
examples/docs/public/index.html
Normal file
@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
<title>our-elm-spa</title>
|
||||
<link rel="shortcut icon" href="/favicon.png" type="image/png">
|
||||
<link rel="stylesheet" href="/styles.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/styles/atom-one-light.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/highlight.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/languages/elm.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/languages/html.min.js"></script>
|
||||
<script src="/dist/elm.compiled.js"></script>
|
||||
<script src="/ports.js"></script>
|
||||
<script>
|
||||
window.hljs.initHighlightingOnLoad()
|
||||
window.addEventListener('load', _ => {
|
||||
window.ports.init(Elm.Main.init())
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
17
examples/docs/public/ports.js
Normal file
17
examples/docs/public/ports.js
Normal file
@ -0,0 +1,17 @@
|
||||
// On load, listen to Elm!
|
||||
window.addEventListener('load', _ => {
|
||||
window.ports = {
|
||||
init: (app) =>
|
||||
app.ports.outgoing.subscribe(({ action, data }) =>
|
||||
actions[action]
|
||||
? actions[action](data)
|
||||
: console.warn(`I didn't recognize action "${action}".`)
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
// maps actions to functions!
|
||||
const actions = {
|
||||
'LOG': (message) =>
|
||||
console.log(`From Elm:`, message)
|
||||
}
|
49
examples/docs/public/styles.css
Normal file
49
examples/docs/public/styles.css
Normal file
@ -0,0 +1,49 @@
|
||||
/* you can include CSS here */
|
||||
html, body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.markdown > * {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.markdown > *:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.markdown h3 {
|
||||
margin-top: 1.5em;
|
||||
line-height: 1.1;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.markdown h4 {
|
||||
line-height: 1.2;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.markdown p, ul, ol {
|
||||
line-height: 1.4;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.markdown pre {
|
||||
border: solid 1px #ddd;
|
||||
border-radius: 4px;
|
||||
padding: 1em;
|
||||
margin: 0 calc(4px - 1em);
|
||||
margin-top: 1em;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.markdown a {
|
||||
color: rgb(200, 75, 85);
|
||||
}
|
||||
|
||||
.markdown iframe {
|
||||
width: 100%;
|
||||
margin: 2em -1em;
|
||||
background: #eee;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
||||
}
|
53
examples/docs/src/Components/Hero.elm
Normal file
53
examples/docs/src/Components/Hero.elm
Normal file
@ -0,0 +1,53 @@
|
||||
module Components.Hero exposing (Options, view)
|
||||
|
||||
import Element exposing (..)
|
||||
import Element.Background as Background
|
||||
import Element.Border as Border
|
||||
import Element.Font as Font
|
||||
import Element.Region as Region
|
||||
import Ui exposing (colors, styles)
|
||||
|
||||
|
||||
type alias Options =
|
||||
{ title : String
|
||||
, subtitle : String
|
||||
, links :
|
||||
List
|
||||
{ label : String
|
||||
, url : String
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
view : Options -> Element msg
|
||||
view options =
|
||||
column
|
||||
[ paddingEach
|
||||
{ top = 128
|
||||
, left = 0
|
||||
, right = 0
|
||||
, bottom = 32
|
||||
}
|
||||
, centerX
|
||||
, spacing 24
|
||||
]
|
||||
[ column [ spacing 14, centerX ]
|
||||
[ el
|
||||
[ Font.size 56
|
||||
, Font.bold
|
||||
, centerX
|
||||
, Region.heading 1
|
||||
]
|
||||
(text options.title)
|
||||
, el [ centerX, alpha 0.5, Region.heading 2 ] (text options.subtitle)
|
||||
]
|
||||
, wrappedRow [ spacing 12, centerX ] <|
|
||||
List.map
|
||||
(\{ label, url } ->
|
||||
link styles.button
|
||||
{ label = text label
|
||||
, url = url
|
||||
}
|
||||
)
|
||||
options.links
|
||||
]
|
40
examples/docs/src/Components/Navbar.elm
Normal file
40
examples/docs/src/Components/Navbar.elm
Normal file
@ -0,0 +1,40 @@
|
||||
module Components.Navbar exposing (view)
|
||||
|
||||
import Element exposing (..)
|
||||
import Element.Font as Font
|
||||
import Generated.Routes as Routes exposing (Route, routes)
|
||||
import Ui exposing (colors, styles)
|
||||
|
||||
|
||||
view : Route -> Element msg
|
||||
view currentRoute =
|
||||
row
|
||||
[ spacing 24
|
||||
, centerX
|
||||
, width fill
|
||||
]
|
||||
[ row [ Font.color colors.coral, spacing 16 ]
|
||||
[ el [ Font.semiBold, Font.size 20 ]
|
||||
(viewLink currentRoute ( "elm-spa", routes.top ))
|
||||
, viewLink currentRoute ( "docs", routes.docs )
|
||||
, viewLink currentRoute ( "guide", routes.guide )
|
||||
]
|
||||
, el [ alignRight ] <|
|
||||
link styles.button
|
||||
{ label = text "get started"
|
||||
, url = "/guide"
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
viewLink : Route -> ( String, Route ) -> Element msg
|
||||
viewLink currentRoute ( label, route ) =
|
||||
if currentRoute == route then
|
||||
el styles.link.disabled
|
||||
(text label)
|
||||
|
||||
else
|
||||
link styles.link.enabled
|
||||
{ label = text label
|
||||
, url = Routes.toPath route
|
||||
}
|
2
examples/docs/src/Components/README.md
Normal file
2
examples/docs/src/Components/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# src/Components
|
||||
> views shared across the site
|
49
examples/docs/src/Global.elm
Normal file
49
examples/docs/src/Global.elm
Normal file
@ -0,0 +1,49 @@
|
||||
module Global exposing
|
||||
( Flags
|
||||
, Model
|
||||
, Msg(..)
|
||||
, init
|
||||
, subscriptions
|
||||
, update
|
||||
)
|
||||
|
||||
import Generated.Routes as Routes exposing (Route)
|
||||
import Ports
|
||||
|
||||
|
||||
type alias Flags =
|
||||
()
|
||||
|
||||
|
||||
type alias Model =
|
||||
{}
|
||||
|
||||
|
||||
type Msg
|
||||
= Msg
|
||||
|
||||
|
||||
type alias Commands msg =
|
||||
{ navigate : Route -> Cmd msg
|
||||
}
|
||||
|
||||
|
||||
init : Commands msg -> Flags -> ( Model, Cmd Msg, Cmd msg )
|
||||
init _ _ =
|
||||
( {}
|
||||
, Cmd.none
|
||||
, Ports.log "Hello!"
|
||||
)
|
||||
|
||||
|
||||
update : Commands msg -> Msg -> Model -> ( Model, Cmd Msg, Cmd msg )
|
||||
update _ _ model =
|
||||
( model
|
||||
, Cmd.none
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
|
||||
subscriptions : Model -> Sub Msg
|
||||
subscriptions _ =
|
||||
Sub.none
|
49
examples/docs/src/Layout.elm
Normal file
49
examples/docs/src/Layout.elm
Normal file
@ -0,0 +1,49 @@
|
||||
module Layout exposing (view)
|
||||
|
||||
import Components.Navbar as Navbar
|
||||
import Element exposing (..)
|
||||
import Element.Font as Font
|
||||
import Element.Region as Region
|
||||
import Utils.Spa as Spa
|
||||
|
||||
|
||||
view : Spa.LayoutContext msg -> Element msg
|
||||
view { page, route } =
|
||||
column
|
||||
[ height fill
|
||||
, width (fill |> maximum 512)
|
||||
, centerX
|
||||
, Font.size 16
|
||||
, Font.family
|
||||
[ Font.external
|
||||
{ name = "IBM Plex Sans"
|
||||
, url = "https://fonts.googleapis.com/css?family=IBM+Plex+Sans:400,400i,600,600i"
|
||||
}
|
||||
, Font.sansSerif
|
||||
]
|
||||
, paddingEach
|
||||
{ top = 32
|
||||
, left = 16
|
||||
, right = 16
|
||||
, bottom = 0
|
||||
}
|
||||
]
|
||||
[ el [ Region.navigation, width fill ] (Navbar.view route)
|
||||
, el [ Region.mainContent, width fill, height fill ] page
|
||||
, el [ Region.footer, width fill ] viewFooter
|
||||
]
|
||||
|
||||
|
||||
viewFooter : Element msg
|
||||
viewFooter =
|
||||
row
|
||||
[ width fill
|
||||
, paddingEach { top = 96, left = 0, right = 0, bottom = 48 }
|
||||
, alpha 0.5
|
||||
]
|
||||
[ text "this site was built with elm-spa!"
|
||||
, newTabLink [ alignRight, Font.underline ]
|
||||
{ label = text "github"
|
||||
, url = "https://github.com/ryannhg/elm-spa"
|
||||
}
|
||||
]
|
2
examples/docs/src/Layouts/README.md
Normal file
2
examples/docs/src/Layouts/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# src/Layouts
|
||||
> where all your pages go
|
26
examples/docs/src/Main.elm
Normal file
26
examples/docs/src/Main.elm
Normal file
@ -0,0 +1,26 @@
|
||||
module Main exposing (main)
|
||||
|
||||
import Generated.Pages as Pages
|
||||
import Generated.Routes as Routes exposing (routes)
|
||||
import Global
|
||||
import Spa
|
||||
import Transitions
|
||||
|
||||
|
||||
main : Spa.Program Global.Flags Global.Model Global.Msg Pages.Model Pages.Msg
|
||||
main =
|
||||
Spa.create
|
||||
{ ui = Spa.usingElmUi
|
||||
, transitions = Transitions.transitions
|
||||
, routing =
|
||||
{ routes = Routes.parsers
|
||||
, toPath = Routes.toPath
|
||||
, notFound = routes.notFound
|
||||
}
|
||||
, global =
|
||||
{ init = Global.init
|
||||
, update = Global.update
|
||||
, subscriptions = Global.subscriptions
|
||||
}
|
||||
, page = Pages.page
|
||||
}
|
49
examples/docs/src/Pages/Docs.elm
Normal file
49
examples/docs/src/Pages/Docs.elm
Normal file
@ -0,0 +1,49 @@
|
||||
module Pages.Docs exposing (Model, Msg, page)
|
||||
|
||||
import Components.Hero as Hero
|
||||
import Element exposing (..)
|
||||
import Generated.Params as Params
|
||||
import Spa.Page
|
||||
import Ui
|
||||
import Utils.Spa exposing (Page)
|
||||
|
||||
|
||||
type alias Model =
|
||||
()
|
||||
|
||||
|
||||
type alias Msg =
|
||||
Never
|
||||
|
||||
|
||||
page : Page Params.Docs Model Msg model msg appMsg
|
||||
page =
|
||||
Spa.Page.static
|
||||
{ title = always "docs | elm-spa"
|
||||
, view = always view
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- VIEW
|
||||
|
||||
|
||||
view : Element Msg
|
||||
view =
|
||||
Ui.sections
|
||||
[ Hero.view
|
||||
{ title = "docs"
|
||||
, subtitle = "\"it's not done until the docs are great!\""
|
||||
, links = []
|
||||
}
|
||||
, Ui.markdown """
|
||||
### table of contents
|
||||
|
||||
1. [installation & setup](#installation)
|
||||
1. project structure
|
||||
1. adding pages
|
||||
1. changing layouts
|
||||
1. components and reusable ui
|
||||
|
||||
"""
|
||||
]
|
50
examples/docs/src/Pages/Guide.elm
Normal file
50
examples/docs/src/Pages/Guide.elm
Normal file
@ -0,0 +1,50 @@
|
||||
module Pages.Guide exposing (Model, Msg, page)
|
||||
|
||||
import Components.Hero as Hero
|
||||
import Element exposing (..)
|
||||
import Generated.Params as Params
|
||||
import Spa.Page
|
||||
import Ui
|
||||
import Utils.Spa exposing (Page)
|
||||
|
||||
|
||||
type alias Model =
|
||||
()
|
||||
|
||||
|
||||
type alias Msg =
|
||||
Never
|
||||
|
||||
|
||||
page : Page Params.Guide Model Msg model msg appMsg
|
||||
page =
|
||||
Spa.Page.static
|
||||
{ title = always "guide | elm-spa"
|
||||
, view = always view
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- VIEW
|
||||
|
||||
|
||||
view : Element Msg
|
||||
view =
|
||||
Ui.sections
|
||||
[ Hero.view
|
||||
{ title = "guide"
|
||||
, subtitle = "let's build something together!"
|
||||
, links = []
|
||||
}
|
||||
, Ui.markdown """
|
||||
### what can i build with elm-spa?
|
||||
|
||||
__This entire site!__ And in this guide we'll build it together, from scratch.
|
||||
(Step-by-step, with short videos)
|
||||
|
||||
<iframe title="elm-spa: welcome to the guide!" width="560" height="315" src="https://www.youtube.com/embed/OMDMawvANNs" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
|
||||
Are you officially hyped? Let's [get you setup](/guide/setup)!
|
||||
"""
|
||||
]
|
42
examples/docs/src/Pages/NotFound.elm
Normal file
42
examples/docs/src/Pages/NotFound.elm
Normal file
@ -0,0 +1,42 @@
|
||||
module Pages.NotFound exposing (Model, Msg, page)
|
||||
|
||||
import Components.Hero as Hero
|
||||
import Element exposing (..)
|
||||
import Element.Font as Font
|
||||
import Generated.Params as Params
|
||||
import Generated.Routes as Routes exposing (routes)
|
||||
import Spa.Page
|
||||
import Utils.Spa exposing (Page)
|
||||
|
||||
|
||||
type alias Model =
|
||||
()
|
||||
|
||||
|
||||
type alias Msg =
|
||||
Never
|
||||
|
||||
|
||||
page : Page Params.NotFound Model Msg model msg appMsg
|
||||
page =
|
||||
Spa.Page.static
|
||||
{ title = always "not found | elm-spa"
|
||||
, view = always view
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- VIEW
|
||||
|
||||
|
||||
view : Element Msg
|
||||
view =
|
||||
Hero.view
|
||||
{ title = "page not found?"
|
||||
, subtitle = "it's not you, it's me."
|
||||
, links =
|
||||
[ { label = "but this link works!"
|
||||
, url = "/"
|
||||
}
|
||||
]
|
||||
}
|
3
examples/docs/src/Pages/README.md
Normal file
3
examples/docs/src/Pages/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# src/Pages
|
||||
> where all your pages go
|
||||
|
50
examples/docs/src/Pages/Top.elm
Normal file
50
examples/docs/src/Pages/Top.elm
Normal file
@ -0,0 +1,50 @@
|
||||
module Pages.Top exposing (Model, Msg, page)
|
||||
|
||||
import Components.Hero as Hero
|
||||
import Element exposing (..)
|
||||
import Generated.Params as Params
|
||||
import Spa.Page
|
||||
import Ui
|
||||
import Utils.Spa exposing (Page)
|
||||
|
||||
|
||||
type alias Model =
|
||||
()
|
||||
|
||||
|
||||
type alias Msg =
|
||||
Never
|
||||
|
||||
|
||||
page : Page Params.Top Model Msg model msg appMsg
|
||||
page =
|
||||
Spa.Page.static
|
||||
{ title = always "elm-spa"
|
||||
, view = always view
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- VIEW
|
||||
|
||||
|
||||
view : Element Msg
|
||||
view =
|
||||
Ui.sections
|
||||
[ Hero.view
|
||||
{ title = "elm-spa"
|
||||
, subtitle = "a framework for building single page apps"
|
||||
, links = [ { label = "get started", url = "/guide" } ]
|
||||
}
|
||||
, Ui.markdown """
|
||||
### does elm _need_ a framework?
|
||||
|
||||
__nope, not really–__ it's kinda got one built in! so building something like React, VueJS, or Angular wouldn't really make sense.
|
||||
|
||||
#### ...but even frameworks need frameworks!
|
||||
|
||||
that's why projects like VueJS also have awesome tools like NuxtJS that bring together the best tools in the ecosystem (and a set of shared best practices!)
|
||||
|
||||
welcome to __elm-spa__, a framework for Elm!
|
||||
"""
|
||||
]
|
14
examples/docs/src/Ports.elm
Normal file
14
examples/docs/src/Ports.elm
Normal file
@ -0,0 +1,14 @@
|
||||
port module Ports exposing (log)
|
||||
|
||||
import Json.Encode as Json
|
||||
|
||||
|
||||
port outgoing : { action : String, data : Json.Value } -> Cmd msg
|
||||
|
||||
|
||||
log : String -> Cmd msg
|
||||
log message =
|
||||
outgoing
|
||||
{ action = "LOG"
|
||||
, data = Json.string message
|
||||
}
|
12
examples/docs/src/Transitions.elm
Normal file
12
examples/docs/src/Transitions.elm
Normal file
@ -0,0 +1,12 @@
|
||||
module Transitions exposing (transitions)
|
||||
|
||||
import Spa.Transition as Transition
|
||||
import Utils.Spa as Spa
|
||||
|
||||
|
||||
transitions : Spa.Transitions msg
|
||||
transitions =
|
||||
{ layout = Transition.none
|
||||
, page = Transition.fadeElmUi 300
|
||||
, pages = []
|
||||
}
|
100
examples/docs/src/Ui.elm
Normal file
100
examples/docs/src/Ui.elm
Normal file
@ -0,0 +1,100 @@
|
||||
module Ui exposing
|
||||
( colors
|
||||
, markdown
|
||||
, sections
|
||||
, styles
|
||||
, transition
|
||||
)
|
||||
|
||||
import Element exposing (..)
|
||||
import Element.Background as Background
|
||||
import Element.Border as Border
|
||||
import Element.Font as Font
|
||||
import Html.Attributes as Attr
|
||||
import Markdown
|
||||
|
||||
|
||||
colors : { coral : Color, white : Color }
|
||||
colors =
|
||||
{ coral = rgb255 200 75 85
|
||||
, white = rgb255 255 255 255
|
||||
}
|
||||
|
||||
|
||||
styles :
|
||||
{ button : List (Attribute msg)
|
||||
, link :
|
||||
{ enabled : List (Attribute msg)
|
||||
, disabled : List (Attribute msg)
|
||||
}
|
||||
}
|
||||
styles =
|
||||
{ link =
|
||||
{ enabled =
|
||||
[ Font.underline
|
||||
, transition
|
||||
{ duration = 200
|
||||
, props = [ "opacity" ]
|
||||
}
|
||||
, mouseOver [ alpha 0.5 ]
|
||||
]
|
||||
, disabled =
|
||||
[ alpha 0.5
|
||||
]
|
||||
}
|
||||
, button =
|
||||
[ centerX
|
||||
, Font.size 14
|
||||
, Font.semiBold
|
||||
, Border.solid
|
||||
, Border.width 2
|
||||
, Border.rounded 4
|
||||
, paddingXY 24 8
|
||||
, Font.color colors.coral
|
||||
, Border.color colors.coral
|
||||
, Background.color colors.white
|
||||
, pointer
|
||||
, transition
|
||||
{ duration = 200
|
||||
, props = [ "background", "color" ]
|
||||
}
|
||||
, mouseOver
|
||||
[ Background.color colors.coral
|
||||
, Font.color colors.white
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
sections : List (Element msg) -> Element msg
|
||||
sections =
|
||||
column [ spacing 32, width fill ]
|
||||
|
||||
|
||||
markdown : String -> Element msg
|
||||
markdown =
|
||||
let
|
||||
options =
|
||||
Markdown.defaultOptions
|
||||
|> (\o -> { o | sanitize = False })
|
||||
in
|
||||
Markdown.toHtmlWith options [ Attr.class "markdown" ]
|
||||
>> Element.html
|
||||
>> List.singleton
|
||||
>> paragraph []
|
||||
|
||||
|
||||
transition : { props : List String, duration : Int } -> Attribute msg
|
||||
transition options =
|
||||
options.props
|
||||
|> List.map
|
||||
(\prop ->
|
||||
String.join " "
|
||||
[ prop
|
||||
, String.fromInt options.duration ++ "ms"
|
||||
, "ease-in-out"
|
||||
]
|
||||
)
|
||||
|> String.join ", "
|
||||
|> Attr.style "transition"
|
||||
|> Element.htmlAttribute
|
2
examples/docs/src/Utils/README.md
Normal file
2
examples/docs/src/Utils/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# src/Utils
|
||||
> a place for helper functions
|
72
examples/docs/src/Utils/Spa.elm
Normal file
72
examples/docs/src/Utils/Spa.elm
Normal file
@ -0,0 +1,72 @@
|
||||
module Utils.Spa exposing
|
||||
( Bundle
|
||||
, Init
|
||||
, LayoutContext
|
||||
, Page
|
||||
, PageContext
|
||||
, Recipe
|
||||
, Transitions
|
||||
, Update
|
||||
, layout
|
||||
, recipe
|
||||
)
|
||||
|
||||
import Element exposing (Element)
|
||||
import Generated.Routes as Routes exposing (Route)
|
||||
import Global
|
||||
import Spa.Page
|
||||
import Spa.Types
|
||||
|
||||
|
||||
type alias Page params model msg layoutModel layoutMsg appMsg =
|
||||
Spa.Types.Page Route params model msg (Element msg) layoutModel layoutMsg (Element layoutMsg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
|
||||
|
||||
type alias Recipe params model msg layoutModel layoutMsg appMsg =
|
||||
Spa.Types.Recipe Route params model msg layoutModel layoutMsg (Element layoutMsg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
|
||||
|
||||
type alias Init model msg =
|
||||
Spa.Types.Init Route model msg Global.Model Global.Msg
|
||||
|
||||
|
||||
type alias Update model msg =
|
||||
Spa.Types.Update Route model msg Global.Model Global.Msg
|
||||
|
||||
|
||||
type alias Bundle msg appMsg =
|
||||
Spa.Types.Bundle Route msg (Element msg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
|
||||
|
||||
type alias LayoutContext msg =
|
||||
Spa.Types.LayoutContext Route msg (Element msg) Global.Model Global.Msg
|
||||
|
||||
|
||||
type alias PageContext =
|
||||
Spa.Types.PageContext Route Global.Model
|
||||
|
||||
|
||||
type alias Layout params model msg appMsg =
|
||||
Spa.Types.Layout Route params model msg (Element msg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
|
||||
|
||||
layout :
|
||||
Layout params model msg appMsg
|
||||
-> Page params model msg layoutModel layoutMsg appMsg
|
||||
layout =
|
||||
Spa.Page.layout Element.map
|
||||
|
||||
|
||||
type alias Upgrade params model msg layoutModel layoutMsg appMsg =
|
||||
Spa.Types.Upgrade Route params model msg (Element msg) layoutModel layoutMsg (Element layoutMsg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
|
||||
|
||||
recipe :
|
||||
Upgrade params model msg layoutModel layoutMsg appMsg
|
||||
-> Recipe params model msg layoutModel layoutMsg appMsg
|
||||
recipe =
|
||||
Spa.Page.recipe Element.map
|
||||
|
||||
|
||||
type alias Transitions msg =
|
||||
Spa.Types.Transitions (Element msg)
|
Loading…
Reference in New Issue
Block a user