diff --git a/README.md b/README.md index b9e7706..b99e139 100644 --- a/README.md +++ b/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). \ No newline at end of file +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. \ No newline at end of file diff --git a/docs.json b/docs.json index 89b845a..8048680 100644 --- a/docs.json +++ b/docs.json @@ -1 +1 @@ -[{"name":"Framework","comment":" This module includes the basic building bocks.\r\nMaybe start by copying the follow code into your project:\r\n\r\n```\r\nview : Html msg\r\nview =\r\n Framework.layout [] <|\r\n Element.el Framework.container <|\r\n Element.text \"the first element should be a container.\"\r\n```\r\n\r\n@docs layout, container, layoutOptions, layoutAttributes\r\n\r\n","unions":[],"aliases":[],"values":[{"name":"container","comment":" The container should be the outer most element.\r\nIt centers the content and sets the background to white.\r\n","type":"List.List (Element.Attribute msg)"},{"name":"layout","comment":" A replacement of Element.layout adding both the Framework.layoutOptions and the Framework.layoutAttributes.\r\n","type":"List.List (Element.Attribute msg) -> Element.Element msg -> Html.Html msg"},{"name":"layoutAttributes","comment":" The default Attributes. Check the source code if you want to know more.\r\n","type":"List.List (Element.Attribute msg)"},{"name":"layoutOptions","comment":" The default layoutOptions. Check the source code if you want to know more.\r\n","type":"List.List Element.Option"}],"binops":[]},{"name":"Framework.Button","comment":" This module contains a attribute to style buttons.\r\n\r\n```\r\nInput.button (Button.simple ++ Color.primary) <|\r\n { onPress = Nothing\r\n , label = Element.text \"Button.simple ++ Color.primary\"\r\n }\r\n```\r\n\r\nThe attribute can only be used on `Input.button` but it may be with additional attibutes from this package.\r\n\r\n@docs simple\r\n\r\n","unions":[],"aliases":[],"values":[{"name":"simple","comment":" a simple Button styling. Check the source-code for more information.\r\n","type":"List.List (Element.Attribute msg)"}],"binops":[]},{"name":"Framework.Card","comment":" The Card attributes can be used almost anywere in the elm-ui elements.\r\n\r\nHere are some examples:\r\n\r\n```\r\nElement.column (Card.simple ++ Grid.simple) <|\r\n [ Element.text <| \"adds a border around the column\"\r\n ]\r\n```\r\n\r\n```\r\nElement.el Card.small <|\r\n Element.text \"a basic card\"\r\n```\r\n\r\n```\r\nInput.button (Button.simple ++ Card.large) <|\r\n { onPress = Nothing\r\n , label = Element.text \"a clickable card\"\r\n }\r\n```\r\n\r\n@docs simple, small, large, fill\r\n\r\n","unions":[],"aliases":[],"values":[{"name":"fill","comment":" A card filling all the avaiable space.\r\nCheck the source-code for more information.\r\n","type":"List.List (Element.Attribute msg)"},{"name":"large","comment":" A 480px wide card.\r\nCheck the source-code for more information.\r\n","type":"List.List (Element.Attribute msg)"},{"name":"simple","comment":" A basic card.\r\nCheck the source-code for more information.\r\n","type":"List.List (Element.Attribute msg)"},{"name":"small","comment":" A 240px wide card.\r\nCheck the source-code for more information.\r\n","type":"List.List (Element.Attribute msg)"}],"binops":[]},{"name":"Framework.Color","comment":" This module contains the colors used in the framework.\r\n\r\n@docs cyan, green, lighterGrey, lightGrey, grey, darkGrey, darkerGrey, red, turquoise, yellow\r\n\r\nSome colors also have a Attribute that can be used nearly everywhere.\r\n\r\n@docs danger, light, dark, disabled, info, primary, success, warning\r\n\r\n","unions":[],"aliases":[],"values":[{"name":"cyan","comment":" ","type":"Element.Color"},{"name":"danger","comment":" ","type":"List.List (Element.Attribute msg)"},{"name":"dark","comment":" ","type":"List.List (Element.Attribute msg)"},{"name":"darkGrey","comment":" ","type":"Element.Color"},{"name":"darkerGrey","comment":" ","type":"Element.Color"},{"name":"disabled","comment":" ","type":"List.List (Element.Attribute msg)"},{"name":"green","comment":" ","type":"Element.Color"},{"name":"grey","comment":" ","type":"Element.Color"},{"name":"info","comment":" ","type":"List.List (Element.Attribute msg)"},{"name":"light","comment":" ","type":"List.List (Element.Attribute msg)"},{"name":"lightGrey","comment":" ","type":"Element.Color"},{"name":"lighterGrey","comment":" ","type":"Element.Color"},{"name":"primary","comment":" ","type":"List.List (Element.Attribute msg)"},{"name":"red","comment":" ","type":"Element.Color"},{"name":"success","comment":" ","type":"List.List (Element.Attribute msg)"},{"name":"turquoise","comment":" ","type":"Element.Color"},{"name":"warning","comment":" ","type":"List.List (Element.Attribute msg)"},{"name":"yellow","comment":" ","type":"Element.Color"}],"binops":[]},{"name":"Framework.Grid","comment":" This module include the basic attributes for columns and rows and two variants.\r\nAny of these Attributes can be used for columns and rows.\r\n\r\n```\r\nElement.row Grid.spacedEvenly <|\r\n [ Element.text \"left item\"\r\n , Element.text \"center item\"\r\n , Element.text \"right item\"\r\n ]\r\n```\r\n\r\n@docs simple, spacedEvenly, section\r\n\r\n","unions":[],"aliases":[],"values":[{"name":"section","comment":" The simple attributes but with a horizontal line at the top\r\nCheck the source-code for more information.\r\n","type":"List.List (Element.Attribute msg)"},{"name":"simple","comment":" The basic attributes for columns and rows.\r\nCheck the source-code for more information.\r\n","type":"List.List (Element.Attribute msg)"},{"name":"spacedEvenly","comment":" The simple attibutes but with evenly spaced elements.\r\nCheck the source-code for more information.\r\n","type":"List.List (Element.Attribute msg)"}],"binops":[]},{"name":"Framework.Heading","comment":" Styling for heading\r\n\r\n```\r\nElement.el Heading.h1 <| Element.text \"Only Element.el may be styled as a heading\"\r\n```\r\n\r\n@docs h1, h2, h3, h4, h5, h6\r\n\r\n","unions":[],"aliases":[],"values":[{"name":"h1","comment":" ","type":"List.List (Element.Attribute msg)"},{"name":"h2","comment":" ","type":"List.List (Element.Attribute msg)"},{"name":"h3","comment":" ","type":"List.List (Element.Attribute msg)"},{"name":"h4","comment":" ","type":"List.List (Element.Attribute msg)"},{"name":"h5","comment":" ","type":"List.List (Element.Attribute msg)"},{"name":"h6","comment":" ","type":"List.List (Element.Attribute msg)"}],"binops":[]},{"name":"Framework.Input","comment":" This module exposes simple attibutes for Inputs (beside Buttons) and\r\nstyling for labels.\r\n\r\n```\r\nInput.text Input.simple\r\n { onChange = always ()\r\n , text = \"Input.simple\"\r\n , placeholder = Nothing\r\n , label = Input.labelLeft Input.label <| Element.text \"Input.label\"\r\n }\r\n```\r\n\r\n@docs simple, label\r\n\r\n","unions":[],"aliases":[],"values":[{"name":"label","comment":" ","type":"List.List (Element.Attribute msg)"},{"name":"simple","comment":" ","type":"List.List (Element.Attribute msg)"}],"binops":[]}] \ No newline at end of file +[{"name":"Widget","comment":" This module contains different stateless view functions. No wiring required.\n\nThese widgets should be used by defining the styling seperately:\n\n```\nWidget.button Material.primaryButton\n { text = \"disable me\"\n , icon =\n FeatherIcons.slash\n |> FeatherIcons.withSize 16\n |> FeatherIcons.toHtml []\n |> Element.html\n |> Element.el []\n , onPress =\n if isButtonEnabled then\n ChangedButtonStatus False\n |> Just\n\n else\n Nothing\n }\n```\n\nEvery widgets comes with a type. You can think of the widgets as building blocks.\nYou can create you own widgets by sticking widgets types together.\n\n# Buttons\n\n![Button](https://orasund.github.io/elm-ui-widgets/assets/button.png)\n\n@docs Button, TextButton, iconButton, textButton, button\n\n\n# Select\n\n![Select](https://orasund.github.io/elm-ui-widgets/assets/select.png)\n\n@docs Select, selectButton, select\n\n![multiSelect](https://orasund.github.io/elm-ui-widgets/assets/multiSelect.png)\n\n@docs MultiSelect, multiSelect\n\n\n# Dialog\n\n![dialog](https://orasund.github.io/elm-ui-widgets/assets/dialog.png)\n\n@docs Dialog, modal, dialog\n\n\n# Expansion Panel\n\n![expansionPanel](https://orasund.github.io/elm-ui-widgets/assets/expansionPanel.png)\n\n@docs ExpansionPanel, expansionPanel\n\n\n# List\n\n![list](https://orasund.github.io/elm-ui-widgets/assets/list.png)\n\n@docs row, column, buttonRow, buttonColumn\n\n\n# Sort Table\n\n![sortTable](https://orasund.github.io/elm-ui-widgets/assets/sortTable.png)\n\n@docs SortTable,Column, sortTable, floatColumn, intColumn, stringColumn, unsortableColumn\n\n\n# Text Input\n\n![textInput](https://orasund.github.io/elm-ui-widgets/assets/textInput.png)\n\n@docs TextInput, textInput\n\n\n# Tab\n\n![tab](https://orasund.github.io/elm-ui-widgets/assets/textInput.png)\n\n@docs Tab, tab\n\n","unions":[],"aliases":[{"name":"Button","comment":" Button widget type\n","args":["msg"],"type":"{ text : String.String, icon : Element.Element Basics.Never, onPress : Maybe.Maybe msg }"},{"name":"Column","comment":" Column for the Sort Table widget type\n","args":["a"],"type":"Internal.SortTable.Column a"},{"name":"Dialog","comment":" Dialog widget type\n","args":["msg"],"type":"{ title : Maybe.Maybe String.String, body : Element.Element msg, accept : Maybe.Maybe (Widget.TextButton msg), dismiss : Maybe.Maybe (Widget.TextButton msg) }"},{"name":"ExpansionPanel","comment":" Expansion Panel widget type\n","args":["msg"],"type":"{ onToggle : Basics.Bool -> msg, icon : Element.Element Basics.Never, text : String.String, expandIcon : Element.Element Basics.Never, collapseIcon : Element.Element Basics.Never, content : Element.Element msg, isExpanded : Basics.Bool }"},{"name":"MultiSelect","comment":" Multi Select widget type\n\nTechnical Remark:\n\n* A more suitable name would be \"Options\"\n\n","args":["msg"],"type":"{ selected : Set.Set Basics.Int, options : List.List { text : String.String, icon : Element.Element Basics.Never }, onSelect : Basics.Int -> Maybe.Maybe msg }"},{"name":"Select","comment":" Select widget type\n\nTechnical Remark:\n\n* A more suitable name would be \"Choice\"\n\n","args":["msg"],"type":"{ selected : Maybe.Maybe Basics.Int, options : List.List { text : String.String, icon : Element.Element Basics.Never }, onSelect : Basics.Int -> Maybe.Maybe msg }"},{"name":"SortTable","comment":" Sort Table widget type\n","args":["a","msg"],"type":"{ content : List.List a, columns : List.List (Widget.Column a), sortBy : String.String, asc : Basics.Bool, onChange : String.String -> msg }"},{"name":"Tab","comment":" Tab widget type\n","args":["msg"],"type":"{ tabs : Widget.Select msg, content : Maybe.Maybe Basics.Int -> Element.Element msg }"},{"name":"TextButton","comment":" Button widget type with no icon\n","args":["msg"],"type":"{ text : String.String, onPress : Maybe.Maybe msg }"},{"name":"TextInput","comment":" Text Input widget type\n","args":["msg"],"type":"{ chips : List.List (Widget.Button msg), text : String.String, placeholder : Maybe.Maybe (Element.Input.Placeholder msg), label : String.String, onChange : String.String -> msg }"}],"values":[{"name":"button","comment":" A button containing a text and an icon.\n","type":"Widget.Style.ButtonStyle msg -> { text : String.String, icon : Element.Element Basics.Never, onPress : Maybe.Maybe msg } -> Element.Element msg"},{"name":"buttonColumn","comment":" A column of buttons\n","type":"{ list : Widget.Style.ColumnStyle msg, button : Widget.Style.ButtonStyle msg } -> List.List ( Basics.Bool, Widget.Button msg ) -> Element.Element msg"},{"name":"buttonRow","comment":" A row of buttons\n","type":"{ list : Widget.Style.RowStyle msg, button : Widget.Style.ButtonStyle msg } -> List.List ( Basics.Bool, Widget.Button msg ) -> Element.Element msg"},{"name":"column","comment":" Replacement of `Element.column`\n","type":"Widget.Style.ColumnStyle msg -> List.List (Element.Element msg) -> Element.Element msg"},{"name":"dialog","comment":" A Dialog Window.\n","type":"Widget.Style.DialogStyle msg -> { title : Maybe.Maybe String.String, text : String.String, accept : Maybe.Maybe (Widget.TextButton msg), dismiss : Maybe.Maybe (Widget.TextButton msg) } -> List.List (Element.Attribute msg)"},{"name":"expansionPanel","comment":" An expansion Panel\n","type":"Widget.Style.ExpansionPanelStyle msg -> { onToggle : Basics.Bool -> msg, icon : Element.Element Basics.Never, text : String.String, content : Element.Element msg, isExpanded : Basics.Bool } -> Element.Element msg"},{"name":"floatColumn","comment":" A Column containing a Float\n","type":"{ title : String.String, value : a -> Basics.Float, toString : Basics.Float -> String.String, width : Element.Length } -> Widget.Column a"},{"name":"iconButton","comment":" A button containing only an icon, the text is used for screenreaders.\n","type":"Widget.Style.ButtonStyle msg -> { text : String.String, icon : Element.Element Basics.Never, onPress : Maybe.Maybe msg } -> Element.Element msg"},{"name":"intColumn","comment":" A Column containing a Int\n","type":"{ title : String.String, value : a -> Basics.Int, toString : Basics.Int -> String.String, width : Element.Length } -> Widget.Column a"},{"name":"modal","comment":" A modal.\n\nTechnical Remark:\n\n* To stop the screen from scrolling, set the height of the layout to the height of the screen.\n\n","type":"{ onDismiss : Maybe.Maybe msg, content : Element.Element msg } -> List.List (Element.Attribute msg)"},{"name":"multiSelect","comment":" Selects multible options. This can be used for checkboxes.\n","type":"Widget.MultiSelect msg -> List.List ( Basics.Bool, Widget.Button msg )"},{"name":"row","comment":" Replacement of `Element.row`\n","type":"Widget.Style.RowStyle msg -> List.List (Element.Element msg) -> Element.Element msg"},{"name":"select","comment":" Selects one out of multiple options. This can be used for radio buttons or Menus.\n","type":"Widget.Select msg -> List.List ( Basics.Bool, Widget.Button msg )"},{"name":"selectButton","comment":" A simple button that can be selected.\n","type":"Widget.Style.ButtonStyle msg -> ( Basics.Bool, Widget.Button msg ) -> Element.Element msg"},{"name":"sortTable","comment":" The View\n","type":"Widget.Style.SortTableStyle msg -> { content : List.List a, columns : List.List (Widget.Column a), sortBy : String.String, asc : Basics.Bool, onChange : String.String -> msg } -> Element.Element msg"},{"name":"stringColumn","comment":" A Column containing a String\n","type":"{ title : String.String, value : a -> String.String, toString : String.String -> String.String, width : Element.Length } -> Widget.Column a"},{"name":"tab","comment":" Displayes a list of contents in a tab\n","type":"Widget.Style.TabStyle msg -> { tabs : Widget.Select msg, content : Maybe.Maybe Basics.Int -> Element.Element msg } -> Element.Element msg"},{"name":"textButton","comment":" A button with just text and not icon.\n","type":"Widget.Style.ButtonStyle msg -> { textButton | text : String.String, onPress : Maybe.Maybe msg } -> Element.Element msg"},{"name":"textInput","comment":" A text Input that allows to include chips. ","type":"Widget.Style.TextInputStyle msg -> { chips : List.List (Widget.Button msg), text : String.String, placeholder : Maybe.Maybe (Element.Input.Placeholder msg), label : String.String, onChange : String.String -> msg } -> Element.Element msg"},{"name":"unsortableColumn","comment":" An unsortable Column, when trying to sort by this column, nothing will change.\n","type":"{ title : String.String, toString : a -> String.String, width : Element.Length } -> Widget.Column a"}],"binops":[]},{"name":"Widget.Layout","comment":" Combines multiple concepts from the [material design specification](https://material.io/components/), namely:\n\n* Top App Bar\n* Navigation Draw\n* Side Panel\n* Dialog\n* Snackbar\n\nIt is responsive and changes view to apply to the [material design guidelines](https://material.io/components/app-bars-top).\n\n# Basics\n\n@docs Layout, Part, init, timePassed, view\n\n# Actions\n\n@docs activate, queueMessage\n\n\n","unions":[{"name":"Part","comment":" The currently visible part: either the left sheet, right sheet or the search bar\n","args":[],"cases":[["LeftSheet",[]],["RightSheet",[]],["Search",[]]]}],"aliases":[{"name":"Layout","comment":" The model of the layout containing the snackbar and the currently active side sheet (or search bar)\n","args":["msg"],"type":"{ snackbar : Widget.Snackbar.Snackbar (Widget.Snackbar.Message msg), active : Maybe.Maybe Widget.Layout.Part }"}],"values":[{"name":"activate","comment":" Open either a side sheet or the search bar.\n","type":"Maybe.Maybe Widget.Layout.Part -> Widget.Layout.Layout msg -> Widget.Layout.Layout msg"},{"name":"init","comment":" The initial state of the layout\n","type":"Widget.Layout.Layout msg"},{"name":"queueMessage","comment":" Queues a message and displayes it as a snackbar once no other snackbar is visible.\n","type":"Widget.Snackbar.Message msg -> Widget.Layout.Layout msg -> Widget.Layout.Layout msg"},{"name":"timePassed","comment":" Update the model, put this function into your subscription.\nThe first argument is the seconds that have passed sice the function was called last.\n","type":"Basics.Int -> Widget.Layout.Layout msg -> Widget.Layout.Layout msg"},{"name":"view","comment":" View the layout. Replacement of `Element.layout`.\n","type":"Widget.Style.LayoutStyle msg -> { window : { height : Basics.Int, width : Basics.Int }, dialog : Maybe.Maybe (List.List (Element.Attribute msg)), layout : Widget.Layout.Layout msg, title : Element.Element msg, menu : Widget.Select msg, search : Maybe.Maybe { onChange : String.String -> msg, text : String.String, label : String.String }, actions : List.List (Widget.Button msg), onChangedSidebar : Maybe.Maybe Widget.Layout.Part -> msg } -> Element.Element msg -> Html.Html msg"}],"binops":[]},{"name":"Widget.ScrollingNav","comment":" The Scrolling Nav is a navigation bar thats updates while you scroll through\nthe page. Clicking on a navigation button will scroll directly to that section.\n\n\n# Basics\n\n@docs ScrollingNav, init, view, current, toSelect\n\n\n# Operations\n\n@docs jumpTo, jumpToWithOffset, syncPositions, getPos, setPos\n\n","unions":[],"aliases":[{"name":"ScrollingNav","comment":" ","args":["section"],"type":"{ toString : section -> String.String, fromString : String.String -> Maybe.Maybe section, positions : IntDict.IntDict String.String, arrangement : List.List section, scrollPos : Basics.Int }"}],"values":[{"name":"current","comment":" Returns the current section\n","type":"(String.String -> Maybe.Maybe section) -> Widget.ScrollingNav.ScrollingNav section -> Maybe.Maybe section"},{"name":"getPos","comment":" Syncs the position of of the viewport\n","type":"Task.Task x (Widget.ScrollingNav.ScrollingNav selection -> Widget.ScrollingNav.ScrollingNav selection)"},{"name":"init","comment":" The intial state include the labels and the arrangement of the sections\n","type":"{ toString : section -> String.String, fromString : String.String -> Maybe.Maybe section, arrangement : List.List section, toMsg : Result.Result Browser.Dom.Error (Widget.ScrollingNav.ScrollingNav section -> Widget.ScrollingNav.ScrollingNav section) -> msg } -> ( Widget.ScrollingNav.ScrollingNav section, Platform.Cmd.Cmd msg )"},{"name":"jumpTo","comment":" Scrolls the screen to the respective section\n","type":"{ section : section, onChange : Result.Result Browser.Dom.Error () -> msg } -> Widget.ScrollingNav.ScrollingNav section -> Platform.Cmd.Cmd msg"},{"name":"jumpToWithOffset","comment":" Scrolls the screen to the respective section with some offset\n","type":"{ offset : Basics.Float, section : section, onChange : Result.Result Browser.Dom.Error () -> msg } -> Widget.ScrollingNav.ScrollingNav section -> Platform.Cmd.Cmd msg"},{"name":"setPos","comment":" sets the position of the viewport to show a specific section\n","type":"Basics.Int -> Widget.ScrollingNav.ScrollingNav section -> Widget.ScrollingNav.ScrollingNav section"},{"name":"syncPositions","comment":" Updates the positions of all sections.\nThis functions should be called regularly if the height of elements on your page can change during time.\n","type":"Widget.ScrollingNav.ScrollingNav section -> Task.Task Browser.Dom.Error (Widget.ScrollingNav.ScrollingNav section -> Widget.ScrollingNav.ScrollingNav section)"},{"name":"toSelect","comment":" Returns a select widget containing all section, with the current section selected.\n","type":"(Basics.Int -> Maybe.Maybe msg) -> Widget.ScrollingNav.ScrollingNav section -> Widget.Select msg"},{"name":"view","comment":" Opinionated way of viewing the section.\n\nThis might be useful at first, but you should consider writing your own view function.\n\n```\nview :\n (section -> Element msg)\n -> Model section\n -> List (Element msg)\nview asElement { toString, arrangement } =\n arrangement\n |> List.map\n (\\header ->\n Element.el\n [ header\n |> toString\n |> Attributes.id\n |> Element.htmlAttribute\n , Element.width <| Element.fill\n ]\n <|\n asElement <|\n header\n )\n```\n\n","type":"(section -> Element.Element msg) -> Widget.ScrollingNav.ScrollingNav section -> List.List (Element.Element msg)"}],"binops":[]},{"name":"Widget.Snackbar","comment":" ![Snackbar](https://orasund.github.io/elm-ui-widgets/assets/snackbar.png)\n\nA [snackbar](https://material.io/components/snackbars/) shows notification, one at a time.\n\n\n# Basics\n\n@docs Snackbar, Message, init, current, timePassed, view\n\n\n# Operations\n\n@docs insert, insertFor, dismiss\n\n","unions":[],"aliases":[{"name":"Message","comment":" A message with maybe some action button\n","args":["msg"],"type":"{ text : String.String, button : Maybe.Maybe (Widget.TextButton msg) }"},{"name":"Snackbar","comment":" A snackbar has a queue of Notifications, each with the amount of ms the message should be displayed\n","args":["a"],"type":"{ queue : Queue.Queue ( a, Basics.Int ), current : Maybe.Maybe ( a, Basics.Int ) }"}],"values":[{"name":"current","comment":" Returns the current element.\n","type":"Widget.Snackbar.Snackbar a -> Maybe.Maybe a"},{"name":"dismiss","comment":" Dismiss the current message.\n","type":"Widget.Snackbar.Snackbar a -> Widget.Snackbar.Snackbar a"},{"name":"init","comment":" Inital state\n","type":"Widget.Snackbar.Snackbar a"},{"name":"insert","comment":" Insert a message that will last for 10 seconds.\n","type":"a -> Widget.Snackbar.Snackbar a -> Widget.Snackbar.Snackbar a"},{"name":"insertFor","comment":" Insert a message for a specific amount of milli seconds.\n","type":"Basics.Int -> a -> Widget.Snackbar.Snackbar a -> Widget.Snackbar.Snackbar a"},{"name":"timePassed","comment":" Updates the model. This functions should be called regularly.\nThe first argument is the milli seconds that passed since the last time the function was called.\n","type":"Basics.Int -> Widget.Snackbar.Snackbar a -> Widget.Snackbar.Snackbar a"},{"name":"view","comment":" Views the current Message. (only one at a time)\n","type":"Widget.Style.SnackbarStyle msg -> (a -> Widget.Snackbar.Message msg) -> Widget.Snackbar.Snackbar a -> Maybe.Maybe (Element.Element msg)"}],"binops":[]},{"name":"Widget.Style","comment":" This module contains style types for every widget.\n\n@docs ButtonStyle, ColumnStyle, DialogStyle, ExpansionPanelStyle, LayoutStyle, RowStyle, SnackbarStyle, SortTableStyle, TabStyle, TextInputStyle\n\n","unions":[],"aliases":[{"name":"ButtonStyle","comment":" ","args":["msg"],"type":"{ container : List.List (Element.Attribute msg), labelRow : List.List (Element.Attribute msg), text : List.List (Element.Attribute msg), ifDisabled : List.List (Element.Attribute msg), ifActive : List.List (Element.Attribute msg), otherwise : List.List (Element.Attribute msg) }"},{"name":"ColumnStyle","comment":" ","args":["msg"],"type":"{ containerColumn : List.List (Element.Attribute msg), element : List.List (Element.Attribute msg), ifFirst : List.List (Element.Attribute msg), ifLast : List.List (Element.Attribute msg), otherwise : List.List (Element.Attribute msg) }"},{"name":"DialogStyle","comment":" ","args":["msg"],"type":"{ containerColumn : List.List (Element.Attribute msg), title : List.List (Element.Attribute msg), buttonRow : List.List (Element.Attribute msg), acceptButton : Widget.Style.ButtonStyle msg, dismissButton : Widget.Style.ButtonStyle msg, text : List.List (Element.Attribute msg) }"},{"name":"ExpansionPanelStyle","comment":" Technical Remark:\n\n - If icons are defined in Svg, they might not display correctly.\n To avoid that, make sure to wrap them in `Element.html >> Element.el []`\n\n","args":["msg"],"type":"{ containerColumn : List.List (Element.Attribute msg), panelRow : List.List (Element.Attribute msg), labelRow : List.List (Element.Attribute msg), content : List.List (Element.Attribute msg), expandIcon : Element.Element Basics.Never, collapseIcon : Element.Element Basics.Never }"},{"name":"LayoutStyle","comment":" Technical Remark:\n\n - If icons are defined in Svg, they might not display correctly.\n To avoid that, make sure to wrap them in `Element.html >> Element.el []`\n\n","args":["msg"],"type":"{ container : List.List (Element.Attribute msg), snackbar : Widget.Style.SnackbarStyle msg, layout : List.List (Element.Attribute msg) -> Element.Element msg -> Html.Html msg, header : List.List (Element.Attribute msg), sheet : List.List (Element.Attribute msg), sheetButton : Widget.Style.ButtonStyle msg, menuButton : Widget.Style.ButtonStyle msg, menuTabButton : Widget.Style.ButtonStyle msg, menuIcon : Element.Element Basics.Never, moreVerticalIcon : Element.Element Basics.Never, spacing : Basics.Int, title : List.List (Element.Attribute msg), searchIcon : Element.Element Basics.Never, search : List.List (Element.Attribute msg), searchFill : List.List (Element.Attribute msg) }"},{"name":"RowStyle","comment":" ","args":["msg"],"type":"{ containerRow : List.List (Element.Attribute msg), element : List.List (Element.Attribute msg), ifFirst : List.List (Element.Attribute msg), ifLast : List.List (Element.Attribute msg), otherwise : List.List (Element.Attribute msg) }"},{"name":"SnackbarStyle","comment":" ","args":["msg"],"type":"{ containerRow : List.List (Element.Attribute msg), text : List.List (Element.Attribute msg), button : Widget.Style.ButtonStyle msg }"},{"name":"SortTableStyle","comment":" Technical Remark:\n\n - If icons are defined in Svg, they might not display correctly.\n To avoid that, make sure to wrap them in `Element.html >> Element.el []`\n\n","args":["msg"],"type":"{ containerTable : List.List (Element.Attribute msg), headerButton : Widget.Style.ButtonStyle msg, ascIcon : Element.Element Basics.Never, descIcon : Element.Element Basics.Never, defaultIcon : Element.Element Basics.Never }"},{"name":"TabStyle","comment":" ","args":["msg"],"type":"{ button : Widget.Style.ButtonStyle msg, optionRow : List.List (Element.Attribute msg), containerColumn : List.List (Element.Attribute msg), content : List.List (Element.Attribute msg) }"},{"name":"TextInputStyle","comment":" ","args":["msg"],"type":"{ chipButton : Widget.Style.ButtonStyle msg, containerRow : List.List (Element.Attribute msg), chipsRow : List.List (Element.Attribute msg), input : List.List (Element.Attribute msg) }"}],"values":[],"binops":[]},{"name":"Widget.Style.Material","comment":" ![Example using the Material Design style](https://orasund.github.io/elm-ui-widgets/assets/material-style.png)\n\nThis module implements a Material design theme for all widgets.\n\nThe stylings are following [the official Material Design guidelines](https://material.io/components) as close as possible.\nPlease use these widgets in combination with the official guidelines.\n\nThe typograpahy is taken from [the material design guidelines](https://material.io/design/typography/the-type-system.html#type-scale).\nIts recommended to use a font size of 16px width and the [Roboto Font](https://fonts.google.com/specimen/Roboto?query=Ro).\n\nThe style are not opaque, so you can change every styling to your needs.\n\nIf you have any suggestions or improvements, be sure to leave a PR or a Issue over at the github repos.\n\nYou can use the theme by copying the following code:\n\n```\ntype alias Style msg =\n { dialog : DialogStyle msg\n , expansionPanel : ExpansionPanelStyle msg\n , button : ButtonStyle msg\n , primaryButton : ButtonStyle msg\n , tab : TabStyle msg\n , textInput : TextInputStyle msg\n , chipButton : ButtonStyle msg\n , row : RowStyle msg\n , buttonRow : RowStyle msg\n , column : ColumnStyle msg\n , cardColumn : ColumnStyle msg\n , sortTable : SortTableStyle msg\n , selectButton : ButtonStyle msg\n , layout : LayoutStyle msg\n }\n\nsortTable : Palette -> SortTableStyle msg\nsortTable palette =\n { containerTable = []\n , headerButton = Material.textButton palette\n , ascIcon = Icons.chevronUp |> Element.html |> Element.el []\n , descIcon = Icons.chevronDown |> Element.html |> Element.el []\n , defaultIcon = Element.none\n }\n\n\nstyle : Palette -> Style msg\nstyle palette =\n { sortTable = sortTable palette\n , row = Material.row\n , buttonRow = Material.buttonRow\n , cardColumn = Material.cardColumn palette\n , column = Material.column\n , button = Material.outlinedButton palette\n , primaryButton = Material.containedButton palette\n , selectButton = Material.toggleButton palette\n , tab = Material.tab palette\n , textInput = Material.textInput palette\n , chipButton = Material.chip palette\n , expansionPanel = Material.expansionPanel palette\n , dialog = Material.alertDialog palette\n , layout = Material.layout palette\n }\n```\n\n# Palette\n\n@docs Palette, defaultPalette, darkPalette\n\n\n# Button\n\nDifferent styles for buttons have different meanings.\n\n - Use `textButton` as your default button\n - Use `containedButton` for any important action\n - Use `outlinedButton` if you have more then one important action.\n Use `containedButton` for **the most** important action of the group.\n\n@docs containedButton, outlinedButton, textButton\n\n@docs iconButton, toggleButton, buttonRow\n\n# Card\n\nIn the material design specification the card is not really specified at all.\nIm practice the List seams more useful then a own card widget.\nThus for now we only provide a card containing a list.\n\n@docs cardColumn\n\n# Chip\n\n@docs chip, textInput\n\n# Dialog\n\n@docs alertDialog\n\n\n# Expansion Panel\n\n@docs expansionPanel\n\n\n# List\n\nThe [List widget](https://material.io/components/lists) is a very complex widget that sadly only particially made it into this package.\n\n@docs row, column\n\n# Snackbar\n\n@docs snackbar\n\n# Tab\n\n@docs tab, tabButton\n\n# Layout\n\n@docs layout\n","unions":[],"aliases":[{"name":"Palette","comment":" The material design comes with customizable color palettes.\n\nCheck 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.\n\nFor 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.\n\n","args":[],"type":"{ primary : Color.Color, secondary : Color.Color, background : Color.Color, surface : Color.Color, error : Color.Color, on : { primary : Color.Color, secondary : Color.Color, background : Color.Color, surface : Color.Color, error : Color.Color } }"}],"values":[{"name":"alertDialog","comment":" An alert dialog for important decisions. Use a snackbar for less important notification.\n\n![Alert Dialog](https://material.io/develop/images/content/9d61e2d1bd60599344c7fae5e71c9667.png)\n\n_Image taken from [material.io](https://material.io/develop/android/components/buttons/)_\n\n\n","type":"Widget.Style.Material.Palette -> Widget.Style.DialogStyle msg"},{"name":"buttonRow","comment":" a Row of buttons.\n\nOnly use in combination with `toggleButton`\n\n","type":"Widget.Style.RowStyle msg"},{"name":"cardColumn","comment":" A List styled like a card.\n\nTechnical Remark:\n\nThis is a simplification of the [Material Design Card\n](https://material.io/components/cards) and might get replaced at a later date.\n\n","type":"Widget.Style.Material.Palette -> Widget.Style.ColumnStyle msg"},{"name":"chip","comment":" Chips have the same behaviour as buttons but are visually less important.\n\nIn the [official documentation](https://material.io/components/chips#types) chips have different names depending on where they are used:\n\n - **Input Chips** are used inside a text field. Use `textInput` for this feature.\n - **Choice Chips** are used for selcting an option.\n The material design guidelines recommend using `toggleButton` for icons with no text and chips for text with no icons.\n - **Filter Chips** are used for selecting multiple options. They typically have a done-icon when selected.\n - **Action chips** are like button. Make sure to include an icon when using action chips.\n\nTechnical Remark:\n\n - There seems to be a bug, where in the mouseOver effects are now visible.\n This might have something to do with .\n This needs to be investigated, but for now i leave it at that.\n\n - Desided against the implementation of an outlined chip.\n Please open a new issue or a PR if you want to have it implemented.\n\n","type":"Widget.Style.Material.Palette -> Widget.Style.ButtonStyle msg"},{"name":"column","comment":" A simple styling for a column.\n","type":"Widget.Style.ColumnStyle msg"},{"name":"containedButton","comment":" A contained button representing the most important action of a group.\n\n![Contained Button](https://material.io/develop/images/content/79e62add1830d33fc90edb22212bce53.svg)\n\n_Image taken from [material.io](https://material.io/develop/android/components/buttons/)_\n\n","type":"Widget.Style.Material.Palette -> Widget.Style.ButtonStyle msg"},{"name":"darkPalette","comment":" The offical dark theme of google.\n\n![The dark theme](https://lh3.googleusercontent.com/tv7J2o4ZiSmLYwyBslBs_PLzKyzI8QUV5qdvHGfoAQn9r7pY4Hj5SmW27m3zUWeDtRSE8Cb5_5PQmkbavDfw7XbIL8EodIKZhilRdg=w1064-v0)\n\n_Image take from [material.io](https://material.io/design/color/dark-theme.html#ui-application)_\n\n","type":"Widget.Style.Material.Palette"},{"name":"defaultPalette","comment":" The default color theme.\n\n![The default theme](https://lh3.googleusercontent.com/k6WO1fd7T40A9JvSVfHqs0CPLFyTEDCecsVGxEDhOaTP0wUTPYOVVkxt60hKxBprgNoMqs8OyKqtlaQ4tDBtQJs-fTcZrpZEjxhUVQ=w1064-v0)\n\n_Image take from [material.io](https://material.io/design/color/the-color-system.html#color-theme-creation)_\n\n","type":"Widget.Style.Material.Palette"},{"name":"expansionPanel","comment":" The expansion Panel is an outdated part of the material design specification.\nIn modern implementation it gets replaced with a very sophisticated list widget.\n\nTechnical Remarks:\n\n - The expansion panel is part of an [older version](https://material.io/archive/guidelines/components/expansion-panels.html) of the Material Design.\n The newer version is part of the List component.\n The styling is taken from the [new specification](https://material.io/components/lists#specs).\n - The Icons are taken from [danmarcab/material-icons](https://dark.elm.dmy.fr/packages/danmarcab/material-icons/latest/).\n\n","type":"Widget.Style.Material.Palette -> Widget.Style.ExpansionPanelStyle msg"},{"name":"iconButton","comment":" An single selectable icon.\n\n![Icon Button](https://material.io/develop/images/content/9bc212d8a3ef79bb7ed83a5359651505.png)\n\n_Image taken from [material.io](https://material.io/develop/android/components/buttons/)_\n\nTechnical Remark:\n\n - Could not find any specification details\n\n","type":"Widget.Style.Material.Palette -> Widget.Style.ButtonStyle msg"},{"name":"layout","comment":" The Layout Widget combines the following Material design concepts:\n\n* Top bar\n* Navigation drawer\n* Side Sheet\n* Dialog\n* Snackbar\n\nFuture updates might try to seperate them into there own widgets.\nBut for now they are only available as an all-in-one solution.\n\nTechnical Remark:\n\n - Due to [a bug in Elm-Ui](https://github.com/mdgriffith/elm-ui/issues/47) the menu button still behave wierd.\n I've not found a workaround for it.\n - The Icons are taken from [danmarcab/material-icons](https://dark.elm.dmy.fr/packages/danmarcab/material-icons/latest/).\n - The drawer button as not taken from the specification (This will been to be added later)\n\n","type":"Widget.Style.Material.Palette -> Widget.Style.LayoutStyle msg"},{"name":"outlinedButton","comment":" A outlined button representing an important action within a group.\n\n![Contained Button](https://material.io/develop/images/content/2b50635d38c5fdec260f09be9aeafb10.svg)\n\n_Image taken from [material.io](https://material.io/develop/android/components/buttons/)_\n\n","type":"Widget.Style.Material.Palette -> Widget.Style.ButtonStyle msg"},{"name":"row","comment":" A simple styling for a row.\n","type":"Widget.Style.RowStyle msg"},{"name":"snackbar","comment":" A typical snackbar\n\n![Snackbar](https://material.io/develop/images/content/f2ec5451582a06af5eb20e3dfb3d27d5.svg)\n\n_Image take from [material.io](https://material.io/develop/android/components/snackbar/)_\n\nTechnical Remark:\n\n - The text color of the button was not given in the specification. This implementation\n adujsts the luminance of the color to fit the [w3 accessability standard](https://www.w3.org/TR/WCAG20/#Contrast)\n\n","type":"Widget.Style.Material.Palette -> Widget.Style.SnackbarStyle msg"},{"name":"tab","comment":" A Tab bar meant for only the upper most level. Do not use a tab within a tab.\n","type":"Widget.Style.Material.Palette -> Widget.Style.TabStyle msg"},{"name":"tabButton","comment":" A single Tab button.\n\nTechnical Remark:\n\n* The official specification states that the background color should be the surface color,\n but the pictures and actuall implementations all have no background color.\n So here the background color is also not set.\n","type":"Widget.Style.Material.Palette -> Widget.Style.ButtonStyle msg"},{"name":"textButton","comment":" A text button representing a simple action within a group.\n\n![Text Button](https://material.io/develop/images/content/d3079632c6f54d86f9b7093d541c2ee9.svg)\n\n_Image taken from [material.io](https://material.io/develop/android/components/buttons/)_\n\n","type":"Widget.Style.Material.Palette -> Widget.Style.ButtonStyle msg"},{"name":"textInput","comment":" A text input style that is included only to support input chips.\n\nTechnical Remark:\n\n - This is just a temporary implementation. It will soon be replaced with the official implementation.\n\n","type":"Widget.Style.Material.Palette -> Widget.Style.TextInputStyle msg"},{"name":"toggleButton","comment":" A ToggleButton. Only use as a group in combination with `buttonRow`.\n\n![Toggle Button](https://material.io/develop/images/content/749a1ba8591d02356fa1d6eea2641d96.svg)\n\n_Image taken from [material.io](https://material.io/develop/android/components/buttons/)_\n\nToggle buttons should only be used with the `iconButton` widget, else use chips instead.\n\nTechnical Remark:\n\n - Border color was not defined in the [specification](https://material.io/components/buttons#toggle-button)\n - There are two different versions, one where the selected color is gray and another where the color is primary.\n I noticed the gray version was used more often, so i went with that one.\n\n","type":"Widget.Style.Material.Palette -> Widget.Style.ButtonStyle msg"}],"binops":[]},{"name":"Widget.Style.Template","comment":" ![Example using the Template style](https://orasund.github.io/elm-ui-widgets/assets/template-style.png)\n\nThis package contains mockups designed for writing your own style.\n\nStart by copying the following code and then replace the fields one by one.\n\n```\ntype alias Style msg =\n { dialog : DialogStyle msg\n , expansionPanel : ExpansionPanelStyle msg\n , button : ButtonStyle msg\n , primaryButton : ButtonStyle msg\n , tab : TabStyle msg\n , textInput : TextInputStyle msg\n , chipButton : ButtonStyle msg\n , row : RowStyle msg\n , buttonRow : RowStyle msg\n , column : ColumnStyle msg\n , cardColumn : ColumnStyle msg\n , sortTable : SortTableStyle msg\n , selectButton : ButtonStyle msg\n , layout : LayoutStyle msg\n }\n\nstyle : Style msg\nstyle =\n { sortTable = Template.sortTable <| \"sortTable\"\n , row = Template.row <| \"row\"\n , buttonRow = Template.row <| \"buttonRow\"\n , cardColumn = Template.column <| \"cardRow\"\n , column = Template.column <| \"column\"\n , button = Template.button <| \"button\"\n , primaryButton = Template.button <| \"primaryButton\"\n , tab = Template.tab <| \"tab\"\n , textInput = Template.textInput <| \"textInput\"\n , chipButton = Template.button <| \"chipButton\"\n , expansionPanel = Template.expansionPanel \"expansionPanel\"\n , selectButton = Template.button \"selectButton\"\n , dialog = Template.dialog \"dialog\"\n , layout = Template.layout \"layout\"\n }\n```\n\n\n# Base Elements\n\n@docs box, decoration, icon\n\n\n# Mockups\n\n@docs button, column, dialog, expansionPanel, layout, row, snackbar, sortTable, tab, textInput\n\n","unions":[],"aliases":[],"values":[{"name":"box","comment":" A box representing an element\n","type":"String.String -> List.List (Element.Attribute msg)"},{"name":"button","comment":"\n\n```\nbutton : String -> ButtonStyle msg\nbutton string =\n { container = box <| string ++ \":container\"\n , labelRow = box <| string ++ \":labelRow\"\n , text = box <| string ++ \":text\"\n , ifDisabled = decoration <| string ++ \":ifDisabled\"\n , ifActive = decoration <| string ++ \":ifActive\"\n , otherwise = decoration <| string ++ \":otherwise\"\n }\n```\n\n","type":"String.String -> Widget.Style.ButtonStyle msg"},{"name":"column","comment":"\n\n```\ncolumn : String -> ColumnStyle msg\ncolumn string =\n { containerColumn = box <| string ++ \":containerColumn\"\n , element = box <| string ++ \":element\"\n , ifFirst = box <| string ++ \":ifFirst\"\n , ifLast = box <| string ++ \":ifLast\"\n , otherwise = box <| string ++ \":otherwise\"\n }\n```\n\n","type":"String.String -> Widget.Style.ColumnStyle msg"},{"name":"decoration","comment":" An additional attribute representing a state change.\n","type":"String.String -> List.List (Element.Attribute msg)"},{"name":"dialog","comment":"\n\n```\ndialog : String -> DialogStyle msg\ndialog string =\n { containerColumn = box <| string ++ \":containerColumn\"\n , title = box <| string ++ \":title\"\n , text = box <| string ++ \":text\"\n , buttonRow = box <| string ++ \":buttonRow\"\n , acceptButton = button <| string ++ \":acceptButton\"\n , dismissButton = button <| string ++ \":dismissButton\"\n }\n```\n\n","type":"String.String -> Widget.Style.DialogStyle msg"},{"name":"expansionPanel","comment":"\n\n```\nexpansionPanel : String -> ExpansionPanelStyle msg\nexpansionPanel string =\n { containerColumn = box <| string ++ \":containerColumn\"\n , panelRow = box <| string ++ \":panelRow\"\n , labelRow = box <| string ++ \":labelRow\"\n , content = box <| string ++ \":content\"\n , expandIcon = icon <| string ++ \":expandIcon\"\n , collapseIcon = icon <| string ++ \":collapseIcon\"\n }\n\n```\n\n","type":"String.String -> Widget.Style.ExpansionPanelStyle msg"},{"name":"icon","comment":" A circle representing an icon\n","type":"String.String -> Element.Element msg"},{"name":"layout","comment":"\n\n```\nlayout : String -> LayoutStyle msg\nlayout string =\n { container = box <| string ++ \":container\"\n , snackbar = snackbar <| string ++ \":snackbar\"\n , layout = Element.layout\n , header = box <| string ++ \":header\"\n , menuButton = button <| string ++ \":menuButton\"\n , sheetButton = button <| string ++ \":sheetButton\"\n , menuTabButton = button <| string ++ \":menuTabButton\"\n , sheet = box <| string ++ \":sheet\"\n , menuIcon = icon <| string ++ \":menuIcon\"\n , moreVerticalIcon = icon <| string ++ \":moreVerticalIcon\"\n , spacing = 8\n , title = box <| string ++ \":title\"\n , searchIcon = icon <| string ++ \":searchIcon\"\n , search = box <| string ++ \":search\"\n , searchFill = box <| string ++ \":searchFill\"\n }\n```\n\n","type":"String.String -> Widget.Style.LayoutStyle msg"},{"name":"row","comment":"\n\n```\nrow : String -> RowStyle msg\nrow string =\n { containerRow = box <| string ++ \":containerRow\"\n , element = box <| string ++ \":element\"\n , ifFirst = box <| string ++ \":ifFirst\"\n , ifLast = box <| string ++ \":ifLast\"\n , otherwise = box <| string ++ \":otherwise\"\n }\n```\n\n","type":"String.String -> Widget.Style.RowStyle msg"},{"name":"snackbar","comment":"\n\n```\nsnackbar : String -> SnackbarStyle msg\nsnackbar string =\n { containerRow = box <| string ++ \":containerRow\"\n , button = button <| string ++ \":button\"\n , text = box <| string ++ \":text\"\n }\n```\n\n","type":"String.String -> Widget.Style.SnackbarStyle msg"},{"name":"sortTable","comment":"\n\n```\nsortTable : String -> SortTableStyle msg\nsortTable string =\n { containerTable = box <| string ++ \":containerTable\"\n , headerButton = button <| string ++ \":headerButton\"\n , ascIcon = icon <| string ++ \":ascIcon\"\n , descIcon = icon <| string ++ \":descIcon\"\n , defaultIcon = icon <| string ++ \":defaultIcon\"\n }\n```\n\n","type":"String.String -> Widget.Style.SortTableStyle msg"},{"name":"tab","comment":"\n\n```\ntab : String -> TabStyle msg\ntab string =\n { button = button <| string ++ \":button\"\n , optionRow = box <| string ++ \":optionRow\"\n , containerColumn = box <| string ++ \":containerColumn\"\n , content = box <| string ++ \":content\"\n }\n```\n\n","type":"String.String -> Widget.Style.TabStyle msg"},{"name":"textInput","comment":"\n\n```\ntextInput : String -> TextInputStyle msg\ntextInput string =\n { chipButton = button <| string ++ \":chipButton\"\n , chipsRow = box <| string ++ \":chipsRow\"\n , containerRow = box <| string ++ \":containerRow\"\n , input = box <| string ++ \":input\"\n }\n\n```\n\n","type":"String.String -> Widget.Style.TextInputStyle msg"}],"binops":[]}] \ No newline at end of file diff --git a/elm.json b/elm.json index 1b50a13..d259fd4 100644 --- a/elm.json +++ b/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": { diff --git a/example/src/Example/Button.elm b/example/src/Example/Button.elm index f09a798..0ba4857 100644 --- a/example/src/Example/Button.elm +++ b/example/src/Example/Button.elm @@ -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 + } \ No newline at end of file diff --git a/example/src/Example/Dialog.elm b/example/src/Example/Dialog.elm index aeb182e..b587c3d 100644 --- a/example/src/Example/Dialog.elm +++ b/example/src/Example/Dialog.elm @@ -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 + } \ No newline at end of file diff --git a/example/src/Example/ExpansionPanel.elm b/example/src/Example/ExpansionPanel.elm index 757c16b..566a44b 100644 --- a/example/src/Example/ExpansionPanel.elm +++ b/example/src/Example/ExpansionPanel.elm @@ -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 + } \ No newline at end of file diff --git a/example/src/Example/List.elm b/example/src/Example/List.elm index 5e86224..cdb7b7e 100644 --- a/example/src/Example/List.elm +++ b/example/src/Example/List.elm @@ -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 + } \ No newline at end of file diff --git a/example/src/Example/Modal.elm b/example/src/Example/Modal.elm index 60166a3..f09b0b2 100644 --- a/example/src/Example/Modal.elm +++ b/example/src/Example/Modal.elm @@ -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 + } \ No newline at end of file diff --git a/example/src/Example/MultiSelect.elm b/example/src/Example/MultiSelect.elm index 73cfa0a..acc77e1 100644 --- a/example/src/Example/MultiSelect.elm +++ b/example/src/Example/MultiSelect.elm @@ -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 + } \ No newline at end of file diff --git a/example/src/Example/Select.elm b/example/src/Example/Select.elm index b51e58f..6a9a091 100644 --- a/example/src/Example/Select.elm +++ b/example/src/Example/Select.elm @@ -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 + } \ No newline at end of file diff --git a/example/src/Example/SortTable.elm b/example/src/Example/SortTable.elm index 585c0e7..a3eb7b0 100644 --- a/example/src/Example/SortTable.elm +++ b/example/src/Example/SortTable.elm @@ -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 + } \ No newline at end of file diff --git a/example/src/Example/Tab.elm b/example/src/Example/Tab.elm index 70c53af..f07ca4a 100644 --- a/example/src/Example/Tab.elm +++ b/example/src/Example/Tab.elm @@ -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 + } \ No newline at end of file diff --git a/example/src/Example/TextInput.elm b/example/src/Example/TextInput.elm index ee719c9..786fed9 100644 --- a/example/src/Example/TextInput.elm +++ b/example/src/Example/TextInput.elm @@ -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 + } \ No newline at end of file diff --git a/example/src/Main.elm b/example/src/Main.elm index eeb7e3f..6db0904 100644 --- a/example/src/Main.elm +++ b/example/src/Main.elm @@ -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 diff --git a/src/Widget.elm b/src/Widget.elm index 86ddaad..374c0e6 100644 --- a/src/Widget.elm +++ b/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 diff --git a/src/Widget/Layout.elm b/src/Widget/Layout.elm index 230bc15..2675447 100644 --- a/src/Widget/Layout.elm +++ b/src/Widget/Layout.elm @@ -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 -> diff --git a/src/Widget/ScrollingNav.elm b/src/Widget/ScrollingNav.elm index 4cd7420..83675c0 100644 --- a/src/Widget/ScrollingNav.elm +++ b/src/Widget/ScrollingNav.elm @@ -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 diff --git a/src/Widget/Snackbar.elm b/src/Widget/Snackbar.elm index b93c69c..e84c77d 100644 --- a/src/Widget/Snackbar.elm +++ b/src/Widget/Snackbar.elm @@ -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 diff --git a/src/Widget/Style.elm b/src/Widget/Style.elm index f1e6347..0ce5cf2 100644 --- a/src/Widget/Style.elm +++ b/src/Widget/Style.elm @@ -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. diff --git a/src/Widget/Style/Material.elm b/src/Widget/Style/Material.elm index 300a055..12dcc46 100644 --- a/src/Widget/Style/Material.elm +++ b/src/Widget/Style/Material.elm @@ -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 . 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. diff --git a/src/Widget/Style/Template.elm b/src/Widget/Style/Template.elm index 49785ef..2149525 100644 --- a/src/Widget/Style/Template.elm +++ b/src/Widget/Style/Template.elm @@ -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"