Merge pull request #1127 from NoRedInk/bat/text/area

TextArea.V5
This commit is contained in:
Tessa 2022-10-10 16:12:40 -06:00 committed by GitHub
commit f89cbe6968
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 927 additions and 141 deletions

View File

@ -1,3 +1,5 @@
Nri.Ui.BreadCrumbs.V1,upgrade to V2
Nri.Ui.Checkbox.V5,upgrade to V6
Nri.Ui.InputStyles.V3,upgrade to V4
Nri.Ui.Tabs.V6,upgrade to V7
Nri.Ui.TextArea.V4,upgrade to V5

1 Nri.Ui.BreadCrumbs.V1 upgrade to V2
2 Nri.Ui.Checkbox.V5 upgrade to V6
3 Nri.Ui.InputStyles.V3 upgrade to V4
4 Nri.Ui.Tabs.V6 upgrade to V7
5 Nri.Ui.TextArea.V4 upgrade to V5

View File

@ -40,6 +40,7 @@
"Nri.Ui.Html.Attributes.V2",
"Nri.Ui.Html.V3",
"Nri.Ui.InputStyles.V3",
"Nri.Ui.InputStyles.V4",
"Nri.Ui.Loading.V1",
"Nri.Ui.Logo.V1",
"Nri.Ui.MasteryIcon.V1",
@ -69,6 +70,7 @@
"Nri.Ui.Text.V6",
"Nri.Ui.Text.Writing.V1",
"Nri.Ui.TextArea.V4",
"Nri.Ui.TextArea.V5",
"Nri.Ui.TextInput.V7",
"Nri.Ui.Tooltip.V3",
"Nri.Ui.UiIcon.V1"

View File

@ -68,6 +68,10 @@ hint = 'upgrade to V5'
[forbidden."Nri.Ui.InputStyles.V2"]
hint = 'upgrade to V3'
[forbidden."Nri.Ui.InputStyles.V3"]
hint = 'upgrade to V4'
usages = ['styleguide/../src/Nri/Ui/TextArea/V4.elm']
[forbidden."Nri.Ui.Menu.V1"]
hint = 'upgrade to V3'
@ -163,6 +167,9 @@ usages = [
[forbidden."Nri.Ui.Text.V5"]
hint = 'upgrade to V6'
[forbidden."Nri.Ui.TextArea.V4"]
hint = 'upgrade to V5'
[forbidden."Nri.Ui.TextInput.V6"]
hint = 'upgrade to V7'

67
lib/TextArea/V5.js Normal file
View File

@ -0,0 +1,67 @@
CustomElement = require("../CustomElement");
CustomElement.create({
tagName: "nri-textarea-v45",
initialize: function () {
this._autoresize = false;
},
onConnect: function () {
this._textarea = this.querySelector("textarea");
this._updateListener();
},
observedAttributes: ["data-autoresize"],
onAttributeChange: function (name, previous, next) {
if (name === "data-autoresize") {
this._autoresize = next !== null;
if (!this._textarea) return;
this._updateListener();
}
},
methods: {
_updateListener: function () {
if (this._autoresize) {
this._textarea.addEventListener("input", this._resize);
this._resize();
} else {
this._textarea.removeEventListener("input", this._resize);
}
},
_resize: function () {
var minHeight = null;
var computedStyles = window.getComputedStyle(this._textarea);
if (this._textarea.style.minHeight) {
minHeight = parseInt(this._textarea.style.minHeight, 10);
} else {
minHeight = parseInt(computedStyles.minHeight, 10);
}
if (minHeight === 0) {
minHeight = parseInt(computedStyles.height, 10);
}
this._textarea.style.overflowY = "hidden";
this._textarea.style.minHeight = minHeight + "px";
this._textarea.style.transition = "none";
// the browser does not include border widths in `.scrollHeight`, but we
// sometimes use `box-sizing: border-box` on these elements so we need to
// take it into account when setting the CSS `height`.
var borderOffset = 0;
if (computedStyles.boxSizing === "border-box") {
borderOffset =
parseInt(computedStyles.borderTopWidth, 10) +
parseInt(computedStyles.borderBottomWidth, 10);
}
this._textarea.style.height =
Math.max(minHeight, this._textarea.scrollHeight + borderOffset) + "px";
},
},
});

View File

@ -1,3 +1,4 @@
require("./TextArea/V4");
require("./TextArea/V5");
exports.CustomElement = require("./CustomElement");

View File

@ -12,7 +12,7 @@ import Css
import Html.Styled.Attributes as Attributes
import InputErrorAndGuidanceInternal exposing (ErrorState)
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.InputStyles.V3 as InputStyles exposing (Theme)
import Nri.Ui.InputStyles.V4 as InputStyles exposing (Theme)
{-| -}

View File

@ -20,7 +20,7 @@ import Css exposing (Color)
import Css.Global exposing (Snippet)
import Nri.Ui.Colors.Extra exposing (toCssString)
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.InputStyles.V3 as InputStyles exposing (focusedErrorInputBoxShadow, focusedInputBoxShadow)
import Nri.Ui.InputStyles.V4 as InputStyles exposing (focusedErrorInputBoxShadow, focusedInputBoxShadow)
{-| When :focus-visible, add the two-tone focus ring.

View File

@ -0,0 +1,267 @@
module Nri.Ui.InputStyles.V4 exposing
( label, Theme(..), input
, inputPaddingVertical, inputLineHeight, textAreaHeight, writingLineHeight, writingPadding, writingPaddingTop, writingMinHeight, defaultMarginTop
, focusedInputBoxShadow, focusedErrorInputBoxShadow, errorClass, inputClass
)
{-|
### Changes from V3
- Remove ContentCreation theme
### Patch changes
- expose defaultMarginTop
### Changes from V2
- adds UserGenerated
InputStyles used by the TextInput and TextArea widgets.
@docs label, Theme, input
## Shared hardcoded values
@docs inputPaddingVertical, inputLineHeight, textAreaHeight, writingLineHeight, writingPadding, writingPaddingTop, writingMinHeight, defaultMarginTop
@docs focusedInputBoxShadow, focusedErrorInputBoxShadow, errorClass, inputClass
-}
import Css exposing (..)
import Css.Global
import Nri.Ui.Colors.Extra as ColorsExtra
import Nri.Ui.Colors.V1 exposing (..)
import Nri.Ui.Fonts.V1
{-| -}
type Theme
= Standard
| UserGenerated
| Writing
{-| -}
label : Theme -> Bool -> Style
label theme inError =
let
sharedStyles =
batch
[ backgroundColor white
, left (px 10)
, top zero
, fontSize (px 12)
, Nri.Ui.Fonts.V1.baseFont
, position absolute
, fontWeight (int 600)
, borderRadius (px 4)
, property "transition" "all 0.4s ease"
]
in
case theme of
Standard ->
batch
[ sharedStyles
, padding2 (px 2) (px 5)
, fontSize (px 12)
, color navy
, if inError then
batch [ color purple ]
else
batch []
]
UserGenerated ->
batch
[ sharedStyles
, padding2 zero (px 5)
, fontSize (px 12)
, color navy
, if inError then
batch [ color purple ]
else
batch []
]
Writing ->
batch
[ sharedStyles
, padding2 zero (px 5)
, border3 (px 1) solid gray75
, borderRadius (px 4)
, fontSize (px 15)
, color navy
, if inError then
batch
[ color purple
, backgroundColor white
, borderColor purple
]
else
batch []
]
{-| -}
defaultMarginTop : Float
defaultMarginTop =
9
{-| -}
focusedInputBoxShadow : String
focusedInputBoxShadow =
"inset 0 3px 0 0 " ++ ColorsExtra.toCssString glacier
{-| -}
focusedErrorInputBoxShadow : String
focusedErrorInputBoxShadow =
"inset 0 3px 0 0 " ++ ColorsExtra.toCssString purpleLight
{-| -}
inputClass : String
inputClass =
"nri-input"
{-| -}
errorClass : String
errorClass =
"nri-input-error"
{-| In order to use these styles in an input module, you will need to add the class "override-sass-styles". This is because sass styles in the monolith have higher precendence than the class styles here.
-}
input : Theme -> Style
input theme =
let
sharedStyles =
batch
[ border3 (px 1) solid gray75
, width (pct 100)
, borderRadius (px 8)
, pseudoClass "placeholder"
[ color gray45
]
, color gray20
-- fix bootstrap
, display inlineBlock
, verticalAlign top
, marginBottom zero
, marginTop (px defaultMarginTop)
, boxShadow6 inset zero (px 3) zero zero gray92
, property "transition" "border-color 0.4s ease"
, boxSizing borderBox
, focus
[ borderColor azure
, outline none
, property "box-shadow" focusedInputBoxShadow
]
, Css.Global.withClass errorClass
[ borderColor purple
, boxShadow6 inset zero (px 3) zero zero purpleLight
, focus
[ borderColor purple
, property "box-shadow" focusedErrorInputBoxShadow
]
]
]
in
batch
[ Css.Global.withClass "override-sass-styles"
[ case theme of
Standard ->
batch
[ sharedStyles
, padding2 inputPaddingVertical (px 15)
, fontSize (px 15)
, Nri.Ui.Fonts.V1.baseFont
]
UserGenerated ->
batch
[ sharedStyles
, padding2 inputPaddingVertical (px 15)
, fontSize (px 15)
, Nri.Ui.Fonts.V1.ugFont
]
Writing ->
batch
[ sharedStyles
, Nri.Ui.Fonts.V1.quizFont
, fontSize (px 18)
, lineHeight writingLineHeight
, padding writingPadding
, paddingTop writingPaddingTop
, focus
[ Css.Global.adjacentSiblings
[ Css.Global.label
[ backgroundColor azure
, color white
, borderColor azure
, Css.Global.withClass errorClass
[ backgroundColor purple
, color white
, borderColor purple
]
]
]
]
]
]
]
{-| -}
inputPaddingVertical : Px
inputPaddingVertical =
px 12
{-| -}
inputLineHeight : Px
inputLineHeight =
px 21
{-| -}
textAreaHeight : Px
textAreaHeight =
px 100
{-| -}
writingLineHeight : Px
writingLineHeight =
px 27
{-| -}
writingPadding : Px
writingPadding =
px 15
{-| -}
writingPaddingTop : Px
writingPaddingTop =
px 20
{-| -}
writingMinHeight : Px
writingMinHeight =
px 150

View File

@ -57,7 +57,7 @@ import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.CssVendorPrefix.V1 as VendorPrefixed
import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.Html.Attributes.V2 as Extra
import Nri.Ui.InputStyles.V3 as InputStyles
import Nri.Ui.InputStyles.V4 as InputStyles
import Nri.Ui.Util
import SolidColor

456
src/Nri/Ui/TextArea/V5.elm Normal file
View File

@ -0,0 +1,456 @@
module Nri.Ui.TextArea.V5 exposing
( view, generateId
, Attribute
, value
, onInput, onBlur
, hiddenLabel, visibleLabel
, css, noMargin
, standard, writing
, autoResize, autoResizeSingleLine
, custom, nriDescription, id, testId
, placeholder, autofocus
, disabled, errorIf, errorMessage, guidance
)
{-|
## Changelog
### Changes from V4
- Removes contentCreation view styles
- Changes to a list-based API
- Adds guidance and errorMessage support
- Adds id, custom, nriDescription, testId, css, and noMargin
- Adds disabled support
## The next version of TextArea should:
- update the disabled styles
## Upgrading to V4
- Adds field for onBlur
## The Nri styleguide-specified textarea with overlapping label
## Creating New Versions
When upgrading this module, we need to make sure to also include a new
custom element, or else autosizing will break! This means doing the following:
1. Creating a new module in `lib/TextArea`
2. Requiring that module in `lib/index.js`
## API
@docs view, generateId
@docs Attribute
@docs value
### Event handlers
@docs onInput, onBlur
### Visual behavior
@docs hiddenLabel, visibleLabel
@docs css, noMargin
@docs standard, writing
@docs autoResize, autoResizeSingleLine
### Other
@docs custom, nriDescription, id, testId
@docs placeholder, autofocus
@docs disabled, errorIf, errorMessage, guidance
-}
import Accessibility.Styled.Aria as Aria
import Css exposing (px)
import Html.Styled as Html exposing (Html)
import Html.Styled.Attributes as Attributes
import Html.Styled.Events as Events
import InputErrorAndGuidanceInternal exposing (ErrorState, Guidance)
import InputLabelInternal
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Html.Attributes.V2 as Extra
import Nri.Ui.InputStyles.V4 as InputStyles exposing (Theme(..))
import Nri.Ui.Util exposing (dashify, removePunctuation)
{-| This is private. The public API only exposes `Attribute`.
-}
type alias Config msg =
{ theme : Theme
, guidance : Guidance
, error : ErrorState
, hideLabel : Bool
, value : String
, autofocus : Bool
, onInput : Maybe (String -> msg)
, onBlur : Maybe msg
, placeholder : Maybe String
, noMarginTop : Bool
, containerCss : List Css.Style
, custom : List (Html.Attribute Never)
, id : Maybe String
, height : HeightBehavior
, disabled : Bool
}
defaultConfig : Config msg
defaultConfig =
{ theme = Standard
, guidance = InputErrorAndGuidanceInternal.noGuidance
, error = InputErrorAndGuidanceInternal.noError
, hideLabel = False
, value = ""
, autofocus = False
, onInput = Nothing
, onBlur = Nothing
, placeholder = Nothing
, noMarginTop = False
, containerCss = []
, custom = []
, id = Nothing
, height = Fixed
, disabled = False
}
applyConfig : List (Attribute msg) -> Config msg
applyConfig =
List.foldl (\(Attribute update) config -> update config) defaultConfig
{-| Customizations for the TextArea.
-}
type Attribute msg
= Attribute (Config msg -> Config msg)
{-| Control whether to auto-expand the height.
-}
type HeightBehavior
= Fixed
| AutoResize Height
{-| For specifying the actual height.
-}
type Height
= DefaultHeight
| SingleLine
{-| -}
autoResize : Attribute msg
autoResize =
Attribute (\soFar -> { soFar | height = AutoResize DefaultHeight })
{-| -}
autoResizeSingleLine : Attribute msg
autoResizeSingleLine =
Attribute (\soFar -> { soFar | height = AutoResize SingleLine })
{-| -}
value : String -> Attribute msg
value value_ =
Attribute (\soFar -> { soFar | value = value_ })
{-| If no explicit placeholder is given, the input label will be used as the placeholder.
-}
placeholder : String -> Attribute msg
placeholder text_ =
Attribute (\soFar -> { soFar | placeholder = Just text_ })
{-| This disables the textarea.
-}
disabled : Attribute msg
disabled =
Attribute (\config -> { config | disabled = True })
{-| Sets whether or not the field will be highlighted as having a validation error.
-}
errorIf : Bool -> Attribute msg
errorIf =
Attribute << InputErrorAndGuidanceInternal.setErrorIf
{-| If `Just`, the field will be highlighted as having a validation error,
and the given error message will be shown.
-}
errorMessage : Maybe String -> Attribute msg
errorMessage =
Attribute << InputErrorAndGuidanceInternal.setErrorMessage
{-| A guidance message shows below the input, unless an error message is showing instead.
-}
guidance : String -> Attribute msg
guidance =
Attribute << InputErrorAndGuidanceInternal.setGuidance
{-| Hides the visible label. (There will still be an invisible label for screen readers.)
-}
hiddenLabel : Attribute msg
hiddenLabel =
Attribute (\soFar -> { soFar | hideLabel = True })
{-| Default behavior.
-}
visibleLabel : Attribute msg
visibleLabel =
Attribute (\soFar -> { soFar | hideLabel = False })
{-| Produce the given `msg` when the field is focused.
-}
onInput : (String -> msg) -> Attribute msg
onInput msg =
Attribute (\soFar -> { soFar | onInput = Just msg })
{-| Produce the given `msg` when the field is blurred.
-}
onBlur : msg -> Attribute msg
onBlur msg =
Attribute (\soFar -> { soFar | onBlur = Just msg })
{-| Sets the `autofocus` attribute of the textarea to true.
-}
autofocus : Attribute msg
autofocus =
Attribute (\soFar -> { soFar | autofocus = True })
{-| Adds CSS to the element containing the textarea.
-}
css : List Css.Style -> Attribute msg
css styles =
Attribute (\soFar -> { soFar | containerCss = soFar.containerCss ++ styles })
{-| Remove default spacing from the Input.
-}
noMargin : Bool -> Attribute msg
noMargin removeMargin =
Attribute (\soFar -> { soFar | noMarginTop = removeMargin })
{-| 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 styles change.
Instead, please use the `css` helper.
-}
custom : List (Html.Attribute Never) -> Attribute msg
custom attributes =
Attribute (\soFar -> { soFar | custom = soFar.custom ++ attributes })
{-| Set a custom ID for this text area. If you don't set the id explicitly,
we'll automatically generate one from the label you pass in, but this can
cause problems if you have more than one textarea with the same label on
the page. Use this to be more specific and avoid issues with duplicate IDs.
-}
id : String -> Attribute msg
id id_ =
Attribute (\soFar -> { soFar | id = Just id_ })
{-| -}
nriDescription : String -> Attribute msg
nriDescription description =
custom [ Extra.nriDescription description ]
{-| -}
testId : String -> Attribute msg
testId id_ =
custom [ Extra.testId id_ ]
{-| Use the Standard theme for the TextArea. This is the default.
-}
standard : Attribute msg
standard =
Attribute (\soFar -> { soFar | theme = InputStyles.Standard })
{-| Use the Writing theme for the TextArea.
-}
writing : Attribute msg
writing =
Attribute (\soFar -> { soFar | theme = InputStyles.Writing })
{-| -}
view : String -> List (Attribute msg) -> Html msg
view label attributes =
view_ label (applyConfig attributes)
{-| -}
view_ : String -> Config msg -> Html msg
view_ label config =
let
autoresizeAttrs =
case config.height of
AutoResize _ ->
[ Attributes.attribute "data-autoresize" "" ]
Fixed ->
[]
heightForStyle =
case config.theme of
Standard ->
InputStyles.textAreaHeight
UserGenerated ->
InputStyles.textAreaHeight
Writing ->
InputStyles.writingMinHeight
idValue : String
idValue =
Maybe.withDefault (generateId label) config.id
isInError =
InputErrorAndGuidanceInternal.getIsInError config.error
in
Html.styled (Html.node "nri-textarea-v5")
[ Css.display Css.block, Css.position Css.relative, Css.batch config.containerCss ]
autoresizeAttrs
[ Html.styled Html.textarea
[ InputStyles.input config.theme
, Css.boxSizing Css.borderBox
, case config.height of
AutoResize minimumHeight ->
Css.minHeight (calculateMinHeight config.theme minimumHeight)
Fixed ->
Css.minHeight heightForStyle
, if config.noMarginTop then
Css.important (Css.marginTop Css.zero)
else
Css.batch []
, Css.batch
(if config.disabled then
[ Css.boxShadow Css.none |> Css.important
, Css.backgroundColor Colors.gray85
]
else
[]
)
]
([ Maybe.map Events.onInput config.onInput
|> Maybe.withDefault Extra.none
, Maybe.map Events.onBlur config.onBlur
|> Maybe.withDefault Extra.none
, Attributes.value config.value
, Attributes.disabled config.disabled
, Attributes.id idValue
, Attributes.autofocus config.autofocus
, Attributes.placeholder (Maybe.withDefault label config.placeholder)
, Attributes.attribute "data-gramm" "false" -- disables grammarly to prevent https://github.com/NoRedInk/NoRedInk/issues/14859
, Attributes.class "override-sass-styles custom-focus-ring"
, Attributes.classList
[ ( InputStyles.inputClass, True )
, ( InputStyles.errorClass, isInError )
]
, Aria.invalid isInError
, InputErrorAndGuidanceInternal.describedBy idValue config
]
++ List.map (Attributes.map never) config.custom
)
[]
, InputLabelInternal.view
{ for = idValue
, label = label
, theme = config.theme
}
config
, InputErrorAndGuidanceInternal.view idValue config
]
calculateMinHeight : Theme -> Height -> Css.Px
calculateMinHeight textAreaStyle specifiedHeight =
{- On including padding in this calculation:
When the textarea is autoresized, TextArea.js updates the textarea's
height by taking its scrollHeight. Because scrollHeight's calculation
includes the element's padding no matter what [1], we need to set the
textarea's box-sizing to border-box in order to use the same measurement
for its height as scrollHeight.
So, min-height also needs to be specified in terms of padding + content
height.
[1] https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight
-}
case specifiedHeight of
SingleLine ->
case textAreaStyle of
Standard ->
singleLineHeight
UserGenerated ->
singleLineHeight
Writing ->
writingSingleLineHeight
DefaultHeight ->
case textAreaStyle of
Standard ->
InputStyles.textAreaHeight
UserGenerated ->
InputStyles.textAreaHeight
Writing ->
InputStyles.writingMinHeight
singleLineHeight : Css.Px
singleLineHeight =
px (.numericValue InputStyles.inputPaddingVertical + .numericValue InputStyles.inputLineHeight + .numericValue InputStyles.inputPaddingVertical)
writingSingleLineHeight : Css.Px
writingSingleLineHeight =
px (.numericValue InputStyles.writingPaddingTop + .numericValue InputStyles.writingLineHeight + .numericValue InputStyles.writingPadding)
{-| -}
generateId : String -> String
generateId labelText =
"nri-ui-text-area-" ++ (dashify <| removePunctuation labelText)

View File

@ -63,7 +63,7 @@ import Nri.Ui.ClickableSvg.V2 as ClickableSvg
import Nri.Ui.ClickableText.V3 as ClickableText
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Html.Attributes.V2 as Extra
import Nri.Ui.InputStyles.V3 as InputStyles exposing (defaultMarginTop)
import Nri.Ui.InputStyles.V4 as InputStyles exposing (defaultMarginTop)
import Nri.Ui.Svg.V1 as Svg
import Nri.Ui.UiIcon.V1 as UiIcon
import Nri.Ui.Util exposing (dashify)
@ -465,7 +465,7 @@ value value_ =
Attribute { emptyEventsAndValues | currentValue = Just value_ } identity
{-| If not explicit placeholder is given, the input label will be used as the placeholder.
{-| If no explicit placeholder is given, the input label will be used as the placeholder.
-}
placeholder : String -> Attribute value msg
placeholder text_ =

View File

@ -8,6 +8,7 @@ module CommonControls exposing
, content
, httpError
, romeoAndJulietQuotation
, guidanceAndErrorMessage
, disabledListItem, premiumDisplay
)
@ -26,9 +27,11 @@ module CommonControls exposing
@docs content
@docs httpError
@docs romeoAndJulietQuotation
@docs guidanceAndErrorMessage
-}
import Code
import Css
import Debug.Control as Control exposing (Control)
import Debug.Control.Extra as ControlExtra
@ -394,3 +397,32 @@ css_ helperName ( styles, default ) { moduleName, use } =
, use default
)
)
guidanceAndErrorMessage :
{ moduleName : String
, guidance : String -> b
, errorMessage : Maybe String -> b
, message : String
}
-> Control (List ( String, b ))
-> Control (List ( String, b ))
guidanceAndErrorMessage { moduleName, guidance, errorMessage, message } =
ControlExtra.optionalListItem "guidance"
(Control.string message
|> Control.map
(\str ->
( Code.fromModule moduleName "guidance " ++ Code.string str
, guidance str
)
)
)
>> ControlExtra.optionalListItem "errorMessage"
(Control.map
(\str ->
( Code.fromModule moduleName "errorMessage " ++ Code.withParens (Code.maybeString (Just str))
, errorMessage (Just str)
)
)
(Control.string message)
)

View File

@ -294,26 +294,12 @@ controlAttributes =
]
)
|> ControlExtra.optionalListItem "disclosure" controlDisclosure
|> ControlExtra.optionalListItem "errorMessage"
(Control.map
(\message ->
( "RadioButton.errorMessage (Just \"" ++ message ++ "\")"
, RadioButton.errorMessage (Just message)
)
)
<|
Control.string "The statement must be true."
)
|> ControlExtra.optionalListItem "guidance"
(Control.map
(\content ->
( "RadioButton.guidance \"" ++ content ++ "\""
, RadioButton.guidance content
)
)
<|
Control.string "The statement must be true."
)
|> CommonControls.guidanceAndErrorMessage
{ moduleName = moduleName
, guidance = RadioButton.guidance
, errorMessage = RadioButton.errorMessage
, message = "The statement must be true."
}
labelVisibility : Control ( String, RadioButton.Attribute Selection Msg )

View File

@ -9,6 +9,7 @@ module Examples.Select exposing (Msg, State, example)
import Accessibility.Styled.Key as Key
import Category exposing (Category(..))
import Code
import CommonControls
import Css
import Debug.Control as Control exposing (Control)
import Debug.Control.Extra as ControlExtra
@ -153,25 +154,12 @@ initControls =
)
(Control.bool True)
)
|> ControlExtra.optionalListItem "errorMessage"
(Control.map
(\str ->
( "Select.errorMessage (Just \"" ++ str ++ "\")"
, Select.errorMessage (Just str)
)
)
(Control.string "The right item must be selected.")
)
|> ControlExtra.optionalListItem "guidance"
(Control.map
(\str ->
( "Select.guidance \"" ++ str ++ "\""
, Select.guidance str
)
)
<|
Control.string "The right item must be selected."
)
|> CommonControls.guidanceAndErrorMessage
{ moduleName = moduleName
, guidance = Select.guidance
, errorMessage = Select.errorMessage
, message = "The right item must be selected."
}
|> ControlExtra.optionalListItem "disabled"
(Control.value ( "Select.disabled", Select.disabled ))
|> ControlExtra.optionalListItem "loading"

View File

@ -8,16 +8,18 @@ module Examples.TextArea exposing (Msg, State, example)
import Category exposing (Category(..))
import Code
import CommonControls
import Css
import Debug.Control as Control exposing (Control)
import Debug.Control.Extra as ControlExtra
import Debug.Control.View as ControlView
import Example exposing (Example)
import Html.Styled as Html exposing (Html)
import Html.Styled as Html
import Html.Styled.Attributes as Attributes exposing (css)
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Heading.V3 as Heading
import Nri.Ui.InputStyles.V3 as InputStyles exposing (Theme(..))
import Nri.Ui.TextArea.V4 as TextArea
import Nri.Ui.InputStyles.V4 as InputStyles exposing (Theme(..))
import Nri.Ui.TextArea.V5 as TextArea
moduleName : String
@ -27,7 +29,7 @@ moduleName =
version : Int
version =
4
5
{-| -}
@ -66,29 +68,15 @@ example =
, view =
\ellieLinkConfig state ->
let
settings =
{ label, attributes } =
Control.currentValue state.settings
toExampleCode name =
[ moduleName ++ "." ++ name
, Code.record
[ ( "value", Code.string state.value )
, ( "autofocus", Code.bool False )
, ( "onInput", "identity" )
, ( "onBlur"
, Code.maybe <|
if settings.onBlur then
Just (Code.string "Neener neener Blur happened")
else
Nothing
)
, ( "isInError", Code.bool settings.isInError )
, ( "label", Code.string settings.label )
, ( "height", Tuple.first settings.height )
, ( "placeholder", Code.string settings.placeholder )
, ( "showLabel", Code.bool settings.showLabel )
]
[ moduleName ++ "." ++ name ++ " " ++ Code.string label
, Code.list <|
("TextArea.value " ++ Code.string state.value)
:: "TextArea.onInput identity"
:: List.map Tuple.first attributes
]
|> String.join ""
in
@ -106,28 +94,14 @@ example =
[ { sectionName = "view"
, code = toExampleCode "view"
}
, { sectionName = "writing"
, code = toExampleCode "writing"
}
]
}
, Heading.h2 [ Heading.plaintext "Example" ]
, settings.theme
{ value = state.value
, autofocus = False
, onInput = UpdateValue
, onBlur =
if settings.onBlur then
Just (UpdateValue "Neener neener Blur happened")
else
Nothing
, isInError = settings.isInError
, label = settings.label
, height = Tuple.second settings.height
, placeholder = settings.placeholder
, showLabel = settings.showLabel
}
, TextArea.view label
(TextArea.value state.value
:: TextArea.onInput UpdateValue
:: List.map Tuple.second attributes
)
]
}
@ -148,49 +122,61 @@ init =
type alias Settings =
{ theme : TextArea.Model Msg -> Html Msg
, label : String
, showLabel : Bool
, placeholder : String
, isInError : Bool
, onBlur : Bool
, height : ( String, TextArea.HeightBehavior )
{ label : String
, attributes : List ( String, TextArea.Attribute Msg )
}
controlAttributes : Control (List ( String, TextArea.Attribute Msg ))
controlAttributes =
ControlExtra.list
|> ControlExtra.optionalListItem
"theme"
(CommonControls.choice moduleName
[ ( "standard", TextArea.standard )
, ( "writing", TextArea.writing )
]
)
|> ControlExtra.optionalBoolListItem "onBlur"
( "TextArea.onBlur " ++ Code.string "Neener neener Blur happened"
, TextArea.onBlur (UpdateValue "Neener neener Blur happened")
)
|> ControlExtra.optionalListItem "placeholder"
(Control.string "A long time ago, in a galaxy pretty near here actually..."
|> Control.map
(\str ->
( "TextArea.placeholder " ++ Code.string str
, TextArea.placeholder str
)
)
)
|> ControlExtra.optionalListItem "height"
(CommonControls.choice moduleName
[ ( "autoResize", TextArea.autoResize )
, ( "autoResizeSingleLine", TextArea.autoResizeSingleLine )
]
)
|> CommonControls.guidanceAndErrorMessage
{ moduleName = moduleName
, guidance = TextArea.guidance
, errorMessage = TextArea.errorMessage
, message = "The statement must be true."
}
|> ControlExtra.optionalBoolListItem "disabled"
( "TextArea.disabled", TextArea.disabled )
|> ControlExtra.optionalBoolListItem "noMargin"
( "TextArea.noMargin True", TextArea.noMargin True )
|> ControlExtra.optionalBoolListItem "css"
( "TextArea.css [ Css.backgroundColor Colors.azure ]"
, TextArea.css [ Css.backgroundColor Colors.azure ]
)
initControls : Control Settings
initControls =
Control.record Settings
|> Control.field "theme"
(Control.choice
[ ( "view", Control.value TextArea.view )
, ( "writing", Control.value TextArea.writing )
]
)
|> Control.field "label" (Control.string "Introductory paragraph")
|> Control.field "showLabel" (Control.bool True)
|> Control.field "placeholder" (Control.string "A long time ago, in a galaxy pretty near here actually...")
|> Control.field "isInError" (Control.bool False)
|> Control.field "onBlur" (Control.bool False)
|> Control.field "height"
(Control.choice
[ ( "fixed"
, Control.value ( "TextArea.Fixed", TextArea.Fixed )
)
, ( "autoresize default"
, Control.value
( Code.withParens "TextArea.AutoResize TextArea.DefaultHeight"
, TextArea.AutoResize TextArea.DefaultHeight
)
)
, ( "autoresize singleline"
, Control.value
( Code.withParens "TextArea.AutoResize TextArea.SingleLine"
, TextArea.AutoResize TextArea.SingleLine
)
)
]
)
|> Control.field "attributes" controlAttributes
{-| -}

View File

@ -10,6 +10,7 @@ import Accessibility.Styled exposing (..)
import Accessibility.Styled.Key as Key
import Category exposing (Category(..))
import Code
import CommonControls
import Css
import Debug.Control as Control exposing (Control)
import Debug.Control.Extra as ControlExtra
@ -385,24 +386,12 @@ controlAttributes =
)
|> ControlExtra.optionalBoolListItem "hiddenLabel"
( "TextInput.hiddenLabel", TextInput.hiddenLabel )
|> ControlExtra.optionalListItem "errorMessage"
(Control.map
(\str ->
( "TextInput.errorMessage " ++ Code.withParens (Code.maybeString (Just str))
, TextInput.errorMessage (Just str)
)
)
(Control.string "The statement must be true.")
)
|> ControlExtra.optionalListItem "guidance"
(Control.string "The statement must be true."
|> Control.map
(\str ->
( "TextInput.guidance " ++ Code.string str
, TextInput.guidance str
)
)
)
|> CommonControls.guidanceAndErrorMessage
{ moduleName = moduleName
, guidance = TextInput.guidance
, errorMessage = TextInput.errorMessage
, message = "The statement must be true."
}
|> ControlExtra.optionalBoolListItem "disabled"
( "TextInput.disabled", TextInput.disabled )
|> ControlExtra.optionalBoolListItem "loading"

View File

@ -36,6 +36,7 @@
"Nri.Ui.Html.Attributes.V2",
"Nri.Ui.Html.V3",
"Nri.Ui.InputStyles.V3",
"Nri.Ui.InputStyles.V4",
"Nri.Ui.Loading.V1",
"Nri.Ui.Logo.V1",
"Nri.Ui.MasteryIcon.V1",
@ -45,6 +46,7 @@
"Nri.Ui.Modal.V11",
"Nri.Ui.Page.V3",
"Nri.Ui.Palette.V1",
"Nri.Ui.Panel.V1",
"Nri.Ui.Pennant.V2",
"Nri.Ui.PremiumCheckbox.V8",
"Nri.Ui.RadioButton.V4",
@ -64,6 +66,7 @@
"Nri.Ui.Text.V6",
"Nri.Ui.Text.Writing.V1",
"Nri.Ui.TextArea.V4",
"Nri.Ui.TextArea.V5",
"Nri.Ui.TextInput.V7",
"Nri.Ui.Tooltip.V3",
"Nri.Ui.UiIcon.V1"