mirror of
https://github.com/Orasund/elm-ui-widgets.git
synced 2024-11-22 04:58:49 +03:00
Add AppBar Widget
This commit is contained in:
parent
e5f120a18a
commit
7898a85bb2
224
src/Internal/AppBar.elm
Normal file
224
src/Internal/AppBar.elm
Normal file
@ -0,0 +1,224 @@
|
||||
module Internal.AppBar exposing (AppBarStyle, menuBar, tabBar)
|
||||
|
||||
import Array
|
||||
import Element exposing (Attribute, DeviceClass(..), Element)
|
||||
import Element.Input as Input
|
||||
import Html exposing (Html)
|
||||
import Internal.Button as Button exposing (Button, ButtonStyle)
|
||||
import Internal.Dialog as Dialog
|
||||
import Internal.Item as Item exposing (InsetItemStyle, ItemStyle)
|
||||
import Internal.Modal as Modal exposing (Modal)
|
||||
import Internal.Select as Select exposing (Select)
|
||||
import Internal.Sheet as Sheet exposing (SideSheetStyle)
|
||||
import Internal.TextInput as TextInput exposing (TextInput, TextInputStyle)
|
||||
import Widget.Customize as Customize
|
||||
import Widget.Icon exposing (Icon)
|
||||
import Widget.Snackbar as Snackbar exposing (Message, SnackbarStyle)
|
||||
|
||||
|
||||
type alias AppBarStyle content msg =
|
||||
{ elementRow : List (Attribute msg) --header
|
||||
, content :
|
||||
{ menu :
|
||||
{ elementRow : List (Attribute msg)
|
||||
, content : content
|
||||
}
|
||||
, search : TextInputStyle msg --search
|
||||
, actions :
|
||||
{ elementRow : List (Attribute msg)
|
||||
, content :
|
||||
{ button : ButtonStyle msg --menuButton
|
||||
, searchIcon : Icon msg
|
||||
, moreVerticalIcon : Icon msg
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
menuBar :
|
||||
AppBarStyle
|
||||
{ menuIcon : Icon msg
|
||||
, title : List (Attribute msg)
|
||||
}
|
||||
msg
|
||||
->
|
||||
{ title : Element msg
|
||||
, deviceClass : DeviceClass
|
||||
, openLeftSheet : msg
|
||||
, openRightSheet : msg
|
||||
, openTopSheet : msg
|
||||
, primaryActions : List (Button msg)
|
||||
, moreActions : List (Button msg)
|
||||
, search : Maybe (TextInput msg)
|
||||
}
|
||||
-> Element msg
|
||||
menuBar style m =
|
||||
internalNav
|
||||
[ Button.iconButton style.content.actions.content.button
|
||||
{ onPress = Just <| m.openLeftSheet
|
||||
, icon = style.content.menu.content.menuIcon
|
||||
, text = "Menu"
|
||||
}
|
||||
, m.title |> Element.el style.content.menu.content.title
|
||||
]
|
||||
{ elementRow = style.elementRow
|
||||
, content =
|
||||
{ menu =
|
||||
{ elementRow = style.content.menu.elementRow
|
||||
}
|
||||
, search = style.content.search
|
||||
, actions = style.content.actions
|
||||
}
|
||||
}
|
||||
m
|
||||
|
||||
|
||||
{-| A top bar that displays the menu as tabs
|
||||
-}
|
||||
tabBar :
|
||||
AppBarStyle
|
||||
{ menuTabButton : ButtonStyle msg
|
||||
, title : List (Attribute msg)
|
||||
}
|
||||
msg
|
||||
->
|
||||
{ title : Element msg
|
||||
, menu : Select msg
|
||||
, deviceClass : DeviceClass
|
||||
, openRightSheet : msg
|
||||
, openTopSheet : msg
|
||||
, primaryActions : List (Button msg)
|
||||
, moreActions : List (Button msg)
|
||||
, search : Maybe (TextInput msg)
|
||||
}
|
||||
-> Element msg
|
||||
tabBar style m =
|
||||
internalNav
|
||||
[ m.title |> Element.el style.content.menu.content.title
|
||||
, m.menu
|
||||
|> Select.select
|
||||
|> List.map (Select.selectButton style.content.menu.content.menuTabButton)
|
||||
|> Element.row
|
||||
[ Element.width <| Element.shrink
|
||||
]
|
||||
]
|
||||
{ elementRow = style.elementRow
|
||||
, content =
|
||||
{ menu =
|
||||
{ elementRow = style.content.menu.elementRow
|
||||
}
|
||||
, search = style.content.search
|
||||
, actions = style.content.actions
|
||||
}
|
||||
}
|
||||
m
|
||||
|
||||
|
||||
{-| -}
|
||||
internalNav :
|
||||
List (Element msg)
|
||||
->
|
||||
{ elementRow : List (Attribute msg) --header
|
||||
, content :
|
||||
{ menu :
|
||||
{ elementRow : List (Attribute msg)
|
||||
}
|
||||
, search : TextInputStyle msg --search
|
||||
, actions :
|
||||
{ elementRow : List (Attribute msg)
|
||||
, content :
|
||||
{ button : ButtonStyle msg --menuButton
|
||||
, searchIcon : Icon msg
|
||||
, moreVerticalIcon : Icon msg
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
->
|
||||
{ model
|
||||
| deviceClass : DeviceClass
|
||||
, openRightSheet : msg
|
||||
, openTopSheet : msg
|
||||
, primaryActions : List (Button msg)
|
||||
, moreActions : List (Button msg)
|
||||
, search : Maybe (TextInput msg)
|
||||
}
|
||||
-> Element msg
|
||||
internalNav menuElements style { deviceClass, openRightSheet, openTopSheet, primaryActions, moreActions, search } =
|
||||
[ menuElements
|
||||
|> Element.row style.content.menu.elementRow
|
||||
, if deviceClass == Phone || deviceClass == Tablet then
|
||||
Element.none
|
||||
|
||||
else
|
||||
search
|
||||
|> Maybe.map
|
||||
(\{ onChange, text, label } ->
|
||||
TextInput.textInput style.content.search
|
||||
{ chips = []
|
||||
, onChange = onChange
|
||||
, text = text
|
||||
, placeholder =
|
||||
Just <|
|
||||
Input.placeholder [] <|
|
||||
Element.text label
|
||||
, label = label
|
||||
}
|
||||
)
|
||||
|> Maybe.withDefault Element.none
|
||||
, [ search
|
||||
|> Maybe.map
|
||||
(\{ label } ->
|
||||
if deviceClass == Tablet then
|
||||
[ Button.button style.content.actions.content.button
|
||||
{ onPress = Just <| openTopSheet
|
||||
, icon = style.content.actions.content.searchIcon
|
||||
, text = label
|
||||
}
|
||||
]
|
||||
|
||||
else if deviceClass == Phone then
|
||||
[ Button.iconButton style.content.actions.content.button
|
||||
{ onPress = Just <| openTopSheet
|
||||
, icon = style.content.actions.content.searchIcon
|
||||
, text = label
|
||||
}
|
||||
]
|
||||
|
||||
else
|
||||
[]
|
||||
)
|
||||
|> Maybe.withDefault []
|
||||
, primaryActions
|
||||
|> List.map
|
||||
(if deviceClass == Phone then
|
||||
Button.iconButton style.content.actions.content.button
|
||||
|
||||
else
|
||||
Button.button
|
||||
(style.content.actions.content.button
|
||||
--FIX FOR ISSUE #30
|
||||
|> Customize.elementButton [ Element.width Element.shrink ]
|
||||
)
|
||||
)
|
||||
, if moreActions |> List.isEmpty then
|
||||
[]
|
||||
|
||||
else
|
||||
[ Button.iconButton style.content.actions.content.button
|
||||
{ onPress = Just <| openRightSheet
|
||||
, icon = style.content.actions.content.moreVerticalIcon
|
||||
, text = "More"
|
||||
}
|
||||
]
|
||||
]
|
||||
|> List.concat
|
||||
|> Element.row style.content.actions.elementRow
|
||||
]
|
||||
|> Element.row
|
||||
(style.elementRow
|
||||
++ [ Element.alignTop
|
||||
, Element.width <| Element.fill
|
||||
]
|
||||
)
|
192
src/Internal/Material/AppBar.elm
Normal file
192
src/Internal/Material/AppBar.elm
Normal file
@ -0,0 +1,192 @@
|
||||
module Internal.Material.AppBar exposing (menuBar, tabBar)
|
||||
|
||||
import Element exposing (Attribute)
|
||||
import Element.Background as Background
|
||||
import Element.Border as Border
|
||||
import Element.Font as Font
|
||||
import Internal.AppBar exposing (AppBarStyle)
|
||||
import Internal.Button exposing (ButtonStyle)
|
||||
import Internal.Material.Button as Button
|
||||
import Internal.Material.Icon as Icon
|
||||
import Internal.Material.Item as Item
|
||||
import Internal.Material.Palette exposing (Palette)
|
||||
import Internal.Material.Sheet as Sheet
|
||||
import Internal.Material.Snackbar as Snackbar
|
||||
import Internal.Material.TextInput as TextInput
|
||||
import Svg
|
||||
import Svg.Attributes
|
||||
import Widget.Customize as Customize
|
||||
import Widget.Icon as Icon exposing (Icon)
|
||||
import Widget.Layout exposing (LayoutStyle)
|
||||
import Widget.Material.Color as MaterialColor
|
||||
import Widget.Material.Typography as Typography
|
||||
|
||||
|
||||
menuTabButton : Palette -> ButtonStyle msg
|
||||
menuTabButton palette =
|
||||
{ elementButton =
|
||||
Typography.button
|
||||
++ [ Element.height <| Element.px 56
|
||||
, Element.fill
|
||||
|> Element.maximum 360
|
||||
|> Element.minimum 90
|
||||
|> Element.width
|
||||
, Element.paddingXY 12 16
|
||||
, palette.primary
|
||||
|> MaterialColor.accessibleTextColor
|
||||
|> MaterialColor.fromColor
|
||||
|> Font.color
|
||||
, Element.alignBottom
|
||||
, Element.mouseDown
|
||||
[ palette.primary
|
||||
|> MaterialColor.scaleOpacity MaterialColor.buttonPressedOpacity
|
||||
|> MaterialColor.fromColor
|
||||
|> Background.color
|
||||
]
|
||||
, Element.focused
|
||||
[ palette.primary
|
||||
|> MaterialColor.scaleOpacity MaterialColor.buttonFocusOpacity
|
||||
|> MaterialColor.fromColor
|
||||
|> Background.color
|
||||
]
|
||||
, Element.mouseOver
|
||||
[ palette.primary
|
||||
|> MaterialColor.scaleOpacity MaterialColor.buttonHoverOpacity
|
||||
|> MaterialColor.fromColor
|
||||
|> Background.color
|
||||
]
|
||||
]
|
||||
, ifDisabled =
|
||||
(Button.baseButton palette |> .ifDisabled)
|
||||
++ [ MaterialColor.gray
|
||||
|> MaterialColor.fromColor
|
||||
|> Font.color
|
||||
, Element.mouseDown []
|
||||
, Element.mouseOver []
|
||||
, Element.focused []
|
||||
]
|
||||
, ifActive =
|
||||
[ Border.widthEach
|
||||
{ bottom = 2
|
||||
, left = 0
|
||||
, right = 0
|
||||
, top = 0
|
||||
}
|
||||
]
|
||||
, otherwise =
|
||||
[]
|
||||
, content =
|
||||
{ elementRow =
|
||||
[ Element.spacing <| 8
|
||||
, Element.centerY
|
||||
, Element.centerX
|
||||
]
|
||||
, content =
|
||||
{ text = { contentText = [] }
|
||||
, icon =
|
||||
{ ifActive =
|
||||
{ size = 18
|
||||
, color = palette.primary |> MaterialColor.accessibleTextColor
|
||||
}
|
||||
, ifDisabled =
|
||||
{ size = 18
|
||||
, color = MaterialColor.gray
|
||||
}
|
||||
, otherwise =
|
||||
{ size = 18
|
||||
, color = palette.primary |> MaterialColor.accessibleTextColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
menuBar :
|
||||
Palette
|
||||
->
|
||||
AppBarStyle
|
||||
{ menuIcon : Icon msg
|
||||
, title : List (Attribute msg)
|
||||
}
|
||||
msg
|
||||
menuBar =
|
||||
internalBar
|
||||
{ menuIcon = Icon.menu
|
||||
, title = Typography.h6 ++ [ Element.paddingXY 8 0 ]
|
||||
}
|
||||
|
||||
|
||||
tabBar :
|
||||
Palette
|
||||
->
|
||||
AppBarStyle
|
||||
{ menuTabButton : ButtonStyle msg
|
||||
, title : List (Attribute msg)
|
||||
}
|
||||
msg
|
||||
tabBar palette =
|
||||
internalBar
|
||||
{ menuTabButton = menuTabButton palette
|
||||
, title = Typography.h6 ++ [ Element.paddingXY 8 0 ]
|
||||
}
|
||||
palette
|
||||
|
||||
|
||||
internalBar : content -> Palette -> AppBarStyle content msg
|
||||
internalBar content palette =
|
||||
{ elementRow =
|
||||
(palette.primary
|
||||
|> MaterialColor.textAndBackground
|
||||
)
|
||||
++ [ Element.padding 0
|
||||
, Element.spacing 8
|
||||
, Element.height <| Element.px 56
|
||||
, Element.width <| Element.minimum 360 <| Element.fill
|
||||
]
|
||||
, content =
|
||||
{ menu =
|
||||
{ elementRow =
|
||||
[ Element.width <| Element.shrink
|
||||
, Element.spacing 8
|
||||
]
|
||||
, content = content
|
||||
}
|
||||
, search = TextInput.searchInput palette
|
||||
, actions =
|
||||
{ elementRow =
|
||||
[ Element.alignRight
|
||||
, Element.width Element.shrink
|
||||
]
|
||||
, content =
|
||||
{ button =
|
||||
Button.iconButton palette
|
||||
|> Customize.mapContent
|
||||
(Customize.mapContent
|
||||
(\record ->
|
||||
{ record
|
||||
| icon =
|
||||
{ ifActive =
|
||||
{ size = record.icon.ifActive.size
|
||||
, color =
|
||||
palette.primary
|
||||
|> MaterialColor.accessibleTextColor
|
||||
}
|
||||
, ifDisabled =
|
||||
record.icon.ifDisabled
|
||||
, otherwise =
|
||||
{ size = record.icon.otherwise.size
|
||||
, color =
|
||||
palette.primary
|
||||
|> MaterialColor.accessibleTextColor
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
, searchIcon = Icon.search
|
||||
, moreVerticalIcon = Icon.more_vert
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
module Internal.Material.Icon exposing (expand_less, expand_more, icon)
|
||||
module Internal.Material.Icon exposing (expand_less, expand_more, icon, menu, more_vert, search)
|
||||
|
||||
import Color exposing (Color)
|
||||
import Element exposing (Element)
|
||||
@ -24,6 +24,48 @@ icon { viewBox, size, color } =
|
||||
>> Element.el []
|
||||
|
||||
|
||||
menu : Icon msg
|
||||
menu { size, color } =
|
||||
icon
|
||||
{ viewBox = "0 0 48 48"
|
||||
, size = size
|
||||
, color = color
|
||||
}
|
||||
[ Svg.path
|
||||
[ Svg.Attributes.d "M6 36h36v-4H6v4zm0-10h36v-4H6v4zm0-14v4h36v-4H6z"
|
||||
]
|
||||
[]
|
||||
]
|
||||
|
||||
|
||||
more_vert : Icon msg
|
||||
more_vert { size, color } =
|
||||
icon
|
||||
{ viewBox = "0 0 48 48"
|
||||
, size = size
|
||||
, color = color
|
||||
}
|
||||
[ Svg.path
|
||||
[ Svg.Attributes.d "M24 16c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 4c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 12c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4z"
|
||||
]
|
||||
[]
|
||||
]
|
||||
|
||||
|
||||
search : Icon msg
|
||||
search { size, color } =
|
||||
icon
|
||||
{ viewBox = "0 0 48 48"
|
||||
, size = size
|
||||
, color = color
|
||||
}
|
||||
[ Svg.path
|
||||
[ Svg.Attributes.d "M31 28h-1.59l-.55-.55C30.82 25.18 32 22.23 32 19c0-7.18-5.82-13-13-13S6 11.82 6 19s5.82 13 13 13c3.23 0 6.18-1.18 8.45-3.13l.55.55V31l10 9.98L40.98 38 31 28zm-12 0c-4.97 0-9-4.03-9-9s4.03-9 9-9 9 4.03 9 9-4.03 9-9 9z"
|
||||
]
|
||||
[]
|
||||
]
|
||||
|
||||
|
||||
expand_less : Icon msg
|
||||
expand_less { size, color } =
|
||||
icon
|
||||
|
@ -1,10 +1,11 @@
|
||||
module Internal.Material.Layout exposing (layout, menu, menuTabButton, more_vert, search)
|
||||
module Internal.Material.Layout exposing (layout)
|
||||
|
||||
import Element
|
||||
import Element.Background as Background
|
||||
import Element.Border as Border
|
||||
import Element.Font as Font
|
||||
import Internal.Button exposing (ButtonStyle)
|
||||
import Internal.Material.AppBar as AppBar
|
||||
import Internal.Material.Button as Button
|
||||
import Internal.Material.Icon as Icon
|
||||
import Internal.Material.Item as Item
|
||||
@ -21,128 +22,6 @@ import Widget.Material.Color as MaterialColor
|
||||
import Widget.Material.Typography as Typography
|
||||
|
||||
|
||||
more_vert : Icon msg
|
||||
more_vert { size, color } =
|
||||
Icon.icon
|
||||
{ viewBox = "0 0 48 48"
|
||||
, size = size
|
||||
, color = color
|
||||
}
|
||||
[ Svg.path
|
||||
[ Svg.Attributes.d "M24 16c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 4c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 12c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4z"
|
||||
]
|
||||
[]
|
||||
]
|
||||
|
||||
|
||||
search : Icon msg
|
||||
search { size, color } =
|
||||
Icon.icon
|
||||
{ viewBox = "0 0 48 48"
|
||||
, size = size
|
||||
, color = color
|
||||
}
|
||||
[ Svg.path
|
||||
[ Svg.Attributes.d "M31 28h-1.59l-.55-.55C30.82 25.18 32 22.23 32 19c0-7.18-5.82-13-13-13S6 11.82 6 19s5.82 13 13 13c3.23 0 6.18-1.18 8.45-3.13l.55.55V31l10 9.98L40.98 38 31 28zm-12 0c-4.97 0-9-4.03-9-9s4.03-9 9-9 9 4.03 9 9-4.03 9-9 9z"
|
||||
]
|
||||
[]
|
||||
]
|
||||
|
||||
|
||||
menu : Icon msg
|
||||
menu { size, color } =
|
||||
Icon.icon
|
||||
{ viewBox = "0 0 48 48"
|
||||
, size = size
|
||||
, color = color
|
||||
}
|
||||
[ Svg.path
|
||||
[ Svg.Attributes.d "M6 36h36v-4H6v4zm0-10h36v-4H6v4zm0-14v4h36v-4H6z"
|
||||
]
|
||||
[]
|
||||
]
|
||||
|
||||
|
||||
menuTabButton : Palette -> ButtonStyle msg
|
||||
menuTabButton palette =
|
||||
{ elementButton =
|
||||
Typography.button
|
||||
++ [ Element.height <| Element.px 56
|
||||
, Element.fill
|
||||
|> Element.maximum 360
|
||||
|> Element.minimum 90
|
||||
|> Element.width
|
||||
, Element.paddingXY 12 16
|
||||
, palette.primary
|
||||
|> MaterialColor.accessibleTextColor
|
||||
|> MaterialColor.fromColor
|
||||
|> Font.color
|
||||
, Element.alignBottom
|
||||
, Element.mouseDown
|
||||
[ palette.primary
|
||||
|> MaterialColor.scaleOpacity MaterialColor.buttonPressedOpacity
|
||||
|> MaterialColor.fromColor
|
||||
|> Background.color
|
||||
]
|
||||
, Element.focused
|
||||
[ palette.primary
|
||||
|> MaterialColor.scaleOpacity MaterialColor.buttonFocusOpacity
|
||||
|> MaterialColor.fromColor
|
||||
|> Background.color
|
||||
]
|
||||
, Element.mouseOver
|
||||
[ palette.primary
|
||||
|> MaterialColor.scaleOpacity MaterialColor.buttonHoverOpacity
|
||||
|> MaterialColor.fromColor
|
||||
|> Background.color
|
||||
]
|
||||
]
|
||||
, ifDisabled =
|
||||
(Button.baseButton palette |> .ifDisabled)
|
||||
++ [ MaterialColor.gray
|
||||
|> MaterialColor.fromColor
|
||||
|> Font.color
|
||||
, Element.mouseDown []
|
||||
, Element.mouseOver []
|
||||
, Element.focused []
|
||||
]
|
||||
, ifActive =
|
||||
[ Border.widthEach
|
||||
{ bottom = 2
|
||||
, left = 0
|
||||
, right = 0
|
||||
, top = 0
|
||||
}
|
||||
]
|
||||
, otherwise =
|
||||
[]
|
||||
, content =
|
||||
{ elementRow =
|
||||
[ Element.spacing <| 8
|
||||
, Element.centerY
|
||||
, Element.centerX
|
||||
]
|
||||
, content =
|
||||
{ text = { contentText = [] }
|
||||
, icon =
|
||||
{ ifActive =
|
||||
{ size = 18
|
||||
, color = palette.primary |> MaterialColor.accessibleTextColor
|
||||
}
|
||||
, ifDisabled =
|
||||
{ size = 18
|
||||
, color = MaterialColor.gray
|
||||
}
|
||||
, otherwise =
|
||||
{ size = 18
|
||||
, color = palette.primary |> MaterialColor.accessibleTextColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
layout : Palette -> LayoutStyle msg
|
||||
layout palette =
|
||||
{ container =
|
||||
@ -154,49 +33,13 @@ layout palette =
|
||||
, Font.size 16
|
||||
, Font.letterSpacing 0.5
|
||||
]
|
||||
, menuBar = AppBar.menuBar palette
|
||||
, tabBar = AppBar.tabBar palette
|
||||
, snackbar = Snackbar.snackbar palette
|
||||
, header =
|
||||
(palette.primary
|
||||
|> MaterialColor.textAndBackground
|
||||
)
|
||||
++ [ Element.height <| Element.px 56
|
||||
, Element.padding 16
|
||||
, Element.width <| Element.minimum 360 <| Element.fill
|
||||
]
|
||||
, menuButton =
|
||||
Button.iconButton palette
|
||||
|> Customize.mapContent
|
||||
(Customize.mapContent
|
||||
(\record ->
|
||||
{ record
|
||||
| icon =
|
||||
{ ifActive =
|
||||
{ size = record.icon.ifActive.size
|
||||
, color =
|
||||
palette.primary
|
||||
|> MaterialColor.accessibleTextColor
|
||||
}
|
||||
, ifDisabled =
|
||||
record.icon.ifDisabled
|
||||
, otherwise =
|
||||
{ size = record.icon.otherwise.size
|
||||
, color =
|
||||
palette.primary
|
||||
|> MaterialColor.accessibleTextColor
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
, sheetButton = Item.selectItem palette
|
||||
, menuTabButton = menuTabButton palette
|
||||
, sheet = Sheet.sideSheet palette
|
||||
, menuIcon = menu
|
||||
, moreVerticalIcon = more_vert
|
||||
, spacing = 8
|
||||
, title = Typography.h6 ++ [ Element.paddingXY 8 0 ]
|
||||
, searchIcon = search
|
||||
, search = TextInput.searchInput palette
|
||||
, searchFill =
|
||||
TextInput.textInputBase palette
|
||||
|> Customize.elementRow [ Element.height <| Element.px 56 ]
|
||||
|
@ -8,7 +8,6 @@ module Widget exposing
|
||||
, RowStyle, row, buttonRow
|
||||
, ColumnStyle, column, buttonColumn
|
||||
, ItemStyle, Item
|
||||
, InsetItemStyle, InsetItem, insetItem
|
||||
, ExpansionItemStyle, ExpansionItem, expansionItem
|
||||
, ImageItemStyle, ImageItem, imageItem
|
||||
, MultiLineItemStyle, MultiLineItem, multiLineItem
|
||||
@ -16,12 +15,13 @@ module Widget exposing
|
||||
, DividerStyle, divider
|
||||
, selectItem, asItem
|
||||
, itemList
|
||||
, menuBar, tabBar
|
||||
, SideSheetStyle, sideSheet
|
||||
, SortTableStyle, SortTable, Column, sortTable, floatColumn, intColumn, stringColumn, unsortableColumn
|
||||
, TextInputStyle, TextInput, textInput
|
||||
, TabStyle, Tab, tab
|
||||
, ProgressIndicatorStyle, ProgressIndicator, circularProgressIndicator
|
||||
, FullBleedItemStyle, fullBleedItem
|
||||
, FullBleedItemStyle, InsetItem, InsetItemStyle, fullBleedItem, insetItem
|
||||
)
|
||||
|
||||
{-| This module contains different stateless view functions. No wiring required.
|
||||
@ -122,6 +122,11 @@ You can create you own widgets by sticking widgets types together.
|
||||
@docs itemList
|
||||
|
||||
|
||||
# App Bar
|
||||
|
||||
@docs menuBar, tabBar
|
||||
|
||||
|
||||
# Sheet
|
||||
|
||||
@docs SideSheetStyle, sideSheet
|
||||
@ -165,8 +170,9 @@ You can create you own widgets by sticking widgets types together.
|
||||
-}
|
||||
|
||||
import Color exposing (Color)
|
||||
import Element exposing (Attribute, Element, Length)
|
||||
import Element exposing (Attribute, DeviceClass, Element, Length)
|
||||
import Element.Input exposing (Placeholder)
|
||||
import Internal.AppBar as AppBar exposing (AppBarStyle)
|
||||
import Internal.Button as Button
|
||||
import Internal.Dialog as Dialog
|
||||
import Internal.Item as Item
|
||||
@ -1407,6 +1413,54 @@ buttonColumn =
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- APP BAR
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
menuBar :
|
||||
AppBarStyle
|
||||
{ menuIcon : Icon msg
|
||||
, title : List (Attribute msg)
|
||||
}
|
||||
msg
|
||||
->
|
||||
{ title : Element msg
|
||||
, deviceClass : DeviceClass
|
||||
, openLeftSheet : msg
|
||||
, openRightSheet : msg
|
||||
, openTopSheet : msg
|
||||
, primaryActions : List (Button msg)
|
||||
, moreActions : List (Button msg)
|
||||
, search : Maybe (TextInput msg)
|
||||
}
|
||||
-> Element msg
|
||||
menuBar =
|
||||
AppBar.menuBar
|
||||
|
||||
|
||||
tabBar :
|
||||
AppBarStyle
|
||||
{ menuTabButton : ButtonStyle msg
|
||||
, title : List (Attribute msg)
|
||||
}
|
||||
msg
|
||||
->
|
||||
{ title : Element msg
|
||||
, menu : Select msg
|
||||
, deviceClass : DeviceClass
|
||||
, openRightSheet : msg
|
||||
, openTopSheet : msg
|
||||
, primaryActions : List (Button msg)
|
||||
, moreActions : List (Button msg)
|
||||
, search : Maybe (TextInput msg)
|
||||
}
|
||||
-> Element msg
|
||||
tabBar =
|
||||
AppBar.tabBar
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- SHEET
|
||||
--------------------------------------------------------------------------------
|
||||
|
@ -1,7 +1,6 @@
|
||||
module Widget.Layout exposing
|
||||
( LayoutStyle, Layout, Part(..), init, timePassed
|
||||
, activate, queueMessage
|
||||
, menuBar, tabBar
|
||||
, leftSheet, rightSheet, searchSheet
|
||||
, getDeviceClass, partitionActions, orderModals
|
||||
, view
|
||||
@ -48,6 +47,7 @@ import Array
|
||||
import Element exposing (Attribute, DeviceClass(..), Element)
|
||||
import Element.Input as Input
|
||||
import Html exposing (Html)
|
||||
import Internal.AppBar as AppBar exposing (AppBarStyle)
|
||||
import Internal.Button as Button exposing (Button, ButtonStyle)
|
||||
import Internal.Dialog as Dialog
|
||||
import Internal.Item as Item exposing (InsetItemStyle, ItemStyle)
|
||||
@ -64,19 +64,24 @@ import Widget.Snackbar as Snackbar exposing (Message, SnackbarStyle)
|
||||
type alias LayoutStyle msg =
|
||||
{ container : List (Attribute msg)
|
||||
, snackbar : SnackbarStyle msg
|
||||
, header : List (Attribute msg)
|
||||
, sheet : SideSheetStyle msg
|
||||
, sheetButton : ItemStyle (ButtonStyle msg) msg
|
||||
, menuButton : ButtonStyle msg
|
||||
, menuTabButton : ButtonStyle msg
|
||||
, menuIcon : Icon msg
|
||||
, moreVerticalIcon : Icon msg
|
||||
, spacing : Int
|
||||
, title : List (Attribute msg)
|
||||
, searchIcon : Icon msg
|
||||
, search : TextInputStyle msg
|
||||
, searchFill : TextInputStyle msg
|
||||
, insetItem : ItemStyle (InsetItemStyle msg) msg
|
||||
, menuBar :
|
||||
AppBarStyle
|
||||
{ menuIcon : Icon msg
|
||||
, title : List (Attribute msg)
|
||||
}
|
||||
msg
|
||||
, tabBar :
|
||||
AppBarStyle
|
||||
{ menuTabButton : ButtonStyle msg
|
||||
, title : List (Attribute msg)
|
||||
}
|
||||
msg
|
||||
}
|
||||
|
||||
|
||||
@ -193,191 +198,6 @@ partitionActions actions =
|
||||
}
|
||||
|
||||
|
||||
{-| A top bar that displays a menu icon on the left side.
|
||||
-}
|
||||
menuBar :
|
||||
{ style
|
||||
| menuIcon : Icon msg
|
||||
, title : List (Attribute msg)
|
||||
, header : List (Attribute msg)
|
||||
, menuButton : ButtonStyle msg
|
||||
, moreVerticalIcon : Icon msg
|
||||
, spacing : Int
|
||||
, searchIcon : Icon msg
|
||||
, search : TextInputStyle msg
|
||||
}
|
||||
->
|
||||
{ title : Element msg
|
||||
, deviceClass : DeviceClass
|
||||
, openLeftSheet : msg
|
||||
, openRightSheet : msg
|
||||
, openTopSheet : msg
|
||||
, primaryActions : List (Button msg)
|
||||
, moreActions : List (Button msg)
|
||||
, search : Maybe (TextInput msg)
|
||||
}
|
||||
-> Element msg
|
||||
menuBar style m =
|
||||
internalNav
|
||||
[ Button.iconButton style.menuButton
|
||||
{ onPress = Just <| m.openLeftSheet
|
||||
, icon = style.menuIcon
|
||||
, text = "Menu"
|
||||
}
|
||||
, m.title |> Element.el style.title
|
||||
]
|
||||
style
|
||||
m
|
||||
|
||||
|
||||
{-| A top bar that displays the menu as tabs
|
||||
-}
|
||||
tabBar :
|
||||
{ style
|
||||
| menuTabButton : ButtonStyle msg
|
||||
, title : List (Attribute msg)
|
||||
, header : List (Attribute msg)
|
||||
, menuButton : ButtonStyle msg
|
||||
, moreVerticalIcon : Icon msg
|
||||
, spacing : Int
|
||||
, searchIcon : Icon msg
|
||||
, search : TextInputStyle msg
|
||||
}
|
||||
->
|
||||
{ title : Element msg
|
||||
, menu : Select msg
|
||||
, deviceClass : DeviceClass
|
||||
, openRightSheet : msg
|
||||
, openTopSheet : msg
|
||||
, primaryActions : List (Button msg)
|
||||
, moreActions : List (Button msg)
|
||||
, search : Maybe (TextInput msg)
|
||||
}
|
||||
-> Element msg
|
||||
tabBar style m =
|
||||
internalNav
|
||||
[ m.title |> Element.el style.title
|
||||
, m.menu
|
||||
|> Select.select
|
||||
|> List.map (Select.selectButton style.menuTabButton)
|
||||
|> Element.row
|
||||
[ Element.width <| Element.shrink
|
||||
]
|
||||
]
|
||||
style
|
||||
m
|
||||
|
||||
|
||||
{-| -}
|
||||
internalNav :
|
||||
List (Element msg)
|
||||
->
|
||||
{ style
|
||||
| header : List (Attribute msg)
|
||||
, menuButton : ButtonStyle msg
|
||||
, moreVerticalIcon : Icon msg
|
||||
, spacing : Int
|
||||
, searchIcon : Icon msg
|
||||
, search : TextInputStyle msg
|
||||
}
|
||||
->
|
||||
{ model
|
||||
| deviceClass : DeviceClass
|
||||
, openRightSheet : msg
|
||||
, openTopSheet : msg
|
||||
, primaryActions : List (Button msg)
|
||||
, moreActions : List (Button msg)
|
||||
, search : Maybe (TextInput msg)
|
||||
}
|
||||
-> Element msg
|
||||
internalNav menuElements style { deviceClass, openRightSheet, openTopSheet, primaryActions, moreActions, search } =
|
||||
[ menuElements
|
||||
|> Element.row
|
||||
[ Element.width <| Element.shrink
|
||||
, Element.spacing style.spacing
|
||||
]
|
||||
, if deviceClass == Phone || deviceClass == Tablet then
|
||||
Element.none
|
||||
|
||||
else
|
||||
search
|
||||
|> Maybe.map
|
||||
(\{ onChange, text, label } ->
|
||||
TextInput.textInput style.search
|
||||
{ chips = []
|
||||
, onChange = onChange
|
||||
, text = text
|
||||
, placeholder =
|
||||
Just <|
|
||||
Input.placeholder [] <|
|
||||
Element.text label
|
||||
, label = label
|
||||
}
|
||||
)
|
||||
|> Maybe.withDefault Element.none
|
||||
, [ search
|
||||
|> Maybe.map
|
||||
(\{ label } ->
|
||||
if deviceClass == Tablet then
|
||||
[ Button.button style.menuButton
|
||||
{ onPress = Just <| openTopSheet
|
||||
, icon = style.searchIcon
|
||||
, text = label
|
||||
}
|
||||
]
|
||||
|
||||
else if deviceClass == Phone then
|
||||
[ Button.iconButton style.menuButton
|
||||
{ onPress = Just <| openTopSheet
|
||||
, icon = style.searchIcon
|
||||
, text = label
|
||||
}
|
||||
]
|
||||
|
||||
else
|
||||
[]
|
||||
)
|
||||
|> Maybe.withDefault []
|
||||
, primaryActions
|
||||
|> List.map
|
||||
(if deviceClass == Phone then
|
||||
Button.iconButton style.menuButton
|
||||
|
||||
else
|
||||
Button.button
|
||||
(style.menuButton
|
||||
--FIX FOR ISSUE #30
|
||||
|> Customize.elementButton [ Element.width Element.shrink ]
|
||||
)
|
||||
)
|
||||
, if moreActions |> List.isEmpty then
|
||||
[]
|
||||
|
||||
else
|
||||
[ Button.iconButton style.menuButton
|
||||
{ onPress = Just <| openRightSheet
|
||||
, icon = style.moreVerticalIcon
|
||||
, text = "More"
|
||||
}
|
||||
]
|
||||
]
|
||||
|> List.concat
|
||||
|> Element.row
|
||||
[ Element.alignRight
|
||||
, Element.width Element.shrink
|
||||
]
|
||||
]
|
||||
|> Element.row
|
||||
(style.header
|
||||
++ [ Element.padding 0
|
||||
, Element.centerX
|
||||
, Element.spacing style.spacing
|
||||
, Element.alignTop
|
||||
, Element.width <| Element.fill
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
{-| Left sheet containing a title and a menu.
|
||||
-}
|
||||
leftSheet :
|
||||
@ -524,7 +344,7 @@ view style { search, title, onChangedSidebar, menu, actions, window, dialog, lay
|
||||
|| (deviceClass == Tablet)
|
||||
|| ((menu.options |> List.length) > 5)
|
||||
then
|
||||
menuBar style
|
||||
AppBar.menuBar style.menuBar
|
||||
{ title = title
|
||||
, deviceClass = deviceClass
|
||||
, openLeftSheet = onChangedSidebar <| Just LeftSheet
|
||||
@ -536,7 +356,7 @@ view style { search, title, onChangedSidebar, menu, actions, window, dialog, lay
|
||||
}
|
||||
|
||||
else
|
||||
tabBar style
|
||||
AppBar.tabBar style.tabBar
|
||||
{ title = title
|
||||
, menu = menu
|
||||
, deviceClass = deviceClass
|
||||
|
@ -7,10 +7,11 @@ module Widget.Material exposing
|
||||
, chip, textInput
|
||||
, alertDialog
|
||||
, row, column
|
||||
, menuBar, tabBar
|
||||
, sideSheet
|
||||
, fullBleedItem, insetItem, multiLineItem, imageItem, expansionItem, selectItem
|
||||
, fullBleedDivider, insetDivider, middleDivider
|
||||
, insetHeader, fullBleedHeader
|
||||
, fullBleedHeader, insetHeader
|
||||
, progressIndicator
|
||||
, sortTable
|
||||
, snackbar
|
||||
@ -81,6 +82,11 @@ Thus for now we only provide a card containing a list.
|
||||
@docs row, column
|
||||
|
||||
|
||||
# App Bar
|
||||
|
||||
@docs menuBar, tabBar
|
||||
|
||||
|
||||
# Sheet
|
||||
|
||||
@docs sideSheet
|
||||
@ -129,11 +135,23 @@ Note that you might want to checkout the [file on GitHub](https://github.com/Ora
|
||||
-}
|
||||
|
||||
import Color exposing (Color)
|
||||
import Element exposing (Attribute)
|
||||
import Internal.AppBar exposing (AppBarStyle)
|
||||
import Internal.Button exposing (ButtonStyle)
|
||||
import Internal.Dialog exposing (DialogStyle)
|
||||
import Internal.Item exposing (DividerStyle
|
||||
, ExpansionItemStyle, FullBleedItemStyle, HeaderStyle, ImageItemStyle, ItemStyle, MultiLineItemStyle, InsetItemStyle)
|
||||
import Internal.Item
|
||||
exposing
|
||||
( DividerStyle
|
||||
, ExpansionItemStyle
|
||||
, FullBleedItemStyle
|
||||
, HeaderStyle
|
||||
, ImageItemStyle
|
||||
, InsetItemStyle
|
||||
, ItemStyle
|
||||
, MultiLineItemStyle
|
||||
)
|
||||
import Internal.List exposing (ColumnStyle, RowStyle)
|
||||
import Internal.Material.AppBar as AppBar
|
||||
import Internal.Material.Button as Button
|
||||
import Internal.Material.Chip as Chip
|
||||
import Internal.Material.Dialog as Dialog
|
||||
@ -154,6 +172,7 @@ import Internal.SortTable exposing (SortTableStyle)
|
||||
import Internal.Switch exposing (SwitchStyle)
|
||||
import Internal.Tab exposing (TabStyle)
|
||||
import Internal.TextInput exposing (TextInputStyle)
|
||||
import Widget.Icon exposing (Icon)
|
||||
import Widget.Layout exposing (LayoutStyle)
|
||||
import Widget.Snackbar exposing (SnackbarStyle)
|
||||
|
||||
@ -312,6 +331,36 @@ chip =
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- APP BAR
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
menuBar :
|
||||
Palette
|
||||
->
|
||||
AppBarStyle
|
||||
{ menuIcon : Icon msg
|
||||
, title : List (Attribute msg)
|
||||
}
|
||||
msg
|
||||
menuBar =
|
||||
AppBar.menuBar
|
||||
|
||||
|
||||
tabBar :
|
||||
Palette
|
||||
->
|
||||
AppBarStyle
|
||||
{ menuTabButton : ButtonStyle msg
|
||||
, title : List (Attribute msg)
|
||||
}
|
||||
msg
|
||||
tabBar =
|
||||
AppBar.tabBar
|
||||
|
||||
|
||||
|
||||
{-------------------------------------------------------------------------------
|
||||
-- SHEET
|
||||
-------------------------------------------------------------------------------}
|
||||
|
Loading…
Reference in New Issue
Block a user