mirror of
https://github.com/NoRedInk/noredink-ui.git
synced 2024-12-18 03:01:41 +03:00
Merge pull request #74 from NoRedInk/ink__update-checkbox
Ink update checkbox
This commit is contained in:
commit
3d44b3f1be
@ -16,6 +16,7 @@
|
||||
"Nri.Ui.Colors.Extra",
|
||||
"Nri.Ui.Checkbox.V1",
|
||||
"Nri.Ui.Checkbox.V2",
|
||||
"Nri.Ui.Checkbox.V3",
|
||||
"Nri.Ui.Divider.V1",
|
||||
"Nri.Ui.Dropdown.V1",
|
||||
"Nri.Ui.Effects.V1",
|
||||
|
295
src/Nri/Ui/Checkbox/V3.elm
Normal file
295
src/Nri/Ui/Checkbox/V3.elm
Normal file
@ -0,0 +1,295 @@
|
||||
module Nri.Ui.Checkbox.V3
|
||||
exposing
|
||||
( IsSelected(..)
|
||||
, Model
|
||||
, Theme(..)
|
||||
, view
|
||||
, viewWithLabel
|
||||
)
|
||||
|
||||
{-|
|
||||
|
||||
@docs Model, Theme, IsSelected
|
||||
|
||||
@docs view, viewWithLabel
|
||||
|
||||
-}
|
||||
|
||||
import Accessibility.Styled as Html
|
||||
import Accessibility.Styled.Aria as Aria
|
||||
import Accessibility.Styled.Style
|
||||
import Accessibility.Styled.Widget as Widget
|
||||
import Css exposing (..)
|
||||
import Css.Foreign exposing (Snippet, children, descendants, everything, selector)
|
||||
import Html.Events exposing (defaultOptions)
|
||||
import Html.Styled
|
||||
import Html.Styled.Attributes as Attributes exposing (css)
|
||||
import Html.Styled.Events as Events
|
||||
import Json.Decode
|
||||
import Nri.Ui.AssetPath exposing (Asset(..))
|
||||
import Nri.Ui.AssetPath.Css
|
||||
import Nri.Ui.Fonts.V1 as Fonts
|
||||
import Nri.Ui.Html.Attributes.V2 as ExtraAttributes
|
||||
import Nri.Ui.Html.V2 as HtmlExtra
|
||||
|
||||
|
||||
{-| -}
|
||||
type alias Model msg =
|
||||
{ identifier : String
|
||||
, label : String
|
||||
, setterMsg : Bool -> msg
|
||||
, selected : IsSelected
|
||||
, disabled : Bool
|
||||
, theme : Theme
|
||||
, noOpMsg : msg
|
||||
}
|
||||
|
||||
|
||||
{-|
|
||||
|
||||
= Selected -- Checked (rendered with a checkmark)
|
||||
| NotSelected -- Not Checked (rendered blank)
|
||||
| PartiallySelected -- Indeterminate (rendered dash)
|
||||
|
||||
-}
|
||||
type IsSelected
|
||||
= Selected
|
||||
| NotSelected
|
||||
| PartiallySelected
|
||||
|
||||
|
||||
{-| -}
|
||||
type Theme
|
||||
= Square
|
||||
| LockOnInside
|
||||
|
||||
|
||||
selectedToMaybe : IsSelected -> Maybe Bool
|
||||
selectedToMaybe selected =
|
||||
case selected of
|
||||
Selected ->
|
||||
Just True
|
||||
|
||||
NotSelected ->
|
||||
Just False
|
||||
|
||||
PartiallySelected ->
|
||||
Nothing
|
||||
|
||||
|
||||
{-| Shows a checkbox (the label is only used for accessibility hints)
|
||||
-}
|
||||
view : Assets a -> Model msg -> Html.Html msg
|
||||
view assets model =
|
||||
buildCheckbox assets [] model <|
|
||||
Html.span [ Accessibility.Styled.Style.invisible ]
|
||||
[ Html.text model.label ]
|
||||
|
||||
|
||||
{-| Shows a checkbox and its label text
|
||||
-}
|
||||
viewWithLabel : Assets a -> Model msg -> Html.Html msg
|
||||
viewWithLabel assets model =
|
||||
buildCheckbox assets [] model <|
|
||||
Html.span [] [ Html.text model.label ]
|
||||
|
||||
|
||||
buildCheckbox : Assets a -> List String -> Model msg -> Html.Html msg -> Html.Html msg
|
||||
buildCheckbox assets modifierClasses model labelContent =
|
||||
let
|
||||
toClassList =
|
||||
List.map (\a -> ( "checkbox-" ++ a, True )) >> Attributes.classList
|
||||
in
|
||||
viewCheckbox model <|
|
||||
case model.theme of
|
||||
Square ->
|
||||
{ containerClasses = toClassList (modifierClasses ++ [ "SquareClass" ])
|
||||
, labelStyles =
|
||||
squareLabelStyles model <|
|
||||
case model.selected of
|
||||
Selected ->
|
||||
assets.checkboxChecked_svg
|
||||
|
||||
NotSelected ->
|
||||
assets.checkboxUnchecked_svg
|
||||
|
||||
PartiallySelected ->
|
||||
assets.checkboxCheckedPartially_svg
|
||||
, labelClasses = labelClass model.selected
|
||||
, labelContent = labelContent
|
||||
}
|
||||
|
||||
LockOnInside ->
|
||||
{ containerClasses = toClassList (modifierClasses ++ [ "LockOnInsideClass" ])
|
||||
, labelStyles = lockLabelStyles model assets.checkboxLockOnInside_svg
|
||||
, labelClasses = labelClass model.selected
|
||||
, labelContent = labelContent
|
||||
}
|
||||
|
||||
|
||||
squareLabelStyles : { b | disabled : Bool } -> Asset -> Html.Styled.Attribute msg
|
||||
squareLabelStyles model image =
|
||||
let
|
||||
baseStyles =
|
||||
[ positioning
|
||||
, textStyle
|
||||
, outline none
|
||||
, addIcon image
|
||||
]
|
||||
in
|
||||
css
|
||||
(if model.disabled then
|
||||
[ cursor auto, opacity (num 0.4) ] ++ baseStyles
|
||||
else
|
||||
[ cursor pointer ] ++ baseStyles
|
||||
)
|
||||
|
||||
|
||||
lockLabelStyles : { b | disabled : Bool } -> Asset -> Html.Styled.Attribute msg
|
||||
lockLabelStyles model image =
|
||||
let
|
||||
baseStyles =
|
||||
[ positioning
|
||||
, textStyle
|
||||
, outline none
|
||||
, addIcon image
|
||||
]
|
||||
in
|
||||
css
|
||||
(if model.disabled then
|
||||
[ cursor auto, opacity (num 0.4) ] ++ baseStyles
|
||||
else
|
||||
[ cursor pointer ] ++ baseStyles
|
||||
)
|
||||
|
||||
|
||||
positioning : Style
|
||||
positioning =
|
||||
batch
|
||||
[ display inlineBlock
|
||||
, padding4 (px 13) zero (px 13) (px 35)
|
||||
, verticalAlign middle
|
||||
]
|
||||
|
||||
|
||||
textStyle : Style
|
||||
textStyle =
|
||||
batch
|
||||
[ Fonts.baseFont
|
||||
, fontSize (px 16)
|
||||
]
|
||||
|
||||
|
||||
addIcon : Asset -> Style
|
||||
addIcon icon =
|
||||
batch
|
||||
[ backgroundImage icon
|
||||
, backgroundRepeat noRepeat
|
||||
, backgroundSize (px 24)
|
||||
, property "background-position" "left center"
|
||||
]
|
||||
|
||||
|
||||
labelClass : IsSelected -> Html.Styled.Attribute msg
|
||||
labelClass isSelected =
|
||||
case isSelected of
|
||||
Selected ->
|
||||
Attributes.classList
|
||||
[ ( "checkbox-Label", True )
|
||||
, ( "checkbox-Checked", True )
|
||||
]
|
||||
|
||||
NotSelected ->
|
||||
Attributes.classList
|
||||
[ ( "checkbox-Label", True )
|
||||
, ( "checkbox-Unchecked", True )
|
||||
]
|
||||
|
||||
PartiallySelected ->
|
||||
Attributes.classList
|
||||
[ ( "checkbox-Label", True )
|
||||
, ( "checkbox-Indeterminate", True )
|
||||
]
|
||||
|
||||
|
||||
viewCheckbox :
|
||||
Model msg
|
||||
->
|
||||
{ containerClasses : Html.Attribute msg
|
||||
, labelStyles : Html.Attribute msg
|
||||
, labelClasses : Html.Attribute msg
|
||||
, labelContent : Html.Html msg
|
||||
}
|
||||
-> Html.Html msg
|
||||
viewCheckbox model config =
|
||||
Html.Styled.span
|
||||
[ css
|
||||
[ display block
|
||||
, height inherit
|
||||
, descendants [ Css.Foreign.input [ display none ] ]
|
||||
]
|
||||
, config.containerClasses
|
||||
, Attributes.id <| model.identifier ++ "-container"
|
||||
, -- This is necessary to prevent event propagation.
|
||||
-- See https://github.com/elm-lang/html/issues/96
|
||||
Attributes.map (always model.noOpMsg) <|
|
||||
Events.onWithOptions "click"
|
||||
{ defaultOptions | stopPropagation = True }
|
||||
(Json.Decode.succeed "stop click propagation")
|
||||
]
|
||||
[ Html.checkbox model.identifier
|
||||
(selectedToMaybe model.selected)
|
||||
[ Widget.label model.label
|
||||
, Events.onCheck model.setterMsg
|
||||
, Attributes.id model.identifier
|
||||
, Attributes.disabled model.disabled
|
||||
]
|
||||
, viewLabel model config.labelContent config.labelClasses config.labelStyles
|
||||
]
|
||||
|
||||
|
||||
viewLabel : Model msg -> Html.Html msg -> Html.Attribute msg -> Html.Attribute msg -> Html.Html msg
|
||||
viewLabel model content class theme =
|
||||
Html.Styled.label
|
||||
[ Attributes.for model.identifier
|
||||
, Aria.controls model.identifier
|
||||
, Widget.disabled model.disabled
|
||||
, Widget.checked (selectedToMaybe model.selected)
|
||||
, if not model.disabled then
|
||||
Attributes.tabindex 0
|
||||
else
|
||||
ExtraAttributes.none
|
||||
, if not model.disabled then
|
||||
--TODO: the accessibility keyboard module might make this a tad more readable.
|
||||
HtmlExtra.onKeyUp
|
||||
{ defaultOptions | preventDefault = True }
|
||||
(\keyCode ->
|
||||
-- 32 is the space bar, 13 is enter
|
||||
if (keyCode == 32 || keyCode == 13) && not model.disabled then
|
||||
Just <| model.setterMsg (Maybe.map not (selectedToMaybe model.selected) |> Maybe.withDefault True)
|
||||
else
|
||||
Nothing
|
||||
)
|
||||
else
|
||||
ExtraAttributes.none
|
||||
, class
|
||||
, theme
|
||||
]
|
||||
[ content ]
|
||||
|
||||
|
||||
{-| The assets used in this module.
|
||||
-}
|
||||
type alias Assets r =
|
||||
{ r
|
||||
| checkboxUnchecked_svg : Asset
|
||||
, checkboxChecked_svg : Asset
|
||||
, checkboxCheckedPartially_svg : Asset
|
||||
, checkboxLockOnInside_svg : Asset
|
||||
}
|
||||
|
||||
|
||||
backgroundImage : Asset -> Style
|
||||
backgroundImage =
|
||||
Nri.Ui.AssetPath.Css.url
|
||||
>> property "background-image"
|
40
src/Nri/Ui/Html/Attributes/V2.elm
Normal file
40
src/Nri/Ui/Html/Attributes/V2.elm
Normal file
@ -0,0 +1,40 @@
|
||||
module Nri.Ui.Html.Attributes.V2 exposing (includeIf, none)
|
||||
|
||||
{-| Extras for working with Html.Attributes.
|
||||
|
||||
This is the new version of Nri.Ui.Html.Attributes.Extra.
|
||||
|
||||
@docs none, includeIf
|
||||
|
||||
-}
|
||||
|
||||
import Html.Styled exposing (Attribute)
|
||||
import Html.Styled.Attributes as Attributes
|
||||
import Json.Encode as Encode
|
||||
|
||||
|
||||
{-| Represents an attribute with no semantic meaning, useful for conditionals.
|
||||
|
||||
This is implemented such that whenever Html.Attributes.Extra.none is encountered
|
||||
by VirtualDom it will set a meaningless property on the element object itself to
|
||||
null:
|
||||
|
||||
domNode['Html.Attributes.Extra.none'] = null
|
||||
|
||||
It's totally safe and lets us clean up conditional and maybe attributes
|
||||
|
||||
-}
|
||||
none : Attribute msg
|
||||
none =
|
||||
Attributes.property "Html.Attributes.Extra.none" Encode.null
|
||||
|
||||
|
||||
{-| conditionally include an attribute. Useful for CSS classes generated with
|
||||
`UniqueClass`!
|
||||
-}
|
||||
includeIf : Bool -> Attribute msg -> Attribute msg
|
||||
includeIf cond attr =
|
||||
if cond then
|
||||
attr
|
||||
else
|
||||
none
|
143
src/Nri/Ui/Html/V2.elm
Normal file
143
src/Nri/Ui/Html/V2.elm
Normal file
@ -0,0 +1,143 @@
|
||||
module Nri.Ui.Html.V2 exposing (..)
|
||||
|
||||
{-| For all utils involving HTML. New version of Nri.Ui.Html.Extra.
|
||||
|
||||
@docs role, noOpHref, noOpHrefUrl
|
||||
|
||||
@docs onEsc, onEnter, onKeyUp, onEnterAndSpace
|
||||
|
||||
@docs textFromList, oxfordifyWithHtml, nbsp
|
||||
|
||||
-}
|
||||
|
||||
import Char
|
||||
import Html.Styled as Html exposing (Attribute, Html, span, text)
|
||||
import Html.Styled.Attributes exposing (..)
|
||||
import Html.Styled.Events exposing (..)
|
||||
import Json.Decode
|
||||
|
||||
|
||||
{-| Convenience for defining role attributes, e.g. <div role="tabpanel">
|
||||
-}
|
||||
role : String -> Attribute msg
|
||||
role =
|
||||
attribute "role"
|
||||
|
||||
|
||||
{-| -}
|
||||
noOpHref : Attribute a
|
||||
noOpHref =
|
||||
href noOpHrefUrl
|
||||
|
||||
|
||||
{-| This is a better choice for a no-op than "#" because "#" changes your
|
||||
location bar. See <http://stackoverflow.com/a/20676911> for more details.
|
||||
-}
|
||||
noOpHrefUrl : String
|
||||
noOpHrefUrl =
|
||||
"javascript:void(0)"
|
||||
|
||||
|
||||
{-| -}
|
||||
onEsc : a -> a -> Attribute a
|
||||
onEsc onEscAction onOtherKey =
|
||||
on "keyup"
|
||||
(Json.Decode.map
|
||||
(\keyCode ->
|
||||
if keyCode == 27 then
|
||||
onEscAction
|
||||
else
|
||||
onOtherKey
|
||||
)
|
||||
keyCode
|
||||
)
|
||||
|
||||
|
||||
{-| -}
|
||||
onEnter : a -> Attribute a
|
||||
onEnter onEnterAction =
|
||||
onKeyUp defaultOptions
|
||||
(\keyCode ->
|
||||
if keyCode == 13 then
|
||||
Just onEnterAction
|
||||
else
|
||||
Nothing
|
||||
)
|
||||
|
||||
|
||||
{-| "Buttons" should trigger on Enter and on Space.
|
||||
-}
|
||||
onEnterAndSpace : msg -> Attribute msg
|
||||
onEnterAndSpace msg =
|
||||
onKeyUp defaultOptions
|
||||
(\keyCode ->
|
||||
if keyCode == 13 || keyCode == 32 then
|
||||
Just msg
|
||||
else
|
||||
Nothing
|
||||
)
|
||||
|
||||
|
||||
{-| Convert a keycode into a message on keyup
|
||||
-}
|
||||
onKeyUp : Options -> (Int -> Maybe a) -> Attribute a
|
||||
onKeyUp options toMaybeMsg =
|
||||
onWithOptions "keyup" options <|
|
||||
Json.Decode.andThen
|
||||
(\keyCode ->
|
||||
keyCode
|
||||
|> toMaybeMsg
|
||||
|> Maybe.map Json.Decode.succeed
|
||||
|> Maybe.withDefault (Json.Decode.fail (toString keyCode))
|
||||
)
|
||||
keyCode
|
||||
|
||||
|
||||
{-| Takes a list of strings, joins them with a space and returns it as a Html.text.
|
||||
textFromList ["Hello", "World"] == text [ String.join " " ["Hello", "World" ] ]
|
||||
-}
|
||||
textFromList : List String -> Html msg
|
||||
textFromList =
|
||||
String.join " " >> text
|
||||
|
||||
|
||||
{-| -}
|
||||
oxfordifyWithHtml : String -> String -> List (Html msg) -> List (Html msg)
|
||||
oxfordifyWithHtml pre post items =
|
||||
let
|
||||
textSpan string =
|
||||
span [] [ text string ]
|
||||
|
||||
final centrals =
|
||||
[ textSpan pre ] ++ centrals ++ [ textSpan post ]
|
||||
in
|
||||
case items of
|
||||
[] ->
|
||||
[]
|
||||
|
||||
[ single ] ->
|
||||
final [ single ]
|
||||
|
||||
[ first, second ] ->
|
||||
final [ first, textSpan " and ", second ]
|
||||
|
||||
many ->
|
||||
let
|
||||
beforeAnd =
|
||||
List.take (List.length many - 1) many
|
||||
|
||||
afterAnd =
|
||||
List.drop (List.length many - 1) many
|
||||
|> List.head
|
||||
|> Maybe.withDefault (textSpan "")
|
||||
in
|
||||
final (List.intersperse (textSpan ", ") beforeAnd ++ [ textSpan ", and ", afterAnd ])
|
||||
|
||||
|
||||
{-| Workaround for `Html.text " "` not working in elm.
|
||||
-}
|
||||
nbsp : Html msg
|
||||
nbsp =
|
||||
Char.fromCode 160
|
||||
|> String.fromChar
|
||||
|> Html.text
|
114
src/Nri/Ui/PremiumCheckbox/V1.elm
Normal file
114
src/Nri/Ui/PremiumCheckbox/V1.elm
Normal file
@ -0,0 +1,114 @@
|
||||
module Nri.Ui.PremiumCheckbox.V1 exposing (PremiumConfig, premium)
|
||||
|
||||
{-|
|
||||
|
||||
@docs PremiumConfig, premium
|
||||
|
||||
-}
|
||||
|
||||
import Accessibility.Styled as Html
|
||||
import Css exposing (..)
|
||||
import Html.Styled.Attributes as Attributes exposing (css)
|
||||
import Nri.Ui.AssetPath exposing (Asset(..))
|
||||
import Nri.Ui.AssetPath.Css
|
||||
import Nri.Ui.Checkbox.V3 as Checkbox
|
||||
import Nri.Ui.Data.PremiumLevel as PremiumLevel exposing (PremiumLevel(..))
|
||||
|
||||
|
||||
{-|
|
||||
|
||||
- `onChange`: A message for when the user toggles the checkbox
|
||||
- `onLockedClick`: A message for when the user clicks a checkbox they don't have PremiumLevel for.
|
||||
If you get this message, you should show an `Nri.Ui.Premium.Model.view`
|
||||
|
||||
-}
|
||||
type alias PremiumConfig msg =
|
||||
{ label : String
|
||||
, id : String
|
||||
, selected : Checkbox.IsSelected
|
||||
, disabled : Bool
|
||||
, teacherPremiumLevel : PremiumLevel
|
||||
, contentPremiumLevel : PremiumLevel
|
||||
, showFlagWhenLocked : Bool
|
||||
, onChange : Bool -> msg
|
||||
, onLockedClick : msg
|
||||
, noOpMsg : msg
|
||||
}
|
||||
|
||||
|
||||
{-| A checkbox that should be used for premium content
|
||||
|
||||
This checkbox is locked when the premium level of the content is greater than the premium level of the teacher
|
||||
|
||||
-}
|
||||
premium : Assets a -> PremiumConfig msg -> Html.Html msg
|
||||
premium assets config =
|
||||
let
|
||||
isLocked =
|
||||
not <|
|
||||
PremiumLevel.allowedFor
|
||||
config.contentPremiumLevel
|
||||
config.teacherPremiumLevel
|
||||
in
|
||||
Html.div
|
||||
[ css
|
||||
[ displayFlex
|
||||
, alignItems center
|
||||
]
|
||||
]
|
||||
[ Checkbox.viewWithLabel assets
|
||||
{ identifier = config.id
|
||||
, label = config.label
|
||||
, setterMsg =
|
||||
if isLocked then
|
||||
\_ -> config.onLockedClick
|
||||
else
|
||||
config.onChange
|
||||
, selected = config.selected
|
||||
, disabled = config.disabled
|
||||
, theme =
|
||||
if isLocked then
|
||||
Checkbox.LockOnInside
|
||||
else
|
||||
Checkbox.Square
|
||||
, noOpMsg = config.noOpMsg
|
||||
}
|
||||
, if
|
||||
(isLocked && config.showFlagWhenLocked)
|
||||
|| (not isLocked && config.contentPremiumLevel /= Free)
|
||||
then
|
||||
Html.div
|
||||
[ Attributes.class "checkbox-PremiumClass"
|
||||
, css
|
||||
[ property "content" "''"
|
||||
, display inlineBlock
|
||||
, width (px 26)
|
||||
, height (px 24)
|
||||
, marginLeft (px 8)
|
||||
, backgroundImage assets.iconPremiumFlag_svg
|
||||
, backgroundRepeat noRepeat
|
||||
, backgroundPosition center
|
||||
]
|
||||
]
|
||||
[]
|
||||
else
|
||||
Html.text ""
|
||||
]
|
||||
|
||||
|
||||
{-| The assets used in this module.
|
||||
-}
|
||||
type alias Assets r =
|
||||
{ r
|
||||
| checkboxUnchecked_svg : Asset
|
||||
, checkboxChecked_svg : Asset
|
||||
, checkboxCheckedPartially_svg : Asset
|
||||
, checkboxLockOnInside_svg : Asset
|
||||
, iconPremiumFlag_svg : Asset
|
||||
}
|
||||
|
||||
|
||||
backgroundImage : Asset -> Style
|
||||
backgroundImage =
|
||||
Nri.Ui.AssetPath.Css.url
|
||||
>> property "background-image"
|
@ -9,6 +9,10 @@ type alias Assets =
|
||||
, attention_svg : Asset
|
||||
, bulb : String
|
||||
, calendar : String
|
||||
, checkboxCheckedPartially_svg : Asset
|
||||
, checkboxChecked_svg : Asset
|
||||
, checkboxLockOnInside_svg : Asset
|
||||
, checkboxUnchecked_svg : Asset
|
||||
, checkmark : String
|
||||
, class : String
|
||||
, clever : String
|
||||
@ -32,6 +36,7 @@ type alias Assets =
|
||||
, iconCalendar_svg : Asset
|
||||
, iconCheck_png : Asset
|
||||
, iconFlag_png : Asset
|
||||
, iconPremiumFlag_svg : Asset
|
||||
, icons_arrowDownBlue_svg : Asset
|
||||
, icons_arrowRightBlue_svg : Asset
|
||||
, icons_clockRed_svg : Asset
|
||||
@ -60,6 +65,8 @@ type alias Assets =
|
||||
, premiumLock_svg : Asset
|
||||
, preview : String
|
||||
, quiz : String
|
||||
, rating : String
|
||||
, revising : String
|
||||
, seemore : String
|
||||
, share : String
|
||||
, skip : String
|
||||
@ -69,6 +76,7 @@ type alias Assets =
|
||||
, speedometer : String
|
||||
, squiggly_png : Asset
|
||||
, startingOffBadge_png : Asset
|
||||
, submitting : String
|
||||
, teach_assignments_copyWhite_svg : Asset
|
||||
, twitterBlue_svg : Asset
|
||||
, unarchiveBlue2x_png : Asset
|
||||
@ -76,9 +84,6 @@ type alias Assets =
|
||||
, writingcycle : String
|
||||
, x : String
|
||||
, xWhite_svg : Asset
|
||||
, submitting : String
|
||||
, rating : String
|
||||
, revising : String
|
||||
}
|
||||
|
||||
|
||||
@ -89,6 +94,10 @@ assets =
|
||||
, attention_svg = Asset "assets/images/attention.svg"
|
||||
, bulb = "icon-bulb"
|
||||
, calendar = "icon-calendar"
|
||||
, checkboxCheckedPartially_svg = Asset "assets/images/checkbox_checkedPartially.svg"
|
||||
, checkboxChecked_svg = Asset "assets/images/checkbox_checked.svg"
|
||||
, checkboxLockOnInside_svg = Asset "assets/images/checkbox_lock_on_inside.svg"
|
||||
, checkboxUnchecked_svg = Asset "assets/images/checkbox_unchecked.svg"
|
||||
, checkmark = "icon-checkmark"
|
||||
, class = "icon-class"
|
||||
, clever = "icon-clever"
|
||||
@ -112,6 +121,7 @@ assets =
|
||||
, iconCalendar_svg = Asset "assets/images/icon-calendar.svg"
|
||||
, iconCheck_png = Asset "assets/images/icon-check.png"
|
||||
, iconFlag_png = Asset "assets/images/icon-flag.png"
|
||||
, iconPremiumFlag_svg = Asset "assets/images/icon_premium_flag.svg"
|
||||
, icons_arrowDownBlue_svg = Asset "assets/images/arrow-down-blue.svg"
|
||||
, icons_arrowRightBlue_svg = Asset "assets/images/arrow-right-blue.svg"
|
||||
, icons_clockRed_svg = Asset "assets/images/clock-red.svg"
|
||||
@ -139,6 +149,8 @@ assets =
|
||||
, premiumLock_svg = Asset "assets/images/premium-lock.svg"
|
||||
, preview = "icon-preview"
|
||||
, quiz = "icon-quiz"
|
||||
, rating = "icon-rating"
|
||||
, revising = "icon-revising"
|
||||
, seemore = "icon-seemore"
|
||||
, share = "icon-share"
|
||||
, skip = "icon-skip"
|
||||
@ -148,6 +160,7 @@ assets =
|
||||
, speedometer = "icon-speedometer"
|
||||
, squiggly_png = Asset "assets/images/squiggly.png"
|
||||
, startingOffBadge_png = Asset "assets/images/starting-off-badge.png"
|
||||
, submitting = "icon-submitting"
|
||||
, teach_assignments_copyWhite_svg = Asset "assets/images/copy-white.svg"
|
||||
, twitterBlue_svg = Asset "assets/images/twitter-blue.svg"
|
||||
, unarchiveBlue2x_png = Asset "assets/images/unarchive-blue_2x.png"
|
||||
@ -155,7 +168,4 @@ assets =
|
||||
, writingcycle = "icon-writingcycle"
|
||||
, x = "icon-x"
|
||||
, xWhite_svg = Asset "assets/images/x-white.svg"
|
||||
, submitting = "icon-submitting"
|
||||
, rating = "icon-rating"
|
||||
, revising = "icon-revising"
|
||||
}
|
||||
|
199
styleguide-app/Examples/Checkbox.elm
Normal file
199
styleguide-app/Examples/Checkbox.elm
Normal file
@ -0,0 +1,199 @@
|
||||
module Examples.Checkbox exposing (Msg, State, example, init, update)
|
||||
|
||||
{-|
|
||||
|
||||
@docs Msg, State, example, init, update,
|
||||
|
||||
-}
|
||||
|
||||
import Assets exposing (assets)
|
||||
import Debug.Control as Control exposing (Control)
|
||||
import Html.Styled as Html exposing (..)
|
||||
import ModuleExample as ModuleExample exposing (Category(..), ModuleExample)
|
||||
import Nri.Ui.Checkbox.V3 as Checkbox
|
||||
import Nri.Ui.Data.PremiumLevel as PremiumLevel exposing (PremiumLevel(..))
|
||||
import Nri.Ui.PremiumCheckbox.V1 as PremiumCheckbox
|
||||
import Set exposing (Set)
|
||||
|
||||
|
||||
{-| -}
|
||||
type Msg
|
||||
= ToggleCheck Id Bool
|
||||
| SetPremiumControl (Control PremiumExampleConfig)
|
||||
| NoOp
|
||||
|
||||
|
||||
{-| -}
|
||||
type alias State =
|
||||
{ isChecked : Set String
|
||||
, premiumControl : Control PremiumExampleConfig
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
example : (Msg -> msg) -> State -> ModuleExample msg
|
||||
example parentMessage state =
|
||||
{ filename = "Nri/Checkbox.elm"
|
||||
, category = Inputs
|
||||
, content =
|
||||
[ viewInteractableCheckbox "styleguide-checkbox-interactable" state
|
||||
, viewIndeterminateCheckbox "styleguide-checkbox-indeterminate" state
|
||||
, viewLockedOnInsideCheckbox "styleguide-locked-on-inside-checkbox" state
|
||||
, viewDisabledCheckbox "styleguide-checkbox-disabled" state
|
||||
, h3 [] [ text "Premium Checkboxes" ]
|
||||
, Control.view SetPremiumControl state.premiumControl
|
||||
|> Html.fromUnstyled
|
||||
, viewPremiumCheckboxes state
|
||||
]
|
||||
|> List.map (Html.toUnstyled << Html.map parentMessage)
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
init : State
|
||||
init =
|
||||
{ isChecked = Set.empty
|
||||
, premiumControl =
|
||||
Control.record PremiumExampleConfig
|
||||
|> Control.field "disabled" (Control.bool False)
|
||||
|> Control.field "teacherPremiumLevel"
|
||||
(Control.choice
|
||||
[ ( "Free", Control.value PremiumLevel.Free )
|
||||
, ( "Premium", Control.value PremiumLevel.Premium )
|
||||
, ( "Premium (with writing)", Control.value PremiumLevel.PremiumWithWriting )
|
||||
]
|
||||
)
|
||||
|> Control.field "showFlagWhenLocked" (Control.bool True)
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
update : Msg -> State -> ( State, Cmd Msg )
|
||||
update msg state =
|
||||
case msg of
|
||||
ToggleCheck id checked ->
|
||||
let
|
||||
isChecked =
|
||||
if checked then
|
||||
Set.insert id state.isChecked
|
||||
else
|
||||
Set.remove id state.isChecked
|
||||
in
|
||||
( { state | isChecked = isChecked }, Cmd.none )
|
||||
|
||||
SetPremiumControl premiumControl ->
|
||||
( { state | premiumControl = premiumControl }, Cmd.none )
|
||||
|
||||
NoOp ->
|
||||
( state, Cmd.none )
|
||||
|
||||
|
||||
|
||||
-- INTERNAL
|
||||
|
||||
|
||||
type alias PremiumExampleConfig =
|
||||
{ disabled : Bool
|
||||
, teacherPremiumLevel : PremiumLevel
|
||||
, showFlagWhenLocked : Bool
|
||||
}
|
||||
|
||||
|
||||
viewInteractableCheckbox : Id -> State -> Html Msg
|
||||
viewInteractableCheckbox id state =
|
||||
Checkbox.viewWithLabel
|
||||
assets
|
||||
{ identifier = id
|
||||
, label = "This is an interactable checkbox!"
|
||||
, setterMsg = ToggleCheck id
|
||||
, selected = isSelected id state
|
||||
, disabled = False
|
||||
, theme = Checkbox.Square
|
||||
, noOpMsg = NoOp
|
||||
}
|
||||
|
||||
|
||||
viewIndeterminateCheckbox : Id -> State -> Html Msg
|
||||
viewIndeterminateCheckbox id state =
|
||||
Checkbox.viewWithLabel
|
||||
assets
|
||||
{ identifier = id
|
||||
, label = "This Checkbox is set in an indeterminate state"
|
||||
, setterMsg = ToggleCheck id
|
||||
, selected = Checkbox.PartiallySelected
|
||||
, disabled = True
|
||||
, theme = Checkbox.Square
|
||||
, noOpMsg = NoOp
|
||||
}
|
||||
|
||||
|
||||
viewLockedOnInsideCheckbox : Id -> State -> Html Msg
|
||||
viewLockedOnInsideCheckbox id state =
|
||||
Checkbox.viewWithLabel
|
||||
assets
|
||||
{ identifier = id
|
||||
, label = "I'm a locked Checkbox on the inside"
|
||||
, setterMsg = ToggleCheck id
|
||||
, selected = Checkbox.NotSelected
|
||||
, disabled = True
|
||||
, theme = Checkbox.LockOnInside
|
||||
, noOpMsg = NoOp
|
||||
}
|
||||
|
||||
|
||||
viewDisabledCheckbox : Id -> State -> Html Msg
|
||||
viewDisabledCheckbox id state =
|
||||
Checkbox.viewWithLabel
|
||||
assets
|
||||
{ identifier = id
|
||||
, label = "Disabled theme"
|
||||
, setterMsg = ToggleCheck id
|
||||
, selected = isSelected id state
|
||||
, disabled = True
|
||||
, theme = Checkbox.Square
|
||||
, noOpMsg = NoOp
|
||||
}
|
||||
|
||||
|
||||
viewPremiumCheckboxes : State -> Html Msg
|
||||
viewPremiumCheckboxes state =
|
||||
let
|
||||
config =
|
||||
Control.currentValue state.premiumControl
|
||||
|
||||
checkbox label premiumLevel =
|
||||
PremiumCheckbox.premium
|
||||
assets
|
||||
{ label = label
|
||||
, id = "premium-checkbox-" ++ label
|
||||
, selected =
|
||||
if Set.member label state.isChecked then
|
||||
Checkbox.Selected
|
||||
else
|
||||
Checkbox.NotSelected
|
||||
, disabled = config.disabled
|
||||
, teacherPremiumLevel = config.teacherPremiumLevel
|
||||
, contentPremiumLevel = premiumLevel
|
||||
, showFlagWhenLocked = config.showFlagWhenLocked
|
||||
, onChange = ToggleCheck label
|
||||
, onLockedClick = NoOp
|
||||
, noOpMsg = NoOp
|
||||
}
|
||||
in
|
||||
Html.div []
|
||||
[ checkbox "Identify Adjectives 1 (Free)" PremiumLevel.Free
|
||||
, checkbox "Identify Adjectives 2 (Premium)" PremiumLevel.Premium
|
||||
, checkbox "Revising Wordy Phrases 1 (Writing)" PremiumLevel.PremiumWithWriting
|
||||
]
|
||||
|
||||
|
||||
type alias Id =
|
||||
String
|
||||
|
||||
|
||||
isSelected : Id -> State -> Checkbox.IsSelected
|
||||
isSelected id state =
|
||||
if Set.member id state.isChecked then
|
||||
Checkbox.Selected
|
||||
else
|
||||
Checkbox.NotSelected
|
@ -10,7 +10,8 @@ import Dict exposing (Dict)
|
||||
import Html
|
||||
import Html.Styled
|
||||
import ModuleExample as ModuleExample exposing (Category(..), ModuleExample)
|
||||
import Nri.Ui.Checkbox.V2 as Checkbox
|
||||
import Nri.Ui.AssetPath exposing (Asset(..))
|
||||
import Nri.Ui.Checkbox.V3 as Checkbox
|
||||
import Nri.Ui.Text.V2 as Text
|
||||
import Nri.Ui.TextArea.V3 as TextArea
|
||||
|
||||
@ -27,9 +28,9 @@ type Msg
|
||||
{-| -}
|
||||
type alias State =
|
||||
{ textValues : Dict Int String
|
||||
, showLabel : Bool
|
||||
, isInError : Bool
|
||||
, autoResize : Bool
|
||||
, showLabel : Checkbox.IsSelected
|
||||
, isInError : Checkbox.IsSelected
|
||||
, autoResize : Checkbox.IsSelected
|
||||
}
|
||||
|
||||
|
||||
@ -42,77 +43,80 @@ example parentMessage state =
|
||||
[ Text.heading [ Html.Styled.text "Textarea controls" ]
|
||||
|> Html.Styled.toUnstyled
|
||||
, Html.div []
|
||||
[ Checkbox.viewWithLabel
|
||||
[ Checkbox.viewWithLabel assets
|
||||
{ identifier = "show-textarea-label"
|
||||
, label = "Show Label"
|
||||
, setterMsg = ToggleLabel
|
||||
, isChecked = Just state.showLabel
|
||||
, selected = state.showLabel
|
||||
, disabled = False
|
||||
, theme = Checkbox.Square Checkbox.Default
|
||||
, theme = Checkbox.Square
|
||||
, noOpMsg = NoOp
|
||||
}
|
||||
, Checkbox.viewWithLabel
|
||||
|> Html.Styled.toUnstyled
|
||||
, Checkbox.viewWithLabel assets
|
||||
{ identifier = "textarea-autoresize"
|
||||
, label = "Autoresize"
|
||||
, setterMsg = ToggleAutoResize
|
||||
, isChecked = Just state.autoResize
|
||||
, selected = state.autoResize
|
||||
, disabled = False
|
||||
, theme = Checkbox.Square Checkbox.Default
|
||||
, theme = Checkbox.Square
|
||||
, noOpMsg = NoOp
|
||||
}
|
||||
, Checkbox.viewWithLabel
|
||||
|> Html.Styled.toUnstyled
|
||||
, Checkbox.viewWithLabel assets
|
||||
{ identifier = "textarea-isInError"
|
||||
, label = "Show Error State"
|
||||
, setterMsg = ToggleErrorState
|
||||
, isChecked = Just state.isInError
|
||||
, selected = state.isInError
|
||||
, disabled = False
|
||||
, theme = Checkbox.Square Checkbox.Default
|
||||
, theme = Checkbox.Square
|
||||
, noOpMsg = NoOp
|
||||
}
|
||||
|> Html.Styled.toUnstyled
|
||||
]
|
||||
, TextArea.view
|
||||
{ value = Maybe.withDefault "" <| Dict.get 1 state.textValues
|
||||
, autofocus = False
|
||||
, onInput = InputGiven 1
|
||||
, isInError = state.isInError
|
||||
, isInError = state.isInError == Checkbox.Selected
|
||||
, label = "TextArea.view"
|
||||
, height =
|
||||
if state.autoResize then
|
||||
if state.autoResize == Checkbox.Selected then
|
||||
TextArea.AutoResize TextArea.SingleLine
|
||||
else
|
||||
TextArea.Fixed
|
||||
, placeholder = "Placeholder"
|
||||
, showLabel = state.showLabel
|
||||
, showLabel = state.showLabel == Checkbox.Selected
|
||||
}
|
||||
|> Html.Styled.toUnstyled
|
||||
, TextArea.writing
|
||||
{ value = Maybe.withDefault "" <| Dict.get 2 state.textValues
|
||||
, autofocus = False
|
||||
, onInput = InputGiven 2
|
||||
, isInError = state.isInError
|
||||
, isInError = state.isInError == Checkbox.Selected
|
||||
, label = "TextArea.writing"
|
||||
, height =
|
||||
if state.autoResize then
|
||||
if state.autoResize == Checkbox.Selected then
|
||||
TextArea.AutoResize TextArea.DefaultHeight
|
||||
else
|
||||
TextArea.Fixed
|
||||
, placeholder = "Placeholder"
|
||||
, showLabel = state.showLabel
|
||||
, showLabel = state.showLabel == Checkbox.Selected
|
||||
}
|
||||
|> Html.Styled.toUnstyled
|
||||
, TextArea.contentCreation
|
||||
{ value = Maybe.withDefault "" <| Dict.get 3 state.textValues
|
||||
, autofocus = False
|
||||
, onInput = InputGiven 3
|
||||
, isInError = state.isInError
|
||||
, isInError = state.isInError == Checkbox.Selected
|
||||
, label = "TextArea.contentCreation"
|
||||
, height =
|
||||
if state.autoResize then
|
||||
if state.autoResize == Checkbox.Selected then
|
||||
TextArea.AutoResize TextArea.DefaultHeight
|
||||
else
|
||||
TextArea.Fixed
|
||||
, placeholder = "Placeholder"
|
||||
, showLabel = state.showLabel
|
||||
, showLabel = state.showLabel == Checkbox.Selected
|
||||
}
|
||||
|> Html.Styled.toUnstyled
|
||||
]
|
||||
@ -124,15 +128,22 @@ example parentMessage state =
|
||||
init : State
|
||||
init =
|
||||
{ textValues = Dict.empty
|
||||
, showLabel = True
|
||||
, isInError = False
|
||||
, autoResize = False
|
||||
, showLabel = Checkbox.Selected
|
||||
, isInError = Checkbox.NotSelected
|
||||
, autoResize = Checkbox.NotSelected
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
update : Msg -> State -> ( State, Cmd Msg )
|
||||
update msg state =
|
||||
let
|
||||
toggle bool =
|
||||
if bool then
|
||||
Checkbox.Selected
|
||||
else
|
||||
Checkbox.NotSelected
|
||||
in
|
||||
case msg of
|
||||
InputGiven id newValue ->
|
||||
( { state | textValues = Dict.insert id newValue state.textValues }
|
||||
@ -140,17 +151,17 @@ update msg state =
|
||||
)
|
||||
|
||||
ToggleLabel bool ->
|
||||
( { state | showLabel = bool }
|
||||
( { state | showLabel = toggle bool }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
ToggleErrorState bool ->
|
||||
( { state | isInError = bool }
|
||||
( { state | isInError = toggle bool }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
ToggleAutoResize bool ->
|
||||
( { state | autoResize = bool }
|
||||
( { state | autoResize = toggle bool }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
@ -164,3 +175,15 @@ update msg state =
|
||||
|
||||
type alias Id =
|
||||
Int
|
||||
|
||||
|
||||
assets =
|
||||
{ checkboxUnchecked_svg = Asset "checkboxUnchecked_svg"
|
||||
, checkboxChecked_svg = Asset "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAb1BMVEX///9DoEc2nDt1tXcoly601bU5nD1nr2o/n0Pw9vAzmzhAn0QxmjYumTMqmDAsmTK92r6UxJacyJ1YqFu52LvC3MOQwpIZlCGLwI3M4s2u0q+q0KueyaCkzKX1+fXq8+rh7uHW6NeDvIVztHVssW4Cx6cUAAACZUlEQVR4nO3Zi1LTYBRF4dOSQkqt4AURL6Di+z+jQWVsadJcen5z9pm1HiDZ3yQzSSZmRERERERERERERERERERERERERERERERElKj7uQeUbrVdzz2hbKuqrlMTV9VikZr4BExN/ANMTHwGpiX+AyYl7gJTEveBCYkvgemIh8BkxDZgKmI7sCEuH+ae5lMXcLF8nHuaT93As7mn+QRQPYDqAVQPoHoA1QOoHkD1AKoHUD2A6gFUD6B6ANUDqB5A9QCqB1A9gOoBVA+gegDVA6geQPUAqgfw/3Rd7MhRgLcXhY4cBHhTLc7LEIMA755mFCFGAhYhBgF+f57hTowGdCcGAX672jm1KzEI8GG7WZQhRgFebvZP70YMAlwvNy8HOBGjAOsDoBMxCPB+U7eNcCAGAa7bgQ7EIECzi/OOIScSwwBLEQMByxBDAUsQgwHNfjoTwwG9iQGBDXHpRwwJ9CQGBZo9OhHDAr2IgYFmZw7E0EAPYnDg6cTwwFOJAsDTiBJAsx+TiSLAhng5jSgDnEoUAk4jSgGnEMWA44lywLFEQaDZxxFESeAYoiiwIb4aRpQFDiUKA80+DCBKA4cQxYFmb3qI8sCGuD1GTAA8TkwBPEKs33U9MbWAZm+7iC3/xiWBR4hZgCOJikCzL1f9MmngCKIq0Ozr6+TAhjjkKioDBxG1gWaf+25UdWAvUR/YQ8wANPvU9aqdBXiEmAXYScwD7PjozQRsJeYCthCzAQ+I+YBm76vkwD1iTuAOMSvQ7LpKDvxLzAz8TcwNNLu5TQ40u5t7ABERERERERERERERERFN7hdTvSHAHrHcMgAAAABJRU5ErkJggg=="
|
||||
, checkboxCheckedPartially_svg = Asset "checkboxCheckedPartially_svg"
|
||||
, iconPremiumUnlocked_png = Asset "iconPremiumUnlocked_png"
|
||||
, iconPremiumLocked_png = Asset "iconPremiumLocked_png"
|
||||
, checkboxLockOnInside_svg = Asset "checkboxLockOnInside_svg"
|
||||
, iconPremiumKey_png = Asset "iconPremiumKey_png"
|
||||
, iconPremiumFlag_svg = Asset "iconPremiumFlag_svg"
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ module NriModules exposing (ModuleStates, Msg, init, nriThemedModules, styles, s
|
||||
import Assets exposing (assets)
|
||||
import DEPRECATED.Css.File exposing (Stylesheet, compile, stylesheet)
|
||||
import Examples.Button
|
||||
import Examples.Checkbox
|
||||
import Examples.Colors
|
||||
import Examples.Dropdown
|
||||
import Examples.Fonts
|
||||
@ -31,6 +32,7 @@ import String.Extra
|
||||
|
||||
type alias ModuleStates =
|
||||
{ buttonExampleState : Examples.Button.State
|
||||
, checkboxExampleState : Examples.Checkbox.State
|
||||
, dropdownState : Examples.Dropdown.State Examples.Dropdown.Value
|
||||
, segmentedControlState : Examples.SegmentedControl.State
|
||||
, selectState : Examples.Select.State Examples.Select.Value
|
||||
@ -43,6 +45,7 @@ type alias ModuleStates =
|
||||
init : ModuleStates
|
||||
init =
|
||||
{ buttonExampleState = Examples.Button.init assets
|
||||
, checkboxExampleState = Examples.Checkbox.init
|
||||
, dropdownState = Examples.Dropdown.init
|
||||
, segmentedControlState = Examples.SegmentedControl.init
|
||||
, selectState = Examples.Select.init
|
||||
@ -54,6 +57,7 @@ init =
|
||||
|
||||
type Msg
|
||||
= ButtonExampleMsg Examples.Button.Msg
|
||||
| CheckboxExampleMsg Examples.Checkbox.Msg
|
||||
| DropdownMsg Examples.Dropdown.Msg
|
||||
| SegmentedControlMsg Examples.SegmentedControl.Msg
|
||||
| SelectMsg Examples.Select.Msg
|
||||
@ -76,6 +80,13 @@ update msg moduleStates =
|
||||
, Cmd.map ButtonExampleMsg cmd
|
||||
)
|
||||
|
||||
CheckboxExampleMsg msg ->
|
||||
let
|
||||
( checkboxExampleState, cmd ) =
|
||||
Examples.Checkbox.update msg moduleStates.checkboxExampleState
|
||||
in
|
||||
( { moduleStates | checkboxExampleState = checkboxExampleState }, Cmd.map CheckboxExampleMsg cmd )
|
||||
|
||||
DropdownMsg msg ->
|
||||
let
|
||||
( dropdownState, cmd ) =
|
||||
@ -162,6 +173,7 @@ container width children =
|
||||
nriThemedModules : ModuleStates -> List (ModuleExample Msg)
|
||||
nriThemedModules model =
|
||||
[ Examples.Button.example assets (exampleMessages ButtonExampleMsg) model.buttonExampleState
|
||||
, Examples.Checkbox.example CheckboxExampleMsg model.checkboxExampleState
|
||||
, Examples.Dropdown.example DropdownMsg model.dropdownState
|
||||
, Examples.Icon.example
|
||||
, Examples.Page.example NoOp
|
||||
|
3
styleguide-app/assets/images/checkbox_checked.svg
Normal file
3
styleguide-app/assets/images/checkbox_checked.svg
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:915d0521f5bc23c22b393b71da2cd18503077fed13bec61822ce2900b96b0813
|
||||
size 2051
|
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4e5ceec4a07abd78ea907ec309cae33f146360d908c834b75c1b0e5fb28f5838
|
||||
size 3002
|
3
styleguide-app/assets/images/checkbox_lock_on_inside.svg
Normal file
3
styleguide-app/assets/images/checkbox_lock_on_inside.svg
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d45df2ba55c45815fd7df437ec023b49542c46428548d344480c253abf5b2062
|
||||
size 4341
|
3
styleguide-app/assets/images/checkbox_unchecked.svg
Normal file
3
styleguide-app/assets/images/checkbox_unchecked.svg
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2e10d667be9d7f32ef27714c59a1743796872127eb33870075b013458e6c58c8
|
||||
size 1282
|
3
styleguide-app/assets/images/icon_premium_flag.svg
Normal file
3
styleguide-app/assets/images/icon_premium_flag.svg
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3bcb4a83ca4e7c4739748a81d5f56fbedf9d9925fe1db8e9fe2e4312c3fa21d2
|
||||
size 1069
|
180
tests/Spec/Nri/Ui/PremiumCheckbox/V1.elm
Normal file
180
tests/Spec/Nri/Ui/PremiumCheckbox/V1.elm
Normal file
@ -0,0 +1,180 @@
|
||||
module Spec.Nri.Ui.PremiumCheckbox.V1 exposing (spec)
|
||||
|
||||
import Html.Styled
|
||||
import Nri.Ui.AssetPath exposing (Asset(Asset))
|
||||
import Nri.Ui.Checkbox.V3 exposing (IsSelected(..))
|
||||
import Nri.Ui.Data.PremiumLevel exposing (PremiumLevel(..))
|
||||
import Nri.Ui.PremiumCheckbox.V1 as PremiumCheckbox
|
||||
import Test exposing (..)
|
||||
import Test.Html.Query as Query
|
||||
import Test.Html.Selector as Selector
|
||||
|
||||
|
||||
premiumView config =
|
||||
PremiumCheckbox.premium assets
|
||||
{ label = config.label
|
||||
, id = "id"
|
||||
, selected = config.selected
|
||||
, disabled = config.disabled
|
||||
, teacherPremiumLevel = config.teacherPremiumLevel
|
||||
, contentPremiumLevel = config.contentPremiumLevel
|
||||
, showFlagWhenLocked = config.showFlagWhenLocked
|
||||
, onChange = \_ -> ()
|
||||
, onLockedClick = ()
|
||||
, noOpMsg = ()
|
||||
}
|
||||
|> Html.Styled.toUnstyled
|
||||
|> Query.fromHtml
|
||||
|
||||
|
||||
spec : Test
|
||||
spec =
|
||||
describe "Nri.Ui.PremiumCheckbox.V1"
|
||||
[ describe "premium"
|
||||
[ test "displays the label" <|
|
||||
\() ->
|
||||
premiumView
|
||||
{ label = "i am label"
|
||||
, selected = Selected
|
||||
, disabled = False
|
||||
, teacherPremiumLevel = Free
|
||||
, contentPremiumLevel = Free
|
||||
, showFlagWhenLocked = True
|
||||
}
|
||||
|> Query.has [ Selector.text "i am label" ]
|
||||
, test "appears selected when Selected is passed in" <|
|
||||
\() ->
|
||||
premiumView
|
||||
{ label = "i am label"
|
||||
, selected = Selected
|
||||
, disabled = False
|
||||
, teacherPremiumLevel = Free
|
||||
, contentPremiumLevel = Free
|
||||
, showFlagWhenLocked = True
|
||||
}
|
||||
|> Query.has [ Selector.class "checkbox-Checked" ]
|
||||
, test "appears unselected when NotSelected is passed in" <|
|
||||
\() ->
|
||||
premiumView
|
||||
{ label = "i am label"
|
||||
, selected = NotSelected
|
||||
, disabled = False
|
||||
, teacherPremiumLevel = Free
|
||||
, contentPremiumLevel = Free
|
||||
, showFlagWhenLocked = True
|
||||
}
|
||||
|> Query.has [ Selector.class "checkbox-Unchecked" ]
|
||||
, test "appears partially selected when PartiallySelected is passed in" <|
|
||||
\() ->
|
||||
premiumView
|
||||
{ label = "i am label"
|
||||
, selected = PartiallySelected
|
||||
, disabled = False
|
||||
, teacherPremiumLevel = Free
|
||||
, contentPremiumLevel = Free
|
||||
, showFlagWhenLocked = True
|
||||
}
|
||||
|> Query.has [ Selector.class "checkbox-Indeterminate" ]
|
||||
, test "appears locked when teacherPremiumLevel < contentPremiumLevel" <|
|
||||
\() ->
|
||||
premiumView
|
||||
{ label = "i am label"
|
||||
, selected = PartiallySelected
|
||||
, disabled = False
|
||||
, teacherPremiumLevel = Free
|
||||
, contentPremiumLevel = Premium
|
||||
, showFlagWhenLocked = True
|
||||
}
|
||||
|> Query.has [ Selector.class "checkbox-LockOnInsideClass" ]
|
||||
, test "appears unlocked when teacherPremiumLevel >= contentPremiumLevel" <|
|
||||
\() ->
|
||||
premiumView
|
||||
{ label = "i am label"
|
||||
, selected = PartiallySelected
|
||||
, disabled = False
|
||||
, teacherPremiumLevel = Premium
|
||||
, contentPremiumLevel = Premium
|
||||
, showFlagWhenLocked = True
|
||||
}
|
||||
|> Query.hasNot [ Selector.class "checkbox-LockOnInsideClass" ]
|
||||
, test "appears with P flag when teacherPremiumLevel >= contentPremiumLevel" <|
|
||||
\() ->
|
||||
premiumView
|
||||
{ label = "i am label"
|
||||
, selected = PartiallySelected
|
||||
, disabled = False
|
||||
, teacherPremiumLevel = Premium
|
||||
, contentPremiumLevel = Premium
|
||||
, showFlagWhenLocked = False
|
||||
}
|
||||
|> Query.has [ Selector.class "checkbox-PremiumClass" ]
|
||||
, test "does not appear with P flag when teacherPremiumLevel < contentPremiumLevel and showFlagWhenLocked = False" <|
|
||||
\() ->
|
||||
premiumView
|
||||
{ label = "i am label"
|
||||
, selected = PartiallySelected
|
||||
, disabled = False
|
||||
, teacherPremiumLevel = Free
|
||||
, contentPremiumLevel = Premium
|
||||
, showFlagWhenLocked = False
|
||||
}
|
||||
|> Query.hasNot [ Selector.class "checkbox-PremiumClass" ]
|
||||
, test "appears with P flag for Premium content when teacherPremiumLevel < contentPremiumLevel and showFlagWhenLocked = True" <|
|
||||
\() ->
|
||||
premiumView
|
||||
{ label = "i am label"
|
||||
, selected = PartiallySelected
|
||||
, disabled = False
|
||||
, teacherPremiumLevel = Free
|
||||
, contentPremiumLevel = Premium
|
||||
, showFlagWhenLocked = True
|
||||
}
|
||||
|> Query.has [ Selector.class "checkbox-PremiumClass" ]
|
||||
, test "never shows P flag for nonPremium content" <|
|
||||
\() ->
|
||||
premiumView
|
||||
{ label = "i am label"
|
||||
, selected = PartiallySelected
|
||||
, disabled = False
|
||||
, teacherPremiumLevel = Free
|
||||
, contentPremiumLevel = Free
|
||||
, showFlagWhenLocked = True
|
||||
}
|
||||
|> Query.hasNot [ Selector.class "checkbox-PremiumClass" ]
|
||||
, test "is not disabled when disabled = False and the checkbox is unlocked" <|
|
||||
\() ->
|
||||
premiumView
|
||||
{ label = "i am label"
|
||||
, selected = PartiallySelected
|
||||
, disabled = False
|
||||
, teacherPremiumLevel = Free
|
||||
, contentPremiumLevel = Free
|
||||
, showFlagWhenLocked = True
|
||||
}
|
||||
|> Query.has [ Selector.disabled False ]
|
||||
, test "is disabled when disabled = True and the checkbox is unlocked" <|
|
||||
\() ->
|
||||
premiumView
|
||||
{ label = "i am label"
|
||||
, selected = PartiallySelected
|
||||
, disabled = True
|
||||
, teacherPremiumLevel = Free
|
||||
, contentPremiumLevel = Free
|
||||
, showFlagWhenLocked = True
|
||||
}
|
||||
|> Query.has [ Selector.disabled True ]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
assets =
|
||||
{ checkboxUnchecked_svg = Asset "checkboxUnchecked reference"
|
||||
, checkboxChecked_svg = Asset "checkboxChecked reference"
|
||||
, checkboxCheckedPartially_svg = Asset "checkboxCheckedPartially reference"
|
||||
, iconPremiumUnlocked_png = Asset "iconPremiumUnlocked reference"
|
||||
, iconCheck_png = Asset "iconCheck reference"
|
||||
, iconPremiumLocked_png = Asset "iconPremiumLocked reference"
|
||||
, checkboxLockOnInside_svg = Asset "checkboxLockOnInside reference"
|
||||
, iconPremiumKey_png = Asset "iconPremiumKey reference"
|
||||
, iconPremiumFlag_svg = Asset "iconPremiumFlag reference"
|
||||
}
|
@ -14,6 +14,7 @@
|
||||
"elm-community/elm-test": "4.0.0 <= v < 5.0.0",
|
||||
"elm-lang/core": "5.1.1 <= v < 6.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0",
|
||||
"elm-lang/svg": "2.0.0 <= v < 3.0.0",
|
||||
"pablohirafuji/elm-markdown": "2.0.4 <= v < 3.0.0",
|
||||
"rtfeldman/elm-css": "13.1.1 <= v < 14.0.0",
|
||||
"rtfeldman/elm-css-helpers": "2.1.0 <= v < 3.0.0",
|
||||
|
Loading…
Reference in New Issue
Block a user