mirror of
https://github.com/Orasund/elm-ui-widgets.git
synced 2024-08-15 17:30:30 +03:00
Ready to Merge
This commit is contained in:
parent
bb3ae50376
commit
86ff420314
147
README.md
147
README.md
@ -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.
|
9
elm.json
9
elm.json
@ -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": {
|
||||
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
|
137
src/Widget.elm
137
src/Widget.elm
@ -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
|
||||
|
@ -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
|
||||
->
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user