Merge branch 'master' into tessa/add-svg-button

This commit is contained in:
Stoeffel 2020-03-02 11:46:59 +01:00
commit 03d99a583d
200 changed files with 1624 additions and 199 deletions

2
.gitattributes vendored
View File

@ -1 +1 @@
styleguide-app/assets/images/** filter=lfs diff=lfs merge=lfs -text
lib/noredink-ui/styleguide-app/assets/images/** filter=lfs diff=lfs merge=lfs -text

View File

@ -19,6 +19,7 @@ before_install:
make && make install;
cd ..;
fi
cd lib/noredink-ui
install:
- travis_retry $TRAVIS_BUILD_DIR/sysconfcpus/bin/sysconfcpus -n 2 make -B setup

View File

@ -3,7 +3,7 @@
"name": "NoRedInk/noredink-ui",
"summary": "UI Widgets we use at NRI",
"license": "BSD-3-Clause",
"version": "7.17.0",
"version": "7.21.0",
"exposed-modules": [
"Nri.Ui",
"Nri.Ui.Accordion.V1",
@ -24,6 +24,7 @@
"Nri.Ui.Button.V7",
"Nri.Ui.Button.V8",
"Nri.Ui.Button.V9",
"Nri.Ui.Button.V10",
"Nri.Ui.Callout.V1",
"Nri.Ui.Checkbox.V3",
"Nri.Ui.Checkbox.V4",
@ -73,6 +74,7 @@
"Nri.Ui.SegmentedControl.V8",
"Nri.Ui.Select.V5",
"Nri.Ui.Select.V6",
"Nri.Ui.Select.V7",
"Nri.Ui.Slide.V1",
"Nri.Ui.SlideModal.V1",
"Nri.Ui.SlideModal.V2",

View File

@ -4,6 +4,11 @@ module Nri.Ui.BannerAlert.V6 exposing (alert, error, neutral, success)
@docs alert, error, neutral, success
# Post-release patches
- adjusts link styles
Changes from V5:
- takes HTML rather than BannerContent
@ -341,5 +346,14 @@ notification =
, Css.lineHeight (Css.px 27)
, Css.maxWidth (Css.px 600)
, Nri.Ui.Fonts.V1.baseFont
, Css.Global.descendants
[ Css.Global.a
[ Css.textDecoration Css.none
, Css.color Colors.azure
, Css.borderBottom3 (Css.px 1) Css.solid Colors.azure
, Css.visited
[ Css.color Colors.azure ]
]
]
]
[]

View File

@ -0,0 +1,967 @@
module Nri.Ui.Button.V10 exposing
( button, link
, Attribute
, icon, custom, css
, onClick
, href, linkSpa, linkExternal, linkWithMethod, linkWithTracking, linkExternalWithTracking
, small, medium, large
, exactWidth, unboundedWidth, fillContainerWidth
, primary, secondary, danger, premium
, enabled, unfulfilled, disabled, error, loading, success
, delete
, toggleButton
)
{-|
# Changes from V9:
- Explicitly zeroes out all margin
- adds `css` helper
# Create a button or link
@docs button, link
@docs Attribute
@docs icon, custom, css
## Behavior
@docs onClick
@docs href, linkSpa, linkExternal, linkWithMethod, linkWithTracking, linkExternalWithTracking
## Sizing
@docs small, medium, large
@docs exactWidth, unboundedWidth, fillContainerWidth
## Change the color scheme
@docs primary, secondary, danger, premium
## Change the state (buttons only)
@docs enabled, unfulfilled, disabled, error, loading, success
# Commonly-used buttons
@docs delete
@docs toggleButton
-}
import Accessibility.Styled as Html exposing (Html)
import Accessibility.Styled.Role as Role
import Accessibility.Styled.Widget as Widget
import AttributeExtras exposing (targetBlank)
import Css exposing (Style)
import Css.Global
import EventExtras.Styled as EventExtras
import Html.Styled as Styled
import Html.Styled.Attributes as Attributes
import Html.Styled.Events as Events
import Json.Decode
import Markdown.Block
import Markdown.Inline
import Nri.Ui
import Nri.Ui.AssetPath as AssetPath exposing (Asset)
import Nri.Ui.Colors.Extra as ColorsExtra
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Fonts.V1
import Nri.Ui.Html.Attributes.V2 as AttributesExtra
import Nri.Ui.Svg.V1 as NriSvg exposing (Svg)
import Svg
import Svg.Attributes
styledName : String -> String
styledName suffix =
"Nri-Ui-Button-V10-" ++ suffix
{-|
Button.button "My great button!"
[ Button.onClick ()
, Button.enabled
]
By default, the button is enabled, Medium sized, with primary colors, and an unbounded width.
-}
button : String -> List (Attribute msg) -> Html msg
button name attributes =
(label name :: attributes)
|> List.foldl (\(Attribute attribute) b -> attribute b) build
|> renderButton
{-|
Button.link "My great link!"
[ Button.href "My href"
, Button.secondary
]
By default, the link is Medium sized, with primary colors, and an unbounded width.
-}
link : String -> List (Attribute msg) -> Html msg
link name attributes =
(label name :: attributes)
|> List.foldl (\(Attribute attribute) l -> attribute l) build
|> renderLink
{-| -}
label : String -> Attribute msg
label label_ =
set (\attributes -> { attributes | label = label_ })
{-| -}
icon : Svg -> Attribute msg
icon icon_ =
set (\attributes -> { attributes | icon = Just icon_ })
{-| Use this helper to add custom attributes.
Do NOT use this helper to add css styles, as they may not be applied the way
you want/expect if underlying Button styles change.
Instead, please use the `css` helper.
-}
custom : List (Html.Attribute msg) -> Attribute msg
custom attributes =
set
(\config ->
{ config
| customAttributes = List.append config.customAttributes attributes
}
)
{-| -}
css : List Style -> Attribute msg
css styles =
set
(\config ->
{ config
| customStyles = List.append config.customStyles styles
}
)
-- LINKING, CLICKING, and TRACKING BEHAVIOR
{-| -}
onClick : msg -> Attribute msg
onClick msg =
set (\attributes -> { attributes | onClick = Just msg })
type Link
= Default
| WithTracking
| SinglePageApp
| WithMethod String
| External
| ExternalWithTracking
{-| -}
href : String -> Attribute msg
href url =
set (\attributes -> { attributes | url = url })
{-| Use this link for routing within a single page app.
This will make a normal <a> tag, but change the Events.onClick behavior to avoid reloading the page.
See <https://github.com/elm-lang/html/issues/110> for details on this implementation.
-}
linkSpa : String -> Attribute msg
linkSpa url =
set
(\attributes ->
{ attributes
| linkType = SinglePageApp
, url = url
}
)
{-| Wrap some text so it looks like a button, but actually is wrapped in an anchor to
some url, and it's an HTTP request (Rails includes JS to make this use the given HTTP method)
-}
linkWithMethod : { method : String, url : String } -> Attribute msg
linkWithMethod { method, url } =
set
(\attributes ->
{ attributes
| linkType = WithMethod method
, url = url
}
)
{-| Wrap some text so it looks like a button, but actually is wrapped in an anchor to some url.
This should only take in messages that result in a Msg that triggers Analytics.trackAndRedirect.
For buttons that trigger other effects on the page, please use Nri.Button.button instead.
-}
linkWithTracking : { track : msg, url : String } -> Attribute msg
linkWithTracking { track, url } =
set
(\attributes ->
{ attributes
| linkType = WithTracking
, url = url
, onClick = Just track
}
)
{-| Wrap some text so it looks like a button, but actually is wrapped in an anchor to
some url and have it open to an external site
-}
linkExternal : String -> Attribute msg
linkExternal url =
set
(\attributes ->
{ attributes
| linkType = External
, url = url
}
)
{-| Wrap some text so it looks like a button, but actually is wrapped in an anchor to some url and have it open to an external site.
-}
linkExternalWithTracking : { track : msg, url : String } -> Attribute msg
linkExternalWithTracking { track, url } =
set
(\attributes ->
{ attributes
| linkType = ExternalWithTracking
, url = url
, onClick = Just track
}
)
-- BUTTON SIZING
{-| -}
small : Attribute msg
small =
set (\attributes -> { attributes | size = Small })
{-| -}
medium : Attribute msg
medium =
set (\attributes -> { attributes | size = Medium })
{-| -}
large : Attribute msg
large =
set (\attributes -> { attributes | size = Large })
-- BUTTON WIDTH
type ButtonWidth
= WidthExact Int
| WidthUnbounded
| WidthFillContainer
{-| Sizes for buttons and links that have button classes
-}
type ButtonSize
= Small
| Medium
| Large
{-| Define a size in `px` for the button's total width.
-}
exactWidth : Int -> Attribute msg
exactWidth inPx =
set (\attributes -> { attributes | width = WidthExact inPx })
{-| Leave the maxiumum width unbounded (there is a minimum width).
-}
unboundedWidth : Attribute msg
unboundedWidth =
set (\attributes -> { attributes | width = WidthUnbounded })
{-| -}
fillContainerWidth : Attribute msg
fillContainerWidth =
set (\attributes -> { attributes | width = WidthFillContainer })
-- COLOR SCHEMES
{-| -}
primary : Attribute msg
primary =
set
(\attributes ->
{ attributes | style = primaryColors }
)
{-| -}
secondary : Attribute msg
secondary =
set
(\attributes ->
{ attributes | style = secondaryColors }
)
{-| -}
danger : Attribute msg
danger =
set
(\attributes ->
{ attributes
| style =
{ background = Colors.red
, hover = Colors.redDark
, text = Colors.white
, border = Nothing
, shadow = Colors.redDark
}
}
)
{-| -}
premium : Attribute msg
premium =
set
(\attributes ->
{ attributes
| style =
{ background = Colors.yellow
, hover = Colors.ochre
, text = Colors.navy
, border = Nothing
, shadow = Colors.ochre
}
}
)
-- BUTTON STATE
type ButtonState
= Enabled
| Unfulfilled
| Disabled
| Error
| Loading
| Success
{-| -}
enabled : Attribute msg
enabled =
set (\attributes -> { attributes | state = Enabled })
{-| Shows inactive styles.
-}
unfulfilled : Attribute msg
unfulfilled =
set (\attributes -> { attributes | state = Unfulfilled })
{-| Shows inactive styling. If a button, this attribute will disable it.
-}
disabled : Attribute msg
disabled =
set (\attributes -> { attributes | state = Disabled })
{-| Shows error styling. If a button, this attribute will disable it.
-}
error : Attribute msg
error =
set (\attributes -> { attributes | state = Error })
{-| Shows loading styling. If a button, this attribute will disable it.
-}
loading : Attribute msg
loading =
set (\attributes -> { attributes | state = Loading })
{-| Shows success styling. If a button, this attribute will disable it.
-}
success : Attribute msg
success =
set (\attributes -> { attributes | state = Success })
{-| -}
type Attribute msg
= Attribute (ButtonOrLink msg -> ButtonOrLink msg)
-- INTERNALS
set :
(ButtonOrLinkAttributes msg -> ButtonOrLinkAttributes msg)
-> Attribute msg
set with =
Attribute (\(ButtonOrLink config) -> ButtonOrLink (with config))
build : ButtonOrLink msg
build =
ButtonOrLink
{ onClick = Nothing
, url = "#"
, linkType = Default
, size = Medium
, style = primaryColors
, width = WidthUnbounded
, label = ""
, state = Enabled
, icon = Nothing
, customAttributes = []
, customStyles = []
}
type ButtonOrLink msg
= ButtonOrLink (ButtonOrLinkAttributes msg)
type alias ButtonOrLinkAttributes msg =
{ onClick : Maybe msg
, url : String
, linkType : Link
, size : ButtonSize
, style : ColorPalette
, width : ButtonWidth
, label : String
, state : ButtonState
, icon : Maybe Svg
, customAttributes : List (Html.Attribute msg)
, customStyles : List Style
}
renderButton : ButtonOrLink msg -> Html msg
renderButton ((ButtonOrLink config) as button_) =
let
buttonStyle_ =
getColorPalette button_
isDisabled =
case config.state of
Enabled ->
False
Disabled ->
True
Error ->
True
Unfulfilled ->
False
Loading ->
True
Success ->
True
in
Nri.Ui.styled Html.button
(styledName "customButton")
[ buttonStyles config.size config.width buttonStyle_ config.customStyles ]
((Maybe.map Events.onClick config.onClick
|> Maybe.withDefault AttributesExtra.none
)
:: Attributes.disabled isDisabled
:: Attributes.type_ "button"
:: config.customAttributes
)
[ viewLabel config.icon config.label ]
renderLink : ButtonOrLink msg -> Html msg
renderLink ((ButtonOrLink config) as link_) =
let
colorPalette =
getColorPalette link_
linkBase linkFunctionName extraAttrs =
Nri.Ui.styled Styled.a
(styledName linkFunctionName)
[ buttonStyles config.size config.width colorPalette config.customStyles ]
(Attributes.href config.url :: extraAttrs)
[ viewLabel config.icon config.label ]
in
case config.linkType of
Default ->
linkBase "link"
(Attributes.target "_self" :: config.customAttributes)
SinglePageApp ->
linkBase "linkSpa"
((Maybe.map EventExtras.onClickPreventDefaultForLinkWithHref config.onClick
|> Maybe.withDefault AttributesExtra.none
)
:: config.customAttributes
)
WithMethod method ->
linkBase "linkWithMethod"
(Attributes.attribute "data-method" method
:: config.customAttributes
)
WithTracking ->
linkBase
"linkWithTracking"
((Maybe.map
(\msg ->
Events.preventDefaultOn "click"
(Json.Decode.succeed ( msg, True ))
)
config.onClick
|> Maybe.withDefault AttributesExtra.none
)
:: config.customAttributes
)
External ->
linkBase "linkExternal"
(targetBlank ++ config.customAttributes)
ExternalWithTracking ->
linkBase "linkExternalWithTracking"
(List.concat
[ targetBlank
, config.onClick
|> Maybe.map
(\onClickMsg ->
[ Events.onClick onClickMsg
, Events.on "auxclick" (Json.Decode.succeed onClickMsg)
]
)
|> Maybe.withDefault []
, config.customAttributes
]
)
-- DELETE BUTTON
{-| A delete button (blue X)
-}
delete : { label : String, onClick : msg } -> Html msg
delete config =
Nri.Ui.styled Html.button
(styledName "delete")
[ Css.display Css.inlineBlock
, Css.backgroundRepeat Css.noRepeat
, Css.backgroundColor Css.transparent
, Css.backgroundPosition Css.center
, Css.backgroundSize Css.contain
, Css.border Css.zero
, Css.width (Css.px 15)
, Css.height (Css.px 15)
, Css.padding Css.zero
, Css.margin2 Css.zero (Css.px 6)
, Css.cursor Css.pointer
, Css.color Colors.azure
]
[ Events.onClick config.onClick
, Attributes.type_ "button"
, -- reference: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_button_role#Labeling_buttons
Widget.label config.label
]
[ Svg.svg [ Svg.Attributes.viewBox "0 0 25 25" ]
[ Svg.title [] [ Styled.toUnstyled (Styled.text "Delete") ]
, Svg.path
[ Svg.Attributes.fill "#146aff" -- TODO: this should be azure, but css colors aren't extractable afaik
, Svg.Attributes.d "M1.067 6.015c-1.423-1.422-1.423-3.526 0-4.948 1.422-1.423 3.526-1.423 4.948 0l6.371 6.37 6.371-6.37c1.422-1.423 3.783-1.423 5.176 0 1.423 1.422 1.423 3.782 0 5.176l-6.37 6.37 6.37 6.372c1.423 1.422 1.423 3.526 0 4.948-1.422 1.423-3.526 1.423-4.948 0l-6.371-6.37-6.371 6.37c-1.422 1.423-3.783 1.423-5.176 0-1.423-1.422-1.423-3.782 0-5.176l6.37-6.143-6.37-6.599z"
]
[]
]
|> Styled.fromUnstyled
]
-- TOGGLE BUTTON
{-| A button that can be toggled into a pressed state and back again.
-}
toggleButton :
{ label : String
, onSelect : msg
, onDeselect : msg
, pressed : Bool
}
-> Html msg
toggleButton config =
let
toggledStyles =
if config.pressed then
Css.batch
[ Css.color Colors.gray20
, Css.backgroundColor Colors.glacier
, Css.boxShadow5 Css.inset Css.zero (Css.px 3) Css.zero (ColorsExtra.withAlpha 0.2 Colors.gray20)
, Css.border3 (Css.px 1) Css.solid Colors.azure
, Css.fontWeight Css.bold
]
else
Css.batch
[]
in
Nri.Ui.styled Html.button
(styledName "toggleButton")
[ buttonStyles Medium WidthUnbounded secondaryColors []
, toggledStyles
]
[ Events.onClick
(if config.pressed then
config.onDeselect
else
config.onSelect
)
, Widget.pressed <| Just config.pressed
-- reference: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_button_role#Labeling_buttons
, Role.button
-- Note: setting type: 'button' removes the default behavior of submit
-- equivalent to preventDefaultBehavior = false
-- https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-name
, Attributes.type_ "button"
]
[ viewLabel Nothing config.label ]
buttonStyles : ButtonSize -> ButtonWidth -> ColorPalette -> List Style -> Style
buttonStyles size width colors customStyles =
Css.batch
[ buttonStyle
, sizeStyle size width
, colorStyle colors
, Css.batch customStyles
]
viewLabel : Maybe Svg -> String -> Html msg
viewLabel maybeSvg label_ =
Nri.Ui.styled Html.span
"button-label-span"
[ Css.overflow Css.hidden -- Keep scrollbars out of our button
, Css.overflowWrap Css.breakWord -- Ensure that words that exceed the button width break instead of disappearing
, Css.padding2 (Css.px 2) Css.zero -- Without a bit of bottom padding, text that extends below the baseline, like "g" gets cut off
]
[]
(case maybeSvg of
Nothing ->
renderMarkdown label_
Just svg ->
NriSvg.toHtml svg :: renderMarkdown label_
)
renderMarkdown : String -> List (Html msg)
renderMarkdown markdown =
case Markdown.Block.parse Nothing markdown of
-- It seems to be always first wrapped in a `Paragraph` and never directly a `PlainInline`
[ Markdown.Block.Paragraph _ inlines ] ->
List.map (Markdown.Inline.toHtml >> Styled.fromUnstyled) inlines
_ ->
[ Html.text markdown ]
-- STYLES
buttonStyle : Style
buttonStyle =
Css.batch
[ Css.cursor Css.pointer
, -- Specifying the font can and should go away after bootstrap is removed from application.css
Nri.Ui.Fonts.V1.baseFont
, Css.textOverflow Css.ellipsis
, Css.overflow Css.hidden
, Css.textDecoration Css.none
, Css.backgroundImage Css.none
, Css.textShadow Css.none
, Css.property "transition" "background-color 0.2s, color 0.2s, box-shadow 0.2s, border 0.2s, border-width 0s"
, Css.boxShadow Css.none
, Css.border Css.zero
, Css.margin Css.zero
, Css.hover [ Css.textDecoration Css.none ]
, Css.disabled [ Css.cursor Css.notAllowed ]
, Css.display Css.inlineFlex
, Css.alignItems Css.center
, Css.justifyContent Css.center
]
-- COLORS
type alias ColorPalette =
{ background : Css.Color
, hover : Css.Color
, text : Css.Color
, border : Maybe Css.Color
, shadow : Css.Color
}
primaryColors : ColorPalette
primaryColors =
{ background = Colors.azure
, hover = Colors.azureDark
, text = Colors.white
, border = Nothing
, shadow = Colors.azureDark
}
secondaryColors : ColorPalette
secondaryColors =
{ background = Colors.white
, hover = Colors.glacier
, text = Colors.azure
, border = Just <| Colors.azure
, shadow = Colors.azure
}
getColorPalette : ButtonOrLink msg -> ColorPalette
getColorPalette (ButtonOrLink config) =
case config.state of
Enabled ->
config.style
Disabled ->
{ background = Colors.gray92
, hover = Colors.gray92
, text = Colors.gray45
, border = Nothing
, shadow = Colors.gray92
}
Error ->
{ background = Colors.purple
, hover = Colors.purple
, text = Colors.white
, border = Nothing
, shadow = Colors.purple
}
Unfulfilled ->
{ background = Colors.gray92
, hover = Colors.gray92
, text = Colors.gray45
, border = Nothing
, shadow = Colors.gray92
}
Loading ->
{ background = Colors.glacier
, hover = Colors.glacier
, text = Colors.navy
, border = Nothing
, shadow = Colors.glacier
}
Success ->
{ background = Colors.greenDark
, hover = Colors.greenDark
, text = Colors.white
, border = Nothing
, shadow = Colors.greenDark
}
colorStyle : ColorPalette -> Style
colorStyle colorPalette =
Css.batch
[ Css.color colorPalette.text
, Css.backgroundColor colorPalette.background
, Css.fontWeight (Css.int 700)
, Css.textAlign Css.center
, case colorPalette.border of
Nothing ->
Css.borderStyle Css.none
Just color ->
Css.batch
[ Css.borderColor color
, Css.borderStyle Css.solid
]
, Css.borderBottomStyle Css.solid
, Css.borderBottomColor colorPalette.shadow
, Css.fontStyle Css.normal
, Css.hover
[ Css.color colorPalette.text
, Css.backgroundColor colorPalette.hover
, Css.disabled [ Css.backgroundColor colorPalette.background ]
]
, Css.visited [ Css.color colorPalette.text ]
]
sizeStyle : ButtonSize -> ButtonWidth -> Style
sizeStyle size width =
let
config =
case size of
Small ->
{ fontSize = 15
, height = 36
, imageHeight = 15
, shadowHeight = 2
, minWidth = 75
}
Medium ->
{ fontSize = 17
, height = 45
, imageHeight = 15
, shadowHeight = 3
, minWidth = 100
}
Large ->
{ fontSize = 20
, height = 56
, imageHeight = 20
, shadowHeight = 4
, minWidth = 200
}
sizingAttributes =
let
verticalPaddingPx =
2
in
[ Css.minHeight (Css.px config.height)
, Css.paddingTop (Css.px verticalPaddingPx)
, Css.paddingBottom (Css.px verticalPaddingPx)
]
widthAttributes =
case width of
WidthExact pxWidth ->
[ Css.maxWidth (Css.pct 100)
, Css.width (Css.px <| toFloat pxWidth)
, Css.paddingRight (Css.px 4)
, Css.paddingLeft (Css.px 4)
]
WidthUnbounded ->
[ Css.paddingLeft (Css.px 16)
, Css.paddingRight (Css.px 16)
, Css.minWidth (Css.px config.minWidth)
]
WidthFillContainer ->
[ Css.paddingLeft (Css.px 16)
, Css.paddingRight (Css.px 16)
, Css.minWidth (Css.px config.minWidth)
, Css.width (Css.pct 100)
]
lineHeightPx =
case size of
Small ->
15
Medium ->
19
Large ->
22
in
Css.batch
[ Css.fontSize (Css.px config.fontSize)
, Css.borderRadius (Css.px 8)
, Css.lineHeight (Css.px lineHeightPx)
, Css.boxSizing Css.borderBox
, Css.borderWidth (Css.px 1)
, Css.borderBottomWidth (Css.px config.shadowHeight)
, Css.batch sizingAttributes
, Css.batch widthAttributes
, Css.Global.descendants
[ Css.Global.img
[ Css.height (Css.px config.imageHeight)
, Css.marginRight (Css.px <| config.imageHeight / 6)
, Css.position Css.relative
, Css.bottom (Css.px 2)
, Css.verticalAlign Css.middle
]
, Css.Global.svg
[ Css.height (Css.px config.imageHeight) |> Css.important
, Css.width (Css.px config.imageHeight) |> Css.important
, Css.marginRight (Css.px <| config.imageHeight / 6)
, Css.position Css.relative
, Css.bottom (Css.px 2)
, Css.verticalAlign Css.middle
]
, Css.Global.svg
[ Css.important <| Css.height (Css.px config.imageHeight)
, Css.important <| Css.width Css.auto
, Css.maxWidth (Css.px (config.imageHeight * 1.25))
, Css.paddingRight (Css.px <| config.imageHeight / 6)
, Css.position Css.relative
, Css.bottom (Css.px 2)
, Css.verticalAlign Css.middle
]
]
]

View File

@ -557,9 +557,14 @@ renderLink ((ButtonOrLink config) as link_) =
linkBase "linkExternalWithTracking"
(List.concat
[ targetBlank
, [ Maybe.map EventExtras.onClickForLinkWithHref config.onClick
|> Maybe.withDefault AttributesExtra.none
]
, config.onClick
|> Maybe.map
(\onClickMsg ->
[ Events.onClick onClickMsg
, Events.on "auxclick" (Json.Decode.succeed onClickMsg)
]
)
|> Maybe.withDefault []
, config.customAttributes
]
)

View File

@ -5,12 +5,18 @@ module Nri.Ui.ClickableText.V3 exposing
, small, medium, large
, href, onClick
, icon
, custom
, custom, css
)
{-|
# Post-release patches
- adds `css` helper
- add bottom border on hover instead of text decoration
# Changes from V2
- Changes API to be attributes-based rather than config-based
@ -43,11 +49,11 @@ HTML `<a>` elements and are created here with `*Link` functions.
@docs small, medium, large
@docs href, onClick
@docs icon
@docs custom
@docs custom, css
-}
import Css
import Css exposing (Style)
import Html.Styled as Html exposing (..)
import Html.Styled.Attributes as Attributes
import Html.Styled.Events as Events
@ -93,7 +99,13 @@ icon icon_ =
set (\attributes -> { attributes | icon = Just icon_ })
{-| -}
{-| Use this helper to add custom attributes.
Do NOT use this helper to add css styles, as they may not be applied the way
you want/expect if underlying Button styles change.
Instead, please use the `css` helper.
-}
custom : List (Html.Attribute msg) -> Attribute msg
custom attributes =
set
@ -104,6 +116,17 @@ custom attributes =
)
{-| -}
css : List Style -> Attribute msg
css styles =
set
(\config ->
{ config
| customStyles = List.append config.customStyles styles
}
)
{-| -}
onClick : msg -> Attribute msg
onClick msg =
@ -130,7 +153,7 @@ button label_ attributes =
in
Nri.Ui.styled Html.button
(dataDescriptor "button")
clickableTextStyles
(clickableTextStyles ++ config.customStyles)
((Maybe.map Events.onClick config.onClick
|> Maybe.withDefault AttributesExtra.none
)
@ -153,7 +176,7 @@ link label_ attributes =
in
Nri.Ui.styled Html.a
(dataDescriptor "link")
clickableTextStyles
(clickableTextStyles ++ config.customStyles)
(Attributes.href config.url :: config.customAttributes)
[ viewContent config ]
@ -215,7 +238,8 @@ clickableTextStyles =
, Css.textAlign Css.left
, Css.borderStyle Css.none
, Css.textDecoration Css.none
, Css.hover [ Css.textDecoration Css.underline ]
, Css.borderBottom3 (Css.px 1) Css.solid Css.transparent
, Css.hover [ Css.textDecoration Css.none, Css.borderBottom3 (Css.px 1) Css.solid Colors.azure ]
, Css.padding Css.zero
, Css.display Css.inlineBlock
, Css.verticalAlign Css.textBottom
@ -251,6 +275,7 @@ type alias ClickableTextAttributes msg =
, onClick : Maybe msg
, url : String
, customAttributes : List (Html.Attribute msg)
, customStyles : List Style
}
@ -262,6 +287,7 @@ defaults =
, label = ""
, icon = Nothing
, customAttributes = []
, customStyles = []
}

View File

@ -35,7 +35,7 @@ label theme inError =
batch
[ backgroundColor white
, left (px 10)
, top (px 0)
, top (px 1)
, fontSize (px 12)
, Nri.Ui.Fonts.V1.baseFont
, position absolute
@ -109,21 +109,21 @@ input theme isInError =
, verticalAlign top
, marginBottom zero
, marginTop (px 9)
, boxShadow6 inset zero (px 2) zero zero gray92
, boxShadow6 inset zero (px 3) zero zero gray92
, property "transition" "all 0.4s ease"
, boxSizing borderBox
, focus
[ borderColor azure
, outline none
, boxShadow6 inset zero (px 2) zero zero glacier
, boxShadow6 inset zero (px 3) zero zero glacier
]
, if isInError then
batch
[ borderColor purple
, boxShadow6 inset zero (px 2) zero zero purpleLight
, boxShadow6 inset zero (px 3) zero zero purpleLight
, focus
[ borderColor purple
, boxShadow6 inset zero (px 2) zero zero purpleLight
, boxShadow6 inset zero (px 3) zero zero purpleLight
]
]
@ -137,7 +137,7 @@ input theme isInError =
Standard ->
batch
[ sharedStyles
, padding2 inputPaddingVertical (px 14)
, padding2 inputPaddingVertical (px 15)
, fontSize (px 15)
, Nri.Ui.Fonts.V1.baseFont
]
@ -173,7 +173,7 @@ input theme isInError =
ContentCreation ->
batch
[ sharedStyles
, padding2 inputPaddingVertical (px 14)
, padding2 inputPaddingVertical (px 15)
, fontSize (px 15)
, Nri.Ui.Fonts.V1.baseFont
]

View File

@ -1,12 +1,12 @@
module Nri.Ui.Logo.V1 exposing
( noredink
, facebook, twitter, clever
, facebook, twitter, clever, googleClassroom
)
{-|
@docs noredink
@docs facebook, twitter, clever
@docs facebook, twitter, clever, googleClassroom
-}
@ -101,3 +101,38 @@ twitter =
[]
]
|> Nri.Ui.Svg.V1.fromHtml
{-| -}
googleClassroom : Nri.Ui.Svg.V1.Svg
googleClassroom =
Svg.svg
[ Attributes.width "100%"
, Attributes.height "100%"
, Attributes.fill "currentcolor"
, Attributes.viewBox "0 0 20 20"
]
[ Svg.g
[ Attributes.stroke "none"
, Attributes.strokeWidth "1"
, Attributes.fill "none"
, Attributes.fillRule "evenodd"
]
[ Svg.g [ Attributes.transform "translate(-302.000000, -217.000000)" ]
[ Svg.g [ Attributes.transform "translate(66.000000, 207.000000)" ]
[ Svg.g [ Attributes.transform "translate(224.000000, 0.000000)" ]
[ Svg.image
[ Attributes.x "12"
, Attributes.y "10"
, Attributes.width "20"
, Attributes.height "20"
, Attributes.xlinkHref
"data:image/png;base64,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"
]
[]
]
]
]
]
]
|> Nri.Ui.Svg.V1.fromHtml

View File

@ -14,7 +14,7 @@ module Nri.Ui.Modal.V6 exposing
These changes have required major API changes. Be sure to wire up subscriptions!
import Html.Styled exposing (..)
import Nri.Ui.Button.V9 as Button
import Nri.Ui.Button.V10 as Button
import Nri.Ui.Modal.V6 as Modal
type Msg

View File

@ -17,7 +17,7 @@ module Nri.Ui.Modal.V7 exposing
```
import Html.Styled exposing (..)
import Nri.Ui.Button.V9 as Button
import Nri.Ui.Button.V10 as Button
import Nri.Ui.Modal.V7 as Modal
type Msg

View File

@ -18,7 +18,7 @@ module Nri.Ui.Modal.V8 exposing
```
import Html.Styled exposing (..)
import Nri.Ui.Button.V9 as Button
import Nri.Ui.Button.V10 as Button
import Nri.Ui.Modal.V8 as Modal
type Msg
@ -441,7 +441,7 @@ closeButton wrapMsg focusableElementAttrs =
-- make the hitspace extend all the way to the corner
, Css.width (Css.px 40)
, Css.height (Css.px 40)
, Css.padding4 (Css.px 20) (Css.px 20) (Css.px 2) Css.zero
, Css.padding4 (Css.px 20) (Css.px 20) Css.zero Css.zero
-- apply button styles
, Css.borderWidth Css.zero

Some files were not shown because too many files have changed in this diff Show More