Added TextInput, SortTable and Snackbar Pages

This commit is contained in:
Lucas Payr 2021-06-05 17:45:51 +02:00
parent 9a9126daa8
commit 07eae1e43f
8 changed files with 730 additions and 11 deletions

View File

@ -13,6 +13,7 @@
"elm/html": "1.0.0", "elm/html": "1.0.0",
"elm/json": "1.1.3", "elm/json": "1.1.3",
"elm/svg": "1.0.1", "elm/svg": "1.0.1",
"elm/time": "1.0.0",
"elm/url": "1.0.0", "elm/url": "1.0.0",
"elm-explorations/markdown": "1.0.0", "elm-explorations/markdown": "1.0.0",
"ianmackenzie/elm-units": "2.9.0", "ianmackenzie/elm-units": "2.9.0",
@ -26,7 +27,6 @@
}, },
"indirect": { "indirect": {
"elm/regex": "1.0.0", "elm/regex": "1.0.0",
"elm/time": "1.0.0",
"elm/virtual-dom": "1.0.2", "elm/virtual-dom": "1.0.2",
"fredcy/elm-parseint": "2.0.1" "fredcy/elm-parseint": "2.0.1"
} }

View File

@ -4,8 +4,11 @@ import Element
import Page.Button import Page.Button
import Page.PasswordInput import Page.PasswordInput
import Page.Select import Page.Select
import Page.Snackbar
import Page.SortTable
import Page.Switch import Page.Switch
import Page.Tab import Page.Tab
import Page.TextInput
import UIExplorer import UIExplorer
@ -15,6 +18,9 @@ pages =
|> UIExplorer.nextPage "Switch" Page.Switch.page |> UIExplorer.nextPage "Switch" Page.Switch.page
|> UIExplorer.nextPage "Tab" Page.Tab.page |> UIExplorer.nextPage "Tab" Page.Tab.page
|> UIExplorer.nextPage "Password Input" Page.PasswordInput.page |> UIExplorer.nextPage "Password Input" Page.PasswordInput.page
|> UIExplorer.nextPage "Text Input" Page.TextInput.page
|> UIExplorer.nextPage "Sort Table" Page.SortTable.page
|> UIExplorer.nextPage "Snackbar" Page.Snackbar.page
main = main =

View File

@ -1,4 +1,4 @@
module Page exposing (create, demo, viewTile) module Page exposing (create, create2, demo, viewTile)
import Element exposing (Element) import Element exposing (Element)
import UIExplorer exposing (Page) import UIExplorer exposing (Page)
@ -35,6 +35,29 @@ create config =
|> Tile.page |> Tile.page
create2 :
{ title : String
, description : String
, book1 : Group ( StorySelectorModel, () ) (TileMsg StorySelectorMsg ()) ()
, book2 : Group ( StorySelectorModel, () ) (TileMsg StorySelectorMsg ()) ()
, demo : Tile model msg ()
}
-> Page ( ( ( ( (), () ), ( StorySelectorModel, () ) ), ( StorySelectorModel, () ) ), model ) (TileMsg (TileMsg (TileMsg (TileMsg () msg1) (TileMsg StorySelectorMsg ())) (TileMsg StorySelectorMsg ())) msg) ()
create2 config =
Tile.static []
(\_ _ ->
[ config.title |> Element.text |> Element.el Typography.h3
, config.description |> Element.text |> List.singleton |> Element.paragraph []
]
|> Element.column [ Element.spacing 32 ]
)
|> Tile.first
|> Tile.nextGroup config.book1
|> Tile.nextGroup config.book2
|> Tile.next config.demo
|> Tile.page
viewTile : viewTile :
String String
-> Element msg -> Element msg

View File

@ -32,24 +32,24 @@ description =
-} -}
viewFunctions = viewFunctions =
let let
viewCurrentPassword text placeholder label { palette } () = viewCurrentPassword text placeholder label show { palette } () =
Widget.currentPasswordInput (Material.passwordInput palette) Widget.currentPasswordInput (Material.passwordInput palette)
{ text = text { text = text
, placeholder = placeholder , placeholder = placeholder
, label = label , label = label
, onChange = always () , onChange = always ()
, show = False , show = show
} }
--Don't forget to change the title --Don't forget to change the title
|> Page.viewTile "Widget.currentPasswordInput" |> Page.viewTile "Widget.currentPasswordInput"
viewNewPassword text placeholder label { palette } () = viewNewPassword text placeholder label show { palette } () =
Widget.newPasswordInput (Material.passwordInput palette) Widget.newPasswordInput (Material.passwordInput palette)
{ text = text { text = text
, placeholder = placeholder , placeholder = placeholder
, label = label , label = label
, onChange = always () , onChange = always ()
, show = False , show = show
} }
--Don't forget to change the title --Don't forget to change the title
|> Page.viewTile "Widget.newPasswordInput" |> Page.viewTile "Widget.newPasswordInput"
@ -80,6 +80,13 @@ book =
(Story.textStory "Label" (Story.textStory "Label"
"Password" "Password"
) )
|> Story.addStory
(Story.boolStory "Show"
( True
, False
)
True
)
|> Story.build |> Story.build
@ -127,7 +134,7 @@ subscriptions _ =
view : Context -> Model -> Element Msg view : Context -> Model -> Element Msg
view { palette } model = view { palette } model =
[ "Try fill out these fields using autofill" |> Element.text [ "Try filling out these fields using autofill" |> Element.text
, [ "Current Password" , [ "Current Password"
|> Element.text |> Element.text
|> Element.el [ Element.width <| Element.fill ] |> Element.el [ Element.width <| Element.fill ]

View File

@ -0,0 +1,223 @@
module Page.Snackbar exposing (page)
{-| This is an example Page. If you want to add your own pages, simple copy and modify this one.
-}
import Browser
import Element exposing (Element)
import Element.Background as Background
import Material.Icons as MaterialIcons
import Material.Icons.Types exposing (Coloring(..))
import Page
import Time
import UIExplorer.Story as Story exposing (StorySelectorModel, StorySelectorMsg)
import UIExplorer.Tile as Tile exposing (Context, Tile, TileMsg)
import Widget exposing (ButtonStyle, ColumnStyle)
import Widget.Customize as Customize
import Widget.Icon as Icon
import Widget.Material as Material
import Widget.Material.Color as MaterialColor
import Widget.Material.Typography as Typography
import Widget.Snackbar as Snackbar exposing (Snackbar, SnackbarStyle)
{-| The title of this page
-}
title : String
title =
"Button"
{-| The description. I've taken this description directly from the [Material-UI-Specification](https://material.io/components/buttons)
-}
description : String
description =
"Buttons allow users to take actions, and make choices, with a single tap."
{-| List of view functions. Essentially, anything that takes a Button as input.
-}
viewFunctions =
let
viewSnackbar style text button { palette } () =
Snackbar.view (style palette)
identity
(Snackbar.init
|> Snackbar.insert
{ text = text
, button = button
}
)
|> Maybe.withDefault Element.none
--Don't forget to change the title
|> Page.viewTile "Snackbar.view"
in
[ viewSnackbar ]
|> List.foldl Story.addTile
Story.initStaticTiles
{-| Let's you play around with the options.
Note that the order of these stories must follow the order of the arguments from the view functions.
-}
book : Tile.Group ( StorySelectorModel, () ) (TileMsg StorySelectorMsg ()) ()
book =
Story.book (Just "Options")
viewFunctions
--Adding a option for different styles.
|> Story.addStory
(Story.optionListStory "Style"
( "Snackbar", Material.snackbar )
[]
)
--Changing the text of the label
|> Story.addStory
(Story.textStory "Text"
"This is a notification that will close after 10 seconds. Additional notifications are being queued."
)
--Change the Icon
|> Story.addStory
(Story.optionListStory "Button"
( "Button with event handler"
, Just
{ text = "Close"
, onPress = Just ()
}
)
[ ( "Eventless Button"
, Just
{ text = "Close"
, onPress = Nothing
}
)
, ( "None"
, Nothing
)
]
)
|> Story.build
{- This next section is essentially just a normal Elm program. -}
--------------------------------------------------------------------------------
-- Interactive Demonstration
--------------------------------------------------------------------------------
type alias Model =
Snackbar ( String, Bool )
type Msg
= AddSnackbar ( String, Bool )
| TimePassed Int
init : ( Model, Cmd Msg )
init =
( Snackbar.init
, Cmd.none
)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
TimePassed int ->
( model |> Snackbar.timePassed int
, Cmd.none
)
AddSnackbar snack ->
( model |> Snackbar.dismiss |> Snackbar.insert snack
, Cmd.none
)
subscriptions : Model -> Sub Msg
subscriptions _ =
Time.every 50 (always (TimePassed 50))
{-| You can remove the msgMapper. But by doing so, make sure to also change `msg` to `Msg` in the line below.
-}
view : Context -> Model -> Element Msg
view { palette } model =
[ Widget.button (Material.containedButton palette)
{ onPress =
Just <|
AddSnackbar <|
( "This is a notification. It will disappear after 10 seconds."
, False
)
, text = "Add Notification"
, icon = always Element.none
}
, Widget.button (Material.containedButton palette)
{ onPress =
Just <|
AddSnackbar <|
( "You can add another notification if you want."
, True
)
, text = "Add Notification with Action"
, icon = always Element.none
}
]
|> Widget.column Material.column
|> Element.el
[ Element.height <| Element.minimum 200 <| Element.fill
, Element.width <| Element.minimum 400 <| Element.fill
, Element.inFront <|
(model
|> Snackbar.view (Material.snackbar palette)
(\( text, hasButton ) ->
{ text = text
, button =
if hasButton then
Just
{ text = "Add"
, onPress =
Just <|
AddSnackbar ( "This is another message", False )
}
else
Nothing
}
)
|> Maybe.map
(Element.el
[ Element.padding 8
, Element.alignBottom
, Element.alignRight
]
)
|> Maybe.withDefault Element.none
)
]
--------------------------------------------------------------------------------
-- DO NOT MODIFY ANYTHING AFTER THIS LINE
--------------------------------------------------------------------------------
demo : Tile Model Msg ()
demo =
{ init = always init
, update = update
, view = Page.demo view
, subscriptions = subscriptions
}
page =
Page.create
{ title = title
, description = description
, book = book
, demo = demo
}

View File

@ -0,0 +1,250 @@
module Page.SortTable exposing (page)
{-| This is an example Page. If you want to add your own pages, simple copy and modify this one.
-}
import Browser
import Element exposing (Element)
import Element.Background as Background
import Material.Icons as MaterialIcons
import Material.Icons.Types exposing (Coloring(..))
import Page
import UIExplorer.Story as Story exposing (StorySelectorModel, StorySelectorMsg)
import UIExplorer.Tile as Tile exposing (Context, Tile, TileMsg)
import Widget exposing (SortTableStyle)
import Widget.Customize as Customize
import Widget.Icon as Icon
import Widget.Material as Material
import Widget.Material.Color as MaterialColor
import Widget.Material.Typography as Typography
{-| The title of this page
-}
title : String
title =
"Sort Table"
{-| The description. I've taken this description directly from the [Material-UI-Specification](https://material.io/components/buttons)
-}
description : String
description =
"A simple sort table."
{-| List of view functions. Essentially, anything that takes a Button as input.
-}
viewFunctions =
let
viewTable style content columns asc sortBy { palette } () =
Widget.sortTable (style palette)
{ content = content
, columns = columns
, asc = asc
, sortBy = sortBy
, onChange = always ()
}
--Don't forget to change the title
|> Page.viewTile "Widget.sortTable"
in
[ viewTable ]
|> List.foldl Story.addTile
Story.initStaticTiles
{-| Let's you play around with the options.
Note that the order of these stories must follow the order of the arguments from the view functions.
-}
book : Tile.Group ( StorySelectorModel, () ) (TileMsg StorySelectorMsg ()) ()
book =
Story.book (Just "Options")
viewFunctions
--Adding a option for different styles.
|> Story.addStory
(Story.optionListStory "Style"
( "SortTable", Material.sortTable )
[]
)
|> Story.addStory
(Story.optionListStory "Content"
( "Data"
, [ { id = 1, name = "Antonio", rating = 2.456, hash = Nothing }
, { id = 2, name = "Ana", rating = 1.34, hash = Just "45jf" }
, { id = 3, name = "Alfred", rating = 4.22, hash = Just "6fs1" }
, { id = 4, name = "Thomas", rating = 3, hash = Just "k52f" }
]
)
[ ( "None", [] )
]
)
--Changing the text of the label
|> Story.addStory
(Story.optionListStory "Columns"
( "4 Columns"
, [ Widget.intColumn
{ title = "Id"
, value = .id
, toString = \int -> "#" ++ String.fromInt int
, width = Element.fill
}
, Widget.stringColumn
{ title = "Name"
, value = .name
, toString = identity
, width = Element.fill
}
, Widget.floatColumn
{ title = "Rating"
, value = .rating
, toString = String.fromFloat
, width = Element.fill
}
, Widget.unsortableColumn
{ title = "Hash"
, toString = .hash >> Maybe.withDefault "None"
, width = Element.fill
}
]
)
[ ( "1 Column"
, [ Widget.intColumn
{ title = "Id"
, value = .id
, toString = \int -> "#" ++ String.fromInt int
, width = Element.fill
}
]
)
, ( "None", [] )
]
)
--Change the Icon
|> Story.addStory
(Story.boolStory "Sort ascendingly"
( True
, False
)
True
)
|> Story.addStory
(Story.optionListStory "Sort by"
( "Id", "Id" )
[ ( "Name", "Name" )
, ( "Rating", "Rating" )
, ( "Hash", "Hash" )
, ( "None", "" )
]
)
|> Story.build
{- This next section is essentially just a normal Elm program. -}
--------------------------------------------------------------------------------
-- Interactive Demonstration
--------------------------------------------------------------------------------
type alias Model =
{ title : String
, asc : Bool
}
type Msg
= ChangedSorting String
init : ( Model, Cmd Msg )
init =
( { title = "Name", asc = True }
, Cmd.none
)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ChangedSorting string ->
( { title = string
, asc =
if model.title == string then
not model.asc
else
True
}
, Cmd.none
)
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
{-| You can remove the msgMapper. But by doing so, make sure to also change `msg` to `Msg` in the line below.
-}
view : Context -> Model -> Element Msg
view { palette } model =
Widget.sortTable (Material.sortTable palette)
{ content =
[ { id = 1, name = "Antonio", rating = 2.456, hash = Nothing }
, { id = 2, name = "Ana", rating = 1.34, hash = Just "45jf" }
, { id = 3, name = "Alfred", rating = 4.22, hash = Just "6fs1" }
, { id = 4, name = "Thomas", rating = 3, hash = Just "k52f" }
]
, columns =
[ Widget.intColumn
{ title = "Id"
, value = .id
, toString = \int -> "#" ++ String.fromInt int
, width = Element.fill
}
, Widget.stringColumn
{ title = "Name"
, value = .name
, toString = identity
, width = Element.fill
}
, Widget.floatColumn
{ title = "Rating"
, value = .rating
, toString = String.fromFloat
, width = Element.fill
}
, Widget.unsortableColumn
{ title = "Hash"
, toString = .hash >> Maybe.withDefault "None"
, width = Element.fill
}
]
, asc = model.asc
, sortBy = model.title
, onChange = ChangedSorting
}
--------------------------------------------------------------------------------
-- DO NOT MODIFY ANYTHING AFTER THIS LINE
--------------------------------------------------------------------------------
demo : Tile Model Msg ()
demo =
{ init = always init
, update = update
, view = Page.demo view
, subscriptions = subscriptions
}
page =
Page.create
{ title = title
, description = description
, book = book
, demo = demo
}

View File

@ -0,0 +1,214 @@
module Page.TextInput exposing (Model, Msg, init, page, subscriptions, update, view)
import Element exposing (Element)
import Element.Input as Input
import Material.Icons as MaterialIcons
import Material.Icons.Types exposing (Coloring(..))
import Page
import Set exposing (Set)
import UIExplorer.Story as Story
import UIExplorer.Tile exposing (Context, Tile)
import Widget
import Widget.Icon as Icon exposing (Icon)
import Widget.Material as Material
exposing
( darkPalette
, defaultPalette
)
{-| The title of this page
-}
title : String
title =
"Text Input"
{-| The description. I've taken this description directly from the [Material-UI-Specification](https://material.io/components/buttons)
-}
description : String
description =
"Text fields let users enter and edit text."
{-| List of view functions. Essentially, anything that takes a Button as input.
-}
viewFunctions =
let
viewInput chips text placeholder label { palette } () =
Widget.textInput (Material.textInput palette)
{ chips = chips
, text = text
, placeholder = placeholder
, label = label
, onChange = always ()
}
--Don't forget to change the title
|> Page.viewTile "Widget.currentPasswordInput"
in
[ viewInput ]
|> List.foldl Story.addTile
Story.initStaticTiles
book =
Story.book (Just "Options")
viewFunctions
|> Story.addStory
(Story.optionListStory "Chips"
( "3 Chips"
, [ { icon = always Element.none, text = "Apples", onPress = Nothing }
, { icon = MaterialIcons.done |> Icon.elmMaterialIcons Color, text = "", onPress = Just () }
, { icon = MaterialIcons.done |> Icon.elmMaterialIcons Color, text = "Oranges", onPress = Just () }
]
)
[ ( "2 Chips"
, [ { icon = always Element.none, text = "Apples", onPress = Nothing }
, { icon = MaterialIcons.done |> Icon.elmMaterialIcons Color, text = "", onPress = Just () }
]
)
, ( "1 Chips"
, [ { icon = always Element.none, text = "Apples", onPress = Nothing } ]
)
, ( "None", [] )
]
)
|> Story.addStory
(Story.textStory "Text"
"123456789"
)
|> Story.addStory
(Story.boolStory "Placeholder"
( "password"
|> Element.text
|> Input.placeholder []
|> Just
, Nothing
)
True
)
|> Story.addStory
(Story.textStory "Label"
"Name"
)
|> Story.build
---{- This next section is essentially just a normal Elm program. -}
-----------------------------------------------------------------------------
-- Interactive Demonstration
--------------------------------------------------------------------------------
type alias Model =
{ chipTextInput : Set String
, textInput : String
}
type Msg
= ToggleTextInputChip String
| SetTextInput String
init : ( Model, Cmd Msg )
init =
( { chipTextInput = Set.empty
, textInput = ""
}
, Cmd.none
)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ToggleTextInputChip string ->
( { model
| chipTextInput =
model.chipTextInput
|> (if model.chipTextInput |> Set.member string then
Set.remove string
else
Set.insert string
)
}
, Cmd.none
)
SetTextInput string ->
( { model | textInput = string }, Cmd.none )
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
view : Context -> Model -> Element Msg
view { palette } model =
[ { chips =
model.chipTextInput
|> Set.toList
|> List.map
(\string ->
{ icon = always Element.none
, text = string
, onPress =
string
|> ToggleTextInputChip
|> Just
}
)
, text = model.textInput
, placeholder = Nothing
, label = "Chips"
, onChange = SetTextInput
}
|> Widget.textInput (Material.textInput palette)
, model.chipTextInput
|> Set.diff
([ "A", "B", "C" ]
|> Set.fromList
)
|> Set.toList
|> List.map
(\string ->
Widget.button (Material.textInput palette).content.chips.content
{ onPress =
string
|> ToggleTextInputChip
|> Just
, text = string
, icon = always Element.none
}
)
|> Element.wrappedRow [ Element.spacing 10 ]
]
|> Widget.column Material.column
--------------------------------------------------------------------------------
-- DO NOT MODIFY ANYTHING AFTER THIS LINE
--------------------------------------------------------------------------------
demo : Tile Model Msg ()
demo =
{ init = always init
, update = update
, view = Page.demo view
, subscriptions = subscriptions
}
page =
Page.create
{ title = title
, description = description
, book = book
, demo = demo
}

View File

@ -864,8 +864,6 @@ viewSidebar pages config model =
|> Widget.itemList (Material.sideSheet palette) |> Widget.itemList (Material.sideSheet palette)
colorblindnessCss : Html msg colorblindnessCss : Html msg
colorblindnessCss = colorblindnessCss =
Html.node "style" Html.node "style"
@ -1118,8 +1116,6 @@ optionGroupView dark isExpanded selectedItem items itemToString onPress toggleEx
} }
showSearchResults : String -> Bool showSearchResults : String -> Bool
showSearchResults searchText = showSearchResults searchText =
String.length searchText > 1 String.length searchText > 1