ensolabs/designsystemet-elm/1.0.0

Designsystemet.Textfield

A text input wired up with its label, description, prefix, suffix, character counter and error message.

Mirrors Textfield from @digdir/designsystemet-react.

Textfield.new (Ds.label "E-post")
    |> Textfield.withDescription [ Html.text "Vi sender kvitteringen hit" ]
    |> Textfield.withError model.emailError
    |> Textfield.view
        [ Attr.type_ "email"
        , Attr.value model.email
        , Events.onInput ChangedEmail
        ]


Textfield.multiline (Ds.label "Begrunnelse")
    |> Textfield.withCounter { limit = 500, under = "%d tegn igjen", over = "%d tegn for mye" }
    |> Textfield.view [ Attr.value model.reason, Events.onInput ChangedReason ]

The attributes you give view go on the <input /> or <textarea>, like React's rest props. Attributes for the field around it go in withFieldAttributes.

It's built on Field, so <ds-field> links the label, description, counter and error to the input and sets aria-invalid while there is an error. For anything this module doesn't do, build the field yourself from the same parts.

React → Elm

  • <Textfield label="…" /> → Textfield.new (Ds.label "…") |> Textfield.view []
  • aria-label="…" → Textfield.new (Ds.ariaLabel "…")
  • multiline → Textfield.multiline (Ds.label "…")
  • description={…} → Textfield.withDescription [ … ]
  • prefix="NOK" → Textfield.withPrefix "NOK"
  • suffix="kr" → Textfield.withSuffix "kr"
  • counter={140} → Textfield.withCounter { limit = 140, under = "…", over = "…" }
  • error="…" → Textfield.withError (Just "…")
  • className, style, data-size → Textfield.withFieldAttributes [ … ]
  • type, value, onChange, … → Textfield.view [ Attr.type_ …, Attr.value …, Events.onInput … ]

React's counter falls back to Norwegian texts. Here you give both, in your app's language.

type Textfield msg

A text field being configured. Start with new or multiline, end with view.

new : Label msg -> Textfield msg

A one-line text field (an <input />) with this accessible name. With Ds.label the label is shown above it.

multiline : Label msg -> Textfield msg

A text field for longer text (a <textarea>) with this accessible name.

view : List (Attribute msg) -> Textfield msg -> Html msg

Render the field. The attributes go on the <input /> or <textarea>.

Leave out aria-describedby and aria-invalid. The field sets them.

Options

withDescription : List (Html msg) -> Textfield msg -> Textfield msg

Help text between the label and the input.

withPrefix : String -> Textfield msg -> Textfield msg

A short text in front of the input, like "NOK" or "https://". Screen readers skip it, so make sure the label says the same thing.

withSuffix : String -> Textfield msg -> Textfield msg

A short text after the input, like "kr" or "pr. mnd.". Screen readers skip it, so make sure the label says the same thing.

withCounter : Counter -> Textfield msg -> Textfield msg

Count characters against a limit. See Field.counter.

withError : Maybe String -> Textfield msg -> Textfield msg

An error message under the input, or Nothing for none:

|> Textfield.withError (Dict.get "email" model.errors)

It's a String because an error is read aloud with the input, and the same text usually goes in an ErrorSummary too. Keep one list of errors for both and get this field's message with ErrorSummary.messageFor.

withFieldAttributes : List (Attribute msg) -> Textfield msg -> Textfield msg

Attributes for the <ds-field> around everything: Ds.size, a class, …