Ready to Merge

This commit is contained in:
Unknown 2020-05-25 13:58:22 +02:00
parent bb3ae50376
commit 86ff420314
21 changed files with 895 additions and 179 deletions

147
README.md
View File

@ -1,41 +1,24 @@
# Elm-Ui-Widgets
Usefull Widgets written for Elm-ui.
This package contains **independend** widgets (no components) written for [Elm-Ui](https://dark.elm.dmy.fr/packages/mdgriffith/elm-ui/latest/). These widgets have no dependencies to other parts of this package. So you can just use as much as you need.
Examples of all widgets can be found [here](https://orasund.github.io/elm-ui-widgets/). For styling, I used my own [Orasund/elm-ui-framework](https://package.elm-lang.org/packages/Orasund/elm-ui-framework/latest/).
It also supports custom themes and has a material design theme already ready to use.
## Why create such a package?
el
After looking at the current packages that implement various reusable views (and components) I noticed two things:
[Examples of all widgets can be found here](https://orasund.github.io/elm-ui-widgets/).
* There are (nearly) no widgets for Elm-Ui, and that's a problem because while going from `Element` to `Html` is easy, the opposite is not always possible (as a lot of styling in Elm-Ui would not be adapted to the `Html` element.)
* There is collection of widgets, all in one place. A lot of components get reimplemented over and over again. It's hard to keep track of what package is currently the best.
![Example using the Material Design style](https://orasund.github.io/elm-ui-widgets/assets/material-style.png)
This package tries to solve both of these problems.
## Concept
Here are some alternative packages for creating UIs:
**Summary**
* Using Elm-Ui
* [lucamug/style-framework](https://dark.elm.dmy.fr/packages/lucamug/style-framework/latest/) - Full customization requires the cloning of the package.
* [jxxcarlson/elm-widget](https://dark.elm.dmy.fr/packages/jxxcarlson/elm-widget/latest/Widget-Button) - Uses a Builder pattern. Has some redefined customizations.
* [QiTASC/hatchinq](https://dark.elm.dmy.fr/packages/QiTASC/hatchinq/latest/) - Similar Arroach, stillin experimental phase
* Using Elm/Html
* [nathanjohnson320/elm-ui-components](https://dark.elm.dmy.fr/packages/nathanjohnson320/elm-ui-components/latest/) - Sticks with the elm/html way of styling.
* [NoRedInk/noredink-ui](https://dark.elm.dmy.fr/packages/NoRedInk/noredink-ui/latest/) - Similar Approach but no customization options.
* [peterszerzo/elm-natural-ui](https://dark.elm.dmy.fr/packages/peterszerzo/elm-natural-ui/latest) - Uses custom Attributes with some customization.
* Ui Frameworks
* [aforemny/material-components-web-elm](https://dark.elm.dmy.fr/packages/aforemny/material-components-web-elm/latest/) - Wrapper of Material design using custom elements.
* [afidegnum/elm-tailwind](https://dark.elm.dmy.fr/packages/afidegnum/elm-tailwind/latest/) - Wrapper of Tailwind by including the tailwind stylesheet.
* [surprisetalk/elm-bulma](https://dark.elm.dmy.fr/packages/surprisetalk/elm-bulma/latest/) - Wrapper for Bulma by including the bulma stylesheet.
* [rundis/elm-bootstrap](https://dark.elm.dmy.fr/packages/rundis/elm-bootstrap/latest/) - Wrapper for Bootstrap by including the bootstrap stylesheet.
* Each widget comes with a _Widget Type_ and a _Style Type_. The Widget Type is an abstract representation of the widget and the Style Type has all styling attributes.
* Widget Types can be used as building Blocks for more complicated Widgets
(Button -> Select Buttons -> Menu -> Layout)
# Goal
**Example**
The long time goal is to have a universal tool for creating UI-frameworks natively in Elm, in particular a native **Material Design** implementation. It should allow easy customizability and also extendability of existing widgets.
# Example: Button
A good example, how I image the package to work is the button:
Let's look at the button widget.
```elm
button: ButtonStyle msg
@ -47,9 +30,7 @@ button: ButtonStyle msg
-> Element msg
```
In comparison to Elm-Ui's button, we see two new things:
* `List (Attribute msg)` has changed into
In comparison to Elm-Ui's button, we see that `List (Attribute msg)` has changed into a _Style Type_.
```
type alias ButtonStyle msg =
{ container : List (Attribute msg)
@ -58,19 +39,11 @@ In comparison to Elm-Ui's button, we see two new things:
, ifActive : List (Attribute msg)
}
```
* We can display an icon, besides the text. Just like the [Material Design specification](https://material.io/components/buttons) describes it.
Actually there is also a type for the button:
```
type alias Button msg =
{ text : String
, icon : Element Never
, onPress : Maybe msg
}
```
There are also a few different implementations of the button, like the Icon without text:
For actually displaying the button we have a few different implementations:
``` elm
{-| Button with only an icon and no text -}
iconButton :
ButtonStyle msg
->
@ -79,11 +52,8 @@ iconButton :
, onPress : Maybe msg
}
-> Element msg
```
or a Button with no icon
```
{-| Button with a text but no icon -}
textButton :
ButtonStyle msg
->
@ -92,19 +62,86 @@ textButton :
, onPress : Maybe msg
}
-> Element msg
{-| Button with both icon and text -}
button :
ButtonStyle msg
->
{ text : String
, icon : Element Never
, onPress : Maybe msg
}
-> Element msg
```
# Concept
We also have a `Widget Type` for the button:
Here are the reasons why I implemented it that way:
```
type alias Button msg =
{ text : String
, icon : Element Never
, onPress : Maybe msg
}
```
* The core of Elm-Ui-Widgets are **independend** widgets (no components), that can be used without knowing anything else about the package.
* Each widget comes with a _Widget Type_ and a _Style Type_. The Widget Type is an abstract representation of the widget and the Style Type has all styling attributes.
* Style Types should be definable without knowing implementation details
* Widget Types can be use for a Master View Type (Elm-Ui-Widgets might provide some master view types, for example for elm-Markup support)
* Widget Types can be used as building Blocks for more complicated Widgets
(Button -> Select Buttons -> Menu -> Layout)
We can use it to build more complex widgets, for example a select button:
## Where will it go from here
```
type alias Select msg =
{ selected : Maybe Int
, options :
List
{ text : String
, icon : Element Never
}
, onSelect : Int -> Maybe msg
}
I really would like to write a native material-design implementation in Elm. But after doing this package as a first step, (Which I already wrote while having the material.io docs as reference) I am not quite sure how I can avoid a lot of boilerplating. It seems like a [Master View Type](https://www.freecodecamp.org/news/scaling-elm-views-with-master-view-types/) would be the solution, but I'm not quite sure how I can ensure the customizability when my entire page can be described as a single type. (I don't want to know how many parameters such a type would need).
select :
Select msg
-> List ( Bool, Button msg )
selectButton :
ButtonStyle msg
-> ( Bool, Button msg )
-> Element msg
```
## Reusable Views vs. Components
In Elm we like to use reusable views instead of components.
At first this packages had a few components, but they where so complicated to use in comparison, so they got slowly turned into reusable views one by one.
Most could be reduced even further into _view functions_: reusable views without a model.
Currently we have only three reusable views: `Widget.Layout`, `Widget.ScrollingNav` and `Widget.Snackbar`.
## Alternatives
For comparison, here are some alternative packages for creating UIs:
* **Using Elm-Ui**
* [lucamug/style-framework](https://dark.elm.dmy.fr/packages/lucamug/style-framework/latest/) - Full customization requires the cloning of the package.
* [jxxcarlson/elm-widget](https://dark.elm.dmy.fr/packages/jxxcarlson/elm-widget/latest/Widget-Button) - Uses a Builder pattern. Has some redefined customizations.
* [QiTASC/hatchinq](https://dark.elm.dmy.fr/packages/QiTASC/hatchinq/latest/) - Similar Arroach but still in experimental phase
* **Using Elm/Html**
* [nathanjohnson320/elm-ui-components](https://dark.elm.dmy.fr/packages/nathanjohnson320/elm-ui-components/latest/) - Uses the elm/html way of styling.
* [NoRedInk/noredink-ui](https://dark.elm.dmy.fr/packages/NoRedInk/noredink-ui/latest/) - Similar Approach but no customization options.
* [peterszerzo/elm-natural-ui](https://dark.elm.dmy.fr/packages/peterszerzo/elm-natural-ui/latest) - Uses custom Attributes with some customization.
* **Ui Frameworks**
* [aforemny/material-components-web-elm](https://dark.elm.dmy.fr/packages/aforemny/material-components-web-elm/latest/) - Wrapper of Material design using custom elements.
* [afidegnum/elm-tailwind](https://dark.elm.dmy.fr/packages/afidegnum/elm-tailwind/latest/) - Wrapper of Tailwind by including the tailwind stylesheet.
* [surprisetalk/elm-bulma](https://dark.elm.dmy.fr/packages/surprisetalk/elm-bulma/latest/) - Wrapper for Bulma by including the bulma stylesheet.
* [rundis/elm-bootstrap](https://dark.elm.dmy.fr/packages/rundis/elm-bootstrap/latest/) - Wrapper for Bootstrap by including the bootstrap stylesheet.
## Motivation
After looking at the current packages that implement various reusable views (and components) I noticed two things:
* There are (nearly) no widgets for Elm-Ui, and that's a problem because while going from `Element` to `Html` is easy, the opposite is not always possible (as a lot of styling in Elm-Ui would not be adapted to the `Html` element.)
* There is collection of widgets, all in one place. A lot of components get reimplemented over and over again. It's hard to keep track of what package is currently the best.
This package tries to solve both of these problems.
## Changelog
* **Version 2.0** - Complete rewrite of the package. Now including a material design implementation.

File diff suppressed because one or more lines are too long

View File

@ -5,12 +5,13 @@
"license": "BSD-3-Clause",
"version": "1.0.0",
"exposed-modules": [
"Widget.Layout",
"Widget.ScrollingNav",
"Widget.Snackbar",
"Widget",
"Widget.Style",
"Widget.Style.Material",
"Widget.Style.Template"
"Widget.Style.Template",
"Widget.Layout",
"Widget.ScrollingNav",
"Widget.Snackbar"
],
"elm-version": "0.19.0 <= v < 0.20.0",
"dependencies": {

View File

@ -4,7 +4,8 @@ import Element exposing (Element)
import FeatherIcons
import Widget
import Widget.Style exposing (ButtonStyle, RowStyle)
import Widget.Style.Material as Material
import Browser
type alias Style style msg =
{ style
@ -13,6 +14,13 @@ type alias Style style msg =
, row : RowStyle msg
}
materialStyle : Style {} msg
materialStyle =
{ primaryButton = Material.containedButton Material.defaultPalette
, button = Material.outlinedButton Material.defaultPalette
, row = Material.row
}
type Model
= IsButtonEnabled Bool
@ -77,3 +85,12 @@ view msgMapper style (IsButtonEnabled isButtonEnabled) =
}
]
|> Widget.row style.row
main : Program () Model Msg
main =
Browser.element
{ init = always init
, view = view identity materialStyle >> Element.layout []
, update = update
, subscriptions = subscriptions
}

View File

@ -4,7 +4,8 @@ import Element exposing (Element)
import FeatherIcons
import Widget
import Widget.Style exposing (ButtonStyle, DialogStyle)
import Widget.Style.Material as Material
import Browser
type alias Style style msg =
{ style
@ -12,6 +13,11 @@ type alias Style style msg =
, primaryButton : ButtonStyle msg
}
materialStyle : Style {} msg
materialStyle =
{ dialog = Material.alertDialog Material.defaultPalette
, primaryButton = Material.containedButton Material.defaultPalette
}
type Model
= IsOpen Bool
@ -87,3 +93,12 @@ view msgMapper style (IsOpen isOpen) =
[]
)
)
main : Program () Model Msg
main =
Browser.element
{ init = always init
, view = view identity materialStyle >> Element.layout []
, update = update
, subscriptions = subscriptions
}

View File

@ -3,13 +3,18 @@ module Example.ExpansionPanel exposing (Model, Msg, init, subscriptions, update,
import Element exposing (Element)
import Widget
import Widget.Style exposing (ExpansionPanelStyle)
import Widget.Style.Material as Material
import Browser
type alias Style style msg =
{ style
| expansionPanel : ExpansionPanelStyle msg
}
materialStyle : Style {} msg
materialStyle =
{ expansionPanel = Material.expansionPanel Material.defaultPalette
}
type Model
= IsExpanded Bool
@ -49,3 +54,12 @@ view msgMapper style (IsExpanded isExpanded) =
, content = Element.text <| "Hello World"
}
|> Widget.expansionPanel style.expansionPanel
main : Program () Model Msg
main =
Browser.element
{ init = always init
, view = view identity materialStyle >> Element.layout []
, update = update
, subscriptions = subscriptions
}

View File

@ -3,13 +3,18 @@ module Example.List exposing (Model, Msg, init, subscriptions, update, view)
import Element exposing (Element)
import Widget
import Widget.Style exposing (ColumnStyle)
import Widget.Style.Material as Material
import Browser
type alias Style style msg =
{ style
| cardColumn : ColumnStyle msg
}
materialStyle : Style {} msg
materialStyle =
{ cardColumn = Material.cardColumn Material.defaultPalette
}
type alias Model =
()
@ -45,3 +50,12 @@ view _ style () =
, Element.text <| "C"
]
|> Widget.column style.cardColumn
main : Program () Model Msg
main =
Browser.element
{ init = always init
, view = view identity materialStyle >> Element.layout []
, update = update
, subscriptions = subscriptions
}

View File

@ -4,7 +4,8 @@ import Element exposing (Element)
import FeatherIcons
import Widget
import Widget.Style exposing (ButtonStyle, ColumnStyle)
import Widget.Style.Material as Material
import Browser
type alias Style style msg =
{ style
@ -12,6 +13,11 @@ type alias Style style msg =
, primaryButton : ButtonStyle msg
}
materialStyle : Style {} msg
materialStyle =
{ cardColumn = Material.cardColumn Material.defaultPalette
, primaryButton = Material.containedButton Material.defaultPalette
}
type Model
= IsEnabled Bool
@ -86,3 +92,12 @@ view msgMapper style (IsEnabled isEnabled) =
[]
)
)
main : Program () Model Msg
main =
Browser.element
{ init = always init
, view = view identity materialStyle >> Element.layout []
, update = update
, subscriptions = subscriptions
}

View File

@ -4,7 +4,8 @@ import Element exposing (Element)
import Set exposing (Set)
import Widget
import Widget.Style exposing (ButtonStyle, RowStyle)
import Widget.Style.Material as Material
import Browser
type alias Style style msg =
{ style
@ -12,6 +13,11 @@ type alias Style style msg =
, selectButton : ButtonStyle msg
}
materialStyle : Style {} msg
materialStyle =
{ buttonRow = Material.buttonRow
, selectButton = Material.toggleButton Material.defaultPalette
}
type Model
= Selected (Set Int)
@ -67,3 +73,12 @@ view msgMapper style (Selected selected) =
{ list = style.buttonRow
, button = style.selectButton
}
main : Program () Model Msg
main =
Browser.element
{ init = always init
, view = view identity materialStyle >> Element.layout []
, update = update
, subscriptions = subscriptions
}

View File

@ -3,7 +3,8 @@ module Example.Select exposing (Model, Msg, init, subscriptions, update, view)
import Element exposing (Element)
import Widget
import Widget.Style exposing (ButtonStyle, RowStyle)
import Widget.Style.Material as Material
import Browser
type alias Style style msg =
{ style
@ -11,6 +12,11 @@ type alias Style style msg =
, selectButton : ButtonStyle msg
}
materialStyle : Style {} msg
materialStyle =
{ buttonRow = Material.buttonRow
, selectButton = Material.toggleButton Material.defaultPalette
}
type Model
= Selected (Maybe Int)
@ -59,3 +65,12 @@ view msgMapper style (Selected selected) =
{ list = style.buttonRow
, button = style.selectButton
}
main : Program () Model Msg
main =
Browser.element
{ init = always init
, view = view identity materialStyle >> Element.layout []
, update = update
, subscriptions = subscriptions
}

View File

@ -3,13 +3,29 @@ module Example.SortTable exposing (Model, Msg, init, subscriptions, update, view
import Element exposing (Element)
import Widget
import Widget.Style exposing (SortTableStyle)
import Widget.Style.Material as Material
import Browser
type alias Style style msg =
{ style
| sortTable : SortTableStyle msg
}
materialStyle : Style {} msg
materialStyle =
{ sortTable =
{ containerTable = []
, headerButton = Material.textButton Material.defaultPalette
, ascIcon =
Material.expansionPanel Material.defaultPalette
|> .collapseIcon
, descIcon =
Material.expansionPanel Material.defaultPalette
|> .expandIcon
, defaultIcon = Element.none
}
}
type alias Model =
{ title : String
@ -87,3 +103,12 @@ view msgMapper style model =
, sortBy = model.title
, onChange = ChangedSorting >> msgMapper
}
main : Program () Model Msg
main =
Browser.element
{ init = always init
, view = view identity materialStyle >> Element.layout []
, update = update
, subscriptions = subscriptions
}

View File

@ -3,13 +3,18 @@ module Example.Tab exposing (Model, Msg, init, subscriptions, update, view)
import Element exposing (Element)
import Widget
import Widget.Style exposing (TabStyle)
import Widget.Style.Material as Material
import Browser
type alias Style style msg =
{ style
| tab : TabStyle msg
}
materialStyle : Style {} msg
materialStyle =
{ tab = Material.tab Material.defaultPalette
}
type Model
= Selected (Maybe Int)
@ -72,3 +77,12 @@ view msgMapper style (Selected selected) =
)
|> Element.text
}
main : Program () Model Msg
main =
Browser.element
{ init = always init
, view = view identity materialStyle >> Element.layout []
, update = update
, subscriptions = subscriptions
}

View File

@ -4,7 +4,8 @@ import Element exposing (Element)
import Set exposing (Set)
import Widget
import Widget.Style exposing (ColumnStyle, TextInputStyle)
import Widget.Style.Material as Material
import Browser
type alias Style style msg =
{ style
@ -12,6 +13,12 @@ type alias Style style msg =
, column : ColumnStyle msg
}
materialStyle : Style {} msg
materialStyle =
{ textInput = Material.textInput Material.defaultPalette
, column = Material.column
}
type alias Model =
{ chipTextInput : Set String
@ -102,3 +109,12 @@ view msgMapper style model =
|> Element.wrappedRow [ Element.spacing 10 ]
]
|> Widget.column style.column
main : Program () Model Msg
main =
Browser.element
{ init = always init
, view = view identity materialStyle >> Element.layout []
, update = update
, subscriptions = subscriptions
}

View File

@ -28,7 +28,7 @@ import FeatherIcons
type alias LoadedModel =
{ stateless : Stateless.Model
, scrollingNav : ScrollingNav.Model Example
, scrollingNav : ScrollingNav.ScrollingNav Example
, layout : Layout LoadedMsg
, displayDialog : Bool
, window :
@ -52,7 +52,7 @@ type Model
type LoadedMsg
= StatelessSpecific Stateless.Msg
| UpdateScrollingNav (ScrollingNav.Model Example -> ScrollingNav.Model Example)
| UpdateScrollingNav (ScrollingNav.ScrollingNav Example -> ScrollingNav.ScrollingNav Example)
| TimePassed Int
| AddSnackbar ( String, Bool )
| ToggleDialog Bool

View File

@ -4,51 +4,94 @@ module Widget exposing
, Dialog, modal, dialog
, ExpansionPanel, expansionPanel
, row, column, buttonRow, buttonColumn
, ColumnType, sortTable, floatColumn, intColumn, stringColumn, unsortableColumn
, TextInputStyle, textInput
, SortTable,Column, sortTable, floatColumn, intColumn, stringColumn, unsortableColumn
, TextInput, textInput
, Tab, tab
)
{-| This module contains functions for displaying data.
{-| This module contains different stateless view functions. No wiring required.
These widgets should be used by defining the styling seperately:
```
Widget.button Material.primaryButton
{ text = "disable me"
, icon =
FeatherIcons.slash
|> FeatherIcons.withSize 16
|> FeatherIcons.toHtml []
|> Element.html
|> Element.el []
, onPress =
if isButtonEnabled then
ChangedButtonStatus False
|> Just
else
Nothing
}
```
Every widgets comes with a type. You can think of the widgets as building blocks.
You can create you own widgets by sticking widgets types together.
# Buttons
![Button](https://orasund.github.io/elm-ui-widgets/assets/button.png)
@docs Button, TextButton, iconButton, textButton, button
# Select
@docs Select, MultiSelect, selectButton, select, multiSelect
![Select](https://orasund.github.io/elm-ui-widgets/assets/select.png)
@docs Select, selectButton, select
![multiSelect](https://orasund.github.io/elm-ui-widgets/assets/multiSelect.png)
@docs MultiSelect, multiSelect
# Dialog
![dialog](https://orasund.github.io/elm-ui-widgets/assets/dialog.png)
@docs Dialog, modal, dialog
# Expansion Panel
![expansionPanel](https://orasund.github.io/elm-ui-widgets/assets/expansionPanel.png)
@docs ExpansionPanel, expansionPanel
# List
![list](https://orasund.github.io/elm-ui-widgets/assets/list.png)
@docs row, column, buttonRow, buttonColumn
# Sort Table
@docs ColumnType, sortTable, floatColumn, intColumn, stringColumn, unsortableColumn
![sortTable](https://orasund.github.io/elm-ui-widgets/assets/sortTable.png)
@docs SortTable,Column, sortTable, floatColumn, intColumn, stringColumn, unsortableColumn
# Text Input
@docs TextInputStyle, textInput
![textInput](https://orasund.github.io/elm-ui-widgets/assets/textInput.png)
@docs TextInput, textInput
# Tab
![tab](https://orasund.github.io/elm-ui-widgets/assets/textInput.png)
@docs Tab, tab
-}
@ -64,7 +107,7 @@ import Internal.SortTable as SortTable
import Internal.Tab as Tab
import Internal.TextInput as TextInput
import Set exposing (Set)
import Widget.Style exposing (ButtonStyle, ColumnStyle, DialogStyle, ExpansionPanelStyle, RowStyle, SortTableStyle, TabStyle)
import Widget.Style exposing (ButtonStyle,TextInputStyle, ColumnStyle, DialogStyle, ExpansionPanelStyle, RowStyle, SortTableStyle, TabStyle)
@ -73,7 +116,7 @@ import Widget.Style exposing (ButtonStyle, ColumnStyle, DialogStyle, ExpansionPa
----------------------------------------------------------}
{-| A Button as a type
{-| Button widget type
-}
type alias Button msg =
{ text : String
@ -82,7 +125,7 @@ type alias Button msg =
}
{-| A Button with just text as a type
{-| Button widget type with no icon
-}
type alias TextButton msg =
{ text : String
@ -141,9 +184,11 @@ button =
----------------------------------------------------------}
{-| A list of options with at most one selected.
{-| Select widget type
Alternaitve Name: Choice
Technical Remark:
* A more suitable name would be "Choice"
-}
type alias Select msg =
@ -157,9 +202,11 @@ type alias Select msg =
}
{-| A list of options with multiple selected.
{-| Multi Select widget type
Alternative Name: Options
Technical Remark:
* A more suitable name would be "Options"
-}
type alias MultiSelect msg =
@ -207,7 +254,7 @@ multiSelect =
----------------------------------------------------------}
{-| A Dialog window displaying an important choice.
{-| Dialog widget type
-}
type alias Dialog msg =
{ title : Maybe String
@ -219,7 +266,9 @@ type alias Dialog msg =
{-| A modal.
NOTE: to stop the screen from scrolling, set the height of the layout to the height of the screen.
Technical Remark:
* To stop the screen from scrolling, set the height of the layout to the height of the screen.
-}
modal : { onDismiss : Maybe msg, content : Element msg } -> List (Attribute msg)
@ -244,10 +293,11 @@ dialog =
{----------------------------------------------------------
- DIALOG
- EXPANSION PANEL
----------------------------------------------------------}
{-| Expansion Panel widget type
-}
type alias ExpansionPanel msg =
{ onToggle : Bool -> msg
, icon : Element Never
@ -258,7 +308,8 @@ type alias ExpansionPanel msg =
, isExpanded : Bool
}
{-| An expansion Panel
-}
expansionPanel :
ExpansionPanelStyle msg
->
@ -278,17 +329,17 @@ expansionPanel =
- TEXT INPUT
----------------------------------------------------------}
{-| -}
type alias TextInputStyle msg =
{ chipButton : ButtonStyle msg
, containerRow : List (Attribute msg)
, chipsRow : List (Attribute msg)
, input : List (Attribute msg)
{-| Text Input widget type
-}
type alias TextInput msg =
{ chips : List (Button msg)
, text : String
, placeholder : Maybe (Placeholder msg)
, label : String
, onChange : String -> msg
}
{-| -}
{-| A text Input that allows to include chips. -}
textInput :
TextInputStyle msg
->
@ -308,17 +359,20 @@ textInput =
- LIST
----------------------------------------------------------}
{-| Replacement of `Element.row`
-}
row : RowStyle msg -> List (Element msg) -> Element msg
row =
List.row
{-| Replacement of `Element.column`
-}
column : ColumnStyle msg -> List (Element msg) -> Element msg
column =
List.column
{-| A row of buttons
-}
buttonRow :
{ list : RowStyle msg
, button : ButtonStyle msg
@ -328,7 +382,8 @@ buttonRow :
buttonRow =
List.buttonRow
{-| A column of buttons
-}
buttonColumn :
{ list : ColumnStyle msg
, button : ButtonStyle msg
@ -345,16 +400,23 @@ buttonColumn =
----------------------------------------------------------}
{-| A Sortable list allows you to sort coulmn.
{-| Column for the Sort Table widget type
-}
type alias ColumnType a =
SortTable.ColumnType a
type alias Column a =
SortTable.Column a
{-| Sort Table widget type
-}
type alias SortTable a msg=
{ content : List a
, columns : List (Column a)
, sortBy : String
, asc : Bool
, onChange : String -> msg
}
{-| An unsortable Column, when trying to sort by this column, nothing will change.
-}
unsortableColumn :
{ title : String
, toString : a -> String
@ -425,7 +487,8 @@ sortTable =
- TAB
----------------------------------------------------------}
{-| Tab widget type
-}
type alias Tab msg =
{ tabs : Select msg
, content : Maybe Int -> Element msg

View File

@ -1,5 +1,26 @@
module Widget.Layout exposing (Layout, Part(..), activate, init, queueMessage, timePassed, view)
{-| Combines multiple concepts from the [material design specification](https://material.io/components/), namely:
* Top App Bar
* Navigation Draw
* Side Panel
* Dialog
* Snackbar
It is responsive and changes view to apply to the [material design guidelines](https://material.io/components/app-bars-top).
# Basics
@docs Layout, Part, init, timePassed, view
# Actions
@docs activate, queueMessage
-}
import Array
import Element exposing (Attribute, DeviceClass(..), Element)
import Element.Input as Input
@ -8,40 +29,47 @@ import Widget exposing (Button, Select)
import Widget.Snackbar as Snackbar exposing (Message)
import Widget.Style exposing (LayoutStyle)
{-| The currently visible part: either the left sheet, right sheet or the search bar
-}
type Part
= LeftSheet
| RightSheet
| Search
{-| The model of the layout containing the snackbar and the currently active side sheet (or search bar)
-}
type alias Layout msg =
{ snackbar : Snackbar.Model (Message msg)
{ snackbar : Snackbar.Snackbar (Message msg)
, active : Maybe Part
}
{-| The initial state of the layout
-}
init : Layout msg
init =
{ snackbar = Snackbar.init
, active = Nothing
}
{-| Queues a message and displayes it as a snackbar once no other snackbar is visible.
-}
queueMessage : Message msg -> Layout msg -> Layout msg
queueMessage message layout =
{ layout
| snackbar = layout.snackbar |> Snackbar.insert message
}
{-| Open either a side sheet or the search bar.
-}
activate : Maybe Part -> Layout msg -> Layout msg
activate part layout =
{ layout
| active = part
}
{-| Update the model, put this function into your subscription.
The first argument is the seconds that have passed sice the function was called last.
-}
timePassed : Int -> Layout msg -> Layout msg
timePassed sec layout =
case layout.active of
@ -56,7 +84,8 @@ timePassed sec layout =
| snackbar = layout.snackbar |> Snackbar.timePassed sec
}
{-| View the layout. Replacement of `Element.layout`.
-}
view :
LayoutStyle msg
->

View File

@ -1,5 +1,5 @@
module Widget.ScrollingNav exposing
( Model, init, view, current, toSelect
( ScrollingNav, init, view, current, toSelect
, jumpTo, jumpToWithOffset, syncPositions, getPos, setPos
)
@ -9,7 +9,7 @@ the page. Clicking on a navigation button will scroll directly to that section.
# Basics
@docs Model, init, view, current, toSelect
@docs ScrollingNav, init, view, current, toSelect
# Operations
@ -27,7 +27,7 @@ import Widget exposing (Select)
{-| -}
type alias Model section =
type alias ScrollingNav section =
{ toString : section -> String
, fromString : String -> Maybe section
, positions : IntDict String
@ -42,9 +42,9 @@ init :
{ toString : section -> String
, fromString : String -> Maybe section
, arrangement : List section
, toMsg : Result Dom.Error (Model section -> Model section) -> msg
, toMsg : Result Dom.Error (ScrollingNav section -> ScrollingNav section) -> msg
}
-> ( Model section, Cmd msg )
-> ( ScrollingNav section, Cmd msg )
init { toString, fromString, arrangement, toMsg } =
{ toString = toString
, fromString = fromString
@ -62,7 +62,7 @@ init { toString, fromString, arrangement, toMsg } =
{-| Syncs the position of of the viewport
-}
getPos : Task x (Model selection -> Model selection)
getPos : Task x (ScrollingNav selection -> ScrollingNav selection)
getPos =
Dom.getViewport
|> Task.map
@ -75,7 +75,7 @@ getPos =
{-| sets the position of the viewport to show a specific section
-}
setPos : Int -> Model section -> Model section
setPos : Int -> ScrollingNav section -> ScrollingNav section
setPos pos model =
{ model | scrollPos = pos }
@ -86,7 +86,7 @@ jumpTo :
{ section : section
, onChange : Result Dom.Error () -> msg
}
-> Model section
-> ScrollingNav section
-> Cmd msg
jumpTo { section, onChange } { toString } =
Dom.getElement (section |> toString)
@ -104,7 +104,7 @@ jumpToWithOffset :
, section : section
, onChange : Result Dom.Error () -> msg
}
-> Model section
-> ScrollingNav section
-> Cmd msg
jumpToWithOffset { offset, section, onChange } { toString } =
Dom.getElement (section |> toString)
@ -118,7 +118,7 @@ jumpToWithOffset { offset, section, onChange } { toString } =
{-| Updates the positions of all sections.
This functions should be called regularly if the height of elements on your page can change during time.
-}
syncPositions : Model section -> Task Dom.Error (Model section -> Model section)
syncPositions : ScrollingNav section -> Task Dom.Error (ScrollingNav section -> ScrollingNav section)
syncPositions { toString, arrangement } =
arrangement
|> List.map
@ -150,7 +150,7 @@ syncPositions { toString, arrangement } =
{-| Returns the current section
-}
current : (String -> Maybe section) -> Model section -> Maybe section
current : (String -> Maybe section) -> ScrollingNav section -> Maybe section
current fromString { positions, scrollPos } =
positions
|> IntDict.before (scrollPos + 1)
@ -162,7 +162,7 @@ current fromString { positions, scrollPos } =
{-| Returns a select widget containing all section, with the current section selected.
-}
toSelect : (Int -> Maybe msg) -> Model section -> Select msg
toSelect : (Int -> Maybe msg) -> ScrollingNav section -> Select msg
toSelect onSelect ({ arrangement, toString, fromString } as model) =
{ selected =
arrangement
@ -217,7 +217,7 @@ view asElement { toString, arrangement } =
-}
view :
(section -> Element msg)
-> Model section
-> ScrollingNav section
-> List (Element msg)
view asElement { toString, arrangement } =
arrangement

View File

@ -1,14 +1,16 @@
module Widget.Snackbar exposing
( Model, Message, init, current, timePassed, view
( Snackbar, Message, init, current, timePassed, view
, insert, insertFor, dismiss
)
{-| A [snackbar](https://material.io/components/snackbars/) shows notification, one at a time.
{-| ![Snackbar](https://orasund.github.io/elm-ui-widgets/assets/snackbar.png)
A [snackbar](https://material.io/components/snackbars/) shows notification, one at a time.
# Basics
@docs Model, Message, init, current, timePassed, view
@docs Snackbar, Message, init, current, timePassed, view
# Operations
@ -22,7 +24,8 @@ import Queue exposing (Queue)
import Widget exposing (TextButton)
import Widget.Style exposing (SnackbarStyle)
{-| A message with maybe some action button
-}
type alias Message msg =
{ text : String
, button : Maybe (TextButton msg)
@ -31,7 +34,7 @@ type alias Message msg =
{-| A snackbar has a queue of Notifications, each with the amount of ms the message should be displayed
-}
type alias Model a =
type alias Snackbar a =
{ queue : Queue ( a, Int )
, current : Maybe ( a, Int )
}
@ -39,7 +42,7 @@ type alias Model a =
{-| Inital state
-}
init : Model a
init : Snackbar a
init =
{ queue = Queue.empty
, current = Nothing
@ -48,14 +51,14 @@ init =
{-| Insert a message that will last for 10 seconds.
-}
insert : a -> Model a -> Model a
insert : a -> Snackbar a -> Snackbar a
insert =
insertFor 10000
{-| Insert a message for a specific amount of milli seconds.
-}
insertFor : Int -> a -> Model a -> Model a
insertFor : Int -> a -> Snackbar a -> Snackbar a
insertFor removeIn a model =
case model.current of
Nothing ->
@ -67,7 +70,7 @@ insertFor removeIn a model =
{-| Dismiss the current message.
-}
dismiss : Model a -> Model a
dismiss : Snackbar a -> Snackbar a
dismiss model =
{ model | current = Nothing }
@ -75,7 +78,7 @@ dismiss model =
{-| Updates the model. This functions should be called regularly.
The first argument is the milli seconds that passed since the last time the function was called.
-}
timePassed : Int -> Model a -> Model a
timePassed : Int -> Snackbar a -> Snackbar a
timePassed ms model =
case model.current of
Nothing ->
@ -98,7 +101,7 @@ timePassed ms model =
{-| Returns the current element.
-}
current : Model a -> Maybe a
current : Snackbar a -> Maybe a
current model =
model.current |> Maybe.map Tuple.first
@ -108,7 +111,7 @@ current model =
view :
SnackbarStyle msg
-> (a -> Message msg)
-> Model a
-> Snackbar a
-> Maybe (Element msg)
view style toMessage model =
model

View File

@ -1,4 +1,4 @@
module Widget.Style exposing (ButtonStyle, ColumnStyle, DialogStyle, ExpansionPanelStyle, LayoutStyle, RowStyle, SnackbarStyle, SortTableStyle, TabStyle, TextInputStyle)
module Widget.Style exposing (ButtonStyle,ColumnStyle, DialogStyle, ExpansionPanelStyle, LayoutStyle, RowStyle, SnackbarStyle, SortTableStyle, TabStyle, TextInputStyle)
{-| This module contains style types for every widget.

View File

@ -1,47 +1,135 @@
module Widget.Style.Material exposing
( Palette, defaultPalette
( Palette, defaultPalette, darkPalette
, containedButton, outlinedButton, textButton
, toggleButton, buttonRow
, iconButton, toggleButton, buttonRow
, chip, textInput
, alertDialog
, row, column, cardColumn
, expansionPanel
, chip, darkPalette, iconButton, layout, snackbar, tab, tabButton, textInput
, row, column
, cardColumn
, layout, snackbar, tab, tabButton
)
{-|
{-| ![Example using the Material Design style](https://orasund.github.io/elm-ui-widgets/assets/material-style.png)
This module implements a Material design theme for all widgets.
The stylings are following [the official Material Design guidelines](https://material.io/components) as close as possible.
Please use these widgets in combination with the official guidelines.
The typograpahy is taken from [the material design guidelines](https://material.io/design/typography/the-type-system.html#type-scale).
Its recommended to use a font size of 16px width and the [Roboto Font](https://fonts.google.com/specimen/Roboto?query=Ro).
The style are not opaque, so you can change every styling to your needs.
If you have any suggestions or improvements, be sure to leave a PR or a Issue over at the github repos.
You can use the theme by copying the following code:
```
type alias Style msg =
{ dialog : DialogStyle msg
, expansionPanel : ExpansionPanelStyle msg
, button : ButtonStyle msg
, primaryButton : ButtonStyle msg
, tab : TabStyle msg
, textInput : TextInputStyle msg
, chipButton : ButtonStyle msg
, row : RowStyle msg
, buttonRow : RowStyle msg
, column : ColumnStyle msg
, cardColumn : ColumnStyle msg
, sortTable : SortTableStyle msg
, selectButton : ButtonStyle msg
, layout : LayoutStyle msg
}
sortTable : Palette -> SortTableStyle msg
sortTable palette =
{ containerTable = []
, headerButton = Material.textButton palette
, ascIcon = Icons.chevronUp |> Element.html |> Element.el []
, descIcon = Icons.chevronDown |> Element.html |> Element.el []
, defaultIcon = Element.none
}
# Style
@docs style
style : Palette -> Style msg
style palette =
{ sortTable = sortTable palette
, row = Material.row
, buttonRow = Material.buttonRow
, cardColumn = Material.cardColumn palette
, column = Material.column
, button = Material.outlinedButton palette
, primaryButton = Material.containedButton palette
, selectButton = Material.toggleButton palette
, tab = Material.tab palette
, textInput = Material.textInput palette
, chipButton = Material.chip palette
, expansionPanel = Material.expansionPanel palette
, dialog = Material.alertDialog palette
, layout = Material.layout palette
}
```
# Palette
@docs Palette, defaultPalette
@docs Palette, defaultPalette, darkPalette
# Button
Different styles for buttons have different meanings.
- Use `textButton` as your default button
- Use `containedButton` for any important action
- Use `outlinedButton` if you have more then one important action.
Use `containedButton` for **the most** important action of the group.
@docs containedButton, outlinedButton, textButton
@docs toggleButton, buttonRow
@docs iconButton, toggleButton, buttonRow
# Card
In the material design specification the card is not really specified at all.
Im practice the List seams more useful then a own card widget.
Thus for now we only provide a card containing a list.
@docs cardColumn
# Chip
@docs chip, textInput
# Dialog
@docs alertDialog
# List
@docs row, column, cardColumn
# Expansion Panel
@docs expansionPanel
# List
The [List widget](https://material.io/components/lists) is a very complex widget that sadly only particially made it into this package.
@docs row, column
# Snackbar
@docs snackbar
# Tab
@docs tab, tabButton
# Layout
@docs layout
-}
import Color exposing (Color)
@ -97,6 +185,13 @@ h6 =
-------------------------------------------------------------------------------}
{-| The material design comes with customizable color palettes.
Check out [the official documentation about the color system](https://material.io/design/color/the-color-system.html#color-theme-creation) to see how these colors are used.
For the `-on` colors you can use white, for transitions into white, or black,for transitions into black. Other colors are also possible, but i've not seen any website acutally using a different color.
-}
type alias Palette =
{ primary : Color --Color.rgb255 0x62 0x00 0xEE
, secondary : Color --Color.rgb255 0x03 0xda 0xc6
@ -113,6 +208,13 @@ type alias Palette =
}
{-| The default color theme.
![The default theme](https://lh3.googleusercontent.com/k6WO1fd7T40A9JvSVfHqs0CPLFyTEDCecsVGxEDhOaTP0wUTPYOVVkxt60hKxBprgNoMqs8OyKqtlaQ4tDBtQJs-fTcZrpZEjxhUVQ=w1064-v0)
_Image take from [material.io](https://material.io/design/color/the-color-system.html#color-theme-creation)_
-}
defaultPalette : Palette
defaultPalette =
{ primary = Color.rgb255 0x62 0x00 0xEE
@ -130,6 +232,13 @@ defaultPalette =
}
{-| The offical dark theme of google.
![The dark theme](https://lh3.googleusercontent.com/tv7J2o4ZiSmLYwyBslBs_PLzKyzI8QUV5qdvHGfoAQn9r7pY4Hj5SmW27m3zUWeDtRSE8Cb5_5PQmkbavDfw7XbIL8EodIKZhilRdg=w1064-v0)
_Image take from [material.io](https://material.io/design/color/dark-theme.html#ui-application)_
-}
darkPalette : Palette
darkPalette =
{ primary = Color.rgb255 0xBB 0x86 0xFC
@ -362,6 +471,13 @@ baseButton _ =
}
{-| A contained button representing the most important action of a group.
![Contained Button](https://material.io/develop/images/content/79e62add1830d33fc90edb22212bce53.svg)
_Image taken from [material.io](https://material.io/develop/android/components/buttons/)_
-}
containedButton : Palette -> ButtonStyle msg
containedButton palette =
{ container =
@ -413,6 +529,13 @@ containedButton palette =
}
{-| A outlined button representing an important action within a group.
![Contained Button](https://material.io/develop/images/content/2b50635d38c5fdec260f09be9aeafb10.svg)
_Image taken from [material.io](https://material.io/develop/android/components/buttons/)_
-}
outlinedButton : Palette -> ButtonStyle msg
outlinedButton palette =
{ container =
@ -480,6 +603,13 @@ outlinedButton palette =
}
{-| A text button representing a simple action within a group.
![Text Button](https://material.io/develop/images/content/d3079632c6f54d86f9b7093d541c2ee9.svg)
_Image taken from [material.io](https://material.io/develop/android/components/buttons/)_
-}
textButton : Palette -> ButtonStyle msg
textButton palette =
{ container =
@ -526,9 +656,19 @@ textButton palette =
}
{-| Technical Remark:
{-| A ToggleButton. Only use as a group in combination with `buttonRow`.
![Toggle Button](https://material.io/develop/images/content/749a1ba8591d02356fa1d6eea2641d96.svg)
_Image taken from [material.io](https://material.io/develop/android/components/buttons/)_
Toggle buttons should only be used with the `iconButton` widget, else use chips instead.
Technical Remark:
- Border color was not defined in the [specification](https://material.io/components/buttons#toggle-button)
- There are two different versions, one where the selected color is gray and another where the color is primary.
I noticed the gray version was used more often, so i went with that one.
-}
toggleButton : Palette -> ButtonStyle msg
@ -615,7 +755,13 @@ toggleButton palette =
}
{-| Technical Remark:
{-| An single selectable icon.
![Icon Button](https://material.io/develop/images/content/9bc212d8a3ef79bb7ed83a5359651505.png)
_Image taken from [material.io](https://material.io/develop/android/components/buttons/)_
Technical Remark:
- Could not find any specification details
@ -680,9 +826,19 @@ iconButton palette =
-------------------------------------------------------------------------------}
{-| Technical Remark:
{-| Chips have the same behaviour as buttons but are visually less important.
- There seams to be a bug, where in the mouseOver effects are now visible.
In the [official documentation](https://material.io/components/chips#types) chips have different names depending on where they are used:
- **Input Chips** are used inside a text field. Use `textInput` for this feature.
- **Choice Chips** are used for selcting an option.
The material design guidelines recommend using `toggleButton` for icons with no text and chips for text with no icons.
- **Filter Chips** are used for selecting multiple options. They typically have a done-icon when selected.
- **Action chips** are like button. Make sure to include an icon when using action chips.
Technical Remark:
- There seems to be a bug, where in the mouseOver effects are now visible.
This might have something to do with <https://github.com/mdgriffith/elm-ui/issues/47>.
This needs to be investigated, but for now i leave it at that.
@ -760,9 +916,14 @@ chip palette =
-------------------------------------------------------------------------------}
{-| A simple styling for a row.
-}
row : RowStyle msg
row =
{ containerRow = [ Element.spacing 8 ]
{ containerRow =
[ Element.paddingXY 0 8
, Element.spacing 8
]
, element = []
, ifFirst = []
, ifLast = []
@ -770,9 +931,14 @@ row =
}
{-| A simple styling for a column.
-}
column : ColumnStyle msg
column =
{ containerColumn = [ Element.spacing 8 ]
{ containerColumn =
[ Element.paddingXY 0 8
, Element.spacing 8
]
, element = []
, ifFirst = []
, ifLast = []
@ -780,6 +946,11 @@ column =
}
{-| a Row of buttons.
Only use in combination with `toggleButton`
-}
buttonRow : RowStyle msg
buttonRow =
{ containerRow = []
@ -808,7 +979,9 @@ buttonRow =
}
{-| Technical Remark:
{-| A List styled like a card.
Technical Remark:
This is a simplification of the [Material Design Card
](https://material.io/components/cards) and might get replaced at a later date.
@ -880,6 +1053,14 @@ cardColumn palette =
-------------------------------------------------------------------------------}
{-| An alert dialog for important decisions. Use a snackbar for less important notification.
![Alert Dialog](https://material.io/develop/images/content/9d61e2d1bd60599344c7fae5e71c9667.png)
_Image taken from [material.io](https://material.io/develop/android/components/buttons/)_
-}
alertDialog : Palette -> DialogStyle msg
alertDialog palette =
{ containerColumn =
@ -937,7 +1118,10 @@ expand_more =
icon "0 0 48 48" 24 [ Svg.path [ Svg.Attributes.d "M33.17 17.17L24 26.34l-9.17-9.17L12 20l12 12 12-12z" ] [] ]
{-| Technical Remarks:
{-| The expansion Panel is an outdated part of the material design specification.
In modern implementation it gets replaced with a very sophisticated list widget.
Technical Remarks:
- The expansion panel is part of an [older version](https://material.io/archive/guidelines/components/expansion-panels.html) of the Material Design.
The newer version is part of the List component.
@ -985,7 +1169,13 @@ expansionPanel palette =
-------------------------------------------------------------------------------}
{-| Technical Remark:
{-| A typical snackbar
![Snackbar](https://material.io/develop/images/content/f2ec5451582a06af5eb20e3dfb3d27d5.svg)
_Image take from [material.io](https://material.io/develop/android/components/snackbar/)_
Technical Remark:
- The text color of the button was not given in the specification. This implementation
adujsts the luminance of the color to fit the [w3 accessability standard](https://www.w3.org/TR/WCAG20/#Contrast)
@ -1033,7 +1223,9 @@ snackbar palette =
-------------------------------------------------------------------------------}
{-| Technical Remark:
{-| A text input style that is included only to support input chips.
Technical Remark:
- This is just a temporary implementation. It will soon be replaced with the official implementation.
@ -1078,7 +1270,14 @@ textInput palette =
-- T A B
-------------------------------------------------------------------------------}
{-| A single Tab button.
Technical Remark:
* The official specification states that the background color should be the surface color,
but the pictures and actuall implementations all have no background color.
So here the background color is also not set.
-}
tabButton : Palette -> ButtonStyle msg
tabButton palette =
{ container =
@ -1138,7 +1337,8 @@ tabButton palette =
}
{-| -}
{-| A Tab bar meant for only the upper most level. Do not use a tab within a tab.
-}
tab : Palette -> TabStyle msg
tab palette =
{ button = tabButton palette
@ -1292,7 +1492,18 @@ drawerButton palette =
}
{-| Technical Remark:
{-| The Layout Widget combines the following Material design concepts:
* Top bar
* Navigation drawer
* Side Sheet
* Dialog
* Snackbar
Future updates might try to seperate them into there own widgets.
But for now they are only available as an all-in-one solution.
Technical Remark:
- Due to [a bug in Elm-Ui](https://github.com/mdgriffith/elm-ui/issues/47) the menu button still behave wierd.
I've not found a workaround for it.

View File

@ -1,6 +1,61 @@
module Widget.Style.Template exposing (box, button, column, decoration, dialog, expansionPanel, icon, layout, row, snackbar, sortTable, tab, textInput)
module Widget.Style.Template exposing
( box, decoration, icon
, button, column, dialog, expansionPanel, layout, row, snackbar, sortTable, tab, textInput
)
{-| ![Example using the Template style](https://orasund.github.io/elm-ui-widgets/assets/template-style.png)
This package contains mockups designed for writing your own style.
Start by copying the following code and then replace the fields one by one.
```
type alias Style msg =
{ dialog : DialogStyle msg
, expansionPanel : ExpansionPanelStyle msg
, button : ButtonStyle msg
, primaryButton : ButtonStyle msg
, tab : TabStyle msg
, textInput : TextInputStyle msg
, chipButton : ButtonStyle msg
, row : RowStyle msg
, buttonRow : RowStyle msg
, column : ColumnStyle msg
, cardColumn : ColumnStyle msg
, sortTable : SortTableStyle msg
, selectButton : ButtonStyle msg
, layout : LayoutStyle msg
}
style : Style msg
style =
{ sortTable = Template.sortTable <| "sortTable"
, row = Template.row <| "row"
, buttonRow = Template.row <| "buttonRow"
, cardColumn = Template.column <| "cardRow"
, column = Template.column <| "column"
, button = Template.button <| "button"
, primaryButton = Template.button <| "primaryButton"
, tab = Template.tab <| "tab"
, textInput = Template.textInput <| "textInput"
, chipButton = Template.button <| "chipButton"
, expansionPanel = Template.expansionPanel "expansionPanel"
, selectButton = Template.button "selectButton"
, dialog = Template.dialog "dialog"
, layout = Template.layout "layout"
}
```
# Base Elements
@docs box, decoration, icon
# Mockups
@docs button, column, dialog, expansionPanel, layout, row, snackbar, sortTable, tab, textInput
{-| This package
-}
import Element exposing (Attribute, Element)
@ -27,6 +82,8 @@ fontSize =
10
{-| A box representing an element
-}
box : String -> List (Attribute msg)
box string =
[ Border.width 1
@ -39,6 +96,8 @@ box string =
]
{-| An additional attribute representing a state change.
-}
decoration : String -> List (Attribute msg)
decoration string =
[ Element.below <|
@ -48,6 +107,8 @@ decoration string =
]
{-| A circle representing an icon
-}
icon : String -> Element msg
icon string =
Element.none
@ -62,6 +123,21 @@ icon string =
]
{-|
```
button : String -> ButtonStyle msg
button string =
{ container = box <| string ++ ":container"
, labelRow = box <| string ++ ":labelRow"
, text = box <| string ++ ":text"
, ifDisabled = decoration <| string ++ ":ifDisabled"
, ifActive = decoration <| string ++ ":ifActive"
, otherwise = decoration <| string ++ ":otherwise"
}
```
-}
button : String -> ButtonStyle msg
button string =
{ container = box <| string ++ ":container"
@ -73,6 +149,18 @@ button string =
}
{-|
```
snackbar : String -> SnackbarStyle msg
snackbar string =
{ containerRow = box <| string ++ ":containerRow"
, button = button <| string ++ ":button"
, text = box <| string ++ ":text"
}
```
-}
snackbar : String -> SnackbarStyle msg
snackbar string =
{ containerRow = box <| string ++ ":containerRow"
@ -81,6 +169,21 @@ snackbar string =
}
{-|
```
dialog : String -> DialogStyle msg
dialog string =
{ containerColumn = box <| string ++ ":containerColumn"
, title = box <| string ++ ":title"
, text = box <| string ++ ":text"
, buttonRow = box <| string ++ ":buttonRow"
, acceptButton = button <| string ++ ":acceptButton"
, dismissButton = button <| string ++ ":dismissButton"
}
```
-}
dialog : String -> DialogStyle msg
dialog string =
{ containerColumn = box <| string ++ ":containerColumn"
@ -92,6 +195,22 @@ dialog string =
}
{-|
```
expansionPanel : String -> ExpansionPanelStyle msg
expansionPanel string =
{ containerColumn = box <| string ++ ":containerColumn"
, panelRow = box <| string ++ ":panelRow"
, labelRow = box <| string ++ ":labelRow"
, content = box <| string ++ ":content"
, expandIcon = icon <| string ++ ":expandIcon"
, collapseIcon = icon <| string ++ ":collapseIcon"
}
```
-}
expansionPanel : String -> ExpansionPanelStyle msg
expansionPanel string =
{ containerColumn = box <| string ++ ":containerColumn"
@ -103,6 +222,20 @@ expansionPanel string =
}
{-|
```
textInput : String -> TextInputStyle msg
textInput string =
{ chipButton = button <| string ++ ":chipButton"
, chipsRow = box <| string ++ ":chipsRow"
, containerRow = box <| string ++ ":containerRow"
, input = box <| string ++ ":input"
}
```
-}
textInput : String -> TextInputStyle msg
textInput string =
{ chipButton = button <| string ++ ":chipButton"
@ -112,6 +245,19 @@ textInput string =
}
{-|
```
tab : String -> TabStyle msg
tab string =
{ button = button <| string ++ ":button"
, optionRow = box <| string ++ ":optionRow"
, containerColumn = box <| string ++ ":containerColumn"
, content = box <| string ++ ":content"
}
```
-}
tab : String -> TabStyle msg
tab string =
{ button = button <| string ++ ":button"
@ -121,26 +267,68 @@ tab string =
}
{-|
```
row : String -> RowStyle msg
row string =
{ containerRow = box <| string ++ ":containerRow"
, element = box <| string ++ ":element"
, ifFirst = box <| string ++ ":ifFirst"
, ifLast = box <| string ++ ":ifLast"
, otherwise = box <| string ++ ":otherwise"
, ifFirst = decoration <| string ++ ":ifFirst"
, ifLast = decoration <| string ++ ":ifLast"
, otherwise = decoration <| string ++ ":otherwise"
}
```
-}
row : String -> RowStyle msg
row string =
{ containerRow = box <| string ++ ":containerRow"
, element = box <| string ++ ":element"
, ifFirst = decoration <| string ++ ":ifFirst"
, ifLast = decoration <| string ++ ":ifLast"
, otherwise = decoration <| string ++ ":otherwise"
}
{-|
```
column : String -> ColumnStyle msg
column string =
{ containerColumn = box <| string ++ ":containerColumn"
, element = box <| string ++ ":element"
, ifFirst = box <| string ++ ":ifFirst"
, ifLast = box <| string ++ ":ifLast"
, otherwise = box <| string ++ ":otherwise"
, ifFirst = decoration <| string ++ ":ifFirst"
, ifLast = decoration <| string ++ ":ifLast"
, otherwise = decoration <| string ++ ":otherwise"
}
```
-}
column : String -> ColumnStyle msg
column string =
{ containerColumn = box <| string ++ ":containerColumn"
, element = box <| string ++ ":element"
, ifFirst = decoration <| string ++ ":ifFirst"
, ifLast = decoration <| string ++ ":ifLast"
, otherwise = decoration <| string ++ ":otherwise"
}
{-|
```
sortTable : String -> SortTableStyle msg
sortTable string =
{ containerTable = box <| string ++ ":containerTable"
, headerButton = button <| string ++ ":headerButton"
, ascIcon = icon <| string ++ ":ascIcon"
, descIcon = icon <| string ++ ":descIcon"
, defaultIcon = icon <| string ++ ":defaultIcon"
}
```
-}
sortTable : String -> SortTableStyle msg
sortTable string =
{ containerTable = box <| string ++ ":containerTable"
@ -151,6 +339,30 @@ sortTable string =
}
{-|
```
layout : String -> LayoutStyle msg
layout string =
{ container = box <| string ++ ":container"
, snackbar = snackbar <| string ++ ":snackbar"
, layout = Element.layout
, header = box <| string ++ ":header"
, menuButton = button <| string ++ ":menuButton"
, sheetButton = button <| string ++ ":sheetButton"
, menuTabButton = button <| string ++ ":menuTabButton"
, sheet = box <| string ++ ":sheet"
, menuIcon = icon <| string ++ ":menuIcon"
, moreVerticalIcon = icon <| string ++ ":moreVerticalIcon"
, spacing = 8
, title = box <| string ++ ":title"
, searchIcon = icon <| string ++ ":searchIcon"
, search = box <| string ++ ":search"
, searchFill = box <| string ++ ":searchFill"
}
```
-}
layout : String -> LayoutStyle msg
layout string =
{ container = box <| string ++ ":container"