added BottomSheet

This commit is contained in:
Lucas Payr 2021-02-05 13:51:19 +01:00
parent 21f07bdfac
commit 4a3314c72a
17 changed files with 130 additions and 343 deletions

View File

@ -16,6 +16,7 @@ import Example.Tab as Tab
import Example.TextInput as TextInput
import Example.Sheet as Sheet
import Example.AppBar as AppBar
import Example.Snackbar as Snackbar
import Framework.Grid as Grid
import View.States as States
import Example.Layout as Layout
@ -36,6 +37,7 @@ type Example
| SheetExample
| AppBarExample
| LayoutExample
| SnackbarExample
asList : List Example
@ -55,6 +57,7 @@ asList =
, SheetExample
, AppBarExample
, LayoutExample
, SnackbarExample
]
|> List.sortBy toString
@ -103,6 +106,8 @@ toString example =
"App Bar"
LayoutExample ->
"Layout"
SnackbarExample ->
"Snackbar"
fromString : String -> Maybe Example
fromString string =
@ -150,6 +155,9 @@ fromString string =
"Layout" ->
Just LayoutExample
"Snackbar" ->
Just SnackbarExample
_ ->
Nothing
@ -202,6 +210,9 @@ get example =
LayoutExample ->
.layout
SnackbarExample ->
.snackbar
toTests : Example -> msg -> Style msg -> List ( String, Element msg )
@ -251,6 +262,9 @@ toTests example =
LayoutExample ->
States.layout
SnackbarExample ->
States.snackbar
type Msg
@ -269,6 +283,7 @@ type Msg
| Sheet Sheet.Msg
| AppBar AppBar.Msg
| Layout Layout.Msg
| Snackbar Snackbar.Msg
type alias Model =
{ button : Button.Model
@ -286,6 +301,7 @@ type alias Model =
, sheet : Sheet.Model
, appBar : AppBar.Model
, layout : Layout.Model
, snackbar : Snackbar.Model
}
@ -314,6 +330,7 @@ type alias UpgradeCollection =
, sheet : UpgradeRecord Sheet.Model Sheet.Msg
, appBar : UpgradeRecord AppBar.Model AppBar.Msg
, layout : UpgradeRecord Layout.Model Layout.Msg
, snackbar : UpgradeRecord Snackbar.Model Snackbar.Msg
}
@ -333,6 +350,7 @@ type alias ExampleView msg =
, sheet : Element msg
, appBar : Element msg
, layout : Element msg
, snackbar : Element msg
}
@ -383,6 +401,9 @@ init =
( layoutModel, layoutMsg ) =
Layout.init
( snackbarModel, snackbarMsg ) =
Snackbar.init
in
( { button = buttonModel
, switch = switchModel
@ -399,6 +420,7 @@ init =
, sheet = sheetModel
, appBar = appBarModel
, layout = layoutModel
, snackbar = snackbarModel
}
, [ Cmd.map Button buttonMsg
, Cmd.map Switch switchMsg
@ -415,6 +437,7 @@ init =
, Cmd.map Sheet sheetMsg
, Cmd.map AppBar appBarMsg
, Cmd.map Layout layoutMsg
, Cmd.map Snackbar snackbarMsg
]
|> Cmd.batch
)
@ -527,6 +550,13 @@ upgradeRecord =
, updateFun = Layout.update
, subscriptionsFun = Layout.subscriptions
}
, snackbar =
{ from = .snackbar
, to = \model a -> { model | snackbar = a }
, msgMapper = Snackbar
, updateFun = Snackbar.update
, subscriptionsFun = Snackbar.subscriptions
}
}
@ -575,6 +605,8 @@ update msg model =
updateField .appBar m
Layout m ->
updateField .layout m
Snackbar m ->
updateField .snackbar m
)
model
@ -600,6 +632,7 @@ subscriptions model =
, upgradeRecord.sheet |> subFun
, upgradeRecord.appBar |> subFun
, upgradeRecord.layout |> subFun
, upgradeRecord.snackbar |> subFun
]
|> Sub.batch
@ -640,6 +673,8 @@ view msgMapper style model =
AppBar.view (AppBar >> msgMapper) style (.appBar model)
, layout =
Layout.view (Layout >> msgMapper) style (.layout model)
, snackbar =
Snackbar.view (Snackbar >> msgMapper) style (.snackbar model)
}

View File

@ -28,7 +28,6 @@ import Widget
, TabStyle
, TextInputStyle
, InsetItemStyle
, SideSheetStyle
, FullBleedItemStyle
, AppBarStyle
)
@ -137,7 +136,7 @@ type alias Style msg =
, multiLineItem : ItemStyle (MultiLineItemStyle msg) msg
, imageItem : ItemStyle (ImageItemStyle msg) msg
, expansionItem : ExpansionItemStyle msg
, sideSheet : SideSheetStyle msg
, sideSheet : ColumnStyle msg
, fullBleedItem : ItemStyle (FullBleedItemStyle msg) msg
, selectItem : ItemStyle (ButtonStyle msg) msg
, menuBar :

View File

@ -2,7 +2,7 @@ module Example.AppBar exposing (Model, Msg, init, subscriptions, update, view)
import Browser
import FeatherIcons
import Widget exposing (Modal ,ItemStyle ,SideSheetStyle ,Button , TextInput ,TextInputStyle, AppBarStyle,ButtonStyle)
import Widget exposing (Modal ,ItemStyle ,Button , TextInput ,TextInputStyle, AppBarStyle,ButtonStyle)
import Widget.Icon as Icon exposing (Icon)
import Widget.Material as Material
import Element exposing (Attribute, DeviceClass(..), Element)

View File

@ -5,7 +5,7 @@ import Element exposing (Element,Attribute,DeviceClass(..))
import FeatherIcons
import Widget exposing (TextInputStyle ,TextInput
,Dialog,DialogStyle,ColumnStyle
,ButtonStyle,Modal,AppBarStyle, SideSheetStyle,ItemStyle,HeaderStyle,InsetItemStyle)
,ButtonStyle,Modal,AppBarStyle,ItemStyle,HeaderStyle,InsetItemStyle)
import Widget.Icon as Icon exposing (Icon)
import Widget.Material as Material
import Widget.Material.Typography as Typography
@ -29,7 +29,7 @@ type alias Style style msg =
{ style
| container : List (Attribute msg)
, snackbar : SnackbarStyle msg
, sideSheet : SideSheetStyle msg
, sideSheet : ColumnStyle msg
, sheetButton : ItemStyle (ButtonStyle msg) msg
, searchFill : TextInputStyle msg
, insetItem : ItemStyle (InsetItemStyle msg) msg

View File

@ -3,14 +3,14 @@ module Example.Sheet exposing (Model, Msg, init, subscriptions, update, view)
import Browser
import Element exposing (Element)
import FeatherIcons
import Widget exposing (ButtonStyle, SideSheetStyle,ItemStyle,HeaderStyle,InsetItemStyle)
import Widget exposing (ButtonStyle, ColumnStyle,ItemStyle,HeaderStyle,InsetItemStyle)
import Widget.Icon as Icon
import Widget.Material as Material
import Widget.Material.Typography as Typography
type alias Style style msg =
{ style
| sideSheet : SideSheetStyle msg
| sideSheet : ColumnStyle msg
, primaryButton : ButtonStyle msg
, fullBleedHeader : ItemStyle (HeaderStyle msg) msg
, insetItem : ItemStyle (InsetItemStyle msg) msg
@ -100,7 +100,7 @@ view msgMapper style (IsEnabled isEnabled) =
Element.none
}
]
|> Widget.sideSheet style.sideSheet
|> Widget.itemList style.sideSheet
, onDismiss = Just <| msgMapper <| ToggleModal False
}
|> List.singleton

View File

@ -1,11 +1,11 @@
module Main exposing (Model, Msg, init, subscriptions, update, view)
module Example.Snackbar exposing (Model, Msg, init, subscriptions, update, view)
import Browser
import Element exposing (Element)
import FeatherIcons
import Time
import Widget exposing (ButtonStyle, ColumnStyle, RowStyle, SnackbarStyle)
import Widget.Snackbar as Snackbar exposing (Snackbar)
import Widget exposing (ButtonStyle, ColumnStyle, RowStyle)
import Widget.Snackbar as Snackbar exposing (Snackbar,SnackbarStyle)
import Widget.Material as Material
@ -75,7 +75,7 @@ view msgMapper style model =
, False
)
, text = "Add Notification"
, icon = Element.none
, icon = always Element.none
}
, Widget.button style.button
{ onPress =
@ -86,7 +86,7 @@ view msgMapper style model =
, True
)
, text = "Add Notification with Action"
, icon = Element.none
, icon = always Element.none
}
]
|> Widget.column style.column

View File

@ -25,7 +25,7 @@ import Task
import Time
import Widget exposing (Modal,TextInput)
import Widget.Icon as Icon
import Widget.Layout as Layout exposing (Part)
import Widget.Layout as Layout
import Widget.ScrollingNav as ScrollingNav
import Widget.Snackbar as Snackbar exposing (Message)
import Material.Icons.Types exposing (Coloring(..))
@ -151,13 +151,6 @@ updateLoaded msg model =
(Cmd.map StatelessSpecific)
UpdateScrollingNav fun ->
let
_ =
model.scrollingNav |> fun
|> ScrollingNav.current Example.fromString
|> Maybe.map Example.toString
|> Debug.log "section"
in
( { model | scrollingNav = model.scrollingNav |> fun }
, Cmd.none
)

View File

@ -3,7 +3,6 @@ module Stateless exposing (Model, Msg, init, update,subscriptions, view)
import Data.Example as Example
import Data.Theme as Theme exposing (Theme)
import Element exposing (Element)
import Widget.Layout exposing (Part(..))
type alias Model =

View File

@ -1,4 +1,4 @@
module View.States exposing (button, sheet,dialog,layout, icon, list, modal,appBar, multiSelect, progressIndicator, select, sortTable, switch, tab, textInput)
module View.States exposing (button,snackbar, sheet,dialog,layout, icon, list, modal,appBar, multiSelect, progressIndicator, select, sortTable, switch, tab, textInput)
import Data.Style exposing (Style)
import Element exposing (Element)
@ -7,7 +7,7 @@ import Icons
import Set
import Widget
import Widget.Icon as Icon
import Widget.Layout exposing (Part(..))
import Widget.Layout
button : msg -> Style msg -> List ( String, Element msg )
@ -558,4 +558,8 @@ appBar _ style =
layout : msg -> Style msg -> List ( String, Element msg )
layout _ style =
[]
snackbar : msg -> Style msg -> List ( String, Element msg )
snackbar _ style =
[]

View File

@ -9,7 +9,7 @@ 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.Sheet as Sheet
import Internal.TextInput as TextInput exposing (TextInput, TextInputStyle)
import Widget.Customize as Customize
import Widget.Icon exposing (Icon)

View File

@ -174,4 +174,4 @@ buttonColumn style =
style.elementColumn.content.otherwise
, content = style.content
}
>> Element.column style.elementColumn.elementColumn
>> Element.column style.elementColumn.elementColumn

View File

@ -3,6 +3,8 @@ module Internal.Material.List exposing
, cardColumn
, column
, row
, sideSheet
, bottomSheet
)
import Element
@ -146,3 +148,39 @@ cardColumn palette =
]
}
}
sideSheet : Palette -> ColumnStyle msg
sideSheet palette =
{ elementColumn =
(palette.surface |> MaterialColor.textAndBackground)
++ [ Element.width <| Element.maximum 360 <| Element.fill
, Element.height <| Element.fill
, Element.paddingXY 0 8
]
, content =
{ element =
[ Element.width <| Element.fill ]
, ifSingleton = []
, ifFirst = []
, ifLast = []
, otherwise = []
}
}
bottomSheet : Palette -> ColumnStyle msg
bottomSheet palette =
{ elementColumn =
(palette.surface |> MaterialColor.textAndBackground)
++ [ Element.height <| Element.fill
, Element.width <| Element.maximum 360 <| Element.fill
, Element.paddingXY 0 8
]
, content =
{ element =
[ Element.width <| Element.fill ]
, ifSingleton = []
, ifFirst = []
, ifLast = []
, otherwise = []
}
}

View File

@ -1,26 +1,8 @@
module Internal.Material.Sheet exposing (sideSheet)
module Internal.Material.Sheet exposing (deleteMe)
import Element
import Internal.Material.Palette exposing (Palette)
import Internal.Sheet exposing (SideSheetStyle)
import Widget.Material.Color as MaterialColor
sideSheet : Palette -> SideSheetStyle msg
sideSheet palette =
{ element = [ ]
, content =
{ elementColumn =
(palette.surface |> MaterialColor.textAndBackground)
++ [ Element.width <| Element.maximum 360 <| Element.fill
]
, content =
{ element =
[ Element.width <| Element.fill ]
, ifSingleton = []
, ifFirst = []
, ifLast = []
, otherwise = []
}
}
}
deleteMe = True

View File

@ -1,18 +1,10 @@
module Internal.Sheet exposing (SideSheetStyle, sideSheet)
module Internal.Sheet exposing (delete)
import Element exposing (Attribute, Element)
import Internal.Item exposing (Item)
import Internal.List as List exposing (ColumnStyle)
import Internal.List
import Widget.Customize as Customize
delete = "deleteMe Pls"
type alias SideSheetStyle msg =
{ element : List (Attribute msg)
, content : ColumnStyle msg
}
sideSheet : SideSheetStyle msg -> List (Item msg) -> Element msg
sideSheet style =
List.itemList (style.content |> Customize.elementColumn [ Element.height <| Element.fill ])
>> Element.el (style.element ++ [ Element.height <| Element.fill ])
-- >> Element.el (style.element)

View File

@ -16,7 +16,6 @@ module Widget exposing
, selectItem, asItem
, itemList
, menuBar, tabBar
, SideSheetStyle, sideSheet
, SortTableStyle, SortTable, Column, sortTable, floatColumn, intColumn, stringColumn, unsortableColumn
, TextInputStyle, TextInput, textInput
, TabStyle, Tab, tab
@ -127,11 +126,6 @@ You can create you own widgets by sticking widgets types together.
@docs AppBarStyle, menuBar, tabBar
# Sheet
@docs SideSheetStyle, sideSheet
# Sort Table
![SortTable](https://orasund.github.io/elm-ui-widgets/assets/sortTable.png)
@ -1489,24 +1483,6 @@ tabBar =
--------------------------------------------------------------------------------
-- SHEET
--------------------------------------------------------------------------------
type alias SideSheetStyle msg =
{ element : List (Attribute msg)
, content : ColumnStyle msg
}
{-| A sheet is similar to
-}
sideSheet : SideSheetStyle msg -> List (Item msg) -> Element msg
sideSheet =
Sheet.sideSheet
{----------------------------------------------------------
- SORT TABLE

View File

@ -1,9 +1,6 @@
module Widget.Layout exposing
( Part, timePassed
, activate, queueMessage
, leftSheet, rightSheet, searchSheet
( leftSheet, rightSheet, searchSheet
, getDeviceClass, partitionActions, orderModals
, view
)
{-| Combines multiple concepts from the [material design specification](https://material.io/components/), namely:
@ -16,26 +13,12 @@ module Widget.Layout exposing
It is responsive and changes view to apply to the [material design guidelines](https://material.io/components/app-bars-top).
# Basics
@docs Layout, Part, timePassed
# Actions
@docs activate, queueMessage
# Views
## Sheets
# Sheets
@docs leftSheet, rightSheet, searchSheet
## Utility Functions
# Utility Functions
@docs getDeviceClass, partitionActions, orderModals
@ -51,96 +34,13 @@ 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 Internal.List as List exposing (ColumnStyle)
import Widget.Customize as Customize
import Widget.Icon exposing (Icon)
import Widget.Snackbar as Snackbar exposing (Message, SnackbarStyle)
{-| -}
type alias LayoutStyle msg =
{ container : List (Attribute msg)
, snackbar : SnackbarStyle msg
, sheet : SideSheetStyle msg
, sheetButton : ItemStyle (ButtonStyle msg) msg
, spacing : Int
, title : List (Attribute 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
}
{-| 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.Snackbar (Message msg)
, active : Maybe Part
}
{-| 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
Just LeftSheet ->
layout
Just RightSheet ->
layout
_ ->
{ layout
| snackbar = layout.snackbar |> Snackbar.timePassed sec
}
--------------------------------------------------------------------------------
-- View
--------------------------------------------------------------------------------
{-| obtain the Device Calss from a given window.
Checkout Element.classifyDevice for more information.
@ -191,7 +91,7 @@ partitionActions actions =
-}
leftSheet :
{ button : ItemStyle (ButtonStyle msg) msg
, sheet : SideSheetStyle msg
, sheet : ColumnStyle msg
}
->
{ title : Element msg
@ -206,11 +106,9 @@ leftSheet style { title, onDismiss, menu } =
:: (menu
|> Item.selectItem style.button
)
|> Sheet.sideSheet
|> List.itemList
(style.sheet
|> Customize.element [ Element.alignLeft ]
|> Customize.mapContent
(Customize.elementColumn [ Element.width <| Element.fill ])
|> Customize.elementColumn [ Element.alignLeft ]
)
}
@ -218,7 +116,7 @@ leftSheet style { title, onDismiss, menu } =
{-| Right sheet containg a simple list of buttons
-}
rightSheet :
{ sheet : SideSheetStyle msg
{ sheet : ColumnStyle msg
, insetItem : ItemStyle (InsetItemStyle msg) msg
}
->
@ -240,9 +138,9 @@ rightSheet style { onDismiss, moreActions } =
, content = always Element.none
}
)
|> Sheet.sideSheet
|> List.itemList
(style.sheet
|> Customize.element [ Element.alignRight ]
|> Customize.elementColumn [ Element.alignRight ]
)
}
@ -300,137 +198,4 @@ orderModals modals =
, modals.rightSheet
, modals.topSheet
]
|> List.filterMap identity
view :
LayoutStyle msg
->
{ window : { height : Int, width : Int }
, dialog : Maybe (Modal msg)
, layout : Layout msg
, title : Element msg
, menu : Select msg
, search : Maybe (TextInput msg)
, actions : List (Button msg)
, onChangedSidebar : Maybe Part -> msg
}
-> List (Attribute msg)
view style { search, title, onChangedSidebar, menu, actions, window, dialog, layout } =
let
deviceClass : DeviceClass
deviceClass =
getDeviceClass window
{ primaryActions, moreActions } =
partitionActions actions
nav : Element msg
nav =
if
(deviceClass == Phone)
|| (deviceClass == Tablet)
|| ((menu.options |> List.length) > 5)
then
AppBar.menuBar style.menuBar
{ title = title
, deviceClass = deviceClass
, openLeftSheet = Just <| onChangedSidebar <| Just LeftSheet
, openRightSheet =
if moreActions |> List.isEmpty then
Nothing
else
Just <| onChangedSidebar <| Just RightSheet
, openTopSheet = Just <| onChangedSidebar <| Just Search
, primaryActions = primaryActions
, search = search
}
else
AppBar.tabBar style.tabBar
{ title = title
, menu = menu
, deviceClass = deviceClass
, openRightSheet =
if moreActions |> List.isEmpty then
Nothing
else
Just <| onChangedSidebar <| Just RightSheet
, openTopSheet = Just <| onChangedSidebar <| Just Search
, primaryActions = primaryActions
, search = search
}
snackbar : Element msg
snackbar =
layout.snackbar
|> Snackbar.view style.snackbar identity
|> Maybe.map
(Element.el
[ Element.padding style.spacing
, Element.alignBottom
, Element.alignRight
]
)
|> Maybe.withDefault Element.none
onDismiss =
Nothing
|> onChangedSidebar
modals =
orderModals
{ dialog = dialog
, leftSheet =
if layout.active == Just LeftSheet then
leftSheet
{ button = style.sheetButton
, sheet = style.sheet
}
{ title = title
, menu = menu
, onDismiss = onDismiss
}
|> Just
else
Nothing
, rightSheet =
if layout.active == Just RightSheet then
rightSheet
{ sheet = style.sheet
, insetItem = style.insetItem
}
{ onDismiss = onDismiss
, moreActions = moreActions
}
|> Just
else
Nothing
, topSheet =
if layout.active == Just Search then
search
|> Maybe.map
(\textInput ->
searchSheet style.searchFill
{ search = textInput
, onDismiss = onDismiss
}
)
else
Nothing
, bottomSheet = Nothing
}
in
List.concat
[ style.container
, [ Element.inFront nav
, Element.inFront snackbar
]
, modals
|> Modal.singleModal
]
|> List.filterMap identity

View File

@ -8,7 +8,7 @@ module Widget.Material exposing
, alertDialog
, row, column
, menuBar, tabBar
, sideSheet
, sideSheet, bottomSheet
, fullBleedItem, insetItem, multiLineItem, imageItem, expansionItem, selectItem
, fullBleedDivider, insetDivider, middleDivider
, fullBleedHeader, insetHeader
@ -88,7 +88,7 @@ Thus for now we only provide a card containing a list.
# Sheet
@docs sideSheet
@docs sideSheet, bottomSheet
# Item
@ -161,7 +161,6 @@ import Internal.Material.Switch as Switch
import Internal.Material.Tab as Tab
import Internal.Material.TextInput as TextInput
import Internal.ProgressIndicator exposing (ProgressIndicatorStyle)
import Internal.Sheet exposing (SideSheetStyle)
import Internal.SortTable exposing (SortTableStyle)
import Internal.Switch exposing (SwitchStyle)
import Internal.Tab exposing (TabStyle)
@ -353,18 +352,6 @@ tabBar =
AppBar.tabBar
{-------------------------------------------------------------------------------
-- SHEET
-------------------------------------------------------------------------------}
sideSheet : Palette -> SideSheetStyle msg
sideSheet =
Sheet.sideSheet
{-------------------------------------------------------------------------------
-- L I S T
-------------------------------------------------------------------------------}
@ -383,6 +370,22 @@ column : ColumnStyle msg
column =
List.column
{-| A side sheet. Has a maximal width of 360.
-}
sideSheet : Palette -> ColumnStyle msg
sideSheet =
List.sideSheet
{-| A bottom sheet. Has a maximal width of 360.
Should be align to the bottom right corner of the screen.
-}
bottomSheet : Palette -> ColumnStyle msg
bottomSheet =
List.bottomSheet
--------------------------------------------------------------------------------
-- ITEM
--------------------------------------------------------------------------------
{-| A divider covering the full length
-}
@ -497,6 +500,7 @@ selectItem =
{-------------------------------------------------------------------------------
-- D I A L O G
-------------------------------------------------------------------------------}