Merge remote-tracking branch 'origin/master' into zamboni/add-button-v7

This commit is contained in:
Brooke Angel 2018-12-26 14:12:06 -08:00
commit 0fb768cfde
15 changed files with 742 additions and 115 deletions

1
.envrc Normal file
View File

@ -0,0 +1 @@
use nix

3
.gitignore vendored
View File

@ -231,3 +231,6 @@ tags
# End of https://www.gitignore.io/api/osx,elm,vim,node,macos,linux,emacs,sublimetext
dist.js
# generated documentation file from Elm
documentation.json

View File

@ -1,10 +1,8 @@
NPM_PREFIX=$(realpath .)/node_modules
PATH:="${NPM_PREFIX}/.bin:${PATH}"
SHELL:=env PATH=${PATH} /bin/sh
.PHONY: test
test: node_modules
elm-test
npx elm-test
.PHONY: checks
checks:
@ -12,11 +10,11 @@ checks:
.PHONY: diff
diff: node_modules
if (elm diff | tee /dev/stderr | grep -q MAJOR); then echo "MAJOR changes are not allowed!"; exit 1; fi
if (npx elm diff | tee /dev/stderr | grep -q MAJOR); then echo "MAJOR changes are not allowed!"; exit 1; fi
.PHONY: format
format: node_modules
elm-format --validate src && elm-format --validate --elm-version=0.19 tests styleguide-app
npx elm-format --validate src && npx elm-format --validate --elm-version=0.19 tests styleguide-app
.PHONY: clean
clean:
@ -25,16 +23,16 @@ clean:
.PHONY: styleguide-app
styleguide-app: styleguide-app/elm.js
@echo "Visit http://localhost:8000/index.html to see the styleguide app in your browser"
cd styleguide-app && elm reactor
cd styleguide-app && npx elm reactor
documentation.json: node_modules
elm make --docs $@
npx elm make --docs $@
styleguide-app/bundle.js: lib/index.js node_modules
npx browserify --entry styleguide-app/manifest.js --outfile styleguide-app/bundle.js
styleguide-app/elm.js: styleguide-app/bundle.js $(shell find src styleguide-app -type f -name '*.elm')
cd styleguide-app; elm make Main.elm --output=$(@F)
cd styleguide-app; npx elm make Main.elm --output=$(@F)
# plumbing

View File

@ -4,10 +4,7 @@ UI widgets we use.
## Dual publishing notes
This package is published for both 0.18 and 0.19! The 0.18 source code is in src-0.18. While
we still have codebases that utilize either version we'll need to make updates to any version
after 6.0.0 in both src and src-0.18. Eventually, everything will be updated to 0.19 at which
point we will delete src-0.18 and stop publishing for Elm 0.18.
All internal consumers of this repository have been upgrade to Elm 0.19, so we will not be continuing to update the Elm 0.18 source.
## Versioning policy
@ -76,13 +73,19 @@ You can run this locally to catch errors before you push!
Once your PR is merged, you can publish `master` as a new version:
Run the following to bump && publish the version in `elm-packages.json`:
Run the following to bump && publish the version in `elm.json`:
```
elm bump
```
Commit and push your changes in a PR. Once it's approved and merged,
then:
```
elm-package bump
git tag -a 5.10.0 -m "release version 5.10.0"
git push origin master --tags
elm-package publish
git push origin 5.10.0
elm publish
```
You can also add a tag in https://github.com/NoRedInk/noredink-ui/releases/new if you want to add more detail.

View File

@ -3,7 +3,7 @@
"name": "NoRedInk/noredink-ui",
"summary": "UI Widgets we use at NRI",
"license": "BSD-3-Clause",
"version": "6.1.6",
"version": "6.2.0",
"exposed-modules": [
"Nri.Ui.Alert.V2",
"Nri.Ui.AssetPath",
@ -14,6 +14,7 @@
"Nri.Ui.Button.V6",
"Nri.Ui.Button.V7",
"Nri.Ui.Checkbox.V3",
"Nri.Ui.Checkbox.V4",
"Nri.Ui.Colors.Extra",
"Nri.Ui.Colors.V1",
"Nri.Ui.DisclosureIndicator.V1",
@ -33,6 +34,7 @@
"Nri.Ui.Palette.V1",
"Nri.Ui.PremiumCheckbox.V1",
"Nri.Ui.PremiumCheckbox.V2",
"Nri.Ui.PremiumCheckbox.V3",
"Nri.Ui.SegmentedControl.V6",
"Nri.Ui.Select.V5",
"Nri.Ui.Table.V3",

38
package-lock.json generated
View File

@ -568,7 +568,7 @@
},
"browserify-aes": {
"version": "1.2.0",
"resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
"integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
"dev": true,
"requires": {
@ -605,7 +605,7 @@
},
"browserify-rsa": {
"version": "4.0.1",
"resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
"resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
"dev": true,
"requires": {
@ -882,7 +882,7 @@
},
"convert-source-map": {
"version": "1.1.3",
"resolved": "http://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz",
"integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=",
"dev": true
},
@ -910,7 +910,7 @@
},
"create-hash": {
"version": "1.2.0",
"resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
"integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
"dev": true,
"requires": {
@ -923,7 +923,7 @@
},
"create-hmac": {
"version": "1.1.7",
"resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
"resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
"integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
"dev": true,
"requires": {
@ -1108,7 +1108,7 @@
},
"diffie-hellman": {
"version": "5.0.3",
"resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
"integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
"dev": true,
"requires": {
@ -1278,7 +1278,7 @@
},
"expand-range": {
"version": "1.8.2",
"resolved": "http://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
"resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
"integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
"dev": true,
"requires": {
@ -1437,7 +1437,7 @@
},
"fs-extra": {
"version": "0.30.0",
"resolved": "http://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz",
"integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=",
"dev": true,
"requires": {
@ -2451,7 +2451,7 @@
},
"jsonfile": {
"version": "2.4.0",
"resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
"integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
"dev": true,
"requires": {
@ -2712,7 +2712,7 @@
},
"mkdirp": {
"version": "0.5.1",
"resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
"requires": {
@ -2932,7 +2932,7 @@
},
"os-tmpdir": {
"version": "1.0.2",
"resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
@ -2959,7 +2959,7 @@
},
"parse-asn1": {
"version": "5.1.1",
"resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz",
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz",
"integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==",
"dev": true,
"requires": {
@ -3069,7 +3069,7 @@
},
"public-encrypt": {
"version": "4.0.2",
"resolved": "http://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz",
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz",
"integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==",
"dev": true,
"requires": {
@ -3721,7 +3721,7 @@
},
"safe-regex": {
"version": "1.1.0",
"resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
"dev": true,
"requires": {
@ -3771,7 +3771,7 @@
},
"sha.js": {
"version": "2.4.11",
"resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
"dev": true,
"requires": {
@ -3781,7 +3781,7 @@
},
"shasum": {
"version": "1.0.2",
"resolved": "http://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz",
"integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=",
"dev": true,
"requires": {
@ -4147,7 +4147,7 @@
"dependencies": {
"rimraf": {
"version": "2.2.8",
"resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
"integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=",
"dev": true
}
@ -4155,7 +4155,7 @@
},
"through": {
"version": "2.3.8",
"resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
"dev": true
},
@ -4545,7 +4545,7 @@
},
"xmlbuilder": {
"version": "8.2.2",
"resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz",
"integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=",
"dev": true
},

19
shell.nix Normal file
View File

@ -0,0 +1,19 @@
with import (builtins.fetchTarball rec {
# grab a hash from here: https://nixos.org/channels/
name = "nixpkgs-darwin-18.09pre153253.7e88992a8c7";
url = "https://github.com/nixos/nixpkgs/archive/7e88992a8c7b2de0bcb89182d8686b27bd93e46a.tar.gz";
# Hash obtained using `nix-prefetch-url --unpack <url>`
sha256 = "1f6lf4addczi81hchqbzjlhrsmkrj575dmdjdhyl0jkm7ypy2lgk";
}) {};
stdenv.mkDerivation {
name = "noredink-ui";
buildInputs = [
# base dependencies
git
gnumake
# node dependencies
nodePackages.npm
];
}

332
src/Nri/Ui/Checkbox/V4.elm Normal file
View File

@ -0,0 +1,332 @@
module Nri.Ui.Checkbox.V4 exposing
( Model, Theme(..), IsSelected(..)
, view, viewWithLabel, Assets
, selectedFromBool
)
{-|
@docs Model, Theme, IsSelected
@docs view, viewWithLabel, Assets
@docs selectedFromBool
-}
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.Global exposing (Snippet, children, descendants, everything, selector)
import Html.Events
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.Colors.V1 as Colors
import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.Html.Attributes.V2 as ExtraAttributes
import Nri.Ui.Html.V3 as HtmlExtra exposing (defaultOptions)
{-| -}
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
| Locked
{-| If your selectedness is always selected or not selected,
you will likely store that state as a `Bool` in your model.
`selectedFromBool` lets you easily convert that into an `IsSelected` value
for use with `Nri.Ui.Checkbox`.
-}
selectedFromBool : Bool -> IsSelected
selectedFromBool isSelected =
case isSelected of
True ->
Selected
False ->
NotSelected
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 -> Model msg -> Html.Html msg -> Html.Html msg
buildCheckbox assets model labelContent =
viewCheckbox model <|
case model.theme of
Square ->
{ containerClasses = toClassList [ "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
}
Locked ->
{ containerClasses = toClassList [ "Locked" ]
, 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
(baseStyles
++ (if model.disabled then
[ cursor auto, checkboxImageSelector [ opacity (num 0.4) ] ]
else
[ cursor pointer ]
)
)
lockLabelStyles : { b | disabled : Bool } -> Asset -> Html.Styled.Attribute msg
lockLabelStyles model image =
let
baseStyles =
[ positioning
, textStyle
, outline none
, addIcon image
]
in
css
(baseStyles
++ (if model.disabled then
[ cursor auto
, checkboxImageSelector [ opacity (num 0.4) ]
]
else
[ cursor pointer ]
)
)
positioning : Style
positioning =
batch
[ display inlineBlock
, padding4 (px 13) zero (px 13) (px 35)
]
textStyle : Style
textStyle =
batch
[ Fonts.baseFont
, fontSize (px 16)
, fontWeight (int 600)
, color Colors.navy
]
addIcon : Asset -> Style
addIcon icon =
batch
[ position relative
, checkboxImageSelector
[ backgroundImage icon
, backgroundRepeat noRepeat
, backgroundSize (px 24)
, property "content" "''"
, position absolute
, left zero
, top (px 10)
, width (px 24)
, height (px 24)
]
]
checkboxImageSelector : List Style -> Style
checkboxImageSelector =
before
labelClass : IsSelected -> Html.Styled.Attribute msg
labelClass isSelected =
case isSelected of
Selected ->
toClassList [ "Label", "Checked" ]
NotSelected ->
toClassList [ "Label", "Unchecked" ]
PartiallySelected ->
toClassList [ "Label", "Indeterminate" ]
toClassList : List String -> Html.Styled.Attribute msg
toClassList =
List.map (\a -> ( "checkbox-V3__" ++ a, True )) >> Attributes.classList
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 =
let
toggledValue =
selectedToMaybe model.selected
|> Maybe.withDefault False
|> not
in
Html.Styled.span
[ css
[ display block
, height inherit
, descendants [ Css.Global.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.stopPropagationOn "click"
(Json.Decode.succeed ( "stop click propagation", True ))
]
[ Html.checkbox model.identifier
(selectedToMaybe model.selected)
[ Widget.label model.label
, Events.onCheck (\_ -> model.setterMsg toggledValue)
, 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"

View File

@ -184,13 +184,13 @@ input theme isInError =
{-| -}
inputPaddingVertical : Px
inputPaddingVertical =
px 8
px 12
{-| -}
inputLineHeight : Px
inputLineHeight =
px 20
px 21
{-| -}

View File

@ -202,7 +202,7 @@ viewContent : ModalType -> Html msg -> Html msg
viewContent modalType content =
Nri.Ui.styled div
"modal-content"
[ Css.overflowY Css.scroll
[ Css.overflowY Css.auto
, Css.padding2 (Css.px 30) (Css.px 45)
, Css.width (Css.pct 100)
, Css.minHeight (Css.px 150)

View File

@ -0,0 +1,119 @@
module Nri.Ui.PremiumCheckbox.V3 exposing (PremiumConfig, premium, Pennant(..))
{-|
@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.V4 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"

View File

@ -9,9 +9,9 @@ module Examples.Checkbox exposing (Msg, State, example, init, update)
import Assets exposing (assets)
import Html.Styled as Html exposing (..)
import ModuleExample as ModuleExample exposing (Category(..), ModuleExample)
import Nri.Ui.Checkbox.V3 as Checkbox
import Nri.Ui.Checkbox.V4 as Checkbox
import Nri.Ui.Data.PremiumLevel as PremiumLevel exposing (PremiumLevel(..))
import Nri.Ui.PremiumCheckbox.V2 as PremiumCheckbox
import Nri.Ui.PremiumCheckbox.V3 as PremiumCheckbox
import Set exposing (Set)

View File

@ -6,6 +6,7 @@ module Examples.TextArea exposing (Msg, State, example, init, update)
-}
import Assets exposing (assets)
import Dict exposing (Dict)
import Html.Styled as Html
import ModuleExample as ModuleExample exposing (Category(..), ModuleExample)
@ -171,16 +172,3 @@ update msg state =
type alias Id =
Int
assets : { iconPremiumFlag_svg : Asset, iconPremiumKey_png : Asset, iconPremiumLocked_png : Asset, iconPremiumUnlocked_png : Asset, checkboxCheckedPartially_svg : Asset, checkboxChecked_svg : Asset, checkboxLockOnInside_svg : Asset, checkboxUnchecked_svg : Asset }
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"
}

View File

@ -0,0 +1,21 @@
module Spec.Nri.Ui.Checkbox.V4 exposing (all)
import Expect exposing (Expectation)
import Nri.Ui.Checkbox.V4 as Checkbox
import Test exposing (..)
all : Test
all =
describe "Nri.Ui.Checkbox.V3"
[ describe "selectedFromBool"
[ test "it handles Selected" <|
\() ->
Checkbox.selectedFromBool True
|> Expect.equal Checkbox.Selected
, test "it handles NotSelected" <|
\() ->
Checkbox.selectedFromBool False
|> Expect.equal Checkbox.NotSelected
]
]

View File

@ -0,0 +1,141 @@
module Spec.Nri.Ui.PremiumCheckbox.V3 exposing (spec)
import Html.Attributes
import Html.Styled
import Nri.Ui.AssetPath exposing (Asset(..))
import Nri.Ui.Checkbox.V4 exposing (IsSelected(..))
import Nri.Ui.Data.PremiumLevel as PremiumLevel exposing (PremiumLevel(..))
import Nri.Ui.PremiumCheckbox.V3 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"
}