diff --git a/example/src/Data/Style/ElmUiFramework.elm b/example/src/Data/Style/ElmUiFramework.elm index 0b74a43..6cb4486 100644 --- a/example/src/Data/Style/ElmUiFramework.elm +++ b/example/src/Data/Style/ElmUiFramework.elm @@ -195,6 +195,7 @@ dialog = , Element.width <| Element.minimum 280 <| Element.maximum 560 <| Element.fill ] , title = Heading.h3 + , text = [] , buttonRow = Grid.simple ++ [ Element.paddingEach diff --git a/example/src/Data/Style/Material.elm b/example/src/Data/Style/Material.elm index 4ce147c..5e27964 100644 --- a/example/src/Data/Style/Material.elm +++ b/example/src/Data/Style/Material.elm @@ -24,22 +24,56 @@ import Widget.Style ) import Widget.Style.Material as Material exposing (Palette) import Widget.Style.Template as Template +import Icons + +sortTable : Palette -> SortTableStyle msg +sortTable palette = + { containerTable = [] + , headerButton = Material.textButton palette + , ascIcon = Icons.chevronUp |> Element.html |> Element.el [] + , descIcon = Icons.chevronDown |> Element.html |> Element.el [] + , defaultIcon = Element.none + } + +layout : Palette -> String -> LayoutStyle msg +layout palette string = + { container = [Font.family + [ Font.typeface "Roboto" + , Font.sansSerif + ] + ,Font.size 16 + , Font.letterSpacing 0.5] + , snackbar = Material.snackbar palette + , layout = Element.layout + , header = Template.box <| string ++ ":header" + , menuButton = Template.button <| string ++ ":menuButton" + , sheetButton = Template.button <| string ++ ":sheetButton" + , menuTabButton = Template.button <| string ++ ":menuTabButton" + , sheet = Template.box <| string ++ ":sheet" + , menuIcon = Template.icon <| string ++ ":menuIcon" + , moreVerticalIcon = Template.icon <| string ++ ":moreVerticalIcon" + , spacing = 8 + , title = Template.box <| string ++ ":title" + , searchIcon = Template.icon <| string ++ ":searchIcon" + , search = Template.box <| string ++ ":search" + , searchFill = Template.box <| string ++ ":searchFill" + } style : Palette -> Style msg style palette = - { sortTable = Template.sortTable <| "sortTable" + { sortTable = sortTable palette , row = Material.row , buttonRow = Material.buttonRow - , cardColumn = Template.column <| "cardRow" - , column = Template.column <| "column" + , cardColumn = Material.cardColumn palette + , column = Material.column , button = Material.outlinedButton palette , primaryButton = Material.containedButton palette , selectButton = Material.toggleButton palette , tab = Template.tab <| "tab" - , textInput = Template.textInput <| "textInput" - , chipButton = Template.button <| "Button" - , expansionPanel = Template.expansionPanel "expansionPanel" - , dialog = Template.dialog <| "dialog" - , layout = Template.layout "layout" + , textInput = Material.textInput palette + , chipButton = Material.chip palette + , expansionPanel = Material.expansionPanel palette + , dialog = Material.alertDialog palette + , layout = layout palette "layout" } diff --git a/example/src/Example/Dialog.elm b/example/src/Example/Dialog.elm index 1d2a50e..2153615 100644 --- a/example/src/Example/Dialog.elm +++ b/example/src/Example/Dialog.elm @@ -62,11 +62,7 @@ view msgMapper style (IsOpen isOpen) = , Element.width <| Element.minimum 400 <| Element.fill ] ++ (if isOpen then - { body = - "This is a dialog window" - |> Element.text - |> List.singleton - |> Element.paragraph [] + { text = "This is a dialog window" , title = Just "Dialog" , accept = Just diff --git a/example/src/Main.elm b/example/src/Main.elm index 37e4f24..4edb930 100644 --- a/example/src/Main.elm +++ b/example/src/Main.elm @@ -132,11 +132,7 @@ view model = Layout.view style.layout { dialog = if m.displayDialog then - { body = - "This is a dialog window" - |> Element.text - |> List.singleton - |> Element.paragraph [] + { text = "This is a dialog window" , title = Just "Dialog" , accept = Just @@ -210,18 +206,6 @@ view model = , text = "Dark Material Theme" , icon = Icons.penTool |> Element.html |> Element.el [] } - , { onPress = Nothing - , text = "Placeholder" - , icon = Icons.circle |> Element.html |> Element.el [] - } - , { onPress = Nothing - , text = "Placeholder" - , icon = Icons.triangle |> Element.html |> Element.el [] - } - , { onPress = Nothing - , text = "Placeholder" - , icon = Icons.square |> Element.html |> Element.el [] - } ] , onChangedSidebar = ChangedSidebar , title = diff --git a/src/Internal/Dialog.elm b/src/Internal/Dialog.elm index 97a55eb..8470820 100644 --- a/src/Internal/Dialog.elm +++ b/src/Internal/Dialog.elm @@ -9,7 +9,7 @@ import Widget.Style exposing (DialogStyle) type alias Dialog msg = { title : Maybe String - , body : Element msg + , text : String , accept : Maybe (TextButton msg) , dismiss : Maybe (TextButton msg) } @@ -38,7 +38,7 @@ dialog : DialogStyle msg -> Dialog msg -> List (Attribute msg) -dialog style { title, body, accept, dismiss } = +dialog style { title, text, accept, dismiss } = { onDismiss = case ( accept, dismiss ) of ( Nothing, Nothing ) -> @@ -62,7 +62,10 @@ dialog style { title, body, accept, dismiss } = >> Element.el style.title ) |> Maybe.withDefault Element.none - , body + , text + |> Element.text + |> List.singleton + |> Element.paragraph style.text , Element.row ([ Element.alignRight , Element.width <| Element.shrink diff --git a/src/Internal/TextInput.elm b/src/Internal/TextInput.elm index 4d56f81..c4725f5 100644 --- a/src/Internal/TextInput.elm +++ b/src/Internal/TextInput.elm @@ -23,7 +23,11 @@ textInput style { chips, placeholder, label, text, onChange } = else chips - |> List.map (Button.button style.chipButton) + |> List.map + (Button.button style.chipButton + --Workaround for https://github.com/mdgriffith/elm-ui/issues/47 + >> Element.el [] + ) |> Element.row style.chipsRow , Input.text style.input { onChange = onChange diff --git a/src/Widget.elm b/src/Widget.elm index a2ff771..86ddaad 100644 --- a/src/Widget.elm +++ b/src/Widget.elm @@ -233,7 +233,7 @@ dialog : DialogStyle msg -> { title : Maybe String - , body : Element msg + , text : String , accept : Maybe (TextButton msg) , dismiss : Maybe (TextButton msg) } diff --git a/src/Widget/Style.elm b/src/Widget/Style.elm index 6a183c6..605f7ba 100644 --- a/src/Widget/Style.elm +++ b/src/Widget/Style.elm @@ -20,6 +20,7 @@ type alias DialogStyle msg = , buttonRow : List (Attribute msg) , acceptButton : ButtonStyle msg , dismissButton : ButtonStyle msg + , text : List (Attribute msg) } diff --git a/src/Widget/Style/Material.elm b/src/Widget/Style/Material.elm index 6fec9c5..7414537 100644 --- a/src/Widget/Style/Material.elm +++ b/src/Widget/Style/Material.elm @@ -1,6 +1,11 @@ module Widget.Style.Material exposing ( Palette, defaultPalette - , buttonRow, containedButton, darkPalette, outlinedButton, row, textButton, toggleButton + , containedButton, outlinedButton, textButton + , toggleButton, buttonRow + , alertDialog + , row, column, cardColumn + , expansionPanel + , chip, darkPalette, snackbar, textInput ) {-| @@ -18,19 +23,24 @@ module Widget.Style.Material exposing # Button -Material design comes with four types of buttons: +@docs containedButton, outlinedButton, textButton - - Contained buttons for **primary** actions - - Outlined buttons for **secondary** actions - - Text buttons for normal actions - - Toggle buttons for **selecting** an action out of a group +@docs toggleButton, buttonRow -![All four types next to eachother](https://lh3.googleusercontent.com/WTxHKH2jzRSMpsFtwfL-FzlD2wpmFSclAEEx5x55hOpn4IaVcXuYg7DWk6ruqww8WCi-FOItzwz88LTMuTF_15zBTHxU22VCzvebDg=w1064-v0) -_(Image taken from [material.io](https://material.io/components/buttons#usage))_ -| ![Use primary buttons for a single action](https://lh3.googleusercontent.com/O0Xmm8U4xZmXhpGjM1PZQi3K2HGGPhmurZV0Y-Fge-pWBMVIXeI2y_Pdgmsvc5k1pdW-MCsZw5wLPsIb4VEEW4_98RpJqSK_G3eyDg=w1064-v0) | ![Only use one primary button per group](https://lh3.googleusercontent.com/T9NXwqJ3_K_HZQm3_-Lhlp6O6E67OLmIpxC7239p6WLlCAxCa4s01lEgxyNz6uMdPdkpmiyu02RmvPCEfJRugyUuwkSyKuj-V9wupA=w1064-v0) | -| ![Secondary buttons can be used like primary buttons. You can have multiple secondary buttons per group](https://lh3.googleusercontent.com/fNDmzeeVxcH-QHf_EWBCYny1sxKv4qs91qheWWYYwRyd-IEWJut9UtjOSVdbEvQbUC_E-Yh9wTJ_GQG3aXc8HdVT-uVicCAv1meoIQ=w1064-v0) | ![Use select buttons for different options](https://lh3.googleusercontent.com/esmi4QrTD57XxgjEwlR4LP9DenkSUkTUJPJfVhtBtdmahh5xifRJfV_ItOQp5Fm2EVeVORhtZfRqFBmdNzg3cZyW7pkKTCjJOYAfUg=w1064-v0) | -_(Images taken from [material.io](https://material.io/components/buttons#usage))_ +# Dialog + +@docs alertDialog + + +# List + +@docs row, column, cardColumn + + +# Expansion Panel + +@docs expansionPanel -} @@ -42,6 +52,8 @@ import Element.Background as Background import Element.Border as Border import Element.Font as Font import Html.Attributes as Attributes +import Svg exposing (Svg) +import Svg.Attributes import Widget.Style exposing ( ButtonStyle @@ -57,6 +69,29 @@ import Widget.Style +{------------------------------------------------------------------------------- +-- T Y P O G R A P H Y +-------------------------------------------------------------------------------} + + +buttonFont : List (Attribute msg) +buttonFont = + [ Element.htmlAttribute <| Attributes.style "text-transform" "uppercase" + , Font.size 14 + , Font.semiBold --medium + , Font.letterSpacing 1.25 + ] + + +h6 : List (Attribute msg) +h6 = + [ Font.size 20 + , Font.semiBold --medium + , Font.letterSpacing 0.15 + ] + + + {------------------------------------------------------------------------------- -- C O L O R -------------------------------------------------------------------------------} @@ -139,13 +174,91 @@ buttonSelectedOpacity = accessibleTextColor : Color -> Color accessibleTextColor color = - if (1.05 / (Accessibility.luminance color + 0.05)) < 7 then + let + l : Float + l = + 1 + + (color |> Color.toRgba |> .alpha) + * (Accessibility.luminance color - 1) + in + if (1.05 / (l + 0.05)) < 7 then Color.rgb255 0 0 0 else Color.rgb255 255 255 255 +accessibleWithTextColor : Color -> Color -> Color +accessibleWithTextColor c color = + let + l1 : Float + l1 = + 1 + + (c |> Color.toRgba |> .alpha) + * (Accessibility.luminance c - 1) + + l2 : Float + l2 = + 1 + + (color |> Color.toRgba |> .alpha) + * (Accessibility.luminance color - 1) + + newConstrast : Float + newConstrast = + 7 + + lighterLuminance : Float + lighterLuminance = + newConstrast * (l2 + 0.05) - 0.05 + + darkerLuminance : Float + darkerLuminance = + (l2 + 0.05) - 0.05 / newConstrast + in + c + |> (if l1 > l2 then + if ((l1 + 0.05) / (l2 + 0.05)) < 7 then + Convert.colorToLab + >> (\col -> + { col | l = 100 * lighterLuminance } + ) + >> Convert.labToColor + + else + identity + + else if ((l2 + 0.05) / (l1 + 0.05)) < 7 then + Convert.colorToLab + >> (\col -> + { col | l = 100 * darkerLuminance } + ) + >> Convert.labToColor + + else + identity + ) + + +toCIELCH = + Convert.colorToLab + >> (\{ l, a, b } -> + { l = l + , c = sqrt (a * a + b * b) + , h = atan2 b a + } + ) + + +fromCIELCH = + (\{ l, c, h } -> + { l = l + , a = c * cos h + , b = c * sin h + } + ) + >> Convert.labToColor + + {-| using noahzgordon/elm-color-extra for colors -} withShade : Color -> Float -> Color -> Color @@ -156,24 +269,6 @@ withShade c2 amount c1 = |> Color.toRgba |> .alpha - toCIELCH = - Convert.colorToLab - >> (\{ l, a, b } -> - { l = l - , c = sqrt (a * a + b * b) - , h = atan2 b a - } - ) - - fromCIELCH = - (\{ l, c, h } -> - { l = l - , a = c * cos h - , b = c * sin h - } - ) - >> Convert.labToColor - fun a b = { l = (a.l * (1 - amount) + b.l * amount) / 1 , c = (a.c * (1 - amount) + b.c * amount) / 1 @@ -199,6 +294,11 @@ gray = Color.rgb255 0x77 0x77 0x77 +dark : Color +dark = + Color.rgb255 50 50 50 + + fromColor : Color -> Element.Color fromColor = Color.toRgba >> Element.fromRgb @@ -220,6 +320,18 @@ shadow float = } +textAndBackground : Color -> List (Element.Attr decorative msg) +textAndBackground color = + [ color + |> fromColor + |> Background.color + , color + |> accessibleTextColor + |> fromColor + |> Font.color + ] + + {------------------------------------------------------------------------------- -- B U T T O N @@ -229,14 +341,11 @@ shadow float = baseButton : Palette -> ButtonStyle msg baseButton _ = { container = - [ Element.height <| Element.px 36 - , Element.htmlAttribute <| Attributes.style "text-transform" "uppercase" - , Element.paddingXY 8 8 - , Border.rounded <| 4 - , Font.size 14 - , Font.medium - , Font.letterSpacing 1.25 - ] + buttonFont + ++ [ Element.height <| Element.px 36 + , Element.paddingXY 8 8 + , Border.rounded <| 4 + ] , labelRow = [ Element.spacing <| 8 , Element.width <| Element.minimum 32 <| Element.shrink @@ -256,42 +365,24 @@ containedButton palette = { container = (baseButton palette |> .container) ++ [ Border.shadow <| shadow 2 - , Element.mouseDown - [ palette.primary + , Element.mouseDown <| + (palette.primary |> withShade palette.on.primary buttonPressedOpacity - |> fromColor - |> Background.color - , palette.primary - |> withShade palette.on.primary buttonPressedOpacity - |> accessibleTextColor - |> fromColor - |> Font.color - , Border.shadow <| shadow 12 - ] - , Element.mouseOver - [ palette.primary - |> withShade palette.on.primary buttonHoverOpacity - |> fromColor - |> Background.color - , palette.primary - |> withShade palette.on.primary buttonHoverOpacity - |> accessibleTextColor - |> fromColor - |> Font.color - , Border.shadow <| shadow 6 - ] - , Element.focused - [ palette.primary + |> textAndBackground + ) + ++ [ Border.shadow <| shadow 12 ] + , Element.focused <| + (palette.primary |> withShade palette.on.primary buttonFocusOpacity - |> fromColor - |> Background.color - , palette.primary - |> withShade palette.on.primary buttonFocusOpacity - |> accessibleTextColor - |> fromColor - |> Font.color - , Border.shadow <| shadow 6 - ] + |> textAndBackground + ) + ++ [ Border.shadow <| shadow 6 ] + , Element.mouseOver <| + (palette.primary + |> withShade palette.on.primary buttonHoverOpacity + |> textAndBackground + ) + ++ [ Border.shadow <| shadow 6 ] ] , labelRow = (baseButton palette |> .labelRow) @@ -311,25 +402,12 @@ containedButton palette = , Element.focused [] ] , ifActive = - [ palette.primary + palette.primary |> withShade palette.on.primary buttonHoverOpacity - |> fromColor - |> Background.color - , palette.primary - |> withShade palette.on.primary buttonHoverOpacity - |> accessibleTextColor - |> fromColor - |> Font.color - ] + |> textAndBackground , otherwise = - [ palette.primary - |> fromColor - |> Background.color - , palette.primary - |> accessibleTextColor - |> fromColor - |> Font.color - ] + palette.primary + |> textAndBackground } @@ -350,16 +428,6 @@ outlinedButton palette = |> fromColor |> Border.color ] - , Element.mouseOver - [ palette.primary - |> scaleOpacity buttonHoverOpacity - |> fromColor - |> Background.color - , gray - |> withShade palette.primary buttonHoverOpacity - |> fromColor - |> Border.color - ] , Element.focused [ palette.primary |> scaleOpacity buttonFocusOpacity @@ -370,6 +438,16 @@ outlinedButton palette = |> fromColor |> Border.color ] + , Element.mouseOver + [ palette.primary + |> scaleOpacity buttonHoverOpacity + |> fromColor + |> Background.color + , gray + |> withShade palette.primary buttonHoverOpacity + |> fromColor + |> Border.color + ] ] , labelRow = (baseButton palette |> .labelRow) @@ -411,18 +489,18 @@ textButton palette = |> fromColor |> Background.color ] - , Element.mouseOver - [ palette.primary - |> scaleOpacity buttonHoverOpacity - |> fromColor - |> Background.color - ] , Element.focused [ palette.primary |> scaleOpacity buttonFocusOpacity |> fromColor |> Background.color ] + , Element.mouseOver + [ palette.primary + |> scaleOpacity buttonHoverOpacity + |> fromColor + |> Background.color + ] ] , labelRow = baseButton palette |> .labelRow , text = baseButton palette |> .text @@ -454,111 +532,164 @@ textButton palette = toggleButton : Palette -> ButtonStyle msg toggleButton palette = { container = - [ Element.width <| Element.px 48 - , Element.height <| Element.px 48 - , Element.padding 4 - , Element.htmlAttribute <| Attributes.style "text-transform" "uppercase" - , Border.width <| 1 - , Font.size 14 - , Font.medium - , Font.letterSpacing 1.25 - , Element.mouseDown - [ palette.surface - |> withShade palette.on.surface buttonPressedOpacity - |> fromColor - |> Background.color - , palette.surface - |> withShade palette.on.surface buttonPressedOpacity - |> accessibleTextColor - |> fromColor - |> Font.color - , palette.on.surface - |> scaleOpacity 0.14 - |> withShade palette.on.surface buttonPressedOpacity - |> fromColor - |> Border.color - ] - , Element.mouseOver - [ palette.surface - |> withShade palette.on.surface buttonHoverOpacity - |> fromColor - |> Background.color - , palette.surface - |> withShade palette.on.surface buttonHoverOpacity - |> accessibleTextColor - |> fromColor - |> Font.color - , palette.on.surface - |> scaleOpacity 0.14 - |> withShade palette.on.surface buttonHoverOpacity - |> fromColor - |> Border.color - ] - , Element.focused [] - ] + buttonFont + ++ [ Element.width <| Element.px 48 + , Element.height <| Element.px 48 + , Element.padding 4 + , Border.width <| 1 + , Element.mouseDown <| + (palette.surface + |> withShade palette.on.surface buttonPressedOpacity + |> textAndBackground + ) + ++ [ palette.on.surface + |> scaleOpacity 0.14 + |> withShade palette.on.surface buttonPressedOpacity + |> fromColor + |> Border.color + ] + , Element.focused [] + , Element.mouseOver <| + (palette.surface + |> withShade palette.on.surface buttonHoverOpacity + |> textAndBackground + ) + ++ [ palette.on.surface + |> scaleOpacity 0.14 + |> withShade palette.on.surface buttonHoverOpacity + |> fromColor + |> Border.color + ] + ] , labelRow = [ Element.spacing <| 8 , Element.height Element.fill , Element.width Element.fill , Border.rounded 24 , Element.padding 8 - , Element.focused - [ palette.surface + , Element.focused <| + (palette.surface |> withShade palette.on.surface buttonFocusOpacity - |> fromColor - |> Background.color - , palette.surface - |> withShade palette.on.surface buttonFocusOpacity - |> accessibleTextColor - |> fromColor - |> Font.color - ] + |> textAndBackground + ) ] , text = [ Element.centerX ] , ifDisabled = - [ palette.surface - |> fromColor - |> Background.color - , palette.on.surface - |> scaleOpacity 0.14 - |> fromColor - |> Border.color - , gray - |> fromColor - |> Font.color - , Element.mouseDown [] - , Element.mouseOver [] - ] + (baseButton palette |> .ifDisabled) + ++ [ palette.surface + |> fromColor + |> Background.color + , palette.on.surface + |> scaleOpacity 0.14 + |> fromColor + |> Border.color + , gray + |> fromColor + |> Font.color + , Element.mouseDown [] + , Element.mouseOver [] + ] , ifActive = - [ palette.surface + (palette.surface |> withShade palette.on.surface buttonSelectedOpacity - |> fromColor - |> Background.color - , palette.surface - |> withShade palette.on.surface buttonSelectedOpacity - |> accessibleTextColor - |> fromColor - |> Font.color - , palette.on.surface - |> scaleOpacity 0.14 - |> withShade palette.on.surface buttonSelectedOpacity - |> fromColor - |> Border.color - , Element.mouseOver [] - ] + |> textAndBackground + ) + ++ [ palette.on.surface + |> scaleOpacity 0.14 + |> withShade palette.on.surface buttonSelectedOpacity + |> fromColor + |> Border.color + , Element.mouseOver [] + ] , otherwise = - [ palette.surface - |> fromColor - |> Background.color - , palette.surface - |> accessibleTextColor - |> fromColor - |> Font.color - , palette.on.surface - |> scaleOpacity 0.14 - |> fromColor - |> Border.color + (palette.surface + |> textAndBackground + ) + ++ [ palette.on.surface + |> scaleOpacity 0.14 + |> fromColor + |> Border.color + ] + } + + + +{------------------------------------------------------------------------------- +-- C H I P +-------------------------------------------------------------------------------} + + +{-| Implementation Detail: + + - There seams to be a bug, where in the mouseOver effects are now visible. + This might have something to do with . + This needs to be investigated, but for now i leave it at that. + + - Desided against the implementation of an outlined chip. + Please open a new issue or a PR if you want to have it implemented. + +-} +chip : Palette -> ButtonStyle msg +chip palette = + { container = + [ Element.height <| Element.px 32 + , Element.paddingEach + { top = 0 + , right = 12 + , bottom = 0 + , left = 4 + } + , Border.rounded <| 16 + , Element.mouseDown <| + (palette.on.surface + |> scaleOpacity 0.12 + |> withShade palette.on.surface buttonPressedOpacity + |> textAndBackground + ) + , Element.focused <| + (palette.on.surface + |> scaleOpacity 0.12 + |> withShade palette.on.surface buttonFocusOpacity + |> textAndBackground + ) + , Element.mouseOver <| + (palette.on.surface + |> scaleOpacity 0.12 + |> withShade palette.on.surface buttonHoverOpacity + |> textAndBackground + ) ] + , labelRow = [ Element.spacing 0, Element.centerY ] + , text = + [ Element.paddingEach + { top = 0 + , right = 0 + , bottom = 0 + , left = 8 + } + ] + , ifDisabled = + (baseButton palette |> .ifDisabled) + ++ (palette.on.surface + |> scaleOpacity 0.12 + |> withShade palette.on.surface buttonDisabledOpacity + |> textAndBackground + ) + ++ [ Element.mouseDown [] + , Element.mouseOver [] + , Element.focused [] + ] + , ifActive = + (palette.on.surface + |> scaleOpacity 0.12 + |> withShade palette.on.surface buttonSelectedOpacity + |> textAndBackground + ) + ++ [ Border.shadow <| shadow 4 ] + , otherwise = + palette.on.surface + |> scaleOpacity 0.12 + |> textAndBackground } @@ -578,6 +709,16 @@ row = } +column : ColumnStyle msg +column = + { containerColumn = [ Element.spacing 8 ] + , element = [] + , ifFirst = [] + , ifLast = [] + , otherwise = [] + } + + buttonRow : RowStyle msg buttonRow = { containerRow = [] @@ -604,3 +745,268 @@ buttonRow = [ Border.rounded 0 ] } + + +{-| Implementation Detail: + +This is a simplification of the [Material Design Card +](https://material.io/components/cards) and might get replaced at a later date. + +-} +cardColumn : Palette -> ColumnStyle msg +cardColumn palette = + { containerColumn = + [ Element.width <| Element.fill + , Element.mouseOver <| + [ Border.shadow <| shadow 4 ] + , Element.alignTop + , Border.rounded 4 + ] + , element = + [ Element.padding 16 + , Border.rounded 4 + , Border.width 1 + , palette.surface + |> fromColor + |> Background.color + , palette.surface + |> accessibleTextColor + |> fromColor + |> Font.color + , palette.on.surface + |> scaleOpacity 0.14 + |> fromColor + |> Border.color + , Element.width <| Element.minimum 344 <| Element.fill + ] + , ifFirst = + [ Border.roundEach + { topLeft = 4 + , topRight = 4 + , bottomLeft = 0 + , bottomRight = 0 + } + ] + , ifLast = + [ Border.roundEach + { topLeft = 0 + , topRight = 0 + , bottomLeft = 4 + , bottomRight = 4 + } + , Border.widthEach + { top = 0 + , left = 1 + , right = 1 + , bottom = 1 + } + ] + , otherwise = + [ Border.rounded 0 + , Border.widthEach + { top = 0 + , left = 1 + , right = 1 + , bottom = 1 + } + ] + } + + + +{------------------------------------------------------------------------------- +-- D I A L O G +-------------------------------------------------------------------------------} + + +alertDialog : Palette -> DialogStyle msg +alertDialog palette = + { containerColumn = + [ Border.rounded 4 + , Element.fill + |> Element.maximum 560 + |> Element.minimum 280 + |> Element.width + , Element.height <| Element.minimum 182 <| Element.shrink + , Background.color <| fromColor <| palette.surface + ] + , title = h6 ++ [ Element.paddingXY 24 20 ] + , text = [ Element.paddingXY 24 0 ] + , buttonRow = + [ Element.paddingXY 8 8 + , Element.spacing 8 + , Element.alignRight + , Element.alignBottom + ] + , acceptButton = containedButton palette + , dismissButton = textButton palette + } + + + +{------------------------------------------------------------------------------- +-- E X P A N S I O N P A N E L +-------------------------------------------------------------------------------} + + +icon : String -> List (Svg Never) -> Element Never +icon size = + Svg.svg + [ Svg.Attributes.height "24" + , Svg.Attributes.stroke "currentColor" + , Svg.Attributes.fill "currentColor" + , Svg.Attributes.strokeLinecap "round" + , Svg.Attributes.strokeLinejoin "round" + , Svg.Attributes.strokeWidth "2" + , Svg.Attributes.viewBox size + , Svg.Attributes.width "24" + ] + >> Element.html + >> Element.el [] + + +expand_less : Element Never +expand_less = + icon "0 0 48 48" [ Svg.path [ Svg.Attributes.d "M24 16L12 28l2.83 2.83L24 21.66l9.17 9.17L36 28z" ] [] ] + + +expand_more : Element Never +expand_more = + icon "0 0 48 48" [ Svg.path [ Svg.Attributes.d "M33.17 17.17L24 26.34l-9.17-9.17L12 20l12 12 12-12z" ] [] ] + + +{-| Implementation Details: + + - The expansion panel is part of an [older version](https://material.io/archive/guidelines/components/expansion-panels.html) of the Material Design. + The newer version is part of the List component. + The styling is taken from the [new specification](https://material.io/components/lists#specs). + - The Icons are taken from [icidasset/elm-material-icons](https://dark.elm.dmy.fr/packages/icidasset/elm-material-icons/latest) but seem wrong. + +-} +expansionPanel : Palette -> ExpansionPanelStyle msg +expansionPanel palette = + { containerColumn = + [ Background.color <| fromColor <| palette.surface + , Element.width <| Element.fill + ] + , panelRow = + [ Element.height <| Element.px 48 + , Element.spaceEvenly + , Element.padding 14 + , Element.width <| Element.fill + ] + , labelRow = + [ Element.spacing 32 + ] + , content = + [ Element.padding 14 ] + , expandIcon = + expand_more + |> Element.el + [ gray + |> fromColor + |> Font.color + ] + , collapseIcon = + expand_less + |> Element.el + [ gray + |> fromColor + |> Font.color + ] + } + + + +{------------------------------------------------------------------------------- +-- S N A C K B A R +-------------------------------------------------------------------------------} + + +{-| Implementation Detail: + + - The text color of the button was not given in the specification. This implementation + adujsts the luminance of the color to fit the [w3 accessability standard](https://www.w3.org/TR/WCAG20/#Contrast) + +-} +snackbar : Palette -> SnackbarStyle msg +snackbar palette = + { containerRow = + [ dark + |> fromColor + |> Background.color + , dark + |> accessibleTextColor + |> fromColor + |> Font.color + , Border.rounded 4 + , Element.width <| Element.maximum 344 <| Element.fill + , Element.paddingXY 8 6 + , Element.spacing 8 + , Border.shadow <| shadow 2 + ] + , text = + [ Element.centerX + , Element.paddingXY 10 8 + ] + , button = + textButton palette + |> (\b -> + { b + | container = + b.container + ++ [ dark + |> accessibleWithTextColor palette.primary + |> fromColor + |> Font.color + ] + } + ) + } + + + +{------------------------------------------------------------------------------- +-- T E X T I N P U T +-------------------------------------------------------------------------------} + + +{-| Implementation Detail: + + - This is just a temporary implementation. It will soon be replaced with the official implementation. + +-} +textInput : Palette -> TextInputStyle msg +textInput palette = + { chipButton = chip palette + , chipsRow = [ Element.spacing 8 ] + , containerRow = + [ Element.spacing 8 + , Element.paddingXY 8 0 + , Border.width 1 + , Border.rounded 4 + , palette.on.surface + |> scaleOpacity 0.14 + |> fromColor + |> Border.color + , Element.focused + [ Border.shadow <| shadow 4 + , palette.primary + |> fromColor + |> Border.color + ] + , Element.mouseOver [ Border.shadow <| shadow 2 ] + ] + , input = + [ Border.width 0 + , Element.mouseOver [] + , Element.focused [] + ] + } + + + +{------------------------------------------------------------------------------- +-- L A Y O U T +-------------------------------------------------------------------------------} + diff --git a/src/Widget/Style/Template.elm b/src/Widget/Style/Template.elm index 2e303c2..18535aa 100644 --- a/src/Widget/Style/Template.elm +++ b/src/Widget/Style/Template.elm @@ -82,6 +82,7 @@ dialog : String -> DialogStyle msg dialog string = { containerColumn = box <| string ++ ":containerColumn" , title = box <| string ++ ":title" + , text = box <| string ++ ":text" , buttonRow = box <| string ++ ":buttonRow" , acceptButton = button <| string ++ ":acceptButton" , dismissButton = button <| string ++ ":dismissButton" @@ -150,18 +151,18 @@ sortTable string = layout : String -> LayoutStyle msg layout string = { container = box <| string ++ ":container" - , snackbar = snackbar <| string ++ "snackbar" + , snackbar = snackbar <| string ++ ":snackbar" , layout = Element.layout - , header = box <| string ++ "header" - , menuButton = button <| string ++ "menuButton" - , sheetButton = button <| string ++ "sheetButton" - , menuTabButton = button <| string ++ "menuTabButton" - , sheet = box <| string ++ "sheet" - , menuIcon = icon <| string ++ "menuIcon" - , moreVerticalIcon = icon <| string ++ "moreVerticalIcon" + , header = box <| string ++ ":header" + , menuButton = button <| string ++ ":menuButton" + , sheetButton = button <| string ++ ":sheetButton" + , menuTabButton = button <| string ++ ":menuTabButton" + , sheet = box <| string ++ ":sheet" + , menuIcon = icon <| string ++ ":menuIcon" + , moreVerticalIcon = icon <| string ++ ":moreVerticalIcon" , spacing = 8 - , title = box <| string ++ "title" - , searchIcon = icon <| string ++ "searchIcon" - , search = box <| string ++ "search" - , searchFill = box <| string ++ "searchFill" + , title = box <| string ++ ":title" + , searchIcon = icon <| string ++ ":searchIcon" + , search = box <| string ++ ":search" + , searchFill = box <| string ++ ":searchFill" }