Added title items

This commit is contained in:
Lucas Payr 2021-01-23 20:38:15 +01:00
parent 27dfc71667
commit 58d8aef643
11 changed files with 474 additions and 136 deletions

View File

@ -13,13 +13,16 @@ import Widget.Style
, SwitchStyle
, TabStyle
, TextInputStyle
, ItemStyle
, DividerStyle
, TitleStyle
)
type alias Style msg =
{ dialog : DialogStyle msg
, expansionPanel : ExpansionPanelStyle msg
, expansionPanelItem : ExpansionPanelStyle msg
, expansionPanelItem : ItemStyle (ExpansionPanelStyle msg)
, button : ButtonStyle msg
, switch : SwitchStyle msg
, primaryButton : ButtonStyle msg
@ -34,4 +37,9 @@ type alias Style msg =
, selectButton : ButtonStyle msg
, progressIndicator : ProgressIndicatorStyle msg
, layout : LayoutStyle msg
, fullBleedDivider : ItemStyle (DividerStyle msg)
, insetDivider : ItemStyle (DividerStyle msg)
, middleDividers : ItemStyle (DividerStyle msg)
, insetTitle : ItemStyle (TitleStyle msg)
, fullBleedTitle : ItemStyle (TitleStyle msg)
}

View File

@ -27,7 +27,6 @@ import Widget.Style
)
import Widget.Style.Material as Material exposing (Palette)
sortTable : Palette -> SortTableStyle msg
sortTable palette =
{ elementTable = []
@ -59,4 +58,9 @@ style palette =
, progressIndicator = Material.progressIndicator palette
, layout = Material.layout palette
, switch = Material.switch palette
, fullBleedDivider = Material.fullBleedDivider
, insetDivider = Material.insetDivider palette
, middleDividers = Material.middleDividers palette
, insetTitle = Material.insetTitle palette
, fullBleedTitle = Material.fullBleedTitle palette
}

View File

@ -2,7 +2,7 @@ module Data.Theme exposing (Theme(..), toStyle)
import Data.Style exposing (Style)
import Data.Style.Material
import Widget.Style.Material
import Widget.Style.Material exposing (Palette)
type Theme

View File

@ -3,19 +3,27 @@ module Example.List exposing (Model, Msg, init, subscriptions, update, view)
import Browser
import Element exposing (Element)
import Widget
import Widget.Style exposing (ColumnStyle)
import Widget.Style exposing (ColumnStyle,ItemStyle,DividerStyle,TitleStyle)
import Widget.Style.Material as Material
type alias Style style msg =
{ style
| cardColumn : ColumnStyle msg
, insetDivider : ItemStyle (DividerStyle msg)
, middleDividers : ItemStyle (DividerStyle msg)
, insetTitle : ItemStyle (TitleStyle msg)
, fullBleedTitle : ItemStyle (TitleStyle msg)
}
materialStyle : Style {} msg
materialStyle =
{ cardColumn = Material.cardColumn Material.defaultPalette
, insetDivider = Material.insetDivider Material.defaultPalette
, middleDividers = Material.middleDividers Material.defaultPalette
, insetTitle = Material.insetTitle Material.defaultPalette
, fullBleedTitle = Material.fullBleedTitle Material.defaultPalette
}
@ -50,11 +58,16 @@ subscriptions () =
-}
view : (Msg -> msg) -> Style style msg -> Model -> Element msg
view _ style () =
[ Element.text <| "A"
, Element.text <| "B"
, Element.text <| "C"
[ "Section 1"
|> Widget.headerItem style.fullBleedTitle
, Widget.item <| Element.text <| "A"
, "Section 2"
|> Widget.headerItem style.fullBleedTitle
, Widget.item <| Element.text <| "B"
, Widget.divider style.middleDividers
, Widget.item <| Element.text <| "C"
]
|> Widget.column style.cardColumn
|> Widget.itemList style.cardColumn
main : Program () Model Msg

View File

@ -431,12 +431,14 @@ viewLoaded m =
, elem
]
|> Element.column Grid.simple
|> Widget.item
)
:: (if more |> List.isEmpty then
[]
else
[ Widget.expansionPanel style.expansionPanelItem
[ Widget.divider style.fullBleedDivider
, Widget.expansionPanelItem style.expansionPanelItem
{ onToggle =
always
(name
@ -466,7 +468,7 @@ viewLoaded m =
]
)
)
|> Widget.column style.cardColumn
|> Widget.itemList style.cardColumn
)
|> Element.wrappedRow
(Grid.simple

10
src/Internal/Divider.elm Normal file
View File

@ -0,0 +1,10 @@
module Internal.Divider exposing (divider)
import Element exposing (Attribute, Element)
import Internal.Button exposing (Button)
import Internal.Select as Select
import Widget.Style exposing (ButtonStyle, ColumnStyle, ItemStyle, RowStyle)
import Widget.Style.Customize as Customize exposing (content)
type alias Divider

View File

@ -1,13 +1,10 @@
module Internal.ExpansionPanel exposing (ExpansionPanel, expansionPanel)
{-| Part of Material Design Lists
-}
module Internal.ExpansionPanel exposing (ExpansionPanel, expansionPanel, expansionPanelItem)
import Element exposing (Element)
import Element.Events as Events
import Widget.Icon exposing (Icon)
import Widget.Style exposing (ExpansionPanelStyle)
import Widget.Style exposing (ExpansionPanelStyle,ItemStyle)
import Internal.List as List exposing (Item)
type alias ExpansionPanel msg =
{ onToggle : Bool -> msg
@ -51,3 +48,16 @@ expansionPanel style model =
else
Element.none
]
expansionPanelItem :
ItemStyle (ExpansionPanelStyle msg)
->
{ onToggle : Bool -> msg
, icon : Icon
, text : String
, content : Element msg
, isExpanded : Bool
}
-> Item msg
expansionPanelItem style model =
List.toItem style (\s -> expansionPanel s model)

View File

@ -1,22 +1,66 @@
module Internal.List exposing (buttonColumn, buttonRow, column, row)
module Internal.List exposing (Item, buttonColumn, headerItem,buttonRow, column, item, itemList, row, toItem,divider)
import Element exposing (Attribute, Element)
import Internal.Button exposing (Button)
import Internal.Select as Select
import Widget.Style exposing (ButtonStyle, ColumnStyle, ItemStyle, RowStyle)
import Widget.Style.Customize as Customize
import Widget.Style exposing (TitleStyle,DividerStyle,ButtonStyle, ColumnStyle, ItemStyle, RowStyle)
import Widget.Style.Customize as Customize exposing (content)
type alias Item msg =
List (Attribute msg) -> Element msg
item : Element msg -> Item msg
item element =
toItem
{ element = []
, content = ()
}
(always element)
divider : ItemStyle (DividerStyle msg) -> Item msg
divider style =
toItem style (\{element} -> Element.none |> Element.el element )
headerItem : ItemStyle (TitleStyle msg) -> String -> Item msg
headerItem style title =
toItem style
(\{elementColumn,content} ->
[ Element.none
|> Element.el content.divider.element
, title
|> Element.text
|> Element.el content.title
]
|> Element.column elementColumn
)
toItem : ItemStyle style -> (style -> Element msg) -> Item msg
toItem style element =
\attr ->
element style.content
|> Element.el
(attr ++ (style.element |> List.map (Element.mapAttribute never))
)
internal :
ItemStyle msg
-> List (Element msg)
{ element : List (Attribute Never)
, ifFirst : List (Attribute Never)
, ifLast : List (Attribute Never)
, ifSingleton : List (Attribute Never)
, otherwise : List (Attribute Never)
}
-> List (Item msg)
-> List (Element msg)
internal style list =
list
|> List.indexedMap
(\i ->
Element.el <|
style.element
(\i fun ->
fun
(style.element
++ (if List.length list == 1 then
style.ifSingleton
@ -29,16 +73,40 @@ internal style list =
else
style.otherwise
)
|> List.map (Element.mapAttribute never)
)
)
row : RowStyle msg -> List (Element msg) -> Element msg
row style =
internal style.content >> Element.row style.elementRow
List.map
(\a ->
toItem
{ element = style.content.element
, content = ()
}
(always a)
)
>> internal style.content
>> Element.row style.elementRow
column : ColumnStyle msg -> List (Element msg) -> Element msg
column style =
List.map
(\a ->
toItem
{ element = style.content.element
, content = ()
}
(always a)
)
>> itemList style
itemList : ColumnStyle msg -> List (Item msg) -> Element msg
itemList style =
internal style.content >> Element.column style.elementColumn
@ -85,11 +153,21 @@ buttonRow :
-> Element msg
buttonRow style =
internalButton
{ element = style.elementRow.content.element
, ifSingleton = style.elementRow.content.ifSingleton
, ifFirst = style.elementRow.content.ifFirst
, ifLast = style.elementRow.content.ifLast
, otherwise = style.elementRow.content.otherwise
{ element =
style.elementRow.content.element
|> List.map (Element.mapAttribute never)
, ifSingleton =
style.elementRow.content.ifSingleton
|> List.map (Element.mapAttribute never)
, ifFirst =
style.elementRow.content.ifFirst
|> List.map (Element.mapAttribute never)
, ifLast =
style.elementRow.content.ifLast
|> List.map (Element.mapAttribute never)
, otherwise =
style.elementRow.content.otherwise
|> List.map (Element.mapAttribute never)
, content = style.content
}
>> Element.row style.elementRow.elementRow
@ -103,11 +181,21 @@ buttonColumn :
-> Element msg
buttonColumn style =
internalButton
{ element = style.elementColumn.content.element
, ifSingleton = style.elementColumn.content.ifSingleton
, ifFirst = style.elementColumn.content.ifFirst
, ifLast = style.elementColumn.content.ifLast
, otherwise = style.elementColumn.content.otherwise
{ element =
style.elementColumn.content.element
|> List.map (Element.mapAttribute never)
, ifSingleton =
style.elementColumn.content.ifSingleton
|> List.map (Element.mapAttribute never)
, ifFirst =
style.elementColumn.content.ifFirst
|> List.map (Element.mapAttribute never)
, ifLast =
style.elementColumn.content.ifLast
|> List.map (Element.mapAttribute never)
, otherwise =
style.elementColumn.content.otherwise
|> List.map (Element.mapAttribute never)
, content = style.content
}
>> Element.column style.elementColumn.elementColumn

View File

@ -4,13 +4,13 @@ module Widget exposing
, Select, selectButton, select
, MultiSelect, multiSelect
, Dialog, modal, dialog
, ExpansionPanel, expansionPanel
, row, column, buttonRow, buttonColumn
, ExpansionPanel, expansionPanel, expansionPanelItem
, row, column, Item, itemList, item, divider, buttonRow, buttonColumn
, SortTable, Column, sortTable, floatColumn, intColumn, stringColumn, unsortableColumn
, TextInput, textInput
, Tab, tab
, ProgressIndicator, circularProgressIndicator
, buttonSheet
, buttonSheet, headerItem
)
{-| This module contains different stateless view functions. No wiring required.
@ -82,7 +82,7 @@ You can create you own widgets by sticking widgets types together.
[Open in Ellie](https://ellie-app.com/9p5Rv5jfVdFa1)
@docs ExpansionPanel, expansionPanel
@docs ExpansionPanel, expansionPanel, expansionPanelItem
# List
@ -91,7 +91,7 @@ You can create you own widgets by sticking widgets types together.
[Open in Ellie](https://ellie-app.com/9p5RJnDVVCKa1)
@docs row, column, buttonRow, buttonColumn, buttonDrawer
@docs row, column, Item, itemList, item, divider, buttonRow, buttonColumn, buttonDrawer
# Sort Table
@ -152,12 +152,15 @@ import Widget.Style
, ColumnStyle
, DialogStyle
, ExpansionPanelStyle
, ItemStyle
, ProgressIndicatorStyle
, RowStyle
, SortTableStyle
, SwitchStyle
, TabStyle
, TextInputStyle
, DividerStyle
, TitleStyle
)
@ -447,6 +450,27 @@ expansionPanel =
fun
{-| An expansion Panel
-}
expansionPanelItem :
ItemStyle (ExpansionPanelStyle msg)
->
{ onToggle : Bool -> msg
, icon : Icon
, text : String
, content : Element msg
, isExpanded : Bool
}
-> Item msg
expansionPanelItem =
let
fun : ItemStyle (ExpansionPanelStyle msg) -> ExpansionPanel msg -> Item msg
fun =
ExpansionPanel.expansionPanelItem
in
fun
{----------------------------------------------------------
- TEXT INPUT
@ -491,18 +515,69 @@ textInput =
----------------------------------------------------------}
{-| Item widget type.
Use `Widget.item` if you want to turn a simple element into an item.
-}
type alias Item msg =
List (Attribute msg) -> Element msg
{-| Simple element for a list.
-}
item : Element msg -> Item msg
item =
List.item
{-| A divider.
-}
divider : ItemStyle (DividerStyle msg) -> Item msg
divider =
List.divider
{-| A header for a part of a list.
-}
headerItem : ItemStyle (TitleStyle msg) -> String -> Item msg
headerItem =
List.headerItem
{-| Replacement of `Element.row`
-}
row : RowStyle msg -> List (Element msg) -> Element msg
row =
List.row
let
fun : RowStyle msg -> List (Element msg) -> Element msg
fun =
List.row
in
fun
{-| Replacement of `Element.column`
-}
column : ColumnStyle msg -> List (Element msg) -> Element msg
column =
List.column
let
fun : ColumnStyle msg -> List (Element msg) -> Element msg
fun =
List.column
in
fun
{-| Implementation of the Material design list
-}
itemList : ColumnStyle msg -> List (Item msg) -> Element msg
itemList =
let
fun : ColumnStyle msg -> List (Item msg) -> Element msg
fun =
List.itemList
in
fun
{-| A row of buttons

View File

@ -1,14 +1,14 @@
module Widget.Style exposing
( IconStyle, ButtonStyle, SwitchStyle, ColumnStyle, DialogStyle, ItemStyle
, ExpansionPanelStyle, LayoutStyle, RowStyle, SnackbarStyle, SortTableStyle
, TabStyle, TextInputStyle, ProgressIndicatorStyle, ButtonSheetStyle
, TabStyle, TextInputStyle, ProgressIndicatorStyle, ButtonSheetStyle, DividerStyle, TitleStyle
)
{-| This module contains style types for every widget.
@docs IconStyle, ButtonStyle, SwitchStyle, ColumnStyle, DialogStyle, ItemStyle
@docs ExpansionPanelStyle, LayoutStyle, RowStyle, SnackbarStyle, SortTableStyle
@docs TabStyle, TextInputStyle, ProgressIndicatorStyle, ButtonSheetStyle
@docs TabStyle, TextInputStyle, ProgressIndicatorStyle, ButtonSheetStyle, DividerStyle, TitleStyle
-}
@ -161,25 +161,48 @@ type alias TabStyle msg =
{-| -}
type alias ItemStyle msg =
{ element : List (Attribute msg)
, ifFirst : List (Attribute msg)
, ifLast : List (Attribute msg)
, ifSingleton : List (Attribute msg)
, otherwise : List (Attribute msg)
type alias ItemStyle content =
{ element : List (Attribute Never)
, content : content
}
{-| -}
type alias DividerStyle msg =
{ element : List (Attribute msg)
}
{-| -}
type alias TitleStyle msg =
{ elementColumn : List (Attribute msg)
, content :
{ divider : DividerStyle msg
, title : List (Attribute msg)
}
}
{-| -}
type alias RowStyle msg =
{ elementRow : List (Attribute msg)
, content :
{ element : List (Attribute Never)
, ifFirst : List (Attribute Never)
, ifLast : List (Attribute Never)
, ifSingleton : List (Attribute Never)
, otherwise : List (Attribute Never)
}
}
{-| -}
type alias ColumnStyle msg =
{ elementColumn : List (Attribute msg)
, content : ItemStyle msg
, content :
{ element : List (Attribute Never)
, ifFirst : List (Attribute Never)
, ifLast : List (Attribute Never)
, ifSingleton : List (Attribute Never)
, otherwise : List (Attribute Never)
}
}

View File

@ -7,11 +7,12 @@ module Widget.Style.Material exposing
, chip, textInput
, alertDialog
, expansionPanel, expansionPanelItem
, row, column
, row, column, fullBleedDivider
, progressIndicator
, snackbar
, tab, tabButton
, layout
, layout, insetDivider
, middleDividers,insetTitle, fullBleedTitle
)
{-| ![Example using the Material Design style](https://orasund.github.io/elm-ui-widgets/assets/material-style.png)
@ -28,55 +29,6 @@ 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
, progressIndicator : ProgressIndicatorStyle msg
, layout : LayoutStyle msg
}
sortTable : Palette -> SortTableStyle msg
sortTable palette =
{ elementTable = []
, headerButton = Material.textButton palette
, ascIcon = Icons.chevronUp |> Element.html |> Element.el []
, descIcon = Icons.chevronDown |> Element.html |> Element.el []
, defaultIcon = Element.none
}
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
, progressIndicator = Material.progressIndicator palette
, layout = Material.layout palette
}
# Palette
@docs Palette, defaultPalette, darkPalette
@ -109,7 +61,6 @@ Thus for now we only provide a card containing a list.
@docs cardColumn
# Chip
@docs chip, textInput
@ -131,6 +82,12 @@ The [List widget](https://material.io/components/lists) is a very complex widget
@docs row, column
# Item
A List is build from items.
You way want to use special items to visually organize the content of your list.
@docs fullBleedDivider, insetDivider, middleDividers, insetTitle, fullBleedTitle
# Progress Indicator
@ -157,9 +114,6 @@ The [List widget](https://material.io/components/lists) is a very complex widget
To create your own Material Widgets, here are all internal functions.
Note that you might want to checkout the [file on GitHub](https://github.com/Orasund/elm-ui-widgets/blob/master/src/Widget/Style/Material.elm) if you want to tweak some internal behaviour.
## Typography
-}
import Color exposing (Color)
@ -177,6 +131,7 @@ import Widget.Style
, ColumnStyle
, DialogStyle
, ExpansionPanelStyle
, ItemStyle
, LayoutStyle
, ProgressIndicatorStyle
, RowStyle
@ -184,6 +139,8 @@ import Widget.Style
, SwitchStyle
, TabStyle
, TextInputStyle
, DividerStyle
, TitleStyle
)
import Widget.Style.Customize as Customize
import Widget.Style.Material.Color as MaterialColor
@ -1073,6 +1030,145 @@ column =
}
}
{-| A divider covering the full length
-}
fullBleedDivider : ItemStyle (DividerStyle msg)
fullBleedDivider =
{ element =
[ Element.width <| Element.fill
, Element.height <| Element.px 1
, Element.padding 0
, Border.widthEach
{ bottom = 0
, left = 1
, right = 1
, top = 0
}
]
, content = { element = [Element.width <| Element.fill, Element.height <| Element.px 1
,Color.gray
|> fromColor
|> Background.color]
}
}
{-| A divider covering only parts of the width
-}
insetDivider : Palette -> ItemStyle (DividerStyle msg)
insetDivider palette =
{ element =
[ Element.width <| Element.fill
, Element.height <| Element.px 1
, Border.widthEach
{ bottom = 0
, left = 1
, right = 1
, top = 0
}
, Element.paddingEach
{ bottom = 0
, left = 72
, right = 0
, top = 0
}
]
, content = { element = [Element.width <| Element.fill, Element.height <| Element.px 1
,Color.gray
|> fromColor
|> Background.color]
}
}
{-| A divider in the center
-}
middleDividers : Palette -> ItemStyle (DividerStyle msg)
middleDividers palette =
{ element =
[ Element.width <| Element.fill
, Element.height <| Element.px 1
, Border.widthEach
{ bottom = 0
, left = 1
, right = 1
, top = 0
}
, Element.paddingEach
{ bottom = 0
, left = 16
, right = 16
, top = 0
}
]
, content = { element = [Element.width <| Element.fill, Element.height <| Element.px 1
,Color.gray
|> fromColor
|> Background.color]
}
}
{-| A title of a section of a list. Comes with a inset divider.
-}
insetTitle : Palette -> ItemStyle (TitleStyle msg)
insetTitle palette =
{ element =
[ Element.width <| Element.fill
, Border.widthEach
{ bottom = 0
, left = 1
, right = 1
, top = 0
}
, Element.paddingEach
{ bottom = 0
, left = 72
, right = 0
, top = 0
}
]
, content =
{ elementColumn =
[ Element.width <| Element.fill
, Element.spacing <| 12
]
, content =
{ divider = insetDivider palette
|> .content
, title = Typography.body2 ++ [MaterialColor.gray
|> fromColor
|> Font.color]
}
}
}
{-| A title of a section of a list. Comes with a full bleed divider.
-}
fullBleedTitle : Palette -> ItemStyle (TitleStyle msg)
fullBleedTitle palette =
{ element =
[ Element.width <| Element.fill
, Element.padding 0
, Border.widthEach
{ bottom = 0
, left = 1
, right = 1
, top = 0
}
]
, content =
{ elementColumn =
[ Element.width <| Element.fill
, Element.spacing <| 8
]
, content =
{ divider = insetDivider palette
|> .content
, title = Typography.caption ++ [MaterialColor.gray
|> fromColor
|> Font.color
, Element.paddingXY 16 0]
}
}
}
{-| a Row of buttons.
@ -1130,7 +1226,6 @@ cardColumn palette =
, content =
{ element =
[ Element.padding 16
, Border.width 1
, palette.surface
|> fromColor
|> Background.color
@ -1154,6 +1249,12 @@ cardColumn palette =
, bottomLeft = 0
, bottomRight = 0
}
, Border.widthEach
{ top = 1
, left = 1
, right = 1
, bottom = 0
}
]
, ifLast =
[ Border.roundEach
@ -1175,7 +1276,7 @@ cardColumn palette =
{ top = 0
, left = 1
, right = 1
, bottom = 1
, bottom = 0
}
]
}
@ -1285,6 +1386,7 @@ Technical Remarks:
expansionPanel : Palette -> ExpansionPanelStyle msg
expansionPanel palette =
expansionPanelItem palette
|> .content
|> Customize.mapContent
(\record ->
{ record
@ -1313,40 +1415,43 @@ expansionPanel palette =
This is a small workaround to allow expansion panels within cards.
-}
expansionPanelItem : Palette -> ExpansionPanelStyle msg
expansionPanelItem : Palette -> ItemStyle (ExpansionPanelStyle msg)
expansionPanelItem palette =
{ elementColumn =
[ Background.color <| fromColor <| palette.surface
, Element.spacing 14
, Element.width <| Element.fill
]
{ element = []
, content =
{ panel =
{ elementRow =
[ Element.spaceEvenly
, Element.width <| Element.fill
]
, content =
{ label =
{ elementRow = [ Element.spacing 32 ]
, content =
{ icon =
{ size = 16
, color = MaterialColor.gray
{ elementColumn =
[ Background.color <| fromColor <| palette.surface
, Element.spacing 14
, Element.width <| Element.fill
]
, content =
{ panel =
{ elementRow =
[ Element.spaceEvenly
, Element.width <| Element.fill
]
, content =
{ label =
{ elementRow = [ Element.spacing 32 ]
, content =
{ icon =
{ size = 16
, color = MaterialColor.gray
}
, text = { elementText = [] }
}
, text = { elementText = [] }
}
, expandIcon = expand_more
, collapseIcon = expand_less
, icon =
{ size = 24
, color = MaterialColor.gray
}
}
, expandIcon = expand_more
, collapseIcon = expand_less
, icon =
{ size = 24
, color = MaterialColor.gray
}
}
}
, content =
{ element = [ Element.width <| Element.fill ]
, content =
{ element = [ Element.width <| Element.fill ]
}
}
}
}