mirror of
https://github.com/NoRedInk/noredink-ui.git
synced 2024-12-25 06:33:09 +03:00
Adds clickabletext v4
This commit is contained in:
parent
1dd1bebdb3
commit
2f08949fb3
1
elm.json
1
elm.json
@ -32,6 +32,7 @@
|
||||
"Nri.Ui.ClickableText.V1",
|
||||
"Nri.Ui.ClickableText.V2",
|
||||
"Nri.Ui.ClickableText.V3",
|
||||
"Nri.Ui.ClickableText.V4",
|
||||
"Nri.Ui.Colors.Extra",
|
||||
"Nri.Ui.Colors.V1",
|
||||
"Nri.Ui.CssVendorPrefix.V1",
|
||||
|
277
src/Nri/Ui/ClickableText/V4.elm
Normal file
277
src/Nri/Ui/ClickableText/V4.elm
Normal file
@ -0,0 +1,277 @@
|
||||
module Nri.Ui.ClickableText.V4 exposing
|
||||
( button
|
||||
, link
|
||||
, Attribute
|
||||
, small, medium, large
|
||||
, href, onClick
|
||||
, icon
|
||||
, custom
|
||||
)
|
||||
|
||||
{-|
|
||||
|
||||
|
||||
# Changes from V2
|
||||
|
||||
- Changes API to be attributes-based rather than config-based
|
||||
- Makes a hole for custom attributes (like ids and styles)
|
||||
|
||||
|
||||
# About:
|
||||
|
||||
ClickableText looks different from Nri.Ui.Button in that it displays without margin or padding.
|
||||
ClickableText has the suave, traditional look of a "link"!
|
||||
|
||||
For accessibility purposes, buttons that perform an action on the current page should be HTML `<button>`
|
||||
elements and are created here with `*Button` functions. Buttons that take the user to a new page should be
|
||||
HTML `<a>` elements and are created here with `*Link` functions.
|
||||
|
||||
|
||||
# `<button>` creators
|
||||
|
||||
@docs button
|
||||
|
||||
|
||||
# `<a>` creators
|
||||
|
||||
@docs link
|
||||
|
||||
|
||||
# Attributes
|
||||
|
||||
@docs Attribute
|
||||
@docs small, medium, large
|
||||
@docs href, onClick
|
||||
@docs icon
|
||||
@docs custom
|
||||
|
||||
-}
|
||||
|
||||
import Css
|
||||
import Html.Styled as Html exposing (..)
|
||||
import Html.Styled.Attributes as Attributes
|
||||
import Html.Styled.Events as Events
|
||||
import Nri.Ui
|
||||
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)
|
||||
|
||||
|
||||
label : String -> Attribute msg
|
||||
label label_ =
|
||||
set (\attributes -> { attributes | label = label_ })
|
||||
|
||||
|
||||
{-| -}
|
||||
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 })
|
||||
|
||||
|
||||
type Size
|
||||
= Small
|
||||
| Medium
|
||||
| Large
|
||||
|
||||
|
||||
{-| -}
|
||||
icon : Svg -> Attribute msg
|
||||
icon icon_ =
|
||||
set (\attributes -> { attributes | icon = Just icon_ })
|
||||
|
||||
|
||||
{-| -}
|
||||
custom : List (Html.Attribute msg) -> Attribute msg
|
||||
custom attributes =
|
||||
set
|
||||
(\config ->
|
||||
{ config
|
||||
| customAttributes = List.append config.customAttributes attributes
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
{-| -}
|
||||
onClick : msg -> Attribute msg
|
||||
onClick msg =
|
||||
set (\attributes -> { attributes | onClick = Just msg })
|
||||
|
||||
|
||||
{-| -}
|
||||
href : String -> Attribute msg
|
||||
href url =
|
||||
set (\attributes -> { attributes | url = url })
|
||||
|
||||
|
||||
{-| Creates a `<button>` element
|
||||
-}
|
||||
button :
|
||||
String
|
||||
-> List (Attribute msg)
|
||||
-> Html msg
|
||||
button label_ attributes =
|
||||
let
|
||||
config =
|
||||
(label label_ :: attributes)
|
||||
|> List.foldl (\(Attribute attribute) b -> attribute b) defaults
|
||||
in
|
||||
Nri.Ui.styled Html.button
|
||||
(dataDescriptor "button")
|
||||
clickableTextStyles
|
||||
((Maybe.map Events.onClick config.onClick
|
||||
|> Maybe.withDefault AttributesExtra.none
|
||||
)
|
||||
:: config.customAttributes
|
||||
)
|
||||
[ viewContent config ]
|
||||
|
||||
|
||||
{-| Creates a `<a>` element
|
||||
-}
|
||||
link :
|
||||
String
|
||||
-> List (Attribute msg)
|
||||
-> Html msg
|
||||
link label_ attributes =
|
||||
let
|
||||
config =
|
||||
(label label_ :: attributes)
|
||||
|> List.foldl (\(Attribute attribute) l -> attribute l) defaults
|
||||
in
|
||||
Nri.Ui.styled Html.a
|
||||
(dataDescriptor "link")
|
||||
clickableTextStyles
|
||||
(Attributes.href config.url :: config.customAttributes)
|
||||
[ viewContent config ]
|
||||
|
||||
|
||||
viewContent : { a | label : String, size : Size, icon : Maybe Svg } -> Html msg
|
||||
viewContent config =
|
||||
let
|
||||
fontSize =
|
||||
sizeToPx config.size
|
||||
in
|
||||
span [ Attributes.css [ Css.fontSize fontSize ] ]
|
||||
(case config.icon of
|
||||
Just icon_ ->
|
||||
[ div
|
||||
[ Attributes.css
|
||||
[ Css.displayFlex
|
||||
, Css.alignItems Css.center
|
||||
, Css.property "line-height" "normal"
|
||||
]
|
||||
]
|
||||
[ div
|
||||
[ Attributes.css
|
||||
[ Css.height fontSize
|
||||
, Css.maxWidth fontSize
|
||||
, Css.minWidth fontSize -- so it doesn't shrink when the label is long
|
||||
, case config.size of
|
||||
Small ->
|
||||
Css.marginRight (Css.px 3)
|
||||
|
||||
Medium ->
|
||||
Css.marginRight (Css.px 3)
|
||||
|
||||
Large ->
|
||||
Css.marginRight (Css.px 4)
|
||||
]
|
||||
]
|
||||
[ NriSvg.toHtml icon_ ]
|
||||
, span [] [ text config.label ]
|
||||
]
|
||||
]
|
||||
|
||||
Nothing ->
|
||||
[ text config.label ]
|
||||
)
|
||||
|
||||
|
||||
clickableTextStyles : List Css.Style
|
||||
clickableTextStyles =
|
||||
[ Css.cursor Css.pointer
|
||||
, Nri.Ui.Fonts.V1.baseFont
|
||||
, Css.backgroundImage Css.none
|
||||
, Css.textShadow Css.none
|
||||
, Css.boxShadow Css.none
|
||||
, Css.border Css.zero
|
||||
, Css.disabled [ Css.cursor Css.notAllowed ]
|
||||
, Css.color Colors.azure
|
||||
, Css.backgroundColor Css.transparent
|
||||
, Css.fontWeight (Css.int 600)
|
||||
, Css.textAlign Css.left
|
||||
, Css.borderStyle Css.none
|
||||
, Css.textDecoration Css.none
|
||||
, Css.hover [ Css.textDecoration Css.underline ]
|
||||
, Css.padding Css.zero
|
||||
, Css.display Css.inlineBlock
|
||||
, Css.verticalAlign Css.textBottom
|
||||
]
|
||||
|
||||
|
||||
sizeToPx : Size -> Css.Px
|
||||
sizeToPx size =
|
||||
case size of
|
||||
Small ->
|
||||
Css.px 15
|
||||
|
||||
Medium ->
|
||||
Css.px 17
|
||||
|
||||
Large ->
|
||||
Css.px 20
|
||||
|
||||
|
||||
dataDescriptor : String -> String
|
||||
dataDescriptor descriptor =
|
||||
"clickable-text-v2-" ++ descriptor
|
||||
|
||||
|
||||
|
||||
-- Internals
|
||||
|
||||
|
||||
type alias ClickableTextAttributes msg =
|
||||
{ label : String
|
||||
, size : Size
|
||||
, icon : Maybe Svg
|
||||
, onClick : Maybe msg
|
||||
, url : String
|
||||
, customAttributes : List (Html.Attribute msg)
|
||||
}
|
||||
|
||||
|
||||
defaults : ClickableTextAttributes msg
|
||||
defaults =
|
||||
{ onClick = Nothing
|
||||
, url = "#"
|
||||
, size = Medium
|
||||
, label = ""
|
||||
, icon = Nothing
|
||||
, customAttributes = []
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
type Attribute msg
|
||||
= Attribute (ClickableTextAttributes msg -> ClickableTextAttributes msg)
|
||||
|
||||
|
||||
set :
|
||||
(ClickableTextAttributes msg -> ClickableTextAttributes msg)
|
||||
-> Attribute msg
|
||||
set with =
|
||||
Attribute (\config -> with config)
|
Loading…
Reference in New Issue
Block a user