[{"name":"Designsystemet","comment":" Designsystemet for Elm: the components of\n[`@digdir/designsystemet-react`](https://www.npmjs.com/package/@digdir/designsystemet-react),\nas plain Elm view functions.\n\nThe markup matches the React components. Styling comes from\n`@digdir/designsystemet-css` plus your theme. Behaviour (tabs, popovers, dialog\ninvokers, field wiring, tooltips) comes from `@digdir/designsystemet-web`,\nloaded by the npm package `@ensolabs/designsystemet-elm`. Import both once in\nyour JavaScript entry point:\n\n    import \"@digdir/designsystemet-css\";\n    import \"@digdir/designsystemet-css/theme\"; // or your own generated theme\n    import \"@ensolabs/designsystemet-elm\";\n\nMost modules are imported qualified by their short name:\n\n    import Designsystemet as Ds\n    import Designsystemet.Button as Button\n    import Designsystemet.Color as Color\n\n    Button.view [ Ds.color Color.danger, Events.onClick Delete ] [ Html.text \"Slett\" ]\n\n\n# Port version\n\n@docs version\n\n\n# Size and color\n\n`data-size` and `data-color` apply to the element and every Designsystemet\ncomponent inside it, so you can set them on a single component or on a `div`\naround a whole form.\n\n@docs size, color\n\n\n# Color scheme\n\n@docs ColorScheme, colorScheme\n\n\n# Accessible names\n\n@docs Label, label, labelHtml, ariaLabel, labelledBy\n\n","unions":[{"name":"ColorScheme","comment":" Light, dark, or whatever the user's system prefers.\n","args":[],"cases":[["Light",[]],["Dark",[]],["Auto",[]]]}],"aliases":[{"name":"Label","comment":" How a form control gets its accessible name.\n\nReact accepts exactly one of `label`, `aria-label` and `aria-labelledby`.\nHere a control with no name, or two, does not compile.\n\nOpaque (the docs show the internal module it lives in). Build one with [`label`](#label), [`labelHtml`](#labelHtml), [`ariaLabel`](#ariaLabel)\nor [`labelledBy`](#labelledBy).\n\n","args":["msg"],"type":"Designsystemet.Internal.Label.Label msg"}],"values":[{"name":"ariaLabel","comment":" An invisible label, read by screen readers only.\n","type":"String.String -> Designsystemet.Label msg"},{"name":"color","comment":" Set `data-color` on an element.\n\n    Html.section [ Ds.color Color.neutral ] [{- buttons, tags, ... -}]\n\n","type":"Designsystemet.Color.Color -> Html.Attribute msg"},{"name":"colorScheme","comment":" Set `data-color-scheme` on an element, typically the root of your app.\n","type":"Designsystemet.ColorScheme -> Html.Attribute msg"},{"name":"label","comment":" A visible text label.\n","type":"String.String -> Designsystemet.Label msg"},{"name":"labelHtml","comment":" A visible label with markup in it.\n","type":"List.List (Html.Html msg) -> Designsystemet.Label msg"},{"name":"labelledBy","comment":" The `id` of another element on the page that names the control.\n\nA plain `String` rather than a typed id like `Dialog.Id`, because the target\nis usually not rendered by this package.\n\n","type":"String.String -> Designsystemet.Label msg"},{"name":"size","comment":" Set `data-size` on an element.\n\n    Html.form [ Ds.size Size.sm ] [{- every field in here is small -}]\n\n","type":"Designsystemet.Size.Size -> Html.Attribute msg"},{"name":"version","comment":" The version of this port, `\"1.23.0\"`.\n\nThis is the `@digdir/designsystemet-react` version it mirrors, and the\n`-css` and `-web` versions it expects at runtime. Fixes to the port alone add\na suffix: `\"1.23.0-1\"`, `\"1.23.0-2\"`.\n\nThe npm package `@ensolabs/designsystemet-elm` shares this version. The Elm\npackage has its own, since the registry only accepts plain semver.\n\n","type":"String.String"}],"binops":[]},{"name":"Designsystemet.Alert","comment":" A message to the user: information, a warning, an error or a success.\n\nMirrors `Alert` from `@digdir/designsystemet-react`.\n\n    import Designsystemet.Alert as Alert\n    import Designsystemet.Color exposing (Severity(..))\n    import Designsystemet.Heading as Heading\n    import Designsystemet.Paragraph as Paragraph\n\n    Alert.view Warning\n        []\n        [ Heading.h2 [ Heading.size Heading.ExtraSmall ] [ Html.text \"Fristen nærmer seg\" ]\n        , Paragraph.view [] [ Html.text \"Søknaden må sendes innen fredag.\" ]\n        ]\n\nThe CSS adds an icon for the severity, aligned with the heading if the alert\nstarts with one.\n\nScreen readers don't announce an alert by default. If it appears in response\nto a user action, add `Attr.attribute \"role\" \"alert\"` (for\nerrors) or `Attr.attribute \"role\" \"status\"`, and render the container before\nits content changes.\n\n\n# React → Elm\n\n  - `<Alert>` (defaults to info) → `Alert.view Info []`\n  - `data-color=\"danger\"` → `Alert.view Danger []`\n\nThe CSS only styles the four severities, so the color is a required\n[`Severity`](Designsystemet-Color#Severity) rather than any\n[`Color`](Designsystemet-Color#Color).\n\n@docs view\n\n","unions":[],"aliases":[],"values":[{"name":"view","comment":" A `<div class=\"ds-alert\">` in a severity color.\n\nThe severity overrides any `data-color` in the attributes.\n\n","type":"Designsystemet.Color.Severity -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Avatar","comment":" A person or organisation shown as initials, a picture or an icon in a\ncircle.\n\nMirrors `Avatar` from `@digdir/designsystemet-react`.\n\n    Avatar.view { name = Avatar.Label \"Kari Nordmann\", content = Avatar.Initials \"KN\" } []\n\n    Avatar.view\n        { name = Avatar.Tooltip \"Ola Nordmann\"\n        , content = Avatar.Image \"/profiles/ola.jpg\"\n        }\n        [ Avatar.size Avatar.Small ]\n\nThe config has two parts:\n\n  - [`Name`](#Name), what screen readers announce: a label, a label that also\n    shows as a tooltip, or nothing when the name is already next to it.\n  - [`Content`](#Content), what it shows: initials, a picture, an icon, or the\n    default person silhouette.\n\n\n# React → Elm\n\n  - `<Avatar aria-label=\"Kari\">KN</Avatar>` → `Avatar.view { name = Label \"Kari\", content = Initials \"KN\" } []`\n  - `<Avatar data-tooltip=\"Kari\">…` → `{ name = Tooltip \"Kari\", … }`\n  - `<Avatar aria-hidden>…` → `{ name = Decorative, … }`\n  - `<Avatar …><img src=\"…\" alt=\"\" /></Avatar>` → `{ content = Image \"…\", … }`\n  - `<Avatar …><Icon /></Avatar>` → `{ content = Icon icon, … }`\n  - `<Avatar … />` (no children) → `{ content = Placeholder, … }`\n  - `data-size=\"xs\"` → `Avatar.size Avatar.ExtraSmall`\n  - `asChild` + `<a>` → `Avatar.viewAs Html.a { … } [ Attr.href \"…\" ]`\n\nReact's deprecated `initials`, `data-initials` and `variant` props are not\nported. For a square avatar, set the CSS variable:\n`Attr.attribute \"style\" \"--dsc-avatar-radius: var(--ds-border-radius-md)\"`.\n(`Attr.style` can't set custom properties, the names starting with `--`.)\n\n\n# Managed by designsystemet-web\n\nWith a `Tooltip` name, `@digdir/designsystemet-web` shows the tooltip popover\nand keeps the accessible name in sync with `data-tooltip`. On\n[`view`](#view) (`role=\"img\"`) that is the `aria-label` this module already\nrenders, so nothing changes. On [`viewAs`](#viewAs) with `Initials` the element\nhas its own text, so the web layer moves the name from `aria-label` to\n`aria-description`: the link or button is announced by its initials, with the\nname as description. Use a `Label` name if the name must be the accessible\nname.\n\n@docs view, viewAs\n\n\n# Name and content\n\n@docs Name, Content\n\n\n# Sizes\n\n@docs Size, size\n\n","unions":[{"name":"Content","comment":" What the avatar shows.\n\n  - `Initials \"KN\"`: one to three letters, upper-cased by the CSS.\n  - `Image src`: `<img src=\"…\" alt=\"\">`. The `alt` is empty because the\n    [`Name`](#Name) already names the avatar.\n  - `Icon icon`: for example a building for an organisation.\n  - `Placeholder`: the default person silhouette from the CSS.\n\n","args":["msg"],"cases":[["Initials",["String.String"]],["Image",["String.String"]],["Icon",["Html.Html msg"]],["Placeholder",[]]]},{"name":"Name","comment":" Who the avatar is, for assistive technology.\n\n  - `Label name`: the avatar's `aria-label`.\n  - `Tooltip name`: the `aria-label`, also shown as a tooltip on hover and\n    focus. Adds `tabindex=\"0\"` so keyboard users can reach the tooltip.\n  - `Decorative`: `aria-hidden=\"true\"`, for when the name is written next to\n    the avatar.\n\n","args":[],"cases":[["Label",["String.String"]],["Tooltip",["String.String"]],["Decorative",[]]]},{"name":"Size","comment":" [`Designsystemet.Size`](Designsystemet-Size) plus `ExtraSmall`.\n","args":[],"cases":[["ExtraSmall",[]],["Small",[]],["Medium",[]],["Large",[]]]}],"aliases":[],"values":[{"name":"size","comment":" Set the avatar's `data-size`.\n","type":"Designsystemet.Avatar.Size -> Html.Attribute msg"},{"name":"view","comment":" A `<span class=\"ds-avatar\" role=\"img\">`.\n","type":"{ name : Designsystemet.Avatar.Name, content : Designsystemet.Avatar.Content msg } -> List.List (Html.Attribute msg) -> Html.Html msg"},{"name":"viewAs","comment":" An avatar rendered as another element than `<span>` (React's `asChild`),\ntypically a profile link or a menu button. The element keeps its own role, so\nthere is no `role=\"img\"`.\n\n    Avatar.viewAs Html.a\n        { name = Avatar.Label \"Min profil\", content = Avatar.Initials \"KN\" }\n        [ Attr.href \"/profil\" ]\n\n","type":"(List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg) -> { name : Designsystemet.Avatar.Name, content : Designsystemet.Avatar.Content msg } -> List.List (Html.Attribute msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.AvatarStack","comment":" **Experimental.** A row of overlapping [avatars](Designsystemet-Avatar),\nshowing who is involved.\n\nMirrors `EXPERIMENTAL_AvatarStack` from `@digdir/designsystemet-react`. The\nAPI may change in a minor version, as it may upstream.\n\n    AvatarStack.new\n        |> AvatarStack.withExpand AvatarStack.Grow\n        |> AvatarStack.withOverflow \"+3\"\n        |> AvatarStack.view [ Attr.attribute \"aria-label\" \"Saksbehandlere\" ]\n            (List.map viewCaseworker (List.take 4 caseworkers))\n\nEach avatar gets its own `<li>`.\n\n\n# React → Elm\n\n  - `<EXPERIMENTAL_AvatarStack>` → `AvatarStack.new |> AvatarStack.view []`\n  - `expandable` → `AvatarStack.withExpand AvatarStack.Grow`\n  - `expandable=\"fixed\"` → `AvatarStack.withExpand AvatarStack.ReserveSpace`\n  - trailing `<li>+5</li>` → `AvatarStack.withOverflow \"+5\"`\n  - `style={{ '--dsc-avatar-stack-size': … }}` → `Attr.attribute \"style\" \"--dsc-avatar-stack-size: …\"`\n\nThe deprecated `gap`, `avatarSize`, `overlap` and `suffix` props are not\nported: use the CSS variables `--dsc-avatar-stack-gap`,\n`--dsc-avatar-stack-size` and `--dsc-avatar-stack-overlap`, and\n[`withOverflow`](#withOverflow).\n\nSet CSS variables with `Attr.attribute \"style\"`, since `Attr.style` can't set\ncustom properties (names starting with `--`).\n\n@docs AvatarStack, new, view\n\n\n# Options\n\n@docs withExpand, Expand\n@docs withOverflow\n\n","unions":[{"name":"AvatarStack","comment":" Stack options. Start with [`new`](#new), add `with*` options, then\n[`view`](#view).\n","args":[],"cases":[]},{"name":"Expand","comment":" How the avatars spread out to their full size on hover and keyboard focus.\n\n  - `Grow`: the stack widens as the avatars spread, pushing its neighbours.\n  - `ReserveSpace`: the stack always takes the expanded width, so nothing\n    around it moves.\n\n","args":[],"cases":[["Grow",[]],["ReserveSpace",[]]]}],"aliases":[],"values":[{"name":"new","comment":" A stack that doesn't expand and has no overflow text.\n","type":"Designsystemet.AvatarStack.AvatarStack"},{"name":"view","comment":" A `<ul class=\"ds-avatar-stack\">` with each avatar in an `<li>`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Designsystemet.AvatarStack.AvatarStack -> Html.Html msg"},{"name":"withExpand","comment":" Spread the avatars out on hover and focus. Adds `tabindex=\"0\"` so\nkeyboard users can expand it too.\n","type":"Designsystemet.AvatarStack.Expand -> Designsystemet.AvatarStack.AvatarStack -> Designsystemet.AvatarStack.AvatarStack"},{"name":"withOverflow","comment":" Text after the avatars for the ones not shown, such as `\"+5\"`.\n","type":"String.String -> Designsystemet.AvatarStack.AvatarStack -> Designsystemet.AvatarStack.AvatarStack"}],"binops":[]},{"name":"Designsystemet.Badge","comment":" A small, non-interactive marker: a dot for \"something new\", or a count.\n\nMirrors `Badge` and `Badge.Position` from `@digdir/designsystemet-react`.\n\n    Badge.position { placement = Badge.TopRight, overlap = Badge.Rectangle }\n        []\n        [ Badge.view (Badge.Capped { count = model.unread, max = 99 }) [ Ds.color Color.danger ]\n        , inboxIcon\n        ]\n\nThe CSS draws the number from `data-count`, so screen readers don't read it.\nPut it in words where it matters, for example in the `aria-label` of the\nbutton the badge sits on (\"Innboks, 3 uleste\").\n\n\n# React → Elm\n\n  - `<Badge />` → `Badge.view Badge.Dot []`\n  - `<Badge count={5} />` → `Badge.view (Badge.Count 5) []`\n  - `<Badge count={120} maxCount={99} />` → `Badge.view (Badge.Capped { count = 120, max = 99 }) []`\n  - `variant=\"tinted\"` → `Badge.tinted`\n  - `<Badge.Position placement overlap>` → `Badge.position { placement = …, overlap = … } []`\n\nReact ignores `maxCount` without `count`. Here it can't be written.\n\n@docs view, Content, toLabel\n\n\n# Variants\n\n@docs base, tinted\n\n\n# Positioning\n\n@docs position, Corner, Overlap\n\n","unions":[{"name":"Content","comment":" What a badge shows.\n\n  - `Dot`: a marker with no number.\n  - `Count n`: the number `n`.\n  - `Capped { count, max }`: the number, or `\"99+\"` once `count` passes `max`.\n\n","args":[],"cases":[["Dot",[]],["Count",["Basics.Int"]],["Capped",["{ count : Basics.Int, max : Basics.Int }"]]]},{"name":"Corner","comment":" The corner of the element the badge sits on. Unlike\n[`Designsystemet.Placement`](Designsystemet-Placement), it overlaps the\nelement.\n","args":[],"cases":[["TopRight",[]],["TopLeft",[]],["BottomRight",[]],["BottomLeft",[]]]},{"name":"Overlap","comment":" The shape of the element under the badge. Over a `Circle`, such as an\n[`Avatar`](Designsystemet-Avatar), the badge moves in to the circle's edge\ninstead of the bounding box corner.\n","args":[],"cases":[["Rectangle",[]],["Circle",[]]]}],"aliases":[],"values":[{"name":"base","comment":" A solid badge, the default.\n","type":"Html.Attribute msg"},{"name":"position","comment":" A `<span class=\"ds-badge--position\">` that floats the\n[`Badge`](#view) inside it over a corner of the other content.\n\n    Badge.position { placement = Badge.TopRight, overlap = Badge.Circle }\n        []\n        [ Badge.view Badge.Dot [ Ds.color Color.success ]\n        , Avatar.view { name = Avatar.Label \"Kari Nordmann\", content = Avatar.Initials \"KN\" } []\n        ]\n\nReact defaults to `TopRight` and `Rectangle`. The CSS needs both, so here they\nare required.\n\n","type":"{ placement : Designsystemet.Badge.Corner, overlap : Designsystemet.Badge.Overlap } -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"tinted","comment":" A softer badge with a tinted background.\n","type":"Html.Attribute msg"},{"name":"toLabel","comment":" The text a badge shows, or `Nothing` for a dot. Use it for screen-reader\ntext.\n\n    toLabel Dot == Nothing\n\n    toLabel (Count 5) == Just \"5\"\n\n    toLabel (Capped { count = 5, max = 9 }) == Just \"5\"\n\n    toLabel (Capped { count = 10, max = 9 }) == Just \"9+\"\n\nAs in React, a `max` of `0` means no cap. Negative numbers aren't checked, so\nkeep `count` and `max` at zero or above.\n\n","type":"Designsystemet.Badge.Content -> Maybe.Maybe String.String"},{"name":"view","comment":" A `<span class=\"ds-badge\">`. It has no children and shows its\n[`Content`](#Content).\n","type":"Designsystemet.Badge.Content -> List.List (Html.Attribute msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Breadcrumbs","comment":" The current page's place in the site hierarchy, with links to each level\nabove it.\n\nMirrors `Breadcrumbs` from `@digdir/designsystemet-react`.\n\n    Breadcrumbs.new { label = \"Du er her:\" }\n        |> Breadcrumbs.withBackLink { label = \"Tilbake til Saker\" }\n        |> Breadcrumbs.view []\n            [ Breadcrumbs.link [ Attr.href \"/\" ] [ Html.text \"Forside\" ]\n            , Breadcrumbs.link [ Attr.href \"/saker\" ] [ Html.text \"Saker\" ]\n            , Breadcrumbs.link [ Attr.href \"/saker/42\" ] [ Html.text \"Sak 42\" ]\n            ]\n\nThe last link is the current page. `designsystemet-web` marks it with\n`aria-current=\"page\"`.\n\nWide screens show the whole trail. Narrow screens show only the back link from\n[`withBackLink`](#withBackLink), if there is one.\n\n\n# React → Elm\n\n  - `<Breadcrumbs aria-label=\"Du er her:\">` → `Breadcrumbs.new { label = \"Du er her:\" }`\n  - `<Breadcrumbs.List>` + `Item` + `Link` → `Breadcrumbs.link [ Attr.href \"…\" ] […]` in `view`\n  - `<Breadcrumbs.Link aria-label=\"Tilbake til …\">` → `Breadcrumbs.withBackLink { label = \"Tilbake til …\" }`\n  - a lone `<Breadcrumbs.Link aria-label=\"…\">` → `Breadcrumbs.backOnly { label = \"…\" } [ Attr.href \"…\" ] […]`\n\n\n# Differences from React\n\n  - The `aria-label` is required: there is no Norwegian default.\n  - The back link is built from the second-to-last link and your label, so it\n    can't point at the wrong place.\n\n\n# Managed by designsystemet-web\n\nDon't set `role`, `aria-current` on the links, or (after the first render)\n`aria-label`. The web layer removes `aria-label` on narrow screens, where only\nthe back link shows, and Elm only writes it again if you change it.\n\n@docs Breadcrumbs, new, withBackLink, view\n@docs backOnly\n@docs Link, link\n\n","unions":[{"name":"Breadcrumbs","comment":" Breadcrumbs being configured. Start with [`new`](#new), finish with\n[`view`](#view).\n","args":[],"cases":[]},{"name":"Link","comment":" One level in the trail.\n","args":["msg"],"cases":[]}],"aliases":[],"values":[{"name":"backOnly","comment":" Only a link to the level above, on every screen size, for pages without a\ntrail.\n\n    Breadcrumbs.backOnly { label = \"Tilbake til Saker\" }\n        [ Attr.href \"/saker\" ]\n        [ Html.text \"Saker\" ]\n\nThe attributes and children go on the link. `label` is its screen-reader name.\n\n","type":"{ label : String.String } -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"link","comment":" A link to one level, an `<a class=\"ds-link\">`. Give it an `href`.\n\n    Breadcrumbs.link [ Attr.href \"/saker\" ] [ Html.text \"Saker\" ]\n\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Designsystemet.Breadcrumbs.Link msg"},{"name":"new","comment":" Breadcrumbs with a name for screen readers, like `\"Du er her:\"`.\n","type":"{ label : String.String } -> Designsystemet.Breadcrumbs.Breadcrumbs"},{"name":"view","comment":" A `<ds-breadcrumbs class=\"ds-breadcrumbs\">`. List the links from the top\nlevel down to the current page.\n","type":"List.List (Html.Attribute msg) -> List.List (Designsystemet.Breadcrumbs.Link msg) -> Designsystemet.Breadcrumbs.Breadcrumbs -> Html.Html msg"},{"name":"withBackLink","comment":" Add a link to the level above the current page (the second-to-last link).\nNarrow screens show it instead of the trail. It has that link's text; `label`\nis what screen readers announce, like `\"Tilbake til Saker\"`.\n\nWith fewer than two links, no back link is rendered.\n\n","type":"{ label : String.String } -> Designsystemet.Breadcrumbs.Breadcrumbs -> Designsystemet.Breadcrumbs.Breadcrumbs"}],"binops":[]},{"name":"Designsystemet.Button","comment":" Buttons start actions.\n\nMirrors `Button` from `@digdir/designsystemet-react`.\n\n    Button.view [ Events.onClick Save ] [ Html.text \"Lagre\" ]\n\n    Button.view [ Button.secondary, Ds.color Color.danger, Events.onClick Delete ]\n        [ Html.text \"Slett\" ]\n\nButtons default to `type=\"button\"` so they never submit a form by accident.\nPass `Attr.type_ \"submit\"` for a submit button.\n\n\n# React → Elm\n\n  - `<Button>` → `Button.view []`\n  - `variant=\"secondary\"` → `Button.secondary`\n  - `loading` → `Button.loading Busy []`\n  - `icon` + `aria-label` → `Button.icon { label = \"…\", icon = … } []`\n  - `asChild` + `<a>` → `Button.viewAs Html.a [ Attr.href \"…\" ]`\n  - `command` / `commandfor` → `Dialog.showModal id`, `Popover.toggle id`, …\n\n@docs view, viewAs\n\n\n# Variants\n\n@docs primary, secondary, tertiary\n\n\n# Busy buttons\n\n@docs loading, Loading\n\n\n# Icon buttons\n\n@docs icon, iconLoading\n\n","unions":[{"name":"Loading","comment":" Whether a button is waiting for something.\n\n`BusyWith` replaces the spinner with your own loader.\n\n","args":["msg"],"cases":[["Idle",[]],["Busy",[]],["BusyWith",["Html.Html msg"]]]}],"aliases":[],"values":[{"name":"icon","comment":" An icon-only button. The label is required and becomes the `aria-label`,\nsince screen readers can't read the icon.\n\n    Button.icon { label = \"Lukk\", icon = FeatherIcons.x |> FeatherIcons.toHtml [] }\n        [ Button.tertiary, Events.onClick Close ]\n\n","type":"{ label : String.String, icon : Html.Html msg } -> List.List (Html.Attribute msg) -> Html.Html msg"},{"name":"iconLoading","comment":" An icon button that can be busy. While busy, the spinner takes the icon's\nplace.\n","type":"Designsystemet.Button.Loading msg -> { label : String.String, icon : Html.Html msg } -> List.List (Html.Attribute msg) -> Html.Html msg"},{"name":"loading","comment":" A button that can be busy. While busy it gets `aria-busy=\"true\"` and a\nspinner before its label.\n\n    Button.loading\n        (if model.saving then\n            Busy\n\n         else\n            Idle\n        )\n        [ Events.onClick Save ]\n        [ Html.text \"Lagre\" ]\n\nPrefer mapping your own state to `Loading` over an `if`:\n\n    Button.loading (Request.toLoading model.save) [ Events.onClick Save ] [ Html.text \"Lagre\" ]\n\n","type":"Designsystemet.Button.Loading msg -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"primary","comment":" The default, for the main action in a context.\n","type":"Html.Attribute msg"},{"name":"secondary","comment":" For actions next to a primary one.\n","type":"Html.Attribute msg"},{"name":"tertiary","comment":" For low-emphasis actions.\n","type":"Html.Attribute msg"},{"name":"view","comment":" A `<button class=\"ds-button\" type=\"button\">`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"viewAs","comment":" A button rendered as another element than `<button>` (React's `asChild`).\n\n    Button.viewAs Html.a [ Attr.href \"/ny\" ] [ Html.text \"Ny sak\" ]\n\n","type":"(List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg) -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Card","comment":" Cards group content about one thing.\n\nMirrors `Card` and `Card.Block` from `@digdir/designsystemet-react`.\n\n    Card.view []\n        [ Heading.h3 [] [ Html.text \"Byggesak 2024/118\" ]\n        , Paragraph.view [] [ Html.text \"Tilbygg, Storgata 4\" ]\n        ]\n\nSplit a card into sections with [`block`](#block). Blocks are separated by\nlines, and a block holding only an image or video goes edge to edge:\n\n    Card.view []\n        [ Card.block [] [ Html.img [ Attr.src \"/bilder/storgata-4.jpg\", Attr.alt \"\" ] [] ]\n        , Card.block [] [ Heading.h3 [] [ Html.text \"Storgata 4\" ] ]\n        ]\n\n\n# React → Elm\n\n  - `<Card>` → `Card.view []`\n  - `variant=\"tinted\"` → `Card.tinted`\n  - `<Card.Block>` → `Card.block []`\n  - `asChild` + `<a href>` → `Card.viewAs Html.a [ Attr.href \"…\" ]`\n  - `<Card.Block asChild>` → `Card.blockAs Html.section []`\n  - a `<Heading><a>` inside (auto-detected) → `Card.clickable id []` + `Card.mainLink id` on the link\n\n\n# Managed by designsystemet-web\n\nIn a [`clickable`](#clickable) card, `@digdir/designsystemet-web` forwards\nclicks to the main link and adds a `:click-delegate-hover` class to the link\nwhile the pointer is over the card. Keep the main link's `class` stable\nbetween renders, or the hover style flickers.\n\n@docs view, viewAs\n\n\n# Variants\n\n@docs tinted\n\n\n# Blocks\n\n@docs block, blockAs\n\n\n# Clickable cards\n\n@docs clickable, clickableAs, LinkId, linkId, linkIdToString, mainLink\n\n","unions":[{"name":"LinkId","comment":" The `id` of the link a [`clickable`](#clickable) card sends its clicks to.\nA separate type, so it only fits [`mainLink`](#mainLink).\n","args":[],"cases":[]}],"aliases":[],"values":[{"name":"block","comment":" A `<div class=\"ds-card__block\">`: a section of a card, with a line between\nit and the next.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"blockAs","comment":" A block rendered as another element (`Card.Block`'s `asChild`).\n\n    Card.blockAs Html.footer [] [ Html.text \"Sist endret 3. mars\" ]\n\n","type":"(List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg) -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"clickable","comment":" A card where a click anywhere opens its main link. Other links and buttons\ninside still work.\n\nThe link stays a single `<a>`, so screen readers and keyboard users get one\nlink with a short name instead of the card's whole text. Put it in the\nheading: the CSS underlines the heading and gives the card a hover state.\n\n    viewCase : Case -> Html Msg\n    viewCase case_ =\n        let\n            link =\n                caseLink case_\n        in\n        Card.clickable link\n            []\n            [ Heading.h3 []\n                [ Html.a [ Card.mainLink link, Attr.href (Route.toString (Route.Case case_.id)) ]\n                    [ Html.text case_.title ]\n                ]\n            , Paragraph.view [] [ Html.text case_.address ]\n            , Button.view [ Button.tertiary, Events.onClick (Archive case_.id) ] [ Html.text \"Arkiver\" ]\n            ]\n\nReact finds the first link in a heading after rendering. Elm doesn't read the\nDOM, so you name the link, and the shared `LinkId` keeps card and link in\nsync.\n\n`@digdir/designsystemet-web` forwards the clicks (`data-clickdelegatefor`).\nCtrl-, Cmd- and middle-clicks open a new tab, as on the link itself.\n\n","type":"Designsystemet.Card.LinkId -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"clickableAs","comment":" A clickable card as another element, such as a list item or an article:\n\n    Html.ul []\n        (List.map\n            (\\case_ ->\n                Card.clickableAs Html.li (caseLink case_) [] [{- … -}]\n            )\n            cases\n        )\n\n","type":"(List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg) -> Designsystemet.Card.LinkId -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"linkId","comment":" Make a `LinkId` from an id that is unique on the page.\n\n    caseLink : Case -> Card.LinkId\n    caseLink case_ =\n        Card.linkId (\"sak-\" ++ Case.idToString case_.id)\n\n","type":"String.String -> Designsystemet.Card.LinkId"},{"name":"linkIdToString","comment":" The id as a string, for `Browser.Dom.focus` and the like.\n","type":"Designsystemet.Card.LinkId -> String.String"},{"name":"mainLink","comment":" Sets the `id` of the card's main link.\n","type":"Designsystemet.Card.LinkId -> Html.Attribute msg"},{"name":"tinted","comment":" A tinted background instead of the default surface.\n","type":"Html.Attribute msg"},{"name":"view","comment":" A `<div class=\"ds-card\">`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"viewAs","comment":" A card rendered as another element than `<div>` (React's `asChild`). Use\nit for a semantic container (`Html.article`, `Html.li`), or to make the whole\ncard one link or button:\n\n    Card.viewAs Html.a\n        [ Attr.href \"/saker/118\" ]\n        [ Heading.h3 [] [ Html.text \"Byggesak 2024/118\" ] ]\n\nA card that is one `<a>` can't contain other links or buttons. Use\n[`clickable`](#clickable) for that.\n\n","type":"(List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg) -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Checkbox","comment":" A checkbox with its label, description and error message.\n\nMirrors `Checkbox` from `@digdir/designsystemet-react`.\n\n    Checkbox.new (Ds.label \"Jeg har lest vilkårene\")\n        |> Checkbox.withError model.termsError\n        |> Checkbox.view [ Attr.checked model.acceptedTerms, Events.onCheck AcceptedTerms ]\n\nThe attributes you give `view` go on the `<input type=\"checkbox\">`, like\nReact's rest props. Attributes for the field around it (size, outline, position)\ngo in [`withFieldAttributes`](#withFieldAttributes).\n\nFor a group of checkboxes, put them in a [`Fieldset`](Designsystemet-Fieldset)\nwith a legend.\n\nFor a \"select all\" checkbox, add\n[`Input.indeterminate`](Designsystemet-Input#indeterminate) to the attributes.\n\n\n# React → Elm\n\n  - `<Checkbox label=\"…\" />` → `Checkbox.new (Ds.label \"…\") |> Checkbox.view []`\n  - `aria-label=\"…\"` → `Checkbox.new (Ds.ariaLabel \"…\")`\n  - `description={…}` → `Checkbox.withDescription [ … ]`\n  - `error=\"…\"` → `Checkbox.withError (Just \"…\")`\n  - `variant=\"outline\"` → `Checkbox.withFieldAttributes [ Field.outline ]`\n  - `position=\"end\"` → `Checkbox.withFieldAttributes [ Field.position Field.End ]`\n  - `data-size`, `className`, `style` → `Checkbox.withFieldAttributes [ … ]`\n  - `checked`, `value`, `onChange`, … → `Checkbox.view [ Attr.checked …, Events.onCheck … ]`\n  - `data-indeterminate` → `Checkbox.view [ Input.indeterminate ]`\n\nThe wrapper is a [`Field`](Designsystemet-Field): `<ds-field>` connects the\nlabel, description and error to the checkbox, so don't set `id`-based ARIA\nyourself.\n\n@docs Checkbox, new, view\n\n\n# Options\n\n@docs withDescription, withError, withFieldAttributes\n\n","unions":[{"name":"Checkbox","comment":" A checkbox being configured. Start with [`new`](#new), end with\n[`view`](#view).\n","args":["msg"],"cases":[]}],"aliases":[],"values":[{"name":"new","comment":" A checkbox with this accessible name. With\n[`Ds.label`](Designsystemet#label) the label is shown next to the box.\n","type":"Designsystemet.Label msg -> Designsystemet.Checkbox.Checkbox msg"},{"name":"view","comment":" The attributes go on the `<input>`.\n","type":"List.List (Html.Attribute msg) -> Designsystemet.Checkbox.Checkbox msg -> Html.Html msg"},{"name":"withDescription","comment":" Help text under the label.\n","type":"List.List (Html.Html msg) -> Designsystemet.Checkbox.Checkbox msg -> Designsystemet.Checkbox.Checkbox msg"},{"name":"withError","comment":" An error message under the checkbox, or `Nothing` for none. Pass your\nvalidation result in:\n\n    |> Checkbox.withError (Dict.get \"terms\" model.errors)\n\nThe checkbox gets `aria-invalid=\"true\"` while there is an error. With an\n[`ErrorSummary`](Designsystemet-ErrorSummary), read the message from the same\nlist with [`ErrorSummary.messageFor`](Designsystemet-ErrorSummary#messageFor).\n\n","type":"Maybe.Maybe String.String -> Designsystemet.Checkbox.Checkbox msg -> Designsystemet.Checkbox.Checkbox msg"},{"name":"withFieldAttributes","comment":" Attributes for the `<ds-field>` around the checkbox: `Field.outline`,\n`Field.position`, `Ds.size`, a class, …\n","type":"List.List (Html.Attribute msg) -> Designsystemet.Checkbox.Checkbox msg -> Designsystemet.Checkbox.Checkbox msg"}],"binops":[]},{"name":"Designsystemet.Chip","comment":" Small, rounded buttons for filters and choices.\n\nMirrors `Chip` from `@digdir/designsystemet-react`.\n\n    Html.div []\n        [ Chip.checkbox { name = \"status\", value = \"open\", checked = model.showOpen, onCheck = ShowOpenChecked }\n            []\n            [ Html.text \"Åpne saker\" ]\n        , Chip.checkbox { name = \"owner\", value = \"me\", checked = model.showMine, onCheck = ShowMineChecked }\n            []\n            [ Html.text \"Mine saker\" ]\n        ]\n\n    Html.div []\n        (List.map\n            (\\tag ->\n                Chip.removable { removeLabel = \"Trykk for å fjerne\" }\n                    [ Events.onClick (TagRemoved tag) ]\n                    [ Html.text tag ]\n            )\n            model.tags\n        )\n\n\n# React → Elm\n\n  - `<Chip.Button>` → `Chip.button []`\n  - `<Chip.Removable>` → `Chip.removable { removeLabel = \"Trykk for å fjerne\" } []`\n  - `<Chip.Checkbox checked onChange>` → `Chip.checkbox { name, value, checked, onCheck } []`\n  - `<Chip.Radio name checked onChange>` → `Chip.radio { name, value, checked, onSelect } []`\n  - `<Chip.Checkbox name value defaultChecked>` → `Chip.uncontrolledCheckbox { name, value, initiallyChecked = True } []`\n  - `<Chip.Radio name value defaultChecked>` → `Chip.uncontrolledRadio { name, value, initiallyChecked = True } []`\n  - `data-wrap=\"wrap\"` → `Chip.wrap`\n\n\n# Differences from React\n\n  - `Chip.removable` takes the text screen readers hear for removing the chip.\n    React relies on a CSS default (Norwegian, or English for other languages).\n    Here you pass it, and it becomes the `--dsc-chip-removable-label` custom\n    property.\n  - Checkbox and radio chips require a `name` and `value`, so they work in a\n    submitted form. React leaves them optional.\n  - On `Chip.checkbox` and `Chip.radio`, attributes go on the `<label>` so\n    `Ds.color` and `Chip.wrap` work. React puts them on the `<input>`.\n\n\n# Buttons\n\n@docs button, removable\n\n\n# Controlled choices\n\nYour model decides whether the chip is checked. Clicking sends a message.\n\n@docs checkbox, radio\n\n\n# Uncontrolled choices\n\nThe browser tracks the checked state. Use these in a plain submitted `<form>`,\nsuch as a search filter that becomes the query string.\n\n@docs uncontrolledCheckbox, uncontrolledRadio\n\n\n# Wrapping\n\n@docs wrap\n\n","unions":[],"aliases":[],"values":[{"name":"button","comment":" A `<button class=\"ds-chip\" type=\"button\">`, for an action.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"checkbox","comment":" A checkbox chip, usually one of several filters. Clicking sends `onCheck`\nwith the requested state.\n\n`name` and `value` are what a plain `<form>` submits when the chip is checked.\n\n","type":"{ name : String.String, value : String.String, checked : Basics.Bool, onCheck : Basics.Bool -> msg } -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"radio","comment":" A radio chip, for picking one of several. Give the chips in a group the\nsame `name`; `value` is what a plain `<form>` submits for the\nchecked one. Clicking an unchecked chip sends `onSelect`.\n\n    Html.div []\n        [ Chip.radio { name = \"language\", value = \"nb\", checked = model.language == Bokmal, onSelect = LanguageSelected Bokmal }\n            []\n            [ Html.text \"Bokmål\" ]\n        , Chip.radio { name = \"language\", value = \"nn\", checked = model.language == Nynorsk, onSelect = LanguageSelected Nynorsk }\n            []\n            [ Html.text \"Nynorsk\" ]\n        ]\n\n","type":"{ name : String.String, value : String.String, checked : Basics.Bool, onSelect : msg } -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"removable","comment":" A chip with an \"×\", for removing an active filter or a tag. Handle the\nclick yourself. `removeLabel` is what screen readers hear after the chip's\ntext, like `\"Trykk for å fjerne\"`.\n\n    Chip.removable { removeLabel = \"Trykk for å fjerne\" }\n        [ Events.onClick (FilterRemoved filter) ]\n        [ Html.text (Filter.toString filter) ]\n\nThe label is set through the chip's `style` attribute, so use classes rather\nthan `Attr.style` on a removable chip.\n\n","type":"{ removeLabel : String.String } -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"uncontrolledCheckbox","comment":" A checkbox chip whose state the browser tracks. `initiallyChecked` is the\nstate on first render.\n\n    Html.form [ Attr.action \"/saker\", Attr.method \"get\" ]\n        [ Chip.uncontrolledCheckbox { name = \"status\", value = \"open\", initiallyChecked = True }\n            []\n            [ Html.text \"Åpne saker\" ]\n        , Chip.uncontrolledCheckbox { name = \"status\", value = \"closed\", initiallyChecked = False }\n            []\n            [ Html.text \"Lukkede saker\" ]\n        ]\n\n","type":"{ name : String.String, value : String.String, initiallyChecked : Basics.Bool } -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"uncontrolledRadio","comment":" A radio chip whose state the browser tracks. Give the chips in a group the\nsame `name`, and `initiallyChecked = True` to at most one.\n","type":"{ name : String.String, value : String.String, initiallyChecked : Basics.Bool } -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"wrap","comment":" Wrap long text instead of truncating it with \"…\".\n","type":"Html.Attribute msg"}],"binops":[]},{"name":"Designsystemet.Color","comment":" The colors behind `data-color`. Use them with\n[`Designsystemet.color`](Designsystemet#color).\n\nYour theme decides which colors exist. A theme built at\n[theme.designsystemet.no](https://theme.designsystemet.no) has `neutral`,\nusually `accent`, your brand colors and the four severity colors, so\n[`custom`](#custom) takes any name. Keep those names in one module so a typo\ncan only happen once:\n\n    module Theme exposing (brand, highlight)\n\n    import Designsystemet.Color as Color exposing (Color)\n\n    brand : Color\n    brand =\n        Color.custom \"brand1\"\n\n\n# Theme colors\n\n@docs Color, accent, neutral, custom\n\n\n# Severity colors\n\nSome components, such as [`Alert`](Designsystemet-Alert), only make sense in\na severity color. They take a `Severity` instead of a `Color`, so they can't\nget a color the CSS doesn't style.\n\n@docs Severity, fromSeverity, info, success, warning, danger\n\n\n# Conversion\n\n@docs toString\n\n","unions":[{"name":"Color","comment":" A color name from your theme.\n","args":[],"cases":[]},{"name":"Severity","comment":" The four severities every theme has.\n","args":[],"cases":[["Info",[]],["Success",[]],["Warning",[]],["Danger",[]]]}],"aliases":[],"values":[{"name":"accent","comment":" The main color of the default theme.\n","type":"Designsystemet.Color.Color"},{"name":"custom","comment":" Any color your theme defines, like `\"brand1\"` or `\"hospital\"`.\n","type":"String.String -> Designsystemet.Color.Color"},{"name":"danger","comment":" `fromSeverity Danger`: Something went wrong, or can't be undone.\n","type":"Designsystemet.Color.Color"},{"name":"fromSeverity","comment":" A severity as a color, for components that take any color.\n","type":"Designsystemet.Color.Severity -> Designsystemet.Color.Color"},{"name":"info","comment":" `fromSeverity Info`: Neutral information.\n","type":"Designsystemet.Color.Color"},{"name":"neutral","comment":" Grey tones. Every theme has them.\n","type":"Designsystemet.Color.Color"},{"name":"success","comment":" `fromSeverity Success`: Something went well.\n","type":"Designsystemet.Color.Color"},{"name":"toString","comment":" The value written to `data-color`.\n","type":"Designsystemet.Color.Color -> String.String"},{"name":"warning","comment":" `fromSeverity Warning`: Something needs attention.\n","type":"Designsystemet.Color.Color"}],"binops":[]},{"name":"Designsystemet.Details","comment":" A heading that shows or hides the content below it when clicked.\n\nMirrors `Details` from `@digdir/designsystemet-react`.\n\n    Details.view\n        { summary = [ Html.text \"Hvem kan søke?\" ]\n        , content = [ Html.p [] [ Html.text \"Alle som er registrert i Enhetsregisteret.\" ] ]\n        }\n        []\n\nA native [`<details>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details):\nit opens and closes without Elm, and the browser opens it when find-in-page\nmatches text inside. Stack several for an accordion.\n\n\n# Native or controlled\n\n  - [`view`](#view): the browser tracks whether it is open. Nothing goes in\n    your model.\n  - [`controlled`](#controlled): your model decides, and clicking the summary\n    sends a message. Use it to open details from code, or to keep only one\n    open at a time.\n\n\n# React → Elm\n\n  - `<Details>` + `Summary` + `Content` → `Details.view { summary = […], content = […] } []`\n  - `defaultOpen` → `Details.initiallyOpen`\n  - `open` + `onToggle` → `Details.controlled { open, onToggle, summary, content } []`\n  - `variant=\"tinted\"` → `Details.tinted`\n\n\n# Managed by designsystemet-web\n\nDon't set `role` or `aria-expanded` on the summary: a polyfill sets them in\nbrowsers that announce `<details>` badly (Firefox with TalkBack).\n\n@docs view, initiallyOpen\n@docs controlled\n\n\n# Variants\n\n@docs tinted\n\n","unions":[],"aliases":[],"values":[{"name":"controlled","comment":" A `<details class=\"ds-details\">` that is open when `open` is `True`.\nClicking the summary, or pressing Enter or Space on it, sends `onToggle` with\nthe requested state. So does the browser opening it for find-in-page.\n\nHandle every `onToggle`. Elm can't undo the browser opening it for\nfind-in-page: if your model stays closed, the details stays open on screen\nuntil `open` changes.\n\n    Details.controlled\n        { open = model.expanded == Just Eligibility\n        , onToggle = EligibilityToggled\n        , summary = [ Html.text \"Hvem kan søke?\" ]\n        , content = [ eligibility ]\n        }\n        []\n\n","type":"{ open : Basics.Bool, onToggle : Basics.Bool -> msg, summary : List.List (Html.Html msg), content : List.List (Html.Html msg) } -> List.List (Html.Attribute msg) -> Html.Html msg"},{"name":"initiallyOpen","comment":" Start a [`view`](#view) open.\n\n    Details.view { summary = summary, content = content } [ Details.initiallyOpen ]\n\n","type":"Html.Attribute msg"},{"name":"tinted","comment":" A tinted background instead of the default surface color.\n","type":"Html.Attribute msg"},{"name":"view","comment":" A `<details class=\"ds-details\">` that the browser opens and closes. Starts\nclosed.\n","type":"{ summary : List.List (Html.Html msg), content : List.List (Html.Html msg) } -> List.List (Html.Attribute msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Dialog","comment":" A dialog over the page, for a task or message the user must deal with\nbefore continuing.\n\nMirrors `Dialog` from `@digdir/designsystemet-react`.\n\n    import Designsystemet.Button as Button\n    import Designsystemet.Dialog as Dialog\n\n    confirmDelete : Dialog.Id\n    confirmDelete =\n        Dialog.id \"confirm-delete\"\n\n    view : Html Msg\n    view =\n        Html.div []\n            [ Dialog.trigger confirmDelete [] [ Html.text \"Slett sak\" ]\n            , Dialog.new confirmDelete\n                |> Dialog.withCloseButton { label = \"Lukk dialogvindu\" }\n                |> Dialog.view [ Dialog.onClose DeleteDialogClosed ]\n                    [ Dialog.block [] [ Heading.h2 [] [ Html.text \"Slette saken?\" ] ]\n                    , Dialog.block []\n                        [ Button.view [ Events.onClick Delete ] [ Html.text \"Slett\" ]\n                        , Button.view (Button.secondary :: Dialog.close confirmDelete)\n                            [ Html.text \"Avbryt\" ]\n                        ]\n                    ]\n            ]\n\nThe dialog is a native [`<dialog>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog).\nOpen it in one of two ways:\n\n  - From a button, with an [invoker](#invokers) (`command`/`commandfor`,\n    polyfilled by `designsystemet-web`). No message or model field needed.\n  - From your model, with [`open`](#open) and a `Bool`. This is React's `open`\n    prop, for dialogs opened by an event (a timeout, a failed save) rather\n    than a click.\n\n\n# React → Elm\n\n  - `<Dialog id=\"x\">` → `Dialog.new (Dialog.id \"x\") |> Dialog.view [] […]`\n  - `closeButton=\"Lukk\"` (the default) → `Dialog.withCloseButton { label = \"Lukk\" }`\n  - `closeButton={false}` → leave out `withCloseButton`\n  - `<Dialog.Block>` → `Dialog.block []`\n  - `<Dialog.TriggerContext>` → not needed: share a `Dialog.Id`\n  - `<Dialog.Trigger>` → `Dialog.trigger id []`\n  - `<Button command=\"show-modal\" commandfor=\"x\">` → `Button.view (Dialog.showModal id)`\n  - `modal={false}` → `Dialog.nonModal`, or open with `Dialog.showNonModal id`\n  - `placement=\"right\"` → `Dialog.drawer Dialog.Right`\n  - `closedby=\"any\"` → `Dialog.closedByAny`\n  - `onClose` → `Dialog.onClose msg`\n  - `open={isOpen}` + `onClose` → `Dialog.open model.isOpen`, `Dialog.onClose Closed`\n\n\n# Differences from React\n\n  - The close button is opt-in and its label is required. There is no\n    Norwegian default.\n\n\n# Managed by designsystemet-web\n\n  - `aria-haspopup=\"dialog\"` on every button that opens a dialog, set on\n    focus. [`trigger`](#trigger) also renders it up front, as React's\n    `Dialog.Trigger` does. The value is the same, so they don't conflict.\n  - the `closedby=\"any\"` light dismiss, in browsers without native support.\n\n\n# Opening from your model\n\nOpening a dialog takes a method call (`showModal()`), which Elm can't make.\n[`open`](#open) renders the state as `data-open`, and the package's\nJavaScript syncs the element:\n\n```js\nimport \"@ensolabs/designsystemet-elm\"; // once, in your entry point\n```\n\n    Dialog.new sessionExpired\n        |> Dialog.view\n            [ Dialog.open model.sessionExpired\n            , Dialog.onClose SessionDialogClosed\n            ]\n            [{- … -}]\n\nWhen the user closes the dialog (Esc, a close button), it closes and sends\n[`onClose`](#onClose). Set your state back to closed there. Until you do,\n`open True` won't reopen it, since the attribute hasn't changed.\n\n\n# Ids\n\n@docs Id, id, idToString\n\n\n# Dialog\n\n@docs Dialog, new, withCloseButton, view\n\n\n# Content\n\n@docs block\n\n\n# Placement\n\n@docs drawer, Side\n\n\n# Open state\n\n@docs open, nonModal\n\n\n# Light dismiss\n\nHow the user can close the dialog without a close button. The default is\n`closedByCloseRequest` for modal dialogs (Esc closes it).\n\n@docs closedByAny, closedByCloseRequest, closedByNone\n\n\n# Events\n\n@docs onClose\n\n\n# Triggers\n\n@docs trigger\n\n\n# Invokers\n\n`command` and `commandfor` for any `<button>`: a\n[`Button`](Designsystemet-Button), a [`Dropdown`](Designsystemet-Dropdown)\nitem or a plain button. They are lists because the browser needs two\nattributes. Concatenate them with your own:\n\n    Button.view (Button.secondary :: Dialog.close confirmDelete) [ Html.text \"Avbryt\" ]\n\n@docs showModal, showNonModal, close, requestClose\n\n","unions":[{"name":"Dialog","comment":" A dialog being configured. Start with [`new`](#new), finish with\n[`view`](#view).\n","args":[],"cases":[]},{"name":"Id","comment":" The `id` that links a dialog to the buttons that open and close it.\n\nMake one per dialog, as a top-level value, and use it in both places. A\n`Dialog.Id` can't be given to a [`Popover`](Designsystemet-Popover) by\nmistake.\n\n","args":[],"cases":[]},{"name":"Side","comment":" The edge of the screen a drawer slides in from.\n","args":[],"cases":[["Left",[]],["Right",[]],["Top",[]],["Bottom",[]]]}],"aliases":[],"values":[{"name":"block","comment":" A section of the dialog, like a header, the body or a footer of buttons.\n\n    Dialog.view []\n        [ Dialog.block [] [ Heading.h2 [] [ Html.text \"Endre adresse\" ] ]\n        , Dialog.block [] [ addressForm ]\n        , Dialog.block [] [ saveButton, cancelButton ]\n        ]\n        dialog\n\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"close","comment":" Close the dialog immediately, as a \"Cancel\" button does.\n","type":"Designsystemet.Dialog.Id -> List.List (Html.Attribute msg)"},{"name":"closedByAny","comment":" Close on Esc and on a backdrop click. Good for dialogs that only show\ninformation.\n","type":"Html.Attribute msg"},{"name":"closedByCloseRequest","comment":" Close on Esc (or the Android back gesture), but not on a click\noutside.\n","type":"Html.Attribute msg"},{"name":"closedByNone","comment":" Close only from a button in the dialog. Use sparingly, since the user has\nno other way out.\n","type":"Html.Attribute msg"},{"name":"drawer","comment":" Show the dialog as a drawer along one edge of the screen instead of in the\ncenter.\n\n    Dialog.view [ Dialog.drawer Dialog.Right ] [ filterForm ] filters\n\n","type":"Designsystemet.Dialog.Side -> Html.Attribute msg"},{"name":"id","comment":" Name a dialog. The string becomes its DOM `id`, so it must be unique on\nthe page.\n\n    confirmDelete : Dialog.Id\n    confirmDelete =\n        Dialog.id \"confirm-delete\"\n\n","type":"String.String -> Designsystemet.Dialog.Id"},{"name":"idToString","comment":" The DOM `id`, for ports and tests.\n","type":"Designsystemet.Dialog.Id -> String.String"},{"name":"new","comment":" A dialog with no close button.\n","type":"Designsystemet.Dialog.Id -> Designsystemet.Dialog.Dialog"},{"name":"nonModal","comment":" No backdrop, and the page behind stays usable, when opened with\n[`open`](#open). React's `modal={false}`. Invoker buttons choose for\nthemselves with [`showNonModal`](#showNonModal).\n","type":"Html.Attribute msg"},{"name":"onClose","comment":" Sent when the dialog closes, by a close button, Esc, a backdrop click or\ncode.\n\n    Dialog.view [ Dialog.onClose EditDialogClosed ] [{- … -}] editDialog\n\nThe native `close` event. It doesn't bubble, so a nested dialog never\ntriggers it.\n\n","type":"msg -> Html.Attribute msg"},{"name":"open","comment":" Whether the dialog is open, from your model. Needs the companion script\n(see [Opening from your model](#opening-from-your-model)), and an\n[`onClose`](#onClose) that sets your state back when the user closes it.\n\n    Dialog.view [ Dialog.open model.confirming, Dialog.onClose ConfirmClosed ] [{- … -}]\n\n","type":"Basics.Bool -> Html.Attribute msg"},{"name":"requestClose","comment":" Ask the dialog to close, as Esc does. It fires a cancelable `cancel` event\nfirst, for example to warn about unsaved changes.\n","type":"Designsystemet.Dialog.Id -> List.List (Html.Attribute msg)"},{"name":"showModal","comment":" Open the dialog as a modal: the rest of the page is inert behind a\nbackdrop until it closes.\n","type":"Designsystemet.Dialog.Id -> List.List (Html.Attribute msg)"},{"name":"showNonModal","comment":" Open the dialog without a backdrop, leaving the rest of the page usable.\n","type":"Designsystemet.Dialog.Id -> List.List (Html.Attribute msg)"},{"name":"trigger","comment":" A [`Button`](Designsystemet-Button) that opens the dialog as a modal\n(React's `Dialog.Trigger`).\n\n    Dialog.trigger editAddress [ Button.secondary ] [ Html.text \"Endre adresse\" ]\n\nFor a non-modal dialog, use [`showNonModal`](#showNonModal) on a button\ninstead.\n\n","type":"Designsystemet.Dialog.Id -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"view","comment":" A `<dialog class=\"ds-dialog\">`, closed unless you give it [`open`](#open).\n\nPut content directly in it, or split it into [`block`](#block)s with their own\npadding and dividers.\n\nThe `id` always comes from the [`Id`](#Id) given to [`new`](#new), so triggers\nkeep pointing at it. An `Attr.id` in the attributes is ignored.\n\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Designsystemet.Dialog.Dialog -> Html.Html msg"},{"name":"withCloseButton","comment":" Add an \"×\" close button in the top corner. It has no visible text, so\n`label` is what screen readers announce.\n\n    Dialog.new confirmDelete\n        |> Dialog.withCloseButton { label = \"Lukk dialogvindu\" }\n        |> Dialog.view [] [{- … -}]\n\n","type":"{ label : String.String } -> Designsystemet.Dialog.Dialog -> Designsystemet.Dialog.Dialog"}],"binops":[]},{"name":"Designsystemet.Divider","comment":" A horizontal line between pieces of content.\n\nMirrors `Divider` from `@digdir/designsystemet-react`.\n\n    Card.view []\n        [ Card.block [] [ Html.text \"Søker\" ]\n        , Divider.view []\n        , Card.block [] [ Html.text \"Vedlegg\" ]\n        ]\n\n\n# React → Elm\n\n  - `<Divider />` → `Divider.view []`\n\n@docs view\n\n","unions":[],"aliases":[],"values":[{"name":"view","comment":" An `<hr class=\"ds-divider\" aria-hidden=\"true\">`. Hidden from screen\nreaders as decoration. Use headings if the separation matters.\n","type":"List.List (Html.Attribute msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Dropdown","comment":" A menu of actions or links that opens from a button.\n\nMirrors `Dropdown` from `@digdir/designsystemet-react`.\n\n    import Designsystemet.Dropdown as Dropdown\n\n    caseActions : Dropdown.Id\n    caseActions =\n        Dropdown.id \"case-actions\"\n\n    view : Html Msg\n    view =\n        Html.div []\n            [ Dropdown.trigger caseActions [ Button.secondary ] [ Html.text \"Handlinger\" ]\n            , Dropdown.view caseActions\n                []\n                [ Dropdown.heading Heading.H2 [] [ Html.text \"Sak 42\" ]\n                , Dropdown.list []\n                    [ Dropdown.item [] [ Dropdown.button [ Events.onClick Archive ] [ Html.text \"Arkiver\" ] ]\n                    , Dropdown.item [] [ Dropdown.button (Dialog.showModal confirmDelete) [ Html.text \"Slett\" ] ]\n                    ]\n                ]\n            ]\n\nA dropdown is a [`Popover`](Designsystemet-Popover) with menu styling. The\nbrowser opens it from the trigger and closes it on Esc or an outside click;\n`designsystemet-web` positions it. `Dropdown.Id` is a separate type, so a\npopover's id can't open a dropdown by mistake.\n\n\n# React → Elm\n\n  - `<Dropdown id=\"x\">` → `Dropdown.view (Dropdown.id \"x\") []`\n  - `<Dropdown.TriggerContext>` → not needed: share a `Dropdown.Id`\n  - `<Dropdown.Trigger>` → `Dropdown.trigger id []`\n  - `<Dropdown.Heading>` (level 2 by default) → `Dropdown.heading Heading.H2 []`\n  - `<Dropdown.List>` → `Dropdown.list []`\n  - `<Dropdown.Item>` → `Dropdown.item []`\n  - `<Dropdown.Button>` → `Dropdown.button []`\n  - `placement=\"top\"` → `Dropdown.placement Placement.Top`\n  - `open={isOpen}` (controlled) → `Dropdown.open model.isOpen`\n  - `onOpen` / `onClose` → `Dropdown.onToggle`\n\n\n# Differences from React\n\nLike [`Popover`](Designsystemet-Popover), the dropdown is `popover=\"auto\"`,\nso the browser handles light dismiss, which React does in JavaScript.\n\n\n# Managed by designsystemet-web\n\nAs for [`Popover`](Designsystemet-Popover): the position styles\n(`translate`, `scroll-margin-bottom`, `max-height`, `width`), the arrow's\n`--_ds-floating-arrow-*` properties and `data-floating`. Style the dropdown\nwith classes instead of `Attr.style`.\n\n\n# Ids\n\n@docs Id, id, idToString\n\n\n# Dropdown\n\n@docs view, placement\n\n\n# Content\n\n@docs heading, list, item, button\n\n\n# Triggers\n\n@docs trigger\n\n\n# Invokers\n\n@docs toggle, show, hide\n\n\n# Events\n\n@docs open, onToggle, State\n\n","unions":[{"name":"Id","comment":" The `id` that links a dropdown to the buttons that open it.\n","args":[],"cases":[]},{"name":"State","comment":" Whether a dropdown is showing.\n","args":[],"cases":[["Open",[]],["Closed",[]]]}],"aliases":[],"values":[{"name":"button","comment":" A full-width, tertiary [`Button`](Designsystemet-Button) for a menu item.\n\nFor a link, use `Button.viewAs Html.a [ Button.tertiary, Attr.href \"…\" ]`.\nThe dropdown styles it the same way.\n\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"heading","comment":" A heading for the menu or a group in it. As with\n[`Heading`](Designsystemet-Heading), the level is required. React defaults to\n`H2`, but the right level depends on the surrounding page.\n\n    Dropdown.heading Heading.H3 [] [ Html.text \"Sortering\" ]\n\n","type":"Designsystemet.Heading.Level -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"hide","comment":" Close the dropdown, or leave it closed. On a menu item, it closes the menu\nwhen the item is chosen:\n\n    Dropdown.button (Events.onClick Archive :: Dropdown.hide caseActions)\n        [ Html.text \"Arkiver\" ]\n\n","type":"Designsystemet.Dropdown.Id -> List.List (Html.Attribute msg)"},{"name":"id","comment":" Name a dropdown. The string becomes its DOM `id`, so it must be unique on\nthe page.\n","type":"String.String -> Designsystemet.Dropdown.Id"},{"name":"idToString","comment":" The DOM `id`, for ports and tests.\n","type":"Designsystemet.Dropdown.Id -> String.String"},{"name":"item","comment":" One `<li>` in a [`list`](#list). Put a [`button`](#button) or a link in it.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"list","comment":" The `<ul>` of menu items. To group items, use several, each after its own\n[`heading`](#heading).\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"onToggle","comment":" Sent when the dropdown opens or closes, by the trigger, Esc, an outside\nclick or code. See\n[`Popover.onToggle`](Designsystemet-Popover#onToggle).\n","type":"(Designsystemet.Dropdown.State -> msg) -> Html.Attribute msg"},{"name":"open","comment":" Whether the dropdown is open, from your model (React's `open` prop). Like\n[`Popover.open`](Designsystemet-Popover#open), it needs the companion script\nand an [`onToggle`](#onToggle) that updates your state when the user closes it.\n","type":"Basics.Bool -> Html.Attribute msg"},{"name":"placement","comment":" Where the dropdown appears relative to its trigger. Defaults to\n`Placement.BottomEnd`.\n","type":"Designsystemet.Placement.Placement -> Html.Attribute msg"},{"name":"show","comment":" Open the dropdown, or leave it open.\n","type":"Designsystemet.Dropdown.Id -> List.List (Html.Attribute msg)"},{"name":"toggle","comment":" Open the dropdown if closed, close it if open. Concatenate with your own\nattributes on any button:\n\n    Button.icon { label = \"Flere valg\", icon = moreIcon }\n        (Button.tertiary :: Dropdown.toggle rowMenu)\n\n","type":"Designsystemet.Dropdown.Id -> List.List (Html.Attribute msg)"},{"name":"trigger","comment":" A [`Button`](Designsystemet-Button) that opens and closes the dropdown.\n\n    Dropdown.trigger userMenu [ Button.tertiary ] [ Html.text \"Kari Nordmann\" ]\n\n","type":"Designsystemet.Dropdown.Id -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"view","comment":" A `<div class=\"ds-dropdown\" popover>`, by default below its trigger and\naligned to its end edge.\n\nThe `id` always comes from the [`Id`](#Id), so triggers keep pointing at it.\nAn `Attr.id` in the attributes is ignored.\n\n","type":"Designsystemet.Dropdown.Id -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.ErrorSummary","comment":" A list of a form's errors after a failed submit, with a link to each\nfield.\n\nMirrors `ErrorSummary` from `@digdir/designsystemet-react`.\n\nEach error shows up twice: under its field, and as a link to that field in\nthe summary. Keep one list of errors and read both from it:\n\n    emailField : ErrorSummary.FieldId\n    emailField =\n        ErrorSummary.fieldId \"email\"\n\n    validate : Model -> List ErrorSummary.Error\n    validate model =\n        if String.contains \"@\" model.email then\n            []\n\n        else\n            [ { field = emailField, message = \"Skriv inn en gyldig e-postadresse\" } ]\n\n    view : Model -> Html Msg\n    view model =\n        Html.form [ Events.onSubmit Submitted ]\n            [ ErrorSummary.view\n                { heading = \"Du må rette disse feilene før du kan sende inn\"\n                , level = ErrorSummary.H2\n                , errors = model.errors\n                }\n                []\n            , Textfield.new (Ds.label \"E-post\")\n                |> Textfield.withError (ErrorSummary.messageFor emailField model.errors)\n                |> Textfield.view\n                    [ ErrorSummary.linkTarget emailField\n                    , Attr.value model.email\n                    , Events.onInput ChangedEmail\n                    ]\n            ]\n\nThe [`FieldId`](#FieldId) ties the link to its field, and\n[`messageFor`](#messageFor) gives the field the same message. Set\n`model.errors` on submit, not while the user types: `<ds-error-summary>` takes\nfocus when it appears, so screen readers announce it at once.\n\n\n# React → Elm\n\n  - `<ErrorSummary>` → `ErrorSummary.view { … } []`\n  - `<ErrorSummary.Heading>` → `heading` and `level`\n  - `<ErrorSummary.List>` + `.Item` + `.Link` → `errors`\n  - `<ErrorSummary.Link href=\"#email\">` → `{ field = ErrorSummary.fieldId \"email\", … }`\n\n\n# Managed by designsystemet-web\n\n  - `role=\"group\"`, `tabindex=\"-1\"` and `aria-labelledby` on\n    `<ds-error-summary>`\n  - `id` on the heading\n\n\n# Links in `Browser.application`\n\nThe links are plain `<a href=\"#email\">` anchors. In a `Browser.application`\nevery link click goes to your `onUrlRequest`, so the browser won't jump to the\nfield. Move focus there in `update`:\n\n    LinkClicked (Browser.Internal url) ->\n        case url.fragment of\n            Just id ->\n                ( model, Task.attempt (\\_ -> NoOp) (Browser.Dom.focus id) )\n\n            Nothing ->\n                ( model, Nav.pushUrl model.key (Url.toString url) )\n\n@docs view, Level\n\n\n# Errors\n\n@docs Error, messageFor\n\n\n# Field ids\n\n@docs FieldId, fieldId, fieldIdToString, linkTarget\n\n","unions":[{"name":"FieldId","comment":" The `id` of a field that can have an error. A separate type, so the\nsummary's link and its field are built from the same value.\n","args":[],"cases":[]},{"name":"Level","comment":" The summary's heading level. No `H1`: the page already has one, and\n`<ds-error-summary>` only takes its name from an `h2`–`h6`.\n","args":[],"cases":[["H2",[]],["H3",[]],["H4",[]],["H5",[]],["H6",[]]]}],"aliases":[{"name":"Error","comment":" A field and what's wrong with it.\n","args":[],"type":"{ field : Designsystemet.ErrorSummary.FieldId, message : String.String }"}],"values":[{"name":"fieldId","comment":" Make a `FieldId` from an id that is unique on the page.\n","type":"String.String -> Designsystemet.ErrorSummary.FieldId"},{"name":"fieldIdToString","comment":" The id as a string, for `Browser.Dom.focus` and the like.\n","type":"Designsystemet.ErrorSummary.FieldId -> String.String"},{"name":"linkTarget","comment":" Sets the `id` on the input, select or textarea the error is about, so the\nsummary's link jumps there.\n\n    Checkbox.view [ ErrorSummary.linkTarget termsField, Attr.checked model.terms ]\n\n","type":"Designsystemet.ErrorSummary.FieldId -> Html.Attribute msg"},{"name":"messageFor","comment":" The message for one field, ready for `withError` on a\n[`Textfield`](Designsystemet-Textfield), [`Checkbox`](Designsystemet-Checkbox),\n[`Radio`](Designsystemet-Radio) or [`Fieldset`](Designsystemet-Fieldset). If a\nfield has several errors, the first one wins.\n\n    Textfield.withError (ErrorSummary.messageFor emailField model.errors)\n\n","type":"Designsystemet.ErrorSummary.FieldId -> List.List Designsystemet.ErrorSummary.Error -> Maybe.Maybe String.String"},{"name":"view","comment":" A `<ds-error-summary class=\"ds-error-summary\">` with a heading and a list\nof links. The attributes go on `<ds-error-summary>`.\n\nRenders nothing when there are no errors, so you can always call it. The\nsummary appears, and takes focus, once there is something to fix.\n\nReact defaults to `h2`. Here the level is required, as for\n[`Heading`](Designsystemet-Heading).\n\n","type":"{ heading : String.String, level : Designsystemet.ErrorSummary.Level, errors : List.List Designsystemet.ErrorSummary.Error } -> List.List (Html.Attribute msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Field","comment":" A form control wired to its label, description and messages.\n\nMirrors `Field` from `@digdir/designsystemet-react`.\n\n    Field.view []\n        [ Label.view [] [ Html.text \"Beløp\" ]\n        , Field.description [] [ Html.text \"Oppgi beløpet før skatt\" ]\n        , Field.affixes []\n            [ Field.affix [] [ Html.text \"NOK\" ]\n            , Input.view [ Attr.value model.amount, Events.onInput ChangedAmount ]\n            , Field.affix [] [ Html.text \"pr. mnd.\" ]\n            ]\n        , ValidationMessage.view [] [ Html.text \"Beløpet må være et tall\" ]\n        ]\n\nIt renders `<ds-field>`, a custom element from `@digdir/designsystemet-web`\nthat finds the input, select or textarea inside and connects the rest to it.\nYou don't write `for`, `id` or `aria-describedby`.\n\n[`Textfield`](Designsystemet-Textfield), [`Checkbox`](Designsystemet-Checkbox),\n[`Radio`](Designsystemet-Radio) and [`Switch`](Designsystemet-Switch) build\nthe field for you. Use this module for anything else, like a\n[`Select`](Designsystemet-Select) or a [`Suggestion`](Designsystemet-Suggestion)\nwith a label.\n\n\n# React → Elm\n\n  - `<Field>` → `Field.view []`\n  - `position=\"end\"` → `Field.position Field.End`\n  - `<Field.Description>` → `Field.description []`\n  - `<Field.Affixes>` → `Field.affixes []`\n  - `<Field.Affix>` → `Field.affix []`\n  - `<Field.Counter limit={140} over=\"…\" under=\"…\" />` → `Field.counter { limit = 140, over = \"…\", under = \"…\" } []`\n  - `asChild` → not ported: deprecated in React\n\n\n# Managed by designsystemet-web\n\n`<ds-field>` sets these. Don't set them yourself, or Elm and the web\ncomponent overwrite each other:\n\n  - `for` on every `<label>` in the field\n  - `id` on the input (when you haven't set one), on descriptions, messages and\n    the counter\n  - `aria-describedby` and `aria-invalid` on the input\n  - `data-clickdelegatefor` on the field, so a click anywhere on a checkbox or\n    radio field toggles it\n  - `data-label`, `data-state` and `data-color` on the counter\n  - the `--_ds-field-sizing` style on a `<textarea>`, which grows with its text\n\nYour own `id` on the input is fine; the field uses it.\n\n@docs view, viewKeyed\n\n\n# Descriptions\n\n@docs description\n\n\n# Prefix and suffix\n\n@docs affixes, affix\n\n\n# Character counter\n\n@docs Counter, counter\n\n\n# Checkboxes, radios and switches\n\n@docs Position, position, outline\n\n","unions":[{"name":"Position","comment":" Which side of the label a checkbox, radio or switch goes on.\n","args":[],"cases":[["Start",[]],["End",[]]]}],"aliases":[{"name":"Counter","comment":" A character limit and its two texts. `%d` is replaced by the number of\ncharacters.\n\n    { limit = 280\n    , under = \"%d tegn igjen\"\n    , over = \"%d tegn for mye\"\n    }\n\nThere are no default texts.\n\n","args":[],"type":"{ limit : Basics.Int, under : String.String, over : String.String }"}],"values":[{"name":"affix","comment":" Short text before or after the input, like a currency or unit. Use it\ninside [`affixes`](#affixes).\n\nIt has `aria-hidden=\"true\"`, so repeat it in the label or description:\n\"Beløp i kroner\", not \"Beløp\".\n\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"affixes","comment":" Wraps an input with its prefix and suffix so they look like one control.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"counter","comment":" Shows how many characters are left, or how many too many, in the field's\ninput or textarea. Put it after the input.\n\n    Field.view []\n        [ Label.view [] [ Html.text \"Begrunnelse\" ]\n        , Textarea.view [ Events.onInput ChangedReason ]\n        , Field.counter { limit = 500, under = \"%d tegn igjen\", over = \"%d tegn for mye\" } []\n        ]\n\n`<ds-field>` updates the count, text and \"too many\" state as the user types,\nso the element is empty in Elm's view. Going over the limit sets\n`aria-invalid` on the input but doesn't stop typing, so check the length in\n`update`.\n\n","type":"Designsystemet.Field.Counter -> List.List (Html.Attribute msg) -> Html.Html msg"},{"name":"description","comment":" Help text, read by screen readers along with the label. Put it between the\nlabel and the input.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"outline","comment":" A border around a checkbox, radio or switch field, showing that the whole\nbox is clickable. Set it on the field.\n","type":"Html.Attribute msg"},{"name":"position","comment":" Put the checkbox, radio or switch at the start (default) or end of the\nfield. Set it on the field, not the input.\n\n    Switch.new (Ds.label \"Varsle meg på e-post\")\n        |> Switch.withFieldAttributes [ Field.position Field.End ]\n        |> Switch.view [ Attr.checked model.notify, Events.onCheck ToggledNotify ]\n\n","type":"Designsystemet.Field.Position -> Html.Attribute msg"},{"name":"view","comment":" A `<ds-field class=\"ds-field\">` holding exactly one input, select or\ntextarea. Group several fields with a [`Fieldset`](Designsystemet-Fieldset).\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"viewKeyed","comment":" A field whose parts come and go. Give every child a key.\n\nElm matches children by position. If a description appears before the input\n(say, a hint shown once the user starts typing), the input shifts one place\nand Elm rebuilds it, so the user loses focus mid-word. Keys prevent that.\n\n    Field.viewKeyed []\n        (List.filterMap identity\n            [ Just ( \"label\", Label.view [] [ Html.text \"Passord\" ] )\n            , Maybe.map (\\hint -> ( \"description\", Field.description [] [ Html.text hint ] )) model.hint\n            , Just ( \"input\", Input.view [ Attr.type_ \"password\", Events.onInput PasswordChanged ] )\n            ]\n        )\n\n[`Textfield`](Designsystemet-Textfield) does this for you.\n\n","type":"List.List (Html.Attribute msg) -> List.List ( String.String, Html.Html msg ) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Fieldset","comment":" Related fields under one legend, such as radio buttons for one question\nor the parts of an address.\n\nMirrors `Fieldset` from `@digdir/designsystemet-react`.\n\n    Fieldset.new [ Html.text \"Hvor vil du hente pakken?\" ]\n        |> Fieldset.withDescription [ Html.text \"Du får en SMS når den er klar\" ]\n        |> Fieldset.withError model.pickupError\n        |> Fieldset.view [] (List.map (pickupOption model.pickup) [ PickupPoint, HomeDelivery ])\n\n    pickupOption : Maybe Pickup -> Pickup -> Html Msg\n    pickupOption selected pickup =\n        Radio.new (Ds.label (Pickup.toLabel pickup))\n            |> Radio.view\n                [ Attr.name \"pickup\"\n                , Attr.checked (selected == Just pickup)\n                , Events.onCheck (\\_ -> PickedPickup pickup)\n                ]\n\nThe legend names the group, so it is required.\n\nThe error is a [`ValidationMessage`](Designsystemet-ValidationMessage) last\nin the group. Every [`Field`](Designsystemet-Field) inside links it to its\ninput and is marked invalid while it is there. React has no `error` prop; you\nadd the message as a child, which is what this does.\n\n\n# React → Elm\n\n  - `<Fieldset>` + `<Fieldset.Legend>…` → `Fieldset.new [ … ] |> Fieldset.view [] [ … ]`\n  - `<Fieldset.Description>…` → `Fieldset.withDescription [ … ]`\n  - `<ValidationMessage>` as the last child → `Fieldset.withError (Just \"…\")`\n  - `<Fieldset.Legend className=\"…\">` → `Fieldset.withLegendAttributes [ Attr.class \"…\" ]`\n\n\n# Managed by designsystemet-web\n\n  - `aria-labelledby` on the `<fieldset>`, pointing at the legend and the\n    description\n  - `id` on the legend and the description\n\n@docs Fieldset, new, view\n\n\n# Options\n\n@docs withDescription, withError, withLegendAttributes\n\n","unions":[{"name":"Fieldset","comment":" A fieldset being configured. Start with [`new`](#new), end with\n[`view`](#view).\n","args":["msg"],"cases":[]}],"aliases":[],"values":[{"name":"new","comment":" A fieldset with this legend.\n","type":"List.List (Html.Html msg) -> Designsystemet.Fieldset.Fieldset msg"},{"name":"view","comment":" A `<fieldset class=\"ds-fieldset\">`. The attributes go on the\n`<fieldset>`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Designsystemet.Fieldset.Fieldset msg -> Html.Html msg"},{"name":"withDescription","comment":" Help text under the legend, read when the user enters the group.\n","type":"List.List (Html.Html msg) -> Designsystemet.Fieldset.Fieldset msg -> Designsystemet.Fieldset.Fieldset msg"},{"name":"withError","comment":" An error for the whole group, like \"Velg ett alternativ\", or `Nothing`.\n","type":"Maybe.Maybe String.String -> Designsystemet.Fieldset.Fieldset msg -> Designsystemet.Fieldset.Fieldset msg"},{"name":"withLegendAttributes","comment":" Attributes for the `<legend>`. To hide it visually but keep it for screen\nreaders, use `ds-sr-only`:\n\n    Fieldset.new [ Html.text \"Tekst for skjermleser\" ]\n        |> Fieldset.withLegendAttributes [ Attr.class \"ds-sr-only\" ]\n\n","type":"List.List (Html.Attribute msg) -> Designsystemet.Fieldset.Fieldset msg -> Designsystemet.Fieldset.Fieldset msg"}],"binops":[]},{"name":"Designsystemet.FileUpload","comment":" **Experimental.** A drop zone: a large dashed area around a native\n`<input type=\"file\">`.\n\nMirrors `EXPERIMENTAL_FileUpload` from `@digdir/designsystemet-react`. Markup\nand styling may change in any release, as upstream.\n\n    Field.view []\n        [ Label.view [] [ Html.text \"Last opp vedlegg\" ]\n        , FileUpload.view []\n            [ Field.description [] [ Html.text \"Slipp filen her\" ]\n            , Field.description [] [ Html.text \"PDF, maks 2 MB\" ]\n            , Button.viewAs Html.span [ Button.secondary ] [ Html.text \"Velg fil\" ]\n            , Html.input\n                [ Attr.type_ \"file\"\n                , Attr.accept \".pdf\"\n                , Events.on \"change\" (Decode.map PickedFiles filesDecoder)\n                ]\n                []\n            ]\n        ]\n\nThe file input is stretched invisibly over the area, so clicks and drops land\non it. The button is a `<span>` styled as one. Read the files with\n`elm/file`:\n\n    filesDecoder : Decode.Decoder (List File)\n    filesDecoder =\n        Decode.at [ \"target\", \"files\" ] (Decode.list File.decoder)\n\nThe CSS draws an upload icon unless the first child is your own `<svg>`.\n\n\n# React → Elm\n\n  - `<EXPERIMENTAL_FileUpload>` → `FileUpload.view []`\n\n@docs view\n\n","unions":[],"aliases":[],"values":[{"name":"view","comment":" A `<div class=\"ds-file-upload\">`. Put it in a\n[`Field`](Designsystemet-Field) so the label and descriptions connect to the\nfile input.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Heading","comment":" Headings: `<h1>` to `<h6>` with Designsystemet's heading text styles.\n\nMirrors `Heading` from `@digdir/designsystemet-react`.\n\n    Heading.h2 [ Heading.size Heading.Large ] [ Html.text \"Mine saker\" ]\n\nScreen readers and the document outline only see the level. Pick it from the\npage structure, and the size from the design.\n\n\n# React → Elm\n\n  - `<Heading level={1}>` → `Heading.h1 []`\n  - `<Heading>` (level defaults to 2) → `Heading.h2 []`\n  - `level={level}` computed at runtime → `Heading.view level []`\n  - `data-size=\"lg\"` → `Heading.size Heading.Large`\n  - `asChild` + `<legend>` → `Heading.viewAs Html.legend []`\n\nReact defaults to `<h2>`. Here the level is always explicit, since a heading\nat the wrong level is an accessibility bug you can't see on screen.\n\n@docs h1, h2, h3, h4, h5, h6\n\n\n# Computed levels\n\n@docs Level, view, viewAs\n\n\n# Sizes\n\n@docs Size, size\n\n","unions":[{"name":"Level","comment":" A heading level decided at runtime, e.g. in a section component used at\ndifferent depths.\n","args":[],"cases":[["H1",[]],["H2",[]],["H3",[]],["H4",[]],["H5",[]],["H6",[]]]},{"name":"Size","comment":" Headings have their own size scale, wider than\n[`Designsystemet.Size`](Designsystemet-Size). Without a size, a heading is\n`1.3em` of the surrounding text.\n","args":[],"cases":[["TwoExtraSmall",[]],["ExtraSmall",[]],["Small",[]],["Medium",[]],["Large",[]],["ExtraLarge",[]],["TwoExtraLarge",[]]]}],"aliases":[],"values":[{"name":"h1","comment":" A top-level heading: usually one per page.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"h2","comment":" A section heading.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"h3","comment":" A sub-section heading.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"h4","comment":" An `<h4 class=\"ds-heading\">`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"h5","comment":" An `<h5 class=\"ds-heading\">`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"h6","comment":" An `<h6 class=\"ds-heading\">`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"size","comment":" Set the heading's `data-size`.\n","type":"Designsystemet.Heading.Size -> Html.Attribute msg"},{"name":"view","comment":" A heading at a level you computed.\n\n    sectionHeading : Heading.Level -> String -> Html msg\n    sectionHeading level title =\n        Heading.view level [ Heading.size Heading.Small ] [ Html.text title ]\n\n","type":"Designsystemet.Heading.Level -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"viewAs","comment":" Heading styles on another element (React's `asChild`).\n\n    Html.fieldset []\n        [ Heading.viewAs Html.legend\n            [ Heading.size Heading.ExtraSmall ]\n            [ Html.text \"Kontaktinformasjon\" ]\n        ]\n\nUse it only on elements that aren't headings in the outline, like `<legend>`,\n`<caption>` or `<summary>`. Real headings should use [`h1`](#h1)–[`h6`](#h6)\nso assistive technology can navigate by them.\n\n","type":"(List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg) -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Input","comment":" A native `<input>` with Designsystemet styling.\n\nMirrors `Input` from `@digdir/designsystemet-react`.\n\n    Input.view [ Attr.value model.email, Attr.type_ \"email\", Events.onInput ChangedEmail ]\n\nAn input has no label of its own. Put it in a [`Field`](Designsystemet-Field)\nwith a [`Label`](Designsystemet-Label), or use\n[`Textfield`](Designsystemet-Textfield).\n\nAn input is `type=\"text\"` unless you pass another `Attr.type_`.\n\n\n# React → Elm\n\n  - `<Input />` → `Input.view []`\n  - `type=\"email\"` → `Input.view [ Attr.type_ \"email\" ]`\n  - `size={10}` → `Input.view [ Attr.size 10 ]`\n  - `readOnly` → `Input.view [ Attr.readonly True ]`\n  - `role=\"switch\"` → `Input.view [ Attr.attribute \"role\" \"switch\" ]`\n  - `data-indeterminate` → `Input.indeterminate`\n\n\n# Read-only\n\nReact blocks `onChange` and clicks on a read-only input.\n`@digdir/designsystemet-web` does the same for every `readonly` input on the\npage, including checkboxes and radios, so `Attr.readonly True` is enough.\n\n@docs view, indeterminate\n\n","unions":[],"aliases":[],"values":[{"name":"indeterminate","comment":" Show a checkbox as partly checked, e.g. a \"select all\" box when only some\nrows are selected.\n\n    selectAll : List Row -> Html Msg\n    selectAll rows =\n        let\n            selected =\n                List.filter .selected rows\n        in\n        Input.view <|\n            [ Attr.type_ \"checkbox\"\n            , Attr.checked (List.length selected == List.length rows)\n            , Events.onCheck SelectedAll\n            ]\n                ++ (if List.isEmpty selected || selected == rows then\n                        []\n\n                    else\n                        [ Input.indeterminate ]\n                   )\n\nReact sets `data-indeterminate` and lets `<ds-field>` copy it to the DOM\nproperty. This sets the property directly, so it works with or without a\n`Field`. Drop the attribute to clear it.\n\n","type":"Html.Attribute msg"},{"name":"view","comment":" An `<input class=\"ds-input\" type=\"text\">`.\n","type":"List.List (Html.Attribute msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Label","comment":" The `<label>` of a form control.\n\nMirrors `Label` from `@digdir/designsystemet-react`.\n\n[`Textfield`](Designsystemet-Textfield), [`Checkbox`](Designsystemet-Checkbox)\nand friends render their own label from a\n[`Designsystemet.Label`](Designsystemet#Label). Use this module when you build a\nfield by hand with [`Field`](Designsystemet-Field):\n\n    Field.view []\n        [ Label.view [] [ Html.text \"Saksnummer\" ]\n        , Input.view [ Attr.value model.caseNumber, Events.onInput ChangedCaseNumber ]\n        ]\n\nInside a `Field`, leave out `for`. `<ds-field>` connects the label to the\ninput.\n\n\n# React → Elm\n\n  - `<Label>` → `Label.view []`\n  - `asChild` + `<legend>` → `Label.viewAs Html.legend []`\n  - `weight` → not ported: deprecated in React\n\n@docs view, viewAs\n\n","unions":[],"aliases":[],"values":[{"name":"view","comment":" A `<label class=\"ds-label\">`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"viewAs","comment":" Label styling on another element (React's `asChild`).\n\n    Label.viewAs Html.span [] [ Html.text \"Velg dato\" ]\n\n","type":"(List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg) -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Link","comment":" A styled link.\n\nMirrors `Link` from `@digdir/designsystemet-react`.\n\n    Link.view [ Attr.href \"/saker/42\" ] [ Html.text \"Se saken\" ]\n\nWith an icon, wrap the text in a `<span>` so the CSS can space them:\n\n    Link.view [ Attr.href \"mailto:post@example.no\" ]\n        [ mailIcon, Html.span [] [ Html.text \"Send e-post\" ] ]\n\n\n# React → Elm\n\n  - `<Link href=\"…\">` → `Link.view [ Attr.href \"…\" ]`\n  - `data-color=\"neutral\"` → `Ds.color Color.neutral`\n  - `asChild` + `<button>` → `Link.viewAs Html.button [ Attr.type_ \"button\" ]`\n\n@docs view, viewAs\n\n","unions":[],"aliases":[],"values":[{"name":"view","comment":" An `<a class=\"ds-link\">`. Give it an `href`, or keyboards and assistive\ntechnology won't treat it as a link.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"viewAs","comment":" Link styling on another element (React's `asChild`).\n\n    Link.viewAs Html.button\n        [ Attr.type_ \"button\", Events.onClick ShowTerms ]\n        [ Html.text \"Vilkår\" ]\n\nUse a real `<a href>` for navigation. A button is for actions styled as links.\n\n","type":"(List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg) -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.List","comment":" Bulleted and numbered lists with Designsystemet's spacing.\n\nMirrors `List` from `@digdir/designsystemet-react`.\n\nImport it under another name so it doesn't shadow `List` from `elm/core`:\n\n    import Designsystemet.List as DsList\n\n    DsList.ordered []\n        [ DsList.item [] [ Html.text \"Fyll ut skjemaet\" ]\n        , DsList.item [] [ Html.text \"Last opp vedlegg\" ]\n        , DsList.item [] [ Html.text \"Send inn\" ]\n        ]\n\n\n# React → Elm\n\n  - `<List.Unordered>` → `DsList.unordered []`\n  - `<List.Ordered>` → `DsList.ordered []`\n  - `<List.Item>` → `DsList.item []`\n\n`asChild` is not ported. The styling is just the `ds-list` class, so\n`Html.menu [ Attr.class \"ds-list\" ]` does the same, and `List.Item` adds no\nmarkup.\n\n@docs unordered, ordered, item\n\n","unions":[],"aliases":[],"values":[{"name":"item","comment":" An `<li>`. Nest a list inside it for sub-items; the CSS tightens nested\nspacing.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"ordered","comment":" An `<ol class=\"ds-list\">`, for steps or rankings where the order matters.\n`Attr.start` and `Attr.reversed` work as usual.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"unordered","comment":" A `<ul class=\"ds-list\">`, for items in no particular order.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Pagination","comment":" Navigation between the pages of a long list or table.\n\nMirrors `Pagination` and `usePagination` from `@digdir/designsystemet-react`.\n\n    Pagination.buttons\n        { current = model.page\n        , total = model.pageCount\n        , onSelect = PageSelected\n        , labels = paginationLabels\n        }\n        |> Pagination.view []\n\n    paginationLabels : Pagination.Labels\n    paginationLabels =\n        { navigation = \"Bla i sider\"\n        , previous = \"Forrige\"\n        , next = \"Neste\"\n        , page = \\page -> \"Side \" ++ String.fromInt page\n        }\n\nwhich renders\n\n    Forrige  1  …  4  [5]  6  …  12  Neste\n\nVisible pages are picked with the same algorithm as `designsystemet-web`, so\nthe output matches React. Pages are numbered from 1.\n\n\n# Buttons or links\n\n  - [`buttons`](#buttons) send a message. Use them when the page number lives\n    only in your model.\n  - [`links`](#links) are `<a href>`s. Use them when the page number is in the\n    URL, so pages can be bookmarked and opened in new tabs.\n\n\n# React → Elm\n\n  - `usePagination({ currentPage, totalPages, onChange })` → `Pagination.buttons { current, total, onSelect, … }`\n  - `<Pagination.Button asChild><a href>` → `Pagination.links { current, total, toHref, … }`\n  - `showPages={5}` → `Pagination.withMaxVisible 5`\n  - empty `Pagination.Button` with `aria-label` at the ends → `Pagination.withArrowsOnly`\n  - `aria-label=\"Bla i sider\"` → `labels.navigation`\n  - `<Pagination>` + `List` + `Item` + `Button` → all rendered by `Pagination.view`\n  - `pagination({ current, total, show })` (web) → `Pagination.items`\n\n\n# Differences from React\n\n`data-current`, `data-total` and `data-href` are never set. With them,\n`designsystemet-web` would render the pages itself and fight Elm over the\nmarkup.\n\nThe previous and next buttons always have `aria-hidden` (`\"true\"` when there\nis no such page), as with React's `usePagination`. Their visible text is also\ntheir accessible name. The upstream stories give them a longer `aria-label`\n(\"Forrige side\" next to \"Forrige\"), which hides the visible text from screen\nreaders. With [`withArrowsOnly`](#withArrowsOnly) the text becomes the\n`aria-label`, as in the upstream mobile story.\n\n\n# Managed by designsystemet-web\n\nNever set `role` on the pagination yourself.\n\n@docs Pagination, buttons, links, Labels\n@docs withMaxVisible, withArrowsOnly\n@docs view\n\n\n# The algorithm\n\n@docs Item, items\n\n","unions":[{"name":"Item","comment":" One item between the previous and next buttons.\n","args":[],"cases":[["Page",["Basics.Int"]],["Ellipsis",[]]]},{"name":"Pagination","comment":" A pagination being configured. Start with [`buttons`](#buttons) or\n[`links`](#links), finish with [`view`](#view).\n","args":["msg"],"cases":[]}],"aliases":[{"name":"Labels","comment":" The texts in a pagination. Define them once per app or language.\n\n  - `navigation` names the whole thing for screen readers (`aria-label`).\n  - `previous` and `next` are shown next to the arrow on the end buttons.\n  - `page` names one page button for screen readers. The button shows only the\n    number.\n\n","args":[],"type":"{ navigation : String.String, previous : String.String, next : String.String, page : Basics.Int -> String.String }"}],"values":[{"name":"buttons","comment":" Page buttons that send `onSelect` with the page number.\n","type":"{ current : Basics.Int, total : Basics.Int, onSelect : Basics.Int -> msg, labels : Designsystemet.Pagination.Labels } -> Designsystemet.Pagination.Pagination msg"},{"name":"items","comment":" Which items to show. A port of `pagination()` from `designsystemet-web`:\n\n    items { current = 5, total = 12, show = 7 }\n    --> [ Page 1, Ellipsis, Page 4, Page 5, Page 6, Ellipsis, Page 12 ]\n\nThe first and last page are always included (when `show` is at least 5 and 4\nrespectively), and the current page is kept in the middle when possible. Use it\nto render your own pagination.\n\n","type":"{ current : Basics.Int, total : Basics.Int, show : Basics.Int } -> List.List Designsystemet.Pagination.Item"},{"name":"links","comment":" Page links that go to `toHref` of the page number.\n\n    Pagination.links\n        { current = model.page\n        , total = model.pageCount\n        , toHref = \\page -> \"/saker?side=\" ++ String.fromInt page\n        , labels = paginationLabels\n        }\n        |> Pagination.view []\n\n","type":"{ current : Basics.Int, total : Basics.Int, toHref : Basics.Int -> String.String, labels : Designsystemet.Pagination.Labels } -> Designsystemet.Pagination.Pagination msg"},{"name":"view","comment":" Render the `<ds-pagination class=\"ds-pagination\">`.\n","type":"List.List (Html.Attribute msg) -> Designsystemet.Pagination.Pagination msg -> Html.Html msg"},{"name":"withArrowsOnly","comment":" Show only the arrows on the previous and next buttons, for narrow screens.\n`labels.previous` and `labels.next` become their `aria-label`s.\n\n    Pagination.buttons { current = model.page, total = 10, onSelect = PageSelected, labels = labels }\n        |> Pagination.withMaxVisible 3\n        |> Pagination.withArrowsOnly\n        |> Pagination.view []\n\n","type":"Designsystemet.Pagination.Pagination msg -> Designsystemet.Pagination.Pagination msg"},{"name":"withMaxVisible","comment":" Max page items to show, counting each \"…\" but not the previous and next\nbuttons. Defaults to 7. Use 5 or fewer on narrow screens.\n","type":"Basics.Int -> Designsystemet.Pagination.Pagination msg -> Designsystemet.Pagination.Pagination msg"}],"binops":[]},{"name":"Designsystemet.Paragraph","comment":" Body text: a `<p>` with Designsystemet's paragraph styles.\n\nMirrors `Paragraph` from `@digdir/designsystemet-react`.\n\n    Paragraph.view [ Paragraph.long ]\n        [ Html.text \"Saken er sendt til behandling. Du får svar innen tre uker.\" ]\n\n\n# React → Elm\n\n  - `<Paragraph>` → `Paragraph.view []`\n  - `variant=\"long\"` → `Paragraph.long`\n  - `variant=\"short\"` → `Paragraph.short`\n  - `data-size=\"xl\"` → `Paragraph.size Paragraph.ExtraLarge`\n  - `asChild` + `<div>` → `Paragraph.viewAs Html.div []`\n\n@docs view, viewAs\n\n\n# Length\n\nLine height for long or short text. Leave it out for the default.\n\n@docs long, short\n\n\n# Sizes\n\n@docs Size, size\n\n","unions":[{"name":"Size","comment":" Paragraphs have their own size scale, wider than\n[`Designsystemet.Size`](Designsystemet-Size).\n","args":[],"cases":[["ExtraSmall",[]],["Small",[]],["Medium",[]],["Large",[]],["ExtraLarge",[]]]}],"aliases":[],"values":[{"name":"long","comment":" More line height, for long running text like articles.\n","type":"Html.Attribute msg"},{"name":"short","comment":" Less line height, for short text like an ingress or a card summary.\n","type":"Html.Attribute msg"},{"name":"size","comment":" Set the paragraph's `data-size`.\n","type":"Designsystemet.Paragraph.Size -> Html.Attribute msg"},{"name":"view","comment":" A `<p class=\"ds-paragraph\">`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"viewAs","comment":" Paragraph styles on another element (React's `asChild`), e.g. when the text\ncontains block elements that can't go in a `<p>`.\n\n    Paragraph.viewAs Html.div [] [ Html.text \"Vedlegg:\", attachmentList ]\n\n","type":"(List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg) -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Placement","comment":" Where a floating element sits next to the element it belongs to.\n\n[`Popover`](Designsystemet-Popover), [`Dropdown`](Designsystemet-Dropdown)\nand [`Tooltip`](Designsystemet-Tooltip) each have a `placement` attribute that\ntakes one of these:\n\n    Popover.view helpId [ Popover.placement Placement.Right ] [ Html.text \"…\" ]\n\n`designsystemet-web` positions the element with Floating UI and flips it to the\nother side when there is no room, unless you turn that off.\n\nSame as React's `Placement`: Floating UI's placements plus `'none'`.\n\n\n# React → Elm\n\n  - `placement=\"top\"` → `Placement.Top`\n  - `placement=\"bottom-end\"` → `Placement.BottomEnd`\n  - `placement=\"none\"` → `Placement.None`\n\n@docs Placement, toString\n\n","unions":[{"name":"Placement","comment":" A side, and optionally which end of that side to align to.\n\n`TopStart` sits above the trigger with the start edges aligned (left edges in\na left-to-right language). `TopEnd` aligns the end edges.\n\n`None` turns off positioning, for when you do it in CSS.\n\n","args":[],"cases":[["Top",[]],["TopStart",[]],["TopEnd",[]],["Right",[]],["RightStart",[]],["RightEnd",[]],["Bottom",[]],["BottomStart",[]],["BottomEnd",[]],["Left",[]],["LeftStart",[]],["LeftEnd",[]],["None",[]]]}],"aliases":[],"values":[{"name":"toString","comment":" The value written to `data-placement`, like `\"bottom-end\"`.\n","type":"Designsystemet.Placement.Placement -> String.String"}],"binops":[]},{"name":"Designsystemet.Popover","comment":" A small box of content floating next to the button that opened it.\n\nMirrors `Popover` from `@digdir/designsystemet-react`.\n\n    import Designsystemet.Popover as Popover\n\n    deleteInfo : Popover.Id\n    deleteInfo =\n        Popover.id \"delete-info\"\n\n    view : Html Msg\n    view =\n        Html.div []\n            [ Popover.trigger deleteInfo [] [ Html.text \"Hva skjer når jeg sletter?\" ]\n            , Popover.view deleteInfo\n                [ Popover.placement Placement.Bottom ]\n                [ Html.text \"Saken flyttes til papirkurven i 30 dager.\" ]\n            ]\n\nIt's a native [`popover`](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API):\nthe browser opens it on a trigger click and closes it on Esc or a click\noutside, and `designsystemet-web` positions it next to the trigger. Your model\ndoesn't have to track whether it's open. Use [`onToggle`](#onToggle) to find\nout, or [`open`](#open) to open it from your model.\n\n\n# React → Elm\n\n  - `<Popover id=\"x\">` → `Popover.view (Popover.id \"x\") []`\n  - `<Popover.TriggerContext>` → not needed: share a `Popover.Id`\n  - `<Popover.Trigger>` → `Popover.trigger id []`\n  - `<Popover.Trigger inline>` → `Popover.inlineTrigger id []`\n  - `<Button popovertarget=\"x\">` → `Button.view (Popover.toggle id)`\n  - `variant=\"tinted\"` → `Popover.tinted`\n  - `placement=\"bottom\"` → `Popover.placement Placement.Bottom`\n  - `autoPlacement={false}` → `Popover.noAutoPlacement`\n  - `onOpen` / `onClose` → `Popover.onToggle`\n  - `open={isOpen}` + `onOpen`/`onClose` → `Popover.open model.isOpen`, `Popover.onToggle Toggled`\n\n\n# Differences from React\n\n  - The popover is `popover=\"auto\"`. React uses `\"manual\"` and implements\n    light dismiss (Esc, click outside) in JavaScript, which the browser does\n    for `\"auto\"` popovers anyway. Pass `Attr.attribute \"popover\" \"manual\"` for\n    a popover that stays open while others open.\n  - `Popover.inlineTrigger` is `type=\"button\"`, so it never submits a form.\n  - React accepts `autoPlacement={false}` but never renders it, so it has no\n    effect there. [`noAutoPlacement`](#noAutoPlacement) writes the\n    `data-autoplacement=\"false\"` that `designsystemet-web` reads.\n\n\n# Managed by designsystemet-web\n\nWhile it is open, `designsystemet-web` positions the popover by writing\ninline styles (`translate`, `scroll-margin-bottom`, and for lists that scroll\n`max-height` and `width`), the arrow's `--_ds-floating-arrow-x`/`-y`\nproperties, and `data-floating`. Don't set those yourself, and style the\npopover with classes rather than `Attr.style`.\n\n\n# Opening from your model\n\nTo open a popover from your model (say, a hint after a save), use\n[`open`](#open). Only `showPopover()` can open a popover, so `open` renders\n`data-open` and the package's JavaScript (`@ensolabs/designsystemet-elm`,\nimported once) syncs the element. `designsystemet-web` positions the popover\nnext to the element whose `popovertarget` points at it, so you still need a\ntrigger.\n\n    Popover.view saveHint\n        [ Popover.open model.showSaveHint\n        , Popover.onToggle SaveHintToggled\n        ]\n        [ Html.text \"Lagret!\" ]\n\nThe browser still closes it on Esc or a click outside, so handle\n[`onToggle`](#onToggle) and set your state to `Closed`.\n\n\n# Ids\n\n@docs Id, id, idToString\n\n\n# Popover\n\n@docs view\n\n\n# Appearance\n\n@docs tinted, placement, noAutoPlacement\n\n\n# Triggers\n\nA trigger is any button with one of the invoker attribute lists below.\n[`trigger`](#trigger) is a Designsystemet `Button` that toggles the popover.\n\n@docs trigger, inlineTrigger\n\n\n# Invokers\n\nThese put `popovertarget` (and `popovertargetaction`) on any `<button>`, be it\na [`Button`](Designsystemet-Button), a [`Chip`](Designsystemet-Chip) or a plain\none. They are lists because the browser needs two attributes. Concatenate them\nwith your own:\n\n    Button.view (Button.secondary :: Popover.toggle filters) [ Html.text \"Filter\" ]\n\n@docs toggle, show, hide\n\n\n# State\n\n@docs open, State, onToggle\n\n","unions":[{"name":"Id","comment":" The `id` that links a popover to the buttons that open it.\n\nMake one per popover as a top-level value and use it in both places. The type\nkeeps you from passing it to a [`Dialog`](Designsystemet-Dialog) by mistake.\n\n","args":[],"cases":[]},{"name":"State","comment":" Whether a popover is showing.\n","args":[],"cases":[["Open",[]],["Closed",[]]]}],"aliases":[],"values":[{"name":"hide","comment":" Close the popover, or leave it closed. Use it for a \"close\" button inside\nthe popover:\n\n    Button.view (Button.tertiary :: Popover.hide filters) [ Html.text \"Lukk\" ]\n\n","type":"Designsystemet.Popover.Id -> List.List (Html.Attribute msg)"},{"name":"id","comment":" Name a popover. The string becomes its DOM `id`, so it must be unique on\nthe page.\n\n    filters : Popover.Id\n    filters =\n        Popover.id \"case-list-filters\"\n\n","type":"String.String -> Designsystemet.Popover.Id"},{"name":"idToString","comment":" The DOM `id`, for ports and tests.\n","type":"Designsystemet.Popover.Id -> String.String"},{"name":"inlineTrigger","comment":" A trigger styled as a word in running text, with a dotted underline:\n\n    Html.p []\n        [ Html.text \"Søknaden må ha \"\n        , Popover.inlineTrigger orgNumberHelp [] [ Html.text \"organisasjonsnummer\" ]\n        , Html.text \".\"\n        ]\n\n","type":"Designsystemet.Popover.Id -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"noAutoPlacement","comment":" Keep the popover on the requested side even when there is no room. By\ndefault `designsystemet-web` flips it to the opposite side.\n","type":"Html.Attribute msg"},{"name":"onToggle","comment":" Get a message when the popover opens or closes, for any reason: the\ntrigger, Esc, a click outside, or code.\n\n    Popover.view filters [ Popover.onToggle FiltersToggled ] [{- … -}]\n\nThe native `toggle` event, covering React's `onOpen` and `onClose`.\n\n","type":"(Designsystemet.Popover.State -> msg) -> Html.Attribute msg"},{"name":"open","comment":" Whether the popover is open, from your model. See\n[Opening from your model](#opening-from-your-model).\n","type":"Basics.Bool -> Html.Attribute msg"},{"name":"placement","comment":" Which side of the trigger the popover appears on. Defaults to\n`Placement.Top`.\n","type":"Designsystemet.Placement.Placement -> Html.Attribute msg"},{"name":"show","comment":" Open the popover, or leave it open.\n","type":"Designsystemet.Popover.Id -> List.List (Html.Attribute msg)"},{"name":"tinted","comment":" A tinted background instead of the default surface color.\n","type":"Html.Attribute msg"},{"name":"toggle","comment":" Open the popover if closed, close it if open. This is what a trigger does.\n","type":"Designsystemet.Popover.Id -> List.List (Html.Attribute msg)"},{"name":"trigger","comment":" A [`Button`](Designsystemet-Button) that opens and closes the popover.\n\n    Popover.trigger help [ Button.tertiary ] [ Html.text \"Hjelp\" ]\n\n","type":"Designsystemet.Popover.Id -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"view","comment":" A `<div class=\"ds-popover\" popover>`, placed above its trigger by default.\n\nThe `id` always comes from the [`Id`](#Id) so the triggers keep pointing at it.\nAn `Attr.id` in the attributes is ignored.\n\n","type":"Designsystemet.Popover.Id -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Radio","comment":" A radio button with its label, description and error message.\n\nMirrors `Radio` from `@digdir/designsystemet-react`.\n\nRadio buttons come in groups, so put them in a\n[`Fieldset`](Designsystemet-Fieldset) whose legend asks the question:\n\n    Fieldset.new [ Html.text \"Hvordan vil du bli kontaktet?\" ]\n        |> Fieldset.withError model.contactError\n        |> Fieldset.view []\n            (List.map (contactOption model.contact) [ Email, Phone ])\n\n    contactOption : Maybe Contact -> Contact -> Html Msg\n    contactOption selected contact =\n        Radio.new (Ds.label (Contact.toLabel contact))\n            |> Radio.view\n                [ Attr.name \"contact\"\n                , Attr.checked (selected == Just contact)\n                , Events.onCheck (\\_ -> PickedContact contact)\n                ]\n\nAn error on the fieldset is linked to every radio in it, so the radios\nusually don't need [`withError`](#withError).\n\nThe attributes you give `view` go on the `<input type=\"radio\">`, like React's\nrest props. Attributes for the field around it go in\n[`withFieldAttributes`](#withFieldAttributes).\n\n\n# React → Elm\n\n  - `<Radio label=\"…\" />` → `Radio.new (Ds.label \"…\") |> Radio.view []`\n  - `aria-label=\"…\"` → `Radio.new (Ds.ariaLabel \"…\")`\n  - `description={…}` → `Radio.withDescription [ … ]`\n  - `error=\"…\"` → `Radio.withError (Just \"…\")`\n  - `variant=\"outline\"` → `Radio.withFieldAttributes [ Field.outline ]`\n  - `position=\"end\"` → `Radio.withFieldAttributes [ Field.position Field.End ]`\n  - `data-size`, `className`, `style` → `Radio.withFieldAttributes [ … ]`\n  - `name`, `checked`, `onChange`, … → `Radio.view [ Attr.name …, Attr.checked …, … ]`\n\n@docs Radio, new, view\n\n\n# Options\n\n@docs withDescription, withError, withFieldAttributes\n\n","unions":[{"name":"Radio","comment":" A radio button being configured. Start with [`new`](#new), end with\n[`view`](#view).\n","args":["msg"],"cases":[]}],"aliases":[],"values":[{"name":"new","comment":" A radio button with this accessible name. With\n[`Ds.label`](Designsystemet#label) the label is shown next to it.\n","type":"Designsystemet.Label msg -> Designsystemet.Radio.Radio msg"},{"name":"view","comment":" Render the radio button. The attributes go on the `<input>`.\n","type":"List.List (Html.Attribute msg) -> Designsystemet.Radio.Radio msg -> Html.Html msg"},{"name":"withDescription","comment":" Help text under the label.\n","type":"List.List (Html.Html msg) -> Designsystemet.Radio.Radio msg -> Designsystemet.Radio.Radio msg"},{"name":"withError","comment":" An error message under the radio button, or `Nothing` for none.\n","type":"Maybe.Maybe String.String -> Designsystemet.Radio.Radio msg -> Designsystemet.Radio.Radio msg"},{"name":"withFieldAttributes","comment":" Attributes for the `<ds-field>` around the radio button: `Field.outline`,\n`Field.position`, `Ds.size`, a class, …\n","type":"List.List (Html.Attribute msg) -> Designsystemet.Radio.Radio msg -> Designsystemet.Radio.Radio msg"}],"binops":[]},{"name":"Designsystemet.Search","comment":" A search input with a magnifying glass, a button that empties it, and\noptionally a search button.\n\nMirrors `Search` from `@digdir/designsystemet-react`.\n\n    Html.form [ Attr.attribute \"role\" \"search\", Events.onSubmit Searched ]\n        [ Search.new { clearLabel = \"Tøm søket\" }\n            |> Search.withButton { variant = Search.Primary, label = \"Søk\" }\n            |> Search.view\n                [ Attr.attribute \"aria-label\" \"Søk i saker\"\n                , Attr.value model.query\n                , Events.onInput ChangedQuery\n                ]\n        ]\n\nThe attributes you give `view` go on the `<input type=\"search\">`, like the\nprops of React's `Search.Input`. Name it with `aria-label`, or put the whole\nsearch in a [`Field`](Designsystemet-Field) with a\n[`Label`](Designsystemet-Label). Pass `Attr.type_ \"text\"` to drop the\nmagnifying glass.\n\nThe clear button sends the input an `input` event with an empty value, so\n`Events.onInput` sees it like any other edit.\n\n\n# React → Elm\n\n  - `<Search>` + `<Search.Input>` + `<Search.Clear>` → `Search.new { clearLabel = \"…\" } |> Search.view [ … ]`\n  - `data-sr-clear` / `--dsc-suggestion-sr-clear` → `clearLabel`\n  - `<Search.Button>` → `Search.withButton { variant = Search.Primary, label = \"Søk\" }`\n  - `<Search.Button variant=\"secondary\">` → `Search.withButton { variant = Search.Secondary, label = \"Søk\" }`\n  - `<Search.Input type=\"text\">` → `Search.view [ Attr.type_ \"text\" ]`\n\nReact has Norwegian defaults for both button texts. Here they are required.\n\n\n# Managed by designsystemet-web\n\n`Search` renders `<ds-suggestion>`, the same custom element as\n[`Suggestion`](Designsystemet-Suggestion). It writes:\n\n  - `hidden`, `aria-label`, `aria-hidden` and `tabindex` on the clear button\n    (Elm only renders the initial `hidden`, like React, and never changes it)\n  - the other `data-sr-*` texts on `<ds-suggestion>`, from the CSS\n\n@docs Search, new, view\n\n\n# Search button\n\n@docs withButton, ButtonVariant\n\n","unions":[{"name":"ButtonVariant","comment":" The two looks a search button can have.\n","args":[],"cases":[["Primary",[]],["Secondary",[]]]},{"name":"Search","comment":" A search being configured. Start with [`new`](#new), end with\n[`view`](#view).\n","args":["msg"],"cases":[]}],"aliases":[],"values":[{"name":"new","comment":" A search field. `clearLabel` is the screen reader name of the × button\nthat empties it.\n","type":"{ clearLabel : String.String } -> Designsystemet.Search.Search msg"},{"name":"view","comment":" Render the search. The attributes go on the `<input>`.\n","type":"List.List (Html.Attribute msg) -> Designsystemet.Search.Search msg -> Html.Html msg"},{"name":"withButton","comment":" Add a submit button with the text `label` after the input. Put the search in\na `<form>` and handle `Events.onSubmit` there.\n","type":"{ variant : Designsystemet.Search.ButtonVariant, label : String.String } -> Designsystemet.Search.Search msg -> Designsystemet.Search.Search msg"}],"binops":[]},{"name":"Designsystemet.Select","comment":" A native `<select>` with Designsystemet styling.\n\nMirrors `Select` from `@digdir/designsystemet-react`.\n\nTo pick one of your own values, use [`single`](#single):\n\n    municipalities =\n        { options = Municipality.all\n        , selected = model.municipality\n        , toValue = Municipality.toCode\n        , toLabel = Municipality.toName\n        , onSelect = PickedMunicipality\n        , placeholder = \"Velg kommune\"\n        }\n\n    Select.single municipalities [ Attr.required True ]\n\n[`view`](#view), [`option`](#option) and [`optgroup`](#optgroup) are the\nplain elements, for when you need option groups or want to handle the strings\nyourself.\n\nA select needs a label. Put it in a [`Field`](Designsystemet-Field):\n\n    Field.view []\n        [ Label.view [] [ Html.text \"Kommune\" ]\n        , Select.single municipalities [ Attr.required True ]\n        ]\n\n\n# React → Elm\n\n  - `<Select>` + `<Select.Option>`s for your values → `Select.single { … } []`\n  - `<Select>` → `Select.view []`\n  - `<Select.Option value=\"…\">` → `Select.option [ Attr.value \"…\" ]`\n  - `<Select.Optgroup label=\"…\">` → `Select.optgroup { label = \"…\" } []`\n  - `width=\"auto\"` → `Select.autoWidth`\n  - `aria-readonly` → `Select.view [ Attr.attribute \"aria-readonly\" \"true\" ]`\n  - `readOnly` → not ported: deprecated in React, use `aria-readonly`\n\nA `<select>` can't be `readonly` in HTML. With `aria-readonly=\"true\"`,\n`@digdir/designsystemet-web` stops the user from changing it and the CSS shows\nit as read-only.\n\n@docs single\n\n\n# Plain elements\n\n@docs view, option, optgroup\n\n\n# Width\n\n@docs autoWidth, fullWidth\n\n","unions":[],"aliases":[],"values":[{"name":"autoWidth","comment":" As wide as its longest option.\n","type":"Html.Attribute msg"},{"name":"fullWidth","comment":" As wide as its container. This is the default.\n","type":"Html.Attribute msg"},{"name":"optgroup","comment":" A labelled group of options.\n\n    Select.view [ Events.onInput PickedRoom ]\n        [ Select.optgroup { label = \"Bygg A\" }\n            []\n            [ Select.option [ Attr.value \"a101\" ] [ Html.text \"A101\" ]\n            , Select.option [ Attr.value \"a102\" ] [ Html.text \"A102\" ]\n            ]\n        ]\n\n","type":"{ label : String.String } -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"option","comment":" An `<option>`. Mark the chosen one with `Attr.selected True`. Setting\n`value` on the select does nothing on first render, as the options aren't\nthere yet.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"single","comment":" A select for picking one of your own values.\n\n  - `toValue` turns a value into the string the browser keeps in `value`.\n    Give every option a different one.\n  - `toLabel` is the text the user sees.\n  - `onSelect` gets the picked value back as your type.\n  - `placeholder` is the prompt shown while `selected` is `Nothing`. It can't\n    be picked and disappears once something is selected.\n\n`selected` is a `Maybe` so the screen matches the model. Without a prompt, the\nbrowser would show the first option as chosen while your model has nothing.\nIf `selected` isn't among `options` (say the list was reloaded without it),\nthe prompt is shown too.\n\nIf \"none\" is a real choice, make it one of your options:\n\n    Select.single\n        { options = Nothing :: List.map Just Team.all\n        , selected = Just model.team\n        , toValue = Maybe.map Team.toId >> Maybe.withDefault \"\"\n        , toLabel = Maybe.map Team.toName >> Maybe.withDefault \"Ingen\"\n        , onSelect = PickedTeam\n        , placeholder = \"Velg team\"\n        }\n        []\n\nA `<select>` can't refuse a change. The browser already shows the pick when\n`onSelect` arrives, so always store the value. If `update` ignores it, the\nscreen and the model disagree until `selected` changes.\n\nThe attributes go on the `<select>`. The options are keyed by `toValue`, so\nthe list can change under the user without Elm reusing the wrong `<option>`.\n\n","type":"{ options : List.List a, selected : Maybe.Maybe a, toValue : a -> String.String, toLabel : a -> String.String, onSelect : a -> msg, placeholder : String.String } -> List.List (Html.Attribute msg) -> Html.Html msg"},{"name":"view","comment":" A `<select class=\"ds-input\">`. Listen with `Events.onInput`, which gives you\nthe chosen option's `value`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Size","comment":" The size scale behind `data-size`. Use it with\n[`Designsystemet.size`](Designsystemet#size).\n\nThree sizes, as in React, because the theme's CSS defines only `sm`, `md` and\n`lg`. Any other value matches no rule, and everything inside (Tailwind's\nspacing utilities included) silently keeps the parent's size.\n\n@docs Size, sm, md, lg, toString\n\n","unions":[{"name":"Size","comment":" A size. Unset means `md`.\n","args":[],"cases":[]}],"aliases":[],"values":[{"name":"lg","comment":" Large.\n","type":"Designsystemet.Size.Size"},{"name":"md","comment":" Medium, the default.\n","type":"Designsystemet.Size.Size"},{"name":"sm","comment":" Small.\n","type":"Designsystemet.Size.Size"},{"name":"toString","comment":" The value written to `data-size`.\n","type":"Designsystemet.Size.Size -> String.String"}],"binops":[]},{"name":"Designsystemet.Skeleton","comment":" Grey, pulsing placeholders shown while content loads.\n\nMirrors `Skeleton` from `@digdir/designsystemet-react`.\n\n    viewLoadingCase : Html msg\n    viewLoadingCase =\n        Card.view []\n            [ Skeleton.circle { diameter = \"3rem\" } []\n            , Heading.h3 [] [ Skeleton.text { characters = 24 } [] ]\n            , Skeleton.rectangle { width = \"100%\", height = \"8rem\" } []\n            ]\n\nEach shape takes only the measurements it needs: a circle has a diameter, text\na length in characters. Skeletons are hidden from screen readers\n(`aria-hidden=\"true\"`), so signal loading another way, e.g. `aria-busy=\"true\"`\non the region.\n\n\n# React → Elm\n\n  - `<Skeleton width={200} height={100} />` → `Skeleton.rectangle { width = \"200px\", height = \"100px\" } []`\n  - `<Skeleton variant=\"circle\" width=\"3rem\" … />` → `Skeleton.circle { diameter = \"3rem\" } []`\n  - `<Skeleton variant=\"circle\" className=\"size-12\" />` → `Skeleton.round [ Attr.class \"size-12\" ]`\n  - `<Skeleton variant=\"text\" width={24} />` → `Skeleton.text { characters = 24 } []`\n  - `<Skeleton variant=\"text\">En tittel</Skeleton>` → `Skeleton.textLike \"En tittel\" []`\n  - `<Skeleton><Button>…</Button></Skeleton>` → `Skeleton.view [] [ Button.view [] [ … ] ]`\n  - `<Skeleton asChild><Paragraph>…` → `Skeleton.viewAs Paragraph.view [] [ … ]`\n\nReact's `characters` prop is deprecated and does nothing, so it isn't ported.\nReact also syncs the pulse of all skeletons on the page in JavaScript. Elm\ncan't, so skeletons that appear at different times pulse slightly out of step.\n\n@docs rectangle, circle, round, text, textLike\n\n\n# Shaped like content\n\n@docs view, viewAs\n\n","unions":[],"aliases":[],"values":[{"name":"circle","comment":" A circle, for avatars and icons. The diameter is a CSS length.\n\nReact takes a width and a height. A single diameter means it can't come out\noval. It's an inline style, so it wins over classes that set a width or\nheight. To size a circle with classes, use [`round`](#round).\n\n","type":"{ diameter : String.String } -> List.List (Html.Attribute msg) -> Html.Html msg"},{"name":"rectangle","comment":" A rounded rectangle for images, text blocks and other boxes. Width and\nheight are CSS lengths: `\"100%\"`, `\"12rem\"`, `\"200px\"`.\n\nThey are inline styles, like React's `width` and `height`, so they win over any\nclass. To size with classes instead (Tailwind's `w-full h-32`, say), use an\nempty [`view`](#view). Unsized, a skeleton is a full-width block one line high.\n\n    Skeleton.view [ Attr.class \"h-32 w-full\" ] []\n\n","type":"{ width : String.String, height : String.String } -> List.List (Html.Attribute msg) -> Html.Html msg"},{"name":"round","comment":" A circle with no diameter, for sizing with classes. Unsized, it's one line\nof the surrounding text tall. Give it both a width and a height (Tailwind's\n`size-12`, not `w-12` alone).\n\n    Skeleton.round [ Attr.class \"size-12\" ]\n\n","type":"List.List (Html.Attribute msg) -> Html.Html msg"},{"name":"text","comment":" A line of text about `characters` characters long. It sits inline and takes\non the surrounding text's size, so put it where the text will go: a heading, a\nparagraph or a table cell.\n\n    Paragraph.view [] [ Skeleton.text { characters = 40 } [] ]\n\n","type":"{ characters : Basics.Int } -> List.List (Html.Attribute msg) -> Html.Html msg"},{"name":"textLike","comment":" A line of text exactly as long as `placeholder`. Like [`text`](#text) it\nsits inline and takes the surrounding text's size. The placeholder is rendered\nbut invisible.\n\nUse it when you know roughly what will be there, like a title:\n\n    Heading.h2 [] [ Skeleton.textLike \"En medium tittel\" [] ]\n\n","type":"String.String -> List.List (Html.Attribute msg) -> Html.Html msg"},{"name":"view","comment":" A skeleton the size of its content, which is rendered but hidden. Use it\nwhen the size is easiest to give by example: a button, a tag, a name.\n\n    Skeleton.view [] [ Button.view [] [ Html.text \"Send inn\" ] ]\n\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"viewAs","comment":" A content-shaped skeleton on another element (React's `asChild`). The\nelement keeps its layout.\n\n    Skeleton.viewAs Paragraph.view [] [ Html.text \"Et avsnitt med plassholdertekst.\" ]\n\nAny `view` in this package with that shape works as the element.\n\n","type":"(List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg) -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.SkipLink","comment":" A link for keyboard users to jump past the header and navigation to the\nmain content.\n\nMirrors `SkipLink` from `@digdir/designsystemet-react`.\n\n    Html.body []\n        [ SkipLink.view { href = \"#main-content\" } [] [ Html.text \"Hopp til hovedinnhold\" ]\n        , siteHeader\n        , Html.main_ [ Attr.id \"main-content\", Attr.tabindex -1 ] [{- … -}]\n        ]\n\nIt's invisible until focused, so put it first on the page where the first Tab\nreveals it.\n\n\n# React → Elm\n\n  - `<SkipLink href=\"#main\">Hopp</SkipLink>` → `SkipLink.view { href = \"#main\" } [] [ … ]`\n\n@docs view\n\n","unions":[],"aliases":[],"values":[{"name":"view","comment":" An `<a class=\"ds-skip-link\">` to an element on the same page. `href` is `\"#\"`\nplus the target's `id`. Give the target `tabindex=\"-1\"` so it can take focus.\n","type":"{ href : String.String } -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Spinner","comment":" A spinning loading indicator.\n\nMirrors `Spinner` from `@digdir/designsystemet-react`.\n\n    Spinner.view { label = \"Henter saker\" } [ Spinner.size Spinner.Large ]\n\n\n# React → Elm\n\n  - `<Spinner aria-label=\"…\" />` → `Spinner.view { label = \"…\" } []`\n  - `<Spinner aria-hidden />` → `Spinner.decorative []`\n  - `data-size=\"lg\"` → `Spinner.size Spinner.Large`\n\nThe spinner is an `<svg>`, so add classes with `Svg.Attributes.class`, never\n`Html.Attributes.class`. The latter sets the `className` property, which is\nread-only on SVG elements, so the browser throws a `TypeError` and your whole\nview stops rendering.\n\n    Spinner.view { label = \"Henter saker\" } [ SvgAttr.class \"size-6 shrink-0\" ]\n\n@docs view, decorative\n\n\n# Sizes\n\n@docs Size, size\n\n","unions":[{"name":"Size","comment":" Spinners have their own size scale, wider than\n[`Designsystemet.Size`](Designsystemet-Size).\n","args":[],"cases":[["TwoExtraSmall",[]],["ExtraSmall",[]],["Small",[]],["Medium",[]],["Large",[]],["ExtraLarge",[]]]}],"aliases":[],"values":[{"name":"decorative","comment":" A spinner hidden from screen readers, for when something nearby already\nsays work is in progress (like a busy [`Button`](Designsystemet-Button)).\n\nAdd classes with `Svg.Attributes.class`, never `Html.Attributes.class` (it\nthrows on an `<svg>`).\n\n","type":"List.List (Html.Attribute msg) -> Html.Html msg"},{"name":"size","comment":" Set the spinner's `data-size`.\n","type":"Designsystemet.Spinner.Size -> Html.Attribute msg"},{"name":"view","comment":" A spinner announced to screen readers. As in React, `aria-label` is\nrequired unless the spinner is hidden.\n\nAdd classes with `Svg.Attributes.class`, never `Html.Attributes.class` (it\nthrows on an `<svg>`).\n\n","type":"{ label : String.String } -> List.List (Html.Attribute msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Suggestion","comment":" **Experimental.** A combobox: a text input that suggests values from a list\nas you type, for picking one or several.\n\nMirrors `EXPERIMENTAL_Suggestion` from `@digdir/designsystemet-react`. As there,\nthe API and markup may change in any release.\n\n    Field.view []\n        [ Label.view [] [ Html.text \"Kommune\" ]\n        , Suggestion.single\n            { options = Municipality.all\n            , selected = model.municipality\n            , toValue = Municipality.toCode\n            , toLabel = Municipality.toName\n            , onSelect = PickedMunicipality\n            }\n            |> Suggestion.withClear { label = \"Tøm\" }\n            |> Suggestion.withEmptyMessage [ Html.text \"Ingen treff\" ]\n            |> Suggestion.view []\n        ]\n\n    Suggestion.multiple\n        { options = Tag.all\n        , selected = model.tags\n        , toValue = Tag.toId\n        , toLabel = Tag.toName\n        , onChange = ChangedTags\n        }\n        |> Suggestion.withToggle { label = \"Vis alle\" }\n        |> Suggestion.view [ Attr.attribute \"aria-label\" \"Stikkord\" ]\n\nThe attributes you give `view` go on the text `<input>`. Add `Events.onInput`\nthere to get the typed text, e.g. to fetch options from a server.\n\n\n# Controlled only\n\nElm owns the selection. When the user picks or removes a value, the web\ncomponent fires `comboboxbeforeselect`. The module cancels it and sends\n`onSelect` or `onChange` with the new selection, so nothing changes on screen\nuntil your model does.\n\nReact also has an uncontrolled mode (`defaultSelected`) where the web component\nadds and removes selected items itself. That would insert nodes among Elm's, so\nit isn't ported.\n\nIf a value isn't in `options` (or in `selected`, when removing), you get your\ncurrent selection back unchanged and the event is still cancelled.\n\n\n# React → Elm\n\n  - `<Suggestion selected onSelectedChange>` → `Suggestion.single { … }`\n  - `<Suggestion multiple selected onSelectedChange>` → `Suggestion.multiple { … }`\n  - `<Suggestion.Input>` → the attributes of `Suggestion.view`\n  - `<Suggestion.Option value>` → `options`, `toValue`, `toLabel`\n  - `<Suggestion.Toggle aria-label>` → `Suggestion.withToggle { label = \"…\" }`\n  - `<Suggestion.Clear>` + `data-sr-clear` → `Suggestion.withClear { label = \"…\" }`\n  - `<Suggestion.Empty>` → `Suggestion.withEmptyMessage [ … ]`\n  - `<Suggestion.Option label>` with markup in it → `Suggestion.withOptionContent (\\a -> [ … ])`\n  - `filter={false}` → `Suggestion.withoutFiltering`\n  - `filter={fn}` → filter `options` yourself + `withoutFiltering`\n  - `creatable` + `<Suggestion.Empty data-empty=\"…\">` → `Suggestion.withCreatable { … }`\n  - `name` → `Suggestion.withName \"…\"`\n  - `renderSelected` → `toLabel`\n  - `defaultSelected` → not ported: controlled only\n  - `onBeforeMatch` → not ported\n\n\n# Filtering\n\nBy default the web component shows the options whose label contains the typed\ntext, ignoring case, like React's default `filter`. With\n[`withoutFiltering`](#withoutFiltering) every option you pass is shown, so you\ncan filter `options` yourself or show what a server sent back.\n\n\n# Managed by designsystemet-web\n\n`<ds-suggestion>` (built on `u-combobox` and `u-datalist` from u-elements)\nwrites these, so the module never renders them:\n\n  - on the input: `role`, `list`, `popovertarget`, `autocomplete`,\n    `enterkeyhint`, `aria-autocomplete`, `aria-controls`, `aria-expanded`,\n    `aria-activedescendant`, `aria-description`, and its `value` in single\n    mode (it shows the selected label)\n  - on the selected `<data>` items: `aria-label`, `role`, `slot`, `tabindex`,\n    `hidden`\n  - on the options: `selected`, `aria-selected`, `aria-disabled`,\n    `aria-hidden`, `role`, `id`\n  - on the list: `hidden`, `tabindex`, `aria-label`, `data-sr-*`,\n    `data-is-floating`\n  - on the empty option: `hidden`, `label`, `value`, `disabled`,\n    `data-create`\n  - on the clear and toggle buttons: `hidden`, `aria-hidden`, `tabindex`,\n    and `aria-expanded` on the toggle (Elm renders the initial `hidden` and\n    `aria-expanded=\"false\"`, like React, and never changes them)\n  - the `<option>`s of the hidden `<select>` from [`withName`](#withName),\n    and its `multiple` (set from `data-multiple`)\n  - the screen reader texts (`data-sr-*`) other than the clear label, from\n    the CSS custom properties `--dsc-suggestion-sr-*`\n\n@docs Suggestion, single, multiple, view\n\n\n# Buttons and messages\n\n@docs withToggle, withClear, withEmptyMessage, withOptionContent\n\n\n# Behaviour\n\n@docs withoutFiltering, withCreatable, withName\n\n","unions":[{"name":"Suggestion","comment":" A suggestion field being configured. Start with [`single`](#single) or\n[`multiple`](#multiple), end with [`view`](#view).\n","args":["a","msg"],"cases":[]}],"aliases":[],"values":[{"name":"multiple","comment":" Pick any number of values. They are shown as removable chips before the\ninput, in the order of `selected`.\n","type":"{ options : List.List a, selected : List.List a, toValue : a -> String.String, toLabel : a -> String.String, onChange : List.List a -> msg } -> Designsystemet.Suggestion.Suggestion a msg"},{"name":"single","comment":" Pick at most one value. The input shows the selected label.\n\n  - `toValue` must give every option a different string.\n  - `toLabel` is what the user sees and types to find it.\n  - `onSelect` gets `Nothing` when the user clears the field.\n\n","type":"{ options : List.List a, selected : Maybe.Maybe a, toValue : a -> String.String, toLabel : a -> String.String, onSelect : Maybe.Maybe a -> msg } -> Designsystemet.Suggestion.Suggestion a msg"},{"name":"view","comment":" Render the field. The attributes go on the text `<input>`.\n\nIt has no visible label. Put it in a [`Field`](Designsystemet-Field) with a\n[`Label`](Designsystemet-Label), or give the input an `aria-label`.\n\n","type":"List.List (Html.Attribute msg) -> Designsystemet.Suggestion.Suggestion a msg -> Html.Html msg"},{"name":"withClear","comment":" A button, shown as an ×, that empties the input (and in single mode the\nselection). `label` is its accessible name.\n","type":"{ label : String.String } -> Designsystemet.Suggestion.Suggestion a msg -> Designsystemet.Suggestion.Suggestion a msg"},{"name":"withCreatable","comment":" Let the user add a value that isn't among the options.\n\n  - `template` is the text of the \"add\" option in the list; `%s` is replaced by\n    what the user typed: `\"Legg til «%s»\"`.\n  - `onCreate` gets the typed text when the user picks it. Turn it into one of\n    your values, add it to `options` and to the selection.\n\nThe \"add\" option replaces the [`withEmptyMessage`](#withEmptyMessage) message.\n\n","type":"{ template : String.String, onCreate : String.String -> msg } -> Designsystemet.Suggestion.Suggestion a msg -> Designsystemet.Suggestion.Suggestion a msg"},{"name":"withEmptyMessage","comment":" What the list shows when nothing matches, like\n`[ Html.text \"Ingen treff\" ]`. While fetching options from a server, show\n`[ Spinner.decorative [], Html.text \"Laster...\" ]` instead.\n","type":"List.List (Html.Html msg) -> Designsystemet.Suggestion.Suggestion a msg -> Designsystemet.Suggestion.Suggestion a msg"},{"name":"withName","comment":" Submit the selected values with a surrounding `<form>`, under this name. A\nhidden `<select>` holds them.\n","type":"String.String -> Designsystemet.Suggestion.Suggestion a msg -> Designsystemet.Suggestion.Suggestion a msg"},{"name":"withOptionContent","comment":" Show more than the label in each option, like a second line of detail.\n`toLabel` is still what the user types to find it, what the input shows once\npicked, and what a chip says.\n\n    |> Suggestion.withOptionContent\n        (\\place -> [ Html.text place.name, Html.div [] [ Html.text place.county ] ])\n\n","type":"(a -> List.List (Html.Html msg)) -> Designsystemet.Suggestion.Suggestion a msg -> Designsystemet.Suggestion.Suggestion a msg"},{"name":"withToggle","comment":" A button, shown as an arrow, that opens and closes the list. `label` is its\naccessible name.\n","type":"{ label : String.String } -> Designsystemet.Suggestion.Suggestion a msg -> Designsystemet.Suggestion.Suggestion a msg"},{"name":"withoutFiltering","comment":" Show every option you pass, instead of only those matching the typed text.\n","type":"Designsystemet.Suggestion.Suggestion a msg -> Designsystemet.Suggestion.Suggestion a msg"}],"binops":[]},{"name":"Designsystemet.Switch","comment":" An on/off switch for a setting that takes effect right away.\n\nMirrors `Switch` from `@digdir/designsystemet-react`.\n\n    Switch.new (Ds.label \"Mørk modus\")\n        |> Switch.view [ Attr.checked model.darkMode, Events.onCheck ToggledDarkMode ]\n\nIt's an `<input type=\"checkbox\" role=\"switch\">`, so `Events.onCheck` and\n`Attr.checked` work as for a checkbox. Use a [`Checkbox`](Designsystemet-Checkbox)\nwhen the choice only counts once a form is submitted.\n\nThe attributes you give `view` go on the `<input>`, like React's rest props.\nAttributes for the field around it go in\n[`withFieldAttributes`](#withFieldAttributes).\n\n\n# React → Elm\n\n  - `<Switch label=\"…\" />` → `Switch.new (Ds.label \"…\") |> Switch.view []`\n  - `aria-label=\"…\"` → `Switch.new (Ds.ariaLabel \"…\")`\n  - `description={…}` → `Switch.withDescription [ … ]`\n  - `variant=\"outline\"` → `Switch.withFieldAttributes [ Field.outline ]`\n  - `position=\"end\"` → `Switch.withFieldAttributes [ Field.position Field.End ]`\n  - `data-size`, `className`, `style` → `Switch.withFieldAttributes [ … ]`\n  - `checked`, `onChange`, … → `Switch.view [ Attr.checked …, Events.onCheck … ]`\n\nAs in React, a switch has no error message, since a setting that applies\nimmediately can't be wrong.\n\n@docs Switch, new, view\n\n\n# Options\n\n@docs withDescription, withFieldAttributes\n\n","unions":[{"name":"Switch","comment":" A switch being configured. Start with [`new`](#new), end with\n[`view`](#view).\n","args":["msg"],"cases":[]}],"aliases":[],"values":[{"name":"new","comment":" A switch with this accessible name. With\n[`Ds.label`](Designsystemet#label) the label is shown next to it.\n","type":"Designsystemet.Label msg -> Designsystemet.Switch.Switch msg"},{"name":"view","comment":" Render the switch. The attributes go on the `<input>`.\n","type":"List.List (Html.Attribute msg) -> Designsystemet.Switch.Switch msg -> Html.Html msg"},{"name":"withDescription","comment":" Help text under the label.\n","type":"List.List (Html.Html msg) -> Designsystemet.Switch.Switch msg -> Designsystemet.Switch.Switch msg"},{"name":"withFieldAttributes","comment":" Attributes for the `<ds-field>` around the switch: `Field.outline`,\n`Field.position`, `Ds.size`, a class, …\n","type":"List.List (Html.Attribute msg) -> Designsystemet.Switch.Switch msg -> Designsystemet.Switch.Switch msg"}],"binops":[]},{"name":"Designsystemet.Table","comment":" Data in rows and columns.\n\nMirrors `Table` and its parts (`Table.Head`, `Table.Body`, …) from\n`@digdir/designsystemet-react`. Each part is a function with the same shape as\n`Html`, so a table reads like the HTML it renders:\n\n    Table.view [ Table.zebra, Table.border ]\n        [ Html.caption [] [ Html.text \"Byggesaker\" ]\n        , Table.head []\n            [ Table.row []\n                [ Table.headerCell [] [ Html.text \"Saksnummer\" ]\n                , Table.headerCell [] [ Html.text \"Adresse\" ]\n                ]\n            ]\n        , Table.body []\n            (List.map\n                (\\case_ ->\n                    Table.row []\n                        [ Table.cell [] [ Html.text case_.number ]\n                        , Table.cell [] [ Html.text case_.address ]\n                        ]\n                )\n                cases\n            )\n        ]\n\n\n# React → Elm\n\n  - `<Table>` → `Table.view []`\n  - `zebra` / `stickyHeader` / `border` / `hover` → `Table.zebra` / `Table.stickyHeader` / `Table.border` / `Table.hover`\n  - `<Table.Head>` / `Body` / `Foot` → `Table.head []` / `Table.body []` / `Table.foot []`\n  - `<Table.Row>` / `Cell` / `HeaderCell` → `Table.row []` / `Table.cell []` / `Table.headerCell []`\n  - `<Table.HeaderCell sort=\"ascending\" onClick>` → `Table.sortableHeaderCell { sort, column, onSort } []`\n\n@docs view\n\n\n# Options\n\n@docs zebra, stickyHeader, border, hover\n\n\n# Parts\n\n@docs head, body, keyedBody, foot, row, cell, headerCell\n\n\n# Sorting\n\nIn React each header cell has its own `sort` prop, so two columns can both\nclaim to be sorted. Here the sort is one [`Sort`](#Sort) value in your model,\nshared by every sortable header. At most one column is sorted, and each\nheader's `aria-sort` and button follow from it.\n\n    type Column\n        = Number\n        | Address\n\n    type alias Model =\n        { sort : Table.Sort Column, cases : List Case }\n\n    type Msg\n        = SortChanged (Table.Sort Column)\n\n    viewHeader : Table.Sort Column -> Html Msg\n    viewHeader sort =\n        Table.head []\n            [ Table.row []\n                [ Table.sortableHeaderCell { sort = sort, column = Number, onSort = SortChanged }\n                    []\n                    [ Html.text \"Saksnummer\" ]\n                , Table.sortableHeaderCell { sort = sort, column = Address, onSort = SortChanged }\n                    []\n                    [ Html.text \"Adresse\" ]\n                ]\n            ]\n\nSorting the rows is up to you. The table only shows which column is sorted and\nasks for a new sort when a header is clicked.\n\n@docs Sort, Direction, sortableHeaderCell, nextSort\n\n","unions":[{"name":"Direction","comment":" Which way a sorted column is ordered: `aria-sort=\"ascending\"` or\n`\"descending\"`.\n","args":[],"cases":[["Ascending",[]],["Descending",[]]]},{"name":"Sort","comment":" How the table is sorted: not at all, or by one column in one direction.\n`column` is your own type for the table's columns.\n","args":["column"],"cases":[["Unsorted",[]],["SortedBy",["column","Designsystemet.Table.Direction"]]]}],"aliases":[],"values":[{"name":"body","comment":" A `<tbody>`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"border","comment":" A rounded border around the table.\n","type":"Html.Attribute msg"},{"name":"cell","comment":" A `<td>`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"foot","comment":" A `<tfoot>`, for sums and totals.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"head","comment":" A `<thead>`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"headerCell","comment":" A `<th>`. In the body, add `Attr.scope \"row\"` to make it a row header.\nFor a header that sorts its column, use\n[`sortableHeaderCell`](#sortableHeaderCell).\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"hover","comment":" Highlight the body row under the pointer.\n","type":"Html.Attribute msg"},{"name":"keyedBody","comment":" A `<tbody>` with keyed rows, for rows that get sorted, filtered, added or\nremoved. Each row keeps its DOM node as it moves, so focus and input state stay\nwith the right row.\n\n    Table.keyedBody []\n        (List.map (\\case_ -> ( case_.number, viewRow case_ )) (sortCases model.sort model.cases))\n\n","type":"List.List (Html.Attribute msg) -> List.List ( String.String, Html.Html msg ) -> Html.Html msg"},{"name":"nextSort","comment":" The sort after a click on a column's header: a new column starts\nascending, and clicking the sorted column again flips its direction.\n\n    nextSort Address Unsorted == SortedBy Address Ascending\n\n    nextSort Address (SortedBy Number Descending) == SortedBy Address Ascending\n\n    nextSort Address (SortedBy Address Ascending) == SortedBy Address Descending\n\n    nextSort Address (SortedBy Address Descending) == SortedBy Address Ascending\n\nTo have a third click go back to `Unsorted`, handle it in `update`. The\nmessage carries the column either way.\n\n","type":"column -> Designsystemet.Table.Sort column -> Designsystemet.Table.Sort column"},{"name":"row","comment":" A `<tr>`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"sortableHeaderCell","comment":" A header cell with a sort button in it: `<th aria-sort=\"…\"><button\ntype=\"button\">…</button></th>`.\n\n  - `sort` is the table's current sort, the same value for every header.\n  - `column` is the column this header is for.\n  - `onSort` gets the sort from [`nextSort`](#nextSort) when the header is\n    clicked.\n\n`aria-sort` is `\"ascending\"` or `\"descending\"` on the sorted column and\n`\"none\"` on the other sortable ones. The attributes go on the `<th>`.\n\n","type":"{ sort : Designsystemet.Table.Sort column, column : column, onSort : Designsystemet.Table.Sort column -> msg } -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"stickyHeader","comment":" Keep the header in view while the body scrolls. Give the table a\n`max-height` for it to scroll within.\n","type":"Html.Attribute msg"},{"name":"view","comment":" A `<table class=\"ds-table\">`. Put an `Html.caption` first to give it a\nvisible name, styled as a heading.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"zebra","comment":" Stripe every other row.\n","type":"Html.Attribute msg"}],"binops":[]},{"name":"Designsystemet.Tabs","comment":" Content split into panels, one shown at a time.\n\nMirrors `Tabs` from `@digdir/designsystemet-react`.\n\n    type Section\n        = Overview\n        | Documents\n        | History\n\n    sectionId : Section -> String\n    sectionId section =\n        case section of\n            Overview ->\n                \"case-overview\"\n\n            Documents ->\n                \"case-documents\"\n\n            History ->\n                \"case-history\"\n\n    view : Model -> Html Msg\n    view model =\n        Tabs.controlled { toId = sectionId, selected = model.section, onSelect = SectionSelected }\n            []\n            [ Tabs.tab { value = Overview, label = [ Html.text \"Oversikt\" ], panel = [ overview model ] }\n            , Tabs.tab { value = Documents, label = [ Html.text \"Dokumenter\" ], panel = [ documents model ] }\n            , Tabs.tab { value = History, label = [ Html.text \"Historikk\" ], panel = [ history model ] }\n            ]\n\nEach tab carries its panel, so neither can exist without the other.\n\nThe markup is `designsystemet-web`'s `<ds-tabs>`, which handles the keyboard\n(arrow keys, Home, End), focus and showing the right panel.\n\n\n# Controlled or uncontrolled\n\n  - [`uncontrolled`](#uncontrolled): the browser tracks the open tab and\n    nothing goes in your model. Use it when the rest of the page doesn't care\n    which tab is open.\n  - [`controlled`](#controlled): your model says which tab is open, and\n    clicking a tab sends a message instead of switching. Use it when the open\n    tab is in the URL or something else depends on it.\n\n\n# Ids\n\n`toId` turns a value into the DOM `id` of its panel, so it must be unique on\nthe page. Prefix it if you have more than one set of tabs.\n\n\n# React → Elm\n\n  - `<Tabs defaultValue=\"a\">` → `Tabs.uncontrolled { toId = …, initial = A } []`\n  - `<Tabs value={v} onChange={f}>` → `Tabs.controlled { toId = …, selected = v, onSelect = F } []`\n  - `<Tabs.List>` + `<Tabs.Tab value=\"a\">` → `Tabs.tab { value = A, label = […], panel = […] }`\n  - `<Tabs.Panel value=\"a\">` → the `panel` of that `Tabs.tab`\n  - `<Tooltip content=\"…\"><Tabs.Tab>` + icon → `Tabs.iconTab { value = A, label = \"…\", icon = …, panel = […] }`\n  - `<Tabs onChange={f}>` without `value` → use `controlled`\n\n\n# Differences from React\n\nReact puts the raw `value` in each tab's `data-value` and derives the panel\nids from it with `useId`. Here both are `toId value`, since Elm has no `useId`\nand `toId` already gives a unique, readable string.\n\n\n# Managed by designsystemet-web\n\nNever set these yourself: `tabindex` on tabs and panels; `hidden`,\n`aria-hidden`, `aria-labelledby` and `role` on panels; `role` on the list.\nIn uncontrolled tabs, `aria-selected` also belongs to the web component after\nthe first render. Elm writes it again only when `initial` changes. Elm renders\nthe tabs' `role=\"tab\"` and `aria-controls` as React does, with the values the\nweb component would write.\n\n@docs Tab, tab, iconTab\n@docs uncontrolled, controlled\n\n","unions":[{"name":"Tab","comment":" A tab and the panel it shows.\n","args":["a","msg"],"cases":[]}],"aliases":[],"values":[{"name":"controlled","comment":" Tabs your model switches between. Clicking a tab (or pressing Enter or Space\non it) sends `onSelect` with its value. The open tab changes only when\n`selected` does.\n\n    Tabs.controlled\n        { toId = sectionId\n        , selected = model.section\n        , onSelect = SectionSelected\n        }\n        []\n        tabs\n\n","type":"{ toId : a -> String.String, selected : a, onSelect : a -> msg } -> List.List (Html.Attribute msg) -> List.List (Designsystemet.Tabs.Tab a msg) -> Html.Html msg"},{"name":"iconTab","comment":" A tab showing only an icon. The label is required, since an icon means\nnothing to a screen reader or to someone who doesn't recognise it. It names the\ntab and shows as a [tooltip](Designsystemet-Tooltip) on hover and focus.\n\n    Tabs.iconTab\n        { value = Cars\n        , label = \"Dine biler\"\n        , icon = carIcon\n        , panel = [ Html.text \"Du har ingen av denne typen registrert hos oss\" ]\n        }\n\n","type":"{ value : a, label : String.String, icon : Html.Html msg, panel : List.List (Html.Html msg) } -> Designsystemet.Tabs.Tab a msg"},{"name":"tab","comment":" A tab with a `label` (what's on the tab itself) and the `panel` it shows.\n\n    Tabs.tab\n        { value = Documents\n        , label = [ documentIcon, Html.text \"Dokumenter\" ]\n        , panel = [ documentList model.documents ]\n        }\n\n","type":"{ value : a, label : List.List (Html.Html msg), panel : List.List (Html.Html msg) } -> Designsystemet.Tabs.Tab a msg"},{"name":"uncontrolled","comment":" Tabs the browser switches between. `initial` is the tab open on first\nrender.\n\n    Tabs.uncontrolled { toId = sectionId, initial = Overview } [] tabs\n\nIf `initial` changes later, that tab is opened. Otherwise Elm leaves the tabs\nalone.\n\n","type":"{ toId : a -> String.String, initial : a } -> List.List (Html.Attribute msg) -> List.List (Designsystemet.Tabs.Tab a msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Tag","comment":" A label for a category or status.\n\nMirrors `Tag` from `@digdir/designsystemet-react`.\n\n    Tag.view [ Ds.color Color.success ] [ Html.text \"Godkjent\" ]\n\nA tag is not interactive. For something the user can click to filter or\nremove, use a `Chip`.\n\n\n# React → Elm\n\n  - `<Tag>` → `Tag.view []`\n  - `variant=\"outline\"` → `Tag.outline`\n  - `data-color=\"success\"` → `Ds.color Color.success`\n  - `asChild` + `<a>` → `Tag.viewAs Html.a [ Attr.href \"…\" ]`\n\n@docs view, viewAs, outline\n\n","unions":[],"aliases":[],"values":[{"name":"outline","comment":" Border and no fill, for tags that should draw less attention.\n","type":"Html.Attribute msg"},{"name":"view","comment":" A `<span class=\"ds-tag\">`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"viewAs","comment":" Tag styling on another element (React's `asChild`).\n\n    Tag.viewAs Html.a [ Attr.href \"/saker?status=apen\" ] [ Html.text \"Åpen\" ]\n\n","type":"(List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg) -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Textarea","comment":" A native `<textarea>` with Designsystemet styling.\n\nMirrors `Textarea` from `@digdir/designsystemet-react`.\n\n    Textarea.view [ Attr.value model.comment, Events.onInput ChangedComment ]\n\nLike [`Input`](Designsystemet-Input), it needs a label. Put it in a\n[`Field`](Designsystemet-Field) or use\n[`Textfield.multiline`](Designsystemet-Textfield#multiline).\n\nInside a `Field` and without `rows`, the textarea grows with its text.\n\n\n# React → Elm\n\n  - `<Textarea />` → `Textarea.view []`\n  - `rows={4}` → `Textarea.view [ Attr.rows 4 ]`\n  - `<Textarea>Tekst</Textarea>` → `Textarea.view [ Attr.value \"Tekst\" ]`\n\n@docs view\n\n","unions":[],"aliases":[],"values":[{"name":"view","comment":" A `<textarea class=\"ds-input\">`. Set its text with `Attr.value`.\n","type":"List.List (Html.Attribute msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Textfield","comment":" A text input wired up with its label, description, prefix, suffix,\ncharacter counter and error message.\n\nMirrors `Textfield` from `@digdir/designsystemet-react`.\n\n    Textfield.new (Ds.label \"E-post\")\n        |> Textfield.withDescription [ Html.text \"Vi sender kvitteringen hit\" ]\n        |> Textfield.withError model.emailError\n        |> Textfield.view\n            [ Attr.type_ \"email\"\n            , Attr.value model.email\n            , Events.onInput ChangedEmail\n            ]\n\n    Textfield.multiline (Ds.label \"Begrunnelse\")\n        |> Textfield.withCounter { limit = 500, under = \"%d tegn igjen\", over = \"%d tegn for mye\" }\n        |> Textfield.view [ Attr.value model.reason, Events.onInput ChangedReason ]\n\nThe attributes you give `view` go on the `<input>` or `<textarea>`, like\nReact's rest props. Attributes for the field around it go in\n[`withFieldAttributes`](#withFieldAttributes).\n\nIt's built on [`Field`](Designsystemet-Field), so `<ds-field>` links the label,\ndescription, counter and error to the input and sets `aria-invalid` while there\nis an error. For anything this module doesn't do, build the field yourself from\nthe same parts.\n\n\n# React → Elm\n\n  - `<Textfield label=\"…\" />` → `Textfield.new (Ds.label \"…\") |> Textfield.view []`\n  - `aria-label=\"…\"` → `Textfield.new (Ds.ariaLabel \"…\")`\n  - `multiline` → `Textfield.multiline (Ds.label \"…\")`\n  - `description={…}` → `Textfield.withDescription [ … ]`\n  - `prefix=\"NOK\"` → `Textfield.withPrefix \"NOK\"`\n  - `suffix=\"kr\"` → `Textfield.withSuffix \"kr\"`\n  - `counter={140}` → `Textfield.withCounter { limit = 140, under = \"…\", over = \"…\" }`\n  - `error=\"…\"` → `Textfield.withError (Just \"…\")`\n  - `className`, `style`, `data-size` → `Textfield.withFieldAttributes [ … ]`\n  - `type`, `value`, `onChange`, … → `Textfield.view [ Attr.type_ …, Attr.value …, Events.onInput … ]`\n\nReact's counter falls back to Norwegian texts. Here you give both, in your\napp's language.\n\n@docs Textfield, new, multiline, view\n\n\n# Options\n\n@docs withDescription, withPrefix, withSuffix, withCounter, withError\n@docs withFieldAttributes\n\n","unions":[{"name":"Textfield","comment":" A text field being configured. Start with [`new`](#new) or\n[`multiline`](#multiline), end with [`view`](#view).\n","args":["msg"],"cases":[]}],"aliases":[],"values":[{"name":"multiline","comment":" A text field for longer text (a `<textarea>`) with this accessible name.\n","type":"Designsystemet.Label msg -> Designsystemet.Textfield.Textfield msg"},{"name":"new","comment":" A one-line text field (an `<input>`) with this accessible name. With\n[`Ds.label`](Designsystemet#label) the label is shown above it.\n","type":"Designsystemet.Label msg -> Designsystemet.Textfield.Textfield msg"},{"name":"view","comment":" Render the field. The attributes go on the `<input>` or `<textarea>`.\n\nLeave out `aria-describedby` and `aria-invalid`. The field sets them.\n\n","type":"List.List (Html.Attribute msg) -> Designsystemet.Textfield.Textfield msg -> Html.Html msg"},{"name":"withCounter","comment":" Count characters against a limit. See\n[`Field.counter`](Designsystemet-Field#counter).\n","type":"Designsystemet.Field.Counter -> Designsystemet.Textfield.Textfield msg -> Designsystemet.Textfield.Textfield msg"},{"name":"withDescription","comment":" Help text between the label and the input.\n","type":"List.List (Html.Html msg) -> Designsystemet.Textfield.Textfield msg -> Designsystemet.Textfield.Textfield msg"},{"name":"withError","comment":" An error message under the input, or `Nothing` for none:\n\n    |> Textfield.withError (Dict.get \"email\" model.errors)\n\nIt's a `String` because an error is read aloud with the input, and the same\ntext usually goes in an [`ErrorSummary`](Designsystemet-ErrorSummary) too. Keep\none list of errors for both and get this field's message with\n[`ErrorSummary.messageFor`](Designsystemet-ErrorSummary#messageFor).\n\n","type":"Maybe.Maybe String.String -> Designsystemet.Textfield.Textfield msg -> Designsystemet.Textfield.Textfield msg"},{"name":"withFieldAttributes","comment":" Attributes for the `<ds-field>` around everything: `Ds.size`, a class, …\n","type":"List.List (Html.Attribute msg) -> Designsystemet.Textfield.Textfield msg -> Designsystemet.Textfield.Textfield msg"},{"name":"withPrefix","comment":" A short text in front of the input, like `\"NOK\"` or `\"https://\"`. Screen\nreaders skip it, so make sure the label says the same thing.\n","type":"String.String -> Designsystemet.Textfield.Textfield msg -> Designsystemet.Textfield.Textfield msg"},{"name":"withSuffix","comment":" A short text after the input, like `\"kr\"` or `\"pr. mnd.\"`. Screen readers\nskip it, so make sure the label says the same thing.\n","type":"String.String -> Designsystemet.Textfield.Textfield msg -> Designsystemet.Textfield.Textfield msg"}],"binops":[]},{"name":"Designsystemet.ToggleGroup","comment":" A row of buttons where exactly one is chosen, like a segmented control.\n\nMirrors `ToggleGroup` from `@digdir/designsystemet-react`.\n\n    type Layout\n        = List\n        | Grid\n\n    layoutToString : Layout -> String\n    layoutToString layout =\n        case layout of\n            List ->\n                \"list\"\n\n            Grid ->\n                \"grid\"\n\n    ToggleGroup.controlled\n        { name = \"layout\"\n        , label = \"Visning\"\n        , toValue = layoutToString\n        , selected = model.layout\n        , onSelect = LayoutSelected\n        }\n        []\n        [ ToggleGroup.item List [ Html.text \"Liste\" ]\n        , ToggleGroup.item Grid [ Html.text \"Rutenett\" ]\n        ]\n\nIt's a `<fieldset>` of radio buttons, so forms and screen readers treat it like\nany radio group. `designsystemet-web` makes the arrow keys move focus without\nchoosing, and lets Enter choose.\n\n\n# Controlled or uncontrolled\n\n  - [`uncontrolled`](#uncontrolled): the browser tracks the chosen item, like\n    any radio group. Use it in a plain `<form>` that gets submitted, or when\n    nothing else on the page depends on the choice.\n  - [`controlled`](#controlled): your model says which item is chosen, and\n    clicking an item sends a message instead of choosing it.\n\n\n# React → Elm\n\n  - `<ToggleGroup aria-label=\"…\" defaultValue=\"a\">` → `ToggleGroup.uncontrolled { label = \"…\", initial = A, … } []`\n  - `<ToggleGroup value={v} onChange={f}>` → `ToggleGroup.controlled { selected = v, onSelect = F, … } []`\n  - `<ToggleGroup.Item value=\"a\">A</ToggleGroup.Item>` → `ToggleGroup.item A [ Html.text \"A\" ]`\n  - icon-only item + `<Tooltip>` → `ToggleGroup.iconItem { value = A, label = \"…\", icon = … }`\n  - `<ToggleGroup.Item disabled>` → `ToggleGroup.item A […] |> ToggleGroup.disabled`\n  - `<ToggleGroup.Item aria-disabled=\"true\">` → `ToggleGroup.item A […] |> ToggleGroup.disabledFocusable`\n  - `<ToggleGroup.Item readOnly>` → `ToggleGroup.item A […] |> ToggleGroup.readOnly`\n  - `variant=\"secondary\"` → `ToggleGroup.secondary`\n\n\n# Differences from React\n\n  - An icon item's radio button also gets the label as its `aria-label`, so\n    it is named before `designsystemet-web` turns the tooltip into the item's\n    `aria-label`.\n  - The `name` is required. React generates one with `useId`.\n\n\n# Managed by designsystemet-web\n\nNever set these yourself: `role` on the fieldset and the radios, and\n`tabindex` on the radios (the `focusgroup` polyfill moves it around).\n\n@docs uncontrolled, controlled\n\n\n# Items\n\n@docs Item, item, iconItem\n\n\n# Items that can't be chosen\n\n@docs disabled, disabledFocusable, readOnly\n\n\n# Variants\n\n@docs primary, secondary\n\n","unions":[{"name":"Item","comment":" One choice in the group.\n","args":["a","msg"],"cases":[]}],"aliases":[],"values":[{"name":"controlled","comment":" A toggle group your model tracks. Clicking an item (or pressing Enter on it)\nsends `onSelect` with its value. The chosen item changes only when `selected`\ndoes.\n\nThe fields are as in [`uncontrolled`](#uncontrolled), with `selected` and\n`onSelect` instead of `initial`.\n\n","type":"{ name : String.String, label : String.String, toValue : a -> String.String, selected : a, onSelect : a -> msg } -> List.List (Html.Attribute msg) -> List.List (Designsystemet.ToggleGroup.Item a msg) -> Html.Html msg"},{"name":"disabled","comment":" An item that can't be chosen right now. It's dimmed and the keyboard skips\nit.\n\n    ToggleGroup.item Map [ Html.text \"Kart\" ]\n        |> ToggleGroup.disabled\n\n","type":"Designsystemet.ToggleGroup.Item a msg -> Designsystemet.ToggleGroup.Item a msg"},{"name":"disabledFocusable","comment":" A dimmed item the keyboard still reaches, so screen reader users find it\nand hear that it's unavailable (`aria-disabled`).\n\nIn a [`controlled`](#controlled) group it can't be chosen. In an\n[`uncontrolled`](#uncontrolled) group it's only marked unavailable, as in\nReact, and the browser still lets the user choose it.\n\n","type":"Designsystemet.ToggleGroup.Item a msg -> Designsystemet.ToggleGroup.Item a msg"},{"name":"iconItem","comment":" An item showing only an icon. The label is required, since an icon means\nnothing to a screen reader or to someone who doesn't recognise it. It names the\nradio button and shows as a [tooltip](Designsystemet-Tooltip) on hover and\nfocus.\n\n    ToggleGroup.iconItem { value = Grid, label = \"Rutenett\", icon = gridIcon }\n\n","type":"{ value : a, label : String.String, icon : Html.Html msg } -> Designsystemet.ToggleGroup.Item a msg"},{"name":"item","comment":" An item with visible content, usually text.\n\n    ToggleGroup.item Archived [ Html.text \"Arkiverte\" ]\n\n","type":"a -> List.List (Html.Html msg) -> Designsystemet.ToggleGroup.Item a msg"},{"name":"primary","comment":" The default. The chosen item is filled with the main color.\n","type":"Html.Attribute msg"},{"name":"readOnly","comment":" An item that is shown but can't be switched to, for a value fixed in this\ncontext. The keyboard still reaches it, and `designsystemet-web` stops clicks\non it.\n","type":"Designsystemet.ToggleGroup.Item a msg -> Designsystemet.ToggleGroup.Item a msg"},{"name":"secondary","comment":" A quieter look: a tinted track with the chosen item raised on it.\n","type":"Html.Attribute msg"},{"name":"uncontrolled","comment":" A toggle group the browser tracks. `initial` is the item chosen on first\nrender.\n\n    ToggleGroup.uncontrolled\n        { name = \"folder\"\n        , label = \"Filtrering\"\n        , toValue = folderToString\n        , initial = Inbox\n        }\n        []\n        [ ToggleGroup.item Inbox [ Html.text \"Innboks\" ]\n        , ToggleGroup.item Drafts [ Html.text \"Utkast\" ]\n        ]\n\n  - `name` is the radio buttons' `name`, which the value is submitted under in\n    a form. Unique per form.\n  - `label` is the group's accessible name (`aria-label`). To name it with a\n    visible heading, also pass `Attr.attribute \"aria-labelledby\" headingId`,\n    which takes precedence.\n  - `toValue` turns a value into the radio button's `value`.\n\nIf `initial` changes later, that item is chosen. Otherwise Elm leaves the\nchoice to the browser.\n\n","type":"{ name : String.String, label : String.String, toValue : a -> String.String, initial : a } -> List.List (Html.Attribute msg) -> List.List (Designsystemet.ToggleGroup.Item a msg) -> Html.Html msg"}],"binops":[]},{"name":"Designsystemet.Tooltip","comment":" Short text shown when the user hovers over or focuses an element.\n\nMirrors `Tooltip` from `@digdir/designsystemet-react`.\n\nA tooltip is an attribute on the element it explains. `designsystemet-web`\nrenders one shared tooltip next to whichever element with\n[`content`](#content) is hovered or focused.\n\n    Button.icon { label = \"Slett\", icon = trashIcon }\n        [ Button.tertiary, Tooltip.content \"Slett\", Events.onClick Delete ]\n\n    Button.view [ Tooltip.content \"Lagres som utkast\", Tooltip.placement Placement.Bottom ]\n        [ Html.text \"Lagre\" ]\n\nThe element must be focusable so keyboard users see the tooltip. Buttons and\nlinks are. For plain text, use [`onText`](#onText).\n\n\n# Accessible names\n\n`designsystemet-web` also exposes the tooltip text to screen readers:\n\n  - On an element with no text of its own (an icon button), the tooltip becomes\n    its `aria-label`. If you already set a label (as `Button.icon` does), use\n    the same text for both, or the tooltip replaces it.\n  - On an element with text, the tooltip becomes its `aria-description`.\n\n\n# React → Elm\n\n  - `<Tooltip content=\"…\"><button /></Tooltip>` → `Html.button [ Tooltip.content \"…\" ] []`\n  - `<Tooltip content=\"…\">Some text</Tooltip>` → `Tooltip.onText { content = \"…\", text = \"Some text\" } []`\n  - `placement=\"bottom\"` → `Tooltip.placement Placement.Bottom`\n  - `autoPlacement={false}` → `Tooltip.noAutoPlacement`\n\n\n# Differences from React\n\nReact always renders `data-placement=\"top\"` and `data-autoplacement=\"true\"`.\nThose are `designsystemet-web`'s defaults, so they are only rendered when you\nask for something else.\n\n\n# Managed by designsystemet-web\n\nNever set these yourself on an element with a tooltip: `aria-label` (except\nwith the same text, see above) and `aria-description`. The tooltip element\nitself (`.ds-tooltip`) is created by `designsystemet-web`, so don't render one.\n\n\n# Attributes\n\n@docs content, placement, noAutoPlacement\n\n\n# Text with a tooltip\n\n@docs onText\n\n","unions":[],"aliases":[],"values":[{"name":"content","comment":" Give an element a tooltip with this text.\n","type":"String.String -> Html.Attribute msg"},{"name":"noAutoPlacement","comment":" Keep the tooltip on the requested side even when there is no room. By\ndefault `designsystemet-web` flips it to the opposite side.\n","type":"Html.Attribute msg"},{"name":"onText","comment":" Text with a tooltip, like an abbreviation. It's wrapped in a\n`<span tabindex=\"0\">` so keyboard users can focus it.\n\n    Html.p []\n        [ Html.text \"Oppgi \"\n        , Tooltip.onText { content = \"Organisasjonsnummer\", text = \"org.nr.\" } []\n        ]\n\n","type":"{ content : String.String, text : String.String } -> List.List (Html.Attribute msg) -> Html.Html msg"},{"name":"placement","comment":" Which side of the element the tooltip appears on. Defaults to\n`Placement.Top`.\n","type":"Designsystemet.Placement.Placement -> Html.Attribute msg"}],"binops":[]},{"name":"Designsystemet.ValidationMessage","comment":" A message about what the user typed: usually an error, sometimes a warning\nor a confirmation.\n\nMirrors `ValidationMessage` from `@digdir/designsystemet-react`.\n\n    ValidationMessage.view [] [ Html.text \"Skriv inn et gyldig fødselsnummer\" ]\n\n    ValidationMessage.view [ ValidationMessage.severity Color.Success ]\n        [ Html.text \"Brukernavnet er ledig\" ]\n\nA message is an error unless you give it another severity.\n\nInside a [`Field`](Designsystemet-Field), `<ds-field>` links the message to the\ninput with `aria-describedby`, and an error also makes the input\n`aria-invalid=\"true\"`. Messages of other severities are linked but don't make\nthe input invalid. As a direct child of a\n[`Fieldset`](Designsystemet-Fieldset), the message is linked to every field in\nthe group.\n\nThe composites ([`Textfield`](Designsystemet-Textfield),\n[`Checkbox`](Designsystemet-Checkbox), …) render this from `withError`.\n\n\n# React → Elm\n\n  - `<ValidationMessage>` → `ValidationMessage.view []`\n  - `data-color=\"warning\"` → `ValidationMessage.severity Color.Warning`\n  - `asChild` + `<div>` → `ValidationMessage.viewAs Html.div []`\n\n@docs view, viewAs, severity\n\n","unions":[],"aliases":[],"values":[{"name":"severity","comment":" How serious the message is. Defaults to `Danger`. The CSS has an icon and a\ncolor for each of the four.\n","type":"Designsystemet.Color.Severity -> Html.Attribute msg"},{"name":"view","comment":" A `<p class=\"ds-validation-message\" data-field=\"validation\">`.\n","type":"List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"},{"name":"viewAs","comment":" The message on another element (React's `asChild`).\n","type":"(List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg) -> List.List (Html.Attribute msg) -> List.List (Html.Html msg) -> Html.Html msg"}],"binops":[]}]