diff --git a/elm-package.json b/elm-package.json index 100bf398..1a7bf00b 100644 --- a/elm-package.json +++ b/elm-package.json @@ -35,6 +35,7 @@ "Nri.Ui.Page.V1", "Nri.Ui.Palette.V1", "Nri.Ui.PremiumCheckbox.V1", + "Nri.Ui.PremiumCheckbox.V2", "Nri.Ui.SegmentedControl.V1", "Nri.Ui.SegmentedControl.V2", "Nri.Ui.SegmentedControl.V3", diff --git a/src/Nri/Ui/PremiumCheckbox/V2.elm b/src/Nri/Ui/PremiumCheckbox/V2.elm new file mode 100644 index 00000000..0f9d25a2 --- /dev/null +++ b/src/Nri/Ui/PremiumCheckbox/V2.elm @@ -0,0 +1,117 @@ +module Nri.Ui.PremiumCheckbox.V2 exposing (Pennant(..), PremiumConfig, premium) + +{-| + +@docs PremiumConfig, premium, Pennant + +-} + +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 + + +{-| + + - `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 + , isLocked : Bool + , pennant : Maybe Pennant + , onChange : Bool -> msg + , onLockedClick : msg + , noOpMsg : msg + } + + +{-| Premium is the yellow "P" pennant +PremiumWithWriting is the yellow "P+" pennant +-} +type Pennant + = Premium + | PremiumWithWriting + + +{-| A checkbox that should be used for premium content +-} +premium : Assets a -> PremiumConfig msg -> Html.Html msg +premium assets config = + Html.div + [ css + [ displayFlex + , alignItems center + ] + ] + [ Checkbox.viewWithLabel assets + { identifier = config.id + , label = config.label + , setterMsg = + if config.isLocked then + \_ -> config.onLockedClick + else + config.onChange + , selected = config.selected + , disabled = config.disabled + , theme = + if config.isLocked then + Checkbox.Locked + else + Checkbox.Square + , noOpMsg = config.noOpMsg + } + , case config.pennant of + Just pennant -> + Html.div + [ Attributes.class "premium-checkbox-V1__PremiumClass" + , css + [ property "content" "''" + , display inlineBlock + , width (px 26) + , height (px 24) + , marginLeft (px 8) + , backgroundImage + (case pennant of + Premium -> + assets.iconPremiumFlag_svg + + PremiumWithWriting -> + assets.iconPremiumWithWritingFlag_svg + ) + , backgroundRepeat noRepeat + , backgroundPosition center + ] + ] + [] + + Nothing -> + 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 + , iconPremiumWithWritingFlag_svg : Asset + } + + +backgroundImage : Asset -> Style +backgroundImage = + Nri.Ui.AssetPath.Css.url + >> property "background-image" diff --git a/styleguide-app/Assets.elm b/styleguide-app/Assets.elm index 05b4a456..ab0f7f26 100644 --- a/styleguide-app/Assets.elm +++ b/styleguide-app/Assets.elm @@ -39,6 +39,7 @@ type alias Assets = , iconCheck_png : Asset , iconFlag_png : Asset , iconPremiumFlag_svg : Asset + , iconPremiumWithWritingFlag_svg : Asset , icons_arrowDownBlue_svg : Asset , icons_arrowRightBlue_svg : Asset , icons_clockRed_svg : Asset @@ -127,6 +128,7 @@ assets = , 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" + , iconPremiumWithWritingFlag_svg = Asset "assets/images/icon_premium_writing_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" diff --git a/styleguide-app/Examples/Checkbox.elm b/styleguide-app/Examples/Checkbox.elm index e3f87541..65ce5ee4 100644 --- a/styleguide-app/Examples/Checkbox.elm +++ b/styleguide-app/Examples/Checkbox.elm @@ -12,21 +12,19 @@ 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 Nri.Ui.PremiumCheckbox.V2 as PremiumCheckbox import Set exposing (Set) {-| -} type Msg = ToggleCheck Id Bool - | SetPremiumControl (Control PremiumExampleConfig) | NoOp {-| -} type alias State = { isChecked : Set String - , premiumControl : Control PremiumExampleConfig } @@ -41,8 +39,6 @@ example parentMessage 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) @@ -53,17 +49,6 @@ example parentMessage state = 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) } @@ -81,9 +66,6 @@ update msg state = in ( { state | isChecked = isChecked }, Cmd.none ) - SetPremiumControl premiumControl -> - ( { state | premiumControl = premiumControl }, Cmd.none ) - NoOp -> ( state, Cmd.none ) @@ -95,7 +77,7 @@ update msg state = type alias PremiumExampleConfig = { disabled : Bool , teacherPremiumLevel : PremiumLevel - , showFlagWhenLocked : Bool + , pennant : Maybe PremiumCheckbox.Pennant } @@ -158,32 +140,29 @@ viewDisabledCheckbox id state = viewPremiumCheckboxes : State -> Html Msg viewPremiumCheckboxes state = let - config = - Control.currentValue state.premiumControl - - checkbox label premiumLevel = + checkbox config = PremiumCheckbox.premium assets - { label = label - , id = "premium-checkbox-" ++ label + { label = config.label + , id = "premium-checkbox-" ++ config.label , selected = - if Set.member label state.isChecked then + if Set.member config.label state.isChecked then Checkbox.Selected else Checkbox.NotSelected , disabled = config.disabled - , teacherPremiumLevel = config.teacherPremiumLevel - , contentPremiumLevel = premiumLevel - , showFlagWhenLocked = config.showFlagWhenLocked - , onChange = ToggleCheck label + , isLocked = config.isLocked + , pennant = config.pennant + , onChange = ToggleCheck config.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 + [ checkbox { label = "Identify Adjectives 1 (Free)", disabled = False, isLocked = False, pennant = Nothing } + , checkbox { label = "Identify Adjectives 2 (Premium)", disabled = False, isLocked = False, pennant = Just PremiumCheckbox.Premium } + , checkbox { label = "Revising Wordy Phrases 1 (Writing)", disabled = False, isLocked = True, pennant = Just PremiumCheckbox.PremiumWithWriting } + , checkbox { label = "Revising Wordy Phrases 2 (Writing) (Disabled)", disabled = True, isLocked = True, pennant = Just PremiumCheckbox.PremiumWithWriting } ] diff --git a/styleguide-app/assets/images/icon_premium_writing_flag.svg b/styleguide-app/assets/images/icon_premium_writing_flag.svg new file mode 100644 index 00000000..6dd6d2c3 --- /dev/null +++ b/styleguide-app/assets/images/icon_premium_writing_flag.svg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16221aee450224605f8a4aae798ed2ebbba3698fac2dc101d0132729e8f5cdce +size 817 diff --git a/tests/Spec/Nri/Ui/PremiumCheckbox/V2.elm b/tests/Spec/Nri/Ui/PremiumCheckbox/V2.elm new file mode 100644 index 00000000..9a748488 --- /dev/null +++ b/tests/Spec/Nri/Ui/PremiumCheckbox/V2.elm @@ -0,0 +1,141 @@ +module Spec.Nri.Ui.PremiumCheckbox.V2 exposing (spec) + +import Html.Attributes +import Html.Styled +import Nri.Ui.AssetPath exposing (Asset(Asset)) +import Nri.Ui.Checkbox.V3 exposing (IsSelected(..)) +import Nri.Ui.Data.PremiumLevel as PremiumLevel exposing (PremiumLevel(..)) +import Nri.Ui.PremiumCheckbox.V2 as PremiumCheckbox +import Test exposing (..) +import Test.Html.Query as Query +import Test.Html.Selector as Selector + + +premiumView config = + PremiumCheckbox.premium assets + { label = "i am label" + , id = "id" + , selected = config.selected + , disabled = config.disabled + , isLocked = config.isLocked + , pennant = config.pennant + , onChange = \_ -> () + , onLockedClick = () + , noOpMsg = () + } + |> Html.Styled.toUnstyled + |> Query.fromHtml + + +spec : Test +spec = + describe "Nri.Ui.PremiumCheckbox.V2" + [ describe "premium" + [ test "displays the label" <| + \() -> + premiumView + { selected = Selected + , disabled = False + , isLocked = False + , pennant = Nothing + } + |> Query.has [ Selector.text "i am label" ] + , test "appears selected when Selected is passed in" <| + \() -> + premiumView + { selected = Selected + , disabled = False + , isLocked = False + , pennant = Nothing + } + |> Query.has [ Selector.class "checkbox-V3__Checked" ] + , test "appears unselected when NotSelected is passed in" <| + \() -> + premiumView + { selected = NotSelected + , disabled = False + , isLocked = False + , pennant = Nothing + } + |> Query.has [ Selector.class "checkbox-V3__Unchecked" ] + , test "appears partially selected when PartiallySelected is passed in" <| + \() -> + premiumView + { selected = PartiallySelected + , disabled = False + , isLocked = False + , pennant = Nothing + } + |> Query.has [ Selector.class "checkbox-V3__Indeterminate" ] + , test "appears locked when isLocked = True" <| + \() -> + premiumView + { selected = Selected + , disabled = False + , isLocked = True + , pennant = Nothing + } + |> Query.has [ Selector.class "checkbox-V3__Locked" ] + , test "appears unlocked when isLocked = False" <| + \() -> + premiumView + { selected = Selected + , disabled = False + , isLocked = False + , pennant = Nothing + } + |> Query.hasNot [ Selector.class "checkbox-V3__Locked" ] + , test "appears with P flag when Premium pennant is passed in" <| + \() -> + premiumView + { selected = Selected + , disabled = False + , isLocked = False + , pennant = Just PremiumCheckbox.Premium + } + |> Query.find [ Selector.tag "style" ] + |> Query.has [ Selector.text "iconPremiumFlag reference" ] + , test "appears with P+ flag when Premium pennant is passed in" <| + \() -> + premiumView + { selected = Selected + , disabled = False + , isLocked = False + , pennant = Just PremiumCheckbox.PremiumWithWriting + } + |> Query.find [ Selector.tag "style" ] + |> Query.has [ Selector.text "iconPremiumWritingFlag reference" ] + , test "is not disabled when disabled = False" <| + \() -> + premiumView + { selected = Selected + , disabled = False + , isLocked = False + , pennant = Nothing + } + |> Query.has [ Selector.disabled False ] + , test "is disabled when disabled = True" <| + \() -> + premiumView + { selected = Selected + , disabled = True + , isLocked = False + , pennant = Nothing + } + |> 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" + , iconPremiumWithWritingFlag_svg = Asset "iconPremiumWritingFlag reference" + }