diff --git a/docs/public/style.css b/docs/public/style.css index 49fd9c9..91635bc 100644 --- a/docs/public/style.css +++ b/docs/public/style.css @@ -14,6 +14,7 @@ --color--grey-500: #696969; --color--grey-700: #333333; --color--green: #407742; + --color--green-dark: #264727; --color--green-light: #d7ead8; --size--h1: 3em; @@ -30,6 +31,8 @@ --height--header: 102px; } + + /* Resets */ @media screen and (min-width: 1920px ) { html { font-size: 20px; } @@ -90,7 +93,7 @@ main { hr { border: 0; } -.container { max-width: 64em; } +.container { max-width: 64rem; } /* Typography */ @@ -143,6 +146,7 @@ hr { border: 0; } line-height: 1.45; } +.faded { opacity: 0.6; } .markdown { display: flex; @@ -338,9 +342,8 @@ hr { border: 0; } top: 0; left: 0; right: 0; - z-index: 1; + z-index: 2; background: var(--color--grey-100); - box-shadow: 0 1em 1em var(--color--grey-100); } .header__logo { @@ -351,6 +354,13 @@ hr { border: 0; } .header__logo { font-size: 1.25em } } +.page { + min-height: 70vh; + background-color: var(--color--grey-100); + position: relative; + z-index: 1; +} + .sticky { position: sticky; left: 0; @@ -378,6 +388,19 @@ hr { border: 0; } font-size: 1.25em; } +.hero { + padding: 10em 0; +} + +.hero__logo { + font-size: 1.75em; +} + +@media screen and (max-width: 640px) { + .hero { padding: 8em 0 } + .hero__logo { font-size: 1em } +} + /* Search */ .search { @@ -462,4 +485,60 @@ hr { border: 0; } .toc { padding: 1rem; opacity: 0.9; +} + +/* Homepage */ + +.home__section:nth-child(2n + 1) { + background: linear-gradient(30deg, var(--color--green-dark), var(--color--green)); + color: var(--color--white); +} + +.home__section:nth-child(2n + 1) code { + color: var(--color--white); +} + +.home__section:nth-child(2n + 1) .h2 { + text-shadow: 0 0 0.5em rgb(0 0 0 / 25%); +} + +.home__section:nth-child(2n) .markdown { + margin-left: auto; +} + +.home__section-icon { + position: absolute; + top: 50%; + transform: translate(50%, -50%); + right: calc(50% + 18rem); + font-size: 8em; + z-index: 2; +} + +.home__section:nth-child(2n + 1) .home__section-icon { + right: unset; + left: calc(50% + 18rem); + transform: translate(-50%, -50%); +} + +@media screen and (max-width: 800px) { + .home__section-icon { + display: none; + } +} + +@media screen and (max-width: 640px) { + .home__section { font-size: 1em } +} + +/* Footer */ +.footer { + position: fixed; + bottom: 0; + left: 0; + right: 0; +} + +.footer__zone { + padding: 8em 0; } \ No newline at end of file diff --git a/docs/src/Pages/Home_.elm b/docs/src/Pages/Home_.elm index 48d780a..fdbd203 100644 --- a/docs/src/Pages/Home_.elm +++ b/docs/src/Pages/Home_.elm @@ -1,17 +1,19 @@ module Pages.Home_ exposing (Model, Msg, page) import Gen.Params.Home_ exposing (Params) +import Html +import Html.Attributes as Attr import Page import Request import Shared -import UI +import UI exposing (Html) import UI.Layout import View exposing (View) page : Shared.Model -> Request.With Params -> Page.With Model Msg page = - UI.Layout.page + UI.Layout.pageFullWidth { view = view } @@ -28,21 +30,54 @@ view : View Msg view = { title = "elm-spa" , body = - [ UI.hero - { title = "elm-spa" - , description = "single page apps made easy" - } - , UI.markdown { withHeaderLinks = False } """ -## A work in progress! + [ Html.div [ Attr.class "row center-x" ] + [ UI.hero + { title = "elm-spa" + , description = "single page apps made easy" + } + ] + , alternatingMarkdownSections + [ ( "😌", """ +## Build reliable single page applications -This next release of elm-spa isn't _quite_ ready yet. It's currently available in `beta`, and can be installed via __npm__: +With __elm-spa__, you can create production-ready applications with one command: -``` -npm install -g elm-spa@beta +```terminal +npx elm-spa new ``` -For now, feel free to [read the docs](/docs), see the [incomplete guides](/guides), or check the bulleted list of [example projects](/examples) -that aren't available yet. - """ +No need to configure webpack, gulp, or any other NPM dev tools. This single __zero-configuration__ CLI comes with a live-reloading dev server, production-ready build command, and even a few scaffolding commands for new and existing applications. +""" ) + , ( "\u{1FA84}", """ +## Automatic routing + +With __elm-spa__, routing is automatically generated for you based on a standard file-structure convention. This means you'll be able to navigate any project, making it great for onboarding new hires or collaborating with a team! +""" ) + , ( "🔒", """ +## User authentication + +The latest release comes with an easy way to setup user authentication. Use the `Page.protected` API to easily guarantee only logged-in users can view certain pages. +""" ) + , ( "🧠", """ +## Ready to learn more? + +Awesome! Check out [the official guide](/guide) to learn the concepts, or start by looking at a collection of examples. + """ ) + ] ] } + + +alternatingMarkdownSections : List ( String, String ) -> Html msg +alternatingMarkdownSections sections = + let + viewSection ( emoji, str ) = + Html.section [ Attr.class "home__section" ] + [ Html.div [ Attr.class "container relative", Attr.style "padding" "8em 1rem" ] + [ Html.div [ Attr.class "home__section-icon" ] [ Html.text emoji ] + , UI.markdown { withHeaderLinks = False } str + ] + ] + in + Html.main_ [ Attr.class "col" ] + (List.map viewSection sections) diff --git a/docs/src/UI.elm b/docs/src/UI.elm index a863b0f..17d42ae 100644 --- a/docs/src/UI.elm +++ b/docs/src/UI.elm @@ -316,8 +316,8 @@ align = hero : { title : String, description : String } -> Html msg hero options = - Html.div [ Attr.class "pad-y-xl" ] - [ Html.div [ Attr.class "row gap-md pad-y-xl" ] + Html.div [ Attr.class "hero" ] + [ Html.div [ Attr.class "hero__logo row gap-md" ] [ Html.div [ Attr.class "logo" ] [] , Html.div [ Attr.class "col gap-xs" ] [ h1 options.title diff --git a/docs/src/UI/Layout.elm b/docs/src/UI/Layout.elm index f6fc02f..810e33c 100644 --- a/docs/src/UI/Layout.elm +++ b/docs/src/UI/Layout.elm @@ -2,7 +2,7 @@ module UI.Layout exposing ( Model, init , Msg, update , viewDefault, viewDocumentation - , page + , page, pageFullWidth ) {-| @@ -58,7 +58,23 @@ viewDefault : -> List (Html msg) viewDefault options view = [ navbar options - , Html.main_ [ Attr.class "container pad-x-md" ] view + , Html.main_ [ Attr.class "page container pad-x-md" ] view + , footer + ] + + +viewFullWidth : + { model : Model + , onMsg : Msg -> msg + , shared : Shared.Model + , url : Url + } + -> List (Html msg) + -> List (Html msg) +viewFullWidth options view = + [ navbar options + , Html.div [ Attr.class "page" ] view + , footer ] @@ -73,7 +89,7 @@ viewDocumentation : -> List (Html msg) viewDocumentation options markdownContent view = [ navbar options - , Html.div [ Attr.class "container pad-md" ] + , Html.div [ Attr.class "page container pad-md" ] [ UI.row.xl [ UI.align.top, UI.padY.lg ] [ Html.aside [ Attr.class "only-desktop sticky pad-y-lg aside" ] [ UI.Sidebar.viewSidebar @@ -94,6 +110,7 @@ viewDocumentation options markdownContent view = ] ] ] + , footer ] @@ -115,27 +132,41 @@ navbar { onMsg, model, shared, url } = ] [ Html.text options.text ] in - Html.header [ Attr.class "header container pad-y-lg pad-x-md" ] - [ Html.div [ Attr.class "row gap-md spread" ] - [ Html.div [ Attr.class "row align-center gap-lg" ] - [ Html.a [ Attr.class "header__logo", Attr.href "/" ] [ UI.logo ] - , Html.nav [ Attr.class "row gap-md hidden-mobile pad-left-xs" ] - [ navLink { text = "docs", route = Route.Docs } - , navLink { text = "guides ", route = Route.Guides } - , navLink { text = "examples", route = Route.Examples } + Html.header [ Attr.class "header pad-y-lg pad-x-md" ] + [ Html.div [ Attr.class "container" ] + [ Html.div [ Attr.class "row gap-md spread" ] + [ Html.div [ Attr.class "row align-center gap-lg" ] + [ Html.a [ Attr.class "header__logo", Attr.href "/" ] [ UI.logo ] + , Html.nav [ Attr.class "row gap-md hidden-mobile pad-left-xs" ] + [ navLink { text = "docs", route = Route.Docs } + , navLink { text = "guides ", route = Route.Guides } + , navLink { text = "examples", route = Route.Examples } + ] + ] + , Html.div [ Attr.class "row gap-md spread" ] + [ Html.nav [ Attr.class "row gap-md hidden-mobile" ] + [ UI.iconLink { text = "GitHub Repo", icon = UI.icons.github, url = "https://github.com/ryannhg/elm-spa" } + , UI.iconLink { text = "NPM Package", icon = UI.icons.npm, url = "https://npmjs.org/elm-spa" } + , UI.iconLink { text = "Elm Package", icon = UI.icons.elm, url = "https://package.elm-lang.org/packages/ryannhg/elm-spa/latest" } + ] + , UI.Searchbar.view + { index = shared.index + , query = model.query + , onQueryChange = onMsg << OnQueryChange + } ] ] - , Html.div [ Attr.class "row gap-md spread" ] - [ Html.nav [ Attr.class "row gap-md hidden-mobile" ] - [ UI.iconLink { text = "GitHub Repo", icon = UI.icons.github, url = "https://github.com/ryannhg/elm-spa" } - , UI.iconLink { text = "NPM Package", icon = UI.icons.npm, url = "https://npmjs.org/elm-spa" } - , UI.iconLink { text = "Elm Package", icon = UI.icons.elm, url = "https://package.elm-lang.org/packages/ryannhg/elm-spa/latest" } - ] - , UI.Searchbar.view - { index = shared.index - , query = model.query - , onQueryChange = onMsg << OnQueryChange - } + ] + ] + + +footer : Html msg +footer = + Html.div [ Attr.class "footer__zone" ] + [ Html.footer [ Attr.class "footer container pad-top-xl" ] + [ Html.div [ Attr.class "row pad-x-md pad-y-lg pad-top-xl spread faded" ] + [ Html.a [ Attr.href "https://github.com/ryannhg/elm-spa/tree/main/docs", Attr.target "_blank", Attr.class "link" ] [ Html.text "Site source code" ] + , Html.span [] [ Html.text "© 2019 – 2021, Ryan Haskell-Glatz" ] ] ] ] @@ -163,3 +194,23 @@ page options shared req = options.view.body } } + + +pageFullWidth : { view : View Msg } -> Shared.Model -> Request.With params -> Page.With Model Msg +pageFullWidth options shared req = + Page.sandbox + { init = init + , update = update + , view = + \model -> + { title = options.view.title + , body = + viewFullWidth + { shared = shared + , url = req.url + , model = model + , onMsg = identity + } + options.view.body + } + } diff --git a/src/cli/src/cli/build.ts b/src/cli/src/cli/build.ts index 11d03de..3cb925e 100644 --- a/src/cli/src/cli/build.ts +++ b/src/cli/src/cli/build.ts @@ -65,8 +65,6 @@ const createMissingDefaultFiles = async () => { return Promise.all(actions.map(performDefaultFileAction)) } -const identity = (value : T) => value - type FilepathSegments = { kind: PageKind, entry: PageEntry @@ -173,7 +171,6 @@ const compileMainElm = (env: Environment) => async () => { ? path.join(config.folders.src, 'Main.elm') : path.join(config.folders.defaults.dest, 'Main.elm') - return elm.compileToString(inputFilepath, { output: outputFilepath, report: 'json',