@dbcdk/react-components 0.0.202 → 0.0.204

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/components/chip/Chip.d.ts +2 -1
  2. package/dist/components/chip/Chip.module.css +13 -0
  3. package/dist/components/forms/checkbox/Checkbox.cjs +11 -6
  4. package/dist/components/forms/checkbox/Checkbox.d.ts +5 -1
  5. package/dist/components/forms/checkbox/Checkbox.js +11 -6
  6. package/dist/components/forms/checkbox/Checkbox.module.css +6 -7
  7. package/dist/components/forms/form-select/FormSelect.cjs +61 -63
  8. package/dist/components/forms/form-select/FormSelect.d.ts +1 -1
  9. package/dist/components/forms/form-select/FormSelect.js +62 -64
  10. package/dist/components/forms/form-select/FormSelect.module.css +10 -0
  11. package/dist/components/forms/input/Input.cjs +10 -1
  12. package/dist/components/forms/input/Input.js +10 -1
  13. package/dist/components/forms/input/Input.module.css +11 -130
  14. package/dist/components/forms/input-container/InputContainer.cjs +28 -10
  15. package/dist/components/forms/input-container/InputContainer.d.ts +4 -1
  16. package/dist/components/forms/input-container/InputContainer.js +29 -11
  17. package/dist/components/forms/input-container/InputContainer.module.css +33 -3
  18. package/dist/components/forms/input-container/messageIds.cjs +15 -0
  19. package/dist/components/forms/input-container/messageIds.d.ts +13 -0
  20. package/dist/components/forms/input-container/messageIds.js +12 -0
  21. package/dist/components/forms/select/Select.cjs +111 -113
  22. package/dist/components/forms/select/Select.d.ts +1 -1
  23. package/dist/components/forms/select/Select.js +112 -114
  24. package/dist/components/forms/select/Select.module.css +11 -33
  25. package/dist/components/forms/text-area/Textarea.cjs +5 -9
  26. package/dist/components/forms/text-area/Textarea.js +5 -9
  27. package/dist/components/forms/text-area/Textarea.module.css +11 -32
  28. package/package.json +1 -1
@@ -8,7 +8,8 @@ interface ChipProps {
8
8
  loading?: boolean;
9
9
  fullWidth?: boolean;
10
10
  onClose?: () => void;
11
- size?: 'sm' | 'md' | 'lg';
11
+ /** 'xs' fits inside a line of text, e.g. next to a form label */
12
+ size?: 'xs' | 'sm' | 'md' | 'lg';
12
13
  type?: 'default' | 'rounded' | 'outlined';
13
14
  selected?: boolean;
14
15
  }
@@ -94,6 +94,19 @@
94
94
 
95
95
  /* Sizes */
96
96
 
97
+ .xs {
98
+ height: auto;
99
+ padding-block: 0;
100
+ padding-inline: var(--spacing-xs);
101
+ font-size: var(--font-size-xs);
102
+ line-height: var(--line-height-tight);
103
+ }
104
+
105
+ .xs .leading svg {
106
+ inline-size: var(--icon-size-xs);
107
+ block-size: var(--icon-size-xs);
108
+ }
109
+
97
110
  .sm {
98
111
  height: var(--component-size-xs);
99
112
  font-size: var(--font-size-xs);
@@ -6,7 +6,9 @@ var lucideReact = require('lucide-react');
6
6
  var react = require('react');
7
7
  var Tooltip = require('../../../components/overlay/tooltip/Tooltip');
8
8
  var styles = require('./Checkbox.module.css');
9
+ var Circle = require('../../circle/Circle');
9
10
  var InputContainer = require('../input-container/InputContainer');
11
+ var messageIds = require('../input-container/messageIds');
10
12
 
11
13
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
14
 
@@ -24,9 +26,11 @@ function Checkbox({
24
26
  labelAction,
25
27
  size = "md",
26
28
  modified,
29
+ modifiedLabel = "\xC6ndret",
27
30
  containerLabel,
28
31
  error,
29
32
  helpText,
33
+ helpTextAddition,
30
34
  orientation = "horizontal",
31
35
  labelWidth = "160px",
32
36
  fullWidth = false,
@@ -50,12 +54,9 @@ function Checkbox({
50
54
  const content = /* @__PURE__ */ jsxRuntime.jsxs(
51
55
  "span",
52
56
  {
53
- className: [
54
- styles__default.default.container,
55
- size === "sm" ? styles__default.default.containerSm : "",
56
- modified ? styles__default.default.modified : ""
57
- ].filter(Boolean).join(" "),
57
+ className: [styles__default.default.container, size === "sm" ? styles__default.default.containerSm : ""].filter(Boolean).join(" "),
58
58
  "data-cy": dataCy,
59
+ "data-modified": modified ? "true" : void 0,
59
60
  children: [
60
61
  /* @__PURE__ */ jsxRuntime.jsx(Tooltip.Tooltip, { content: tooltip, placement: tooltipPlacement, children: /* @__PURE__ */ jsxRuntime.jsx(
61
62
  "button",
@@ -67,6 +68,7 @@ function Checkbox({
67
68
  "aria-checked": isChecked,
68
69
  "aria-disabled": disabled || void 0,
69
70
  "aria-invalid": Boolean(error) || void 0,
71
+ "aria-describedby": noContainer ? void 0 : messageIds.getDescribedBy(controlId, { error, helpText }),
70
72
  onClick: toggle,
71
73
  className: [
72
74
  styles__default.default.checkbox,
@@ -79,6 +81,7 @@ function Checkbox({
79
81
  }
80
82
  ) }),
81
83
  label && (labelAs === "label" ? /* @__PURE__ */ jsxRuntime.jsx("label", { className: styles__default.default.label, htmlFor: controlId, children: label }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.label, children: label })),
84
+ modified && label && !containerLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.modifiedTag, children: /* @__PURE__ */ jsxRuntime.jsx(Circle.Circle, { size: "2xs", severity: "info", children: modifiedLabel }) }),
82
85
  labelAction && !containerLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.labelAction, "data-checkbox-label-action": "true", children: labelAction }),
83
86
  endAdornment && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.endAdornment, "aria-hidden": endAdornmentAriaHidden, children: endAdornment })
84
87
  ]
@@ -88,12 +91,14 @@ function Checkbox({
88
91
  return /* @__PURE__ */ jsxRuntime.jsx(
89
92
  InputContainer.InputContainer,
90
93
  {
91
- modified,
94
+ modified: containerLabel ? modified : false,
95
+ modifiedLabel,
92
96
  label: containerLabel,
93
97
  labelAction: containerLabel ? labelAction : void 0,
94
98
  htmlFor: controlId,
95
99
  error,
96
100
  helpText,
101
+ helpTextAddition,
97
102
  orientation,
98
103
  size,
99
104
  labelWidth,
@@ -8,7 +8,10 @@ interface CheckboxProps {
8
8
  onChange?: (checked: boolean, event: React.MouseEvent<HTMLButtonElement>) => void;
9
9
  variant?: Variant;
10
10
  disabled?: boolean;
11
+ /** Marks the checkbox as changed since it was last saved. */
11
12
  modified?: boolean;
13
+ /** Text shown for a modified checkbox. */
14
+ modifiedLabel?: string;
12
15
  label?: ReactNode;
13
16
  labelAs?: 'label' | 'span';
14
17
  /**
@@ -32,6 +35,7 @@ interface CheckboxProps {
32
35
  containerLabel?: string;
33
36
  error?: string;
34
37
  helpText?: string;
38
+ helpTextAddition?: ReactNode;
35
39
  orientation?: 'vertical' | 'horizontal';
36
40
  labelWidth?: string;
37
41
  fullWidth?: boolean;
@@ -42,5 +46,5 @@ interface CheckboxProps {
42
46
  tooltip?: ReactNode;
43
47
  tooltipPlacement?: TooltipPlacement;
44
48
  }
45
- export declare function Checkbox({ checked: controlled, onChange, variant, disabled, label, labelAs, endAdornment, endAdornmentAriaHidden, labelAction, size, modified, containerLabel, error, helpText, orientation, labelWidth, fullWidth, required, noContainer, id, 'data-cy': dataCy, tooltip, tooltipPlacement, }: CheckboxProps): JSX.Element;
49
+ export declare function Checkbox({ checked: controlled, onChange, variant, disabled, label, labelAs, endAdornment, endAdornmentAriaHidden, labelAction, size, modified, modifiedLabel, containerLabel, error, helpText, helpTextAddition, orientation, labelWidth, fullWidth, required, noContainer, id, 'data-cy': dataCy, tooltip, tooltipPlacement, }: CheckboxProps): JSX.Element;
46
50
  export {};
@@ -4,7 +4,9 @@ import { Check } from 'lucide-react';
4
4
  import { useState, useId } from 'react';
5
5
  import { Tooltip } from '../../../components/overlay/tooltip/Tooltip';
6
6
  import styles from './Checkbox.module.css';
7
+ import { Circle } from '../../circle/Circle';
7
8
  import { InputContainer } from '../input-container/InputContainer';
9
+ import { getDescribedBy } from '../input-container/messageIds';
8
10
 
9
11
  function Checkbox({
10
12
  checked: controlled,
@@ -18,9 +20,11 @@ function Checkbox({
18
20
  labelAction,
19
21
  size = "md",
20
22
  modified,
23
+ modifiedLabel = "\xC6ndret",
21
24
  containerLabel,
22
25
  error,
23
26
  helpText,
27
+ helpTextAddition,
24
28
  orientation = "horizontal",
25
29
  labelWidth = "160px",
26
30
  fullWidth = false,
@@ -44,12 +48,9 @@ function Checkbox({
44
48
  const content = /* @__PURE__ */ jsxs(
45
49
  "span",
46
50
  {
47
- className: [
48
- styles.container,
49
- size === "sm" ? styles.containerSm : "",
50
- modified ? styles.modified : ""
51
- ].filter(Boolean).join(" "),
51
+ className: [styles.container, size === "sm" ? styles.containerSm : ""].filter(Boolean).join(" "),
52
52
  "data-cy": dataCy,
53
+ "data-modified": modified ? "true" : void 0,
53
54
  children: [
54
55
  /* @__PURE__ */ jsx(Tooltip, { content: tooltip, placement: tooltipPlacement, children: /* @__PURE__ */ jsx(
55
56
  "button",
@@ -61,6 +62,7 @@ function Checkbox({
61
62
  "aria-checked": isChecked,
62
63
  "aria-disabled": disabled || void 0,
63
64
  "aria-invalid": Boolean(error) || void 0,
65
+ "aria-describedby": noContainer ? void 0 : getDescribedBy(controlId, { error, helpText }),
64
66
  onClick: toggle,
65
67
  className: [
66
68
  styles.checkbox,
@@ -73,6 +75,7 @@ function Checkbox({
73
75
  }
74
76
  ) }),
75
77
  label && (labelAs === "label" ? /* @__PURE__ */ jsx("label", { className: styles.label, htmlFor: controlId, children: label }) : /* @__PURE__ */ jsx("span", { className: styles.label, children: label })),
78
+ modified && label && !containerLabel && /* @__PURE__ */ jsx("span", { className: styles.modifiedTag, children: /* @__PURE__ */ jsx(Circle, { size: "2xs", severity: "info", children: modifiedLabel }) }),
76
79
  labelAction && !containerLabel && /* @__PURE__ */ jsx("span", { className: styles.labelAction, "data-checkbox-label-action": "true", children: labelAction }),
77
80
  endAdornment && /* @__PURE__ */ jsx("span", { className: styles.endAdornment, "aria-hidden": endAdornmentAriaHidden, children: endAdornment })
78
81
  ]
@@ -82,12 +85,14 @@ function Checkbox({
82
85
  return /* @__PURE__ */ jsx(
83
86
  InputContainer,
84
87
  {
85
- modified,
88
+ modified: containerLabel ? modified : false,
89
+ modifiedLabel,
86
90
  label: containerLabel,
87
91
  labelAction: containerLabel ? labelAction : void 0,
88
92
  htmlFor: controlId,
89
93
  error,
90
94
  helpText,
95
+ helpTextAddition,
91
96
  orientation,
92
97
  size,
93
98
  labelWidth,
@@ -7,13 +7,6 @@
7
7
  color: var(--color-fg-default);
8
8
  }
9
9
 
10
- .container.modified {
11
- background-color: color-mix(in srgb, var(--color-status-warning-bg) 75%, transparent);
12
- border-radius: var(--border-radius-default);
13
- padding: 0;
14
- display: inline-flex;
15
- }
16
-
17
10
  .containerSm {
18
11
  gap: var(--spacing-xs);
19
12
  }
@@ -135,3 +128,9 @@
135
128
  color: var(--color-fg-on-brand);
136
129
  }
137
130
  }
131
+
132
+ .modifiedTag {
133
+ display: inline-flex;
134
+ flex-shrink: 0;
135
+ color: var(--color-fg-subtle);
136
+ }
@@ -7,6 +7,7 @@ var React = require('react');
7
7
  var useTooltipTrigger = require('../../../components/overlay/tooltip/useTooltipTrigger');
8
8
  var styles = require('./FormSelect.module.css');
9
9
  var InputContainer = require('../input-container/InputContainer');
10
+ var messageIds = require('../input-container/messageIds');
10
11
 
11
12
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
13
 
@@ -58,6 +59,7 @@ function FormSelect({
58
59
  labelAction,
59
60
  error,
60
61
  helpText,
62
+ helpTextAddition,
61
63
  orientation = "vertical",
62
64
  labelWidth = "160px",
63
65
  fullWidth = true,
@@ -83,7 +85,6 @@ function FormSelect({
83
85
  }) {
84
86
  const generatedId = React__namespace.useId();
85
87
  const controlId = id != null ? id : `select-${generatedId}`;
86
- const describedById = `${controlId}-desc`;
87
88
  const selected = React__namespace.useMemo(
88
89
  () => findSelectedOption(options, selectedValue, datakey),
89
90
  [options, selectedValue, datakey]
@@ -94,12 +95,11 @@ function FormSelect({
94
95
  placement: tooltipPlacement,
95
96
  offset: 8
96
97
  });
97
- const describedBy = (() => {
98
- const ids = [];
99
- if (error || helpText) ids.push(describedById);
100
- if (tooltipEnabled) ids.push(tooltipId);
101
- return ids.length ? ids.join(" ") : void 0;
102
- })();
98
+ const describedBy = messageIds.getDescribedBy(
99
+ controlId,
100
+ { error, helpText },
101
+ tooltipEnabled ? tooltipId : void 0
102
+ );
103
103
  const nativeValue = React__namespace.useMemo(() => {
104
104
  if (selected && selected.value != null) return serializeValue(selected.value, datakey);
105
105
  return "";
@@ -116,7 +116,7 @@ function FormSelect({
116
116
  const opt = options.find((o) => serializeValue(o.value, datakey) === raw);
117
117
  if (opt) onChange(opt.value);
118
118
  };
119
- return /* @__PURE__ */ jsxRuntime.jsxs(
119
+ return /* @__PURE__ */ jsxRuntime.jsx(
120
120
  InputContainer.InputContainer,
121
121
  {
122
122
  label,
@@ -125,67 +125,65 @@ function FormSelect({
125
125
  fullWidth,
126
126
  error,
127
127
  helpText,
128
+ helpTextAddition,
128
129
  orientation,
129
130
  labelWidth,
130
131
  required,
131
132
  modified,
132
- children: [
133
- /* @__PURE__ */ jsxRuntime.jsxs(
134
- "div",
135
- {
136
- className: [
137
- styles__default.default.container,
138
- fullWidth ? styles__default.default.fullWidth : "",
139
- canClear ? styles__default.default.withButton : ""
140
- ].filter(Boolean).join(" "),
141
- children: [
142
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.field, children: [
143
- /* @__PURE__ */ jsxRuntime.jsxs(
144
- "select",
145
- {
146
- ...tooltipEnabled ? triggerProps : {},
147
- id: controlId,
148
- name,
149
- className: [styles__default.default.input, styles__default.default[size], styles__default.default[variant]].filter(Boolean).join(" "),
150
- value: nativeValue,
151
- onChange: handleNativeChange,
152
- disabled,
153
- "aria-invalid": Boolean(error) || void 0,
154
- "aria-describedby": describedBy,
155
- "data-cy": dataCy != null ? dataCy : "formselect",
156
- "data-forminput": true,
157
- children: [
158
- includePlaceholderOption && /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: placeholderDisabled, children: placeholder }),
159
- options.map((opt) => {
160
- const v = serializeValue(opt.value, datakey);
161
- return /* @__PURE__ */ jsxRuntime.jsx("option", { value: v, children: opt.label }, v);
162
- })
163
- ]
164
- }
165
- ),
166
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.chevron, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 20 }) })
167
- ] }),
168
- canClear && /* @__PURE__ */ jsxRuntime.jsx(
169
- "button",
133
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
134
+ "div",
135
+ {
136
+ className: [
137
+ styles__default.default.container,
138
+ fullWidth ? styles__default.default.fullWidth : "",
139
+ canClear ? styles__default.default.withButton : ""
140
+ ].filter(Boolean).join(" "),
141
+ children: [
142
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.field, children: [
143
+ /* @__PURE__ */ jsxRuntime.jsxs(
144
+ "select",
170
145
  {
171
- type: "button",
172
- className: styles__default.default.trailingButton,
173
- onClick: (e) => {
174
- e.preventDefault();
175
- e.stopPropagation();
176
- onClear == null ? void 0 : onClear();
177
- },
178
- "aria-label": "Ryd valg",
179
- disabled: !showClear,
180
- "data-cy": dataCy ? `${dataCy}-clear` : "formselect-clear",
181
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 18, "aria-hidden": "true" })
146
+ ...tooltipEnabled ? triggerProps : {},
147
+ id: controlId,
148
+ name,
149
+ className: [styles__default.default.input, styles__default.default[size], styles__default.default[variant]].filter(Boolean).join(" "),
150
+ value: nativeValue,
151
+ onChange: handleNativeChange,
152
+ disabled,
153
+ "aria-invalid": Boolean(error) || void 0,
154
+ "aria-describedby": describedBy,
155
+ "data-cy": dataCy != null ? dataCy : "formselect",
156
+ "data-forminput": true,
157
+ children: [
158
+ includePlaceholderOption && /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: placeholderDisabled, children: placeholder }),
159
+ options.map((opt) => {
160
+ const v = serializeValue(opt.value, datakey);
161
+ return /* @__PURE__ */ jsxRuntime.jsx("option", { value: v, children: opt.label }, v);
162
+ })
163
+ ]
182
164
  }
183
- )
184
- ]
185
- }
186
- ),
187
- (error || helpText) && /* @__PURE__ */ jsxRuntime.jsx("span", { id: describedById, style: { display: "none" }, children: error != null ? error : helpText })
188
- ]
165
+ ),
166
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.chevron, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 20 }) })
167
+ ] }),
168
+ canClear && /* @__PURE__ */ jsxRuntime.jsx(
169
+ "button",
170
+ {
171
+ type: "button",
172
+ className: styles__default.default.trailingButton,
173
+ onClick: (e) => {
174
+ e.preventDefault();
175
+ e.stopPropagation();
176
+ onClear == null ? void 0 : onClear();
177
+ },
178
+ "aria-label": "Ryd valg",
179
+ disabled: !showClear,
180
+ "data-cy": dataCy ? `${dataCy}-clear` : "formselect-clear",
181
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 18, "aria-hidden": "true" })
182
+ }
183
+ )
184
+ ]
185
+ }
186
+ )
189
187
  }
190
188
  );
191
189
  }
@@ -31,5 +31,5 @@ export type FormSelectProps<T> = Omit<InputContainerProps, 'children' | 'htmlFor
31
31
  */
32
32
  allowClearWhenRequired?: boolean;
33
33
  };
34
- export declare function FormSelect<T extends string | number | Record<string, any>>({ label, labelAction, error, helpText, orientation, labelWidth, fullWidth, required, tooltip, tooltipPlacement, modified, id, name, options, selectedValue, onChange, placeholder, size, variant, onClear, datakey, dataCy, disabled, includePlaceholderOption, allowClearWhenRequired, }: FormSelectProps<T>): React.ReactNode;
34
+ export declare function FormSelect<T extends string | number | Record<string, any>>({ label, labelAction, error, helpText, helpTextAddition, orientation, labelWidth, fullWidth, required, tooltip, tooltipPlacement, modified, id, name, options, selectedValue, onChange, placeholder, size, variant, onClear, datakey, dataCy, disabled, includePlaceholderOption, allowClearWhenRequired, }: FormSelectProps<T>): React.ReactNode;
35
35
  export {};
@@ -1,10 +1,11 @@
1
1
  'use client';
2
- import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
3
  import { ChevronDown, X } from 'lucide-react';
4
4
  import * as React from 'react';
5
5
  import { useTooltipTrigger } from '../../../components/overlay/tooltip/useTooltipTrigger';
6
6
  import styles from './FormSelect.module.css';
7
7
  import { InputContainer } from '../input-container/InputContainer';
8
+ import { getDescribedBy } from '../input-container/messageIds';
8
9
 
9
10
  function isEqualValue(a, b, datakey) {
10
11
  if (a === b) return true;
@@ -33,6 +34,7 @@ function FormSelect({
33
34
  labelAction,
34
35
  error,
35
36
  helpText,
37
+ helpTextAddition,
36
38
  orientation = "vertical",
37
39
  labelWidth = "160px",
38
40
  fullWidth = true,
@@ -58,7 +60,6 @@ function FormSelect({
58
60
  }) {
59
61
  const generatedId = React.useId();
60
62
  const controlId = id != null ? id : `select-${generatedId}`;
61
- const describedById = `${controlId}-desc`;
62
63
  const selected = React.useMemo(
63
64
  () => findSelectedOption(options, selectedValue, datakey),
64
65
  [options, selectedValue, datakey]
@@ -69,12 +70,11 @@ function FormSelect({
69
70
  placement: tooltipPlacement,
70
71
  offset: 8
71
72
  });
72
- const describedBy = (() => {
73
- const ids = [];
74
- if (error || helpText) ids.push(describedById);
75
- if (tooltipEnabled) ids.push(tooltipId);
76
- return ids.length ? ids.join(" ") : void 0;
77
- })();
73
+ const describedBy = getDescribedBy(
74
+ controlId,
75
+ { error, helpText },
76
+ tooltipEnabled ? tooltipId : void 0
77
+ );
78
78
  const nativeValue = React.useMemo(() => {
79
79
  if (selected && selected.value != null) return serializeValue(selected.value, datakey);
80
80
  return "";
@@ -91,7 +91,7 @@ function FormSelect({
91
91
  const opt = options.find((o) => serializeValue(o.value, datakey) === raw);
92
92
  if (opt) onChange(opt.value);
93
93
  };
94
- return /* @__PURE__ */ jsxs(
94
+ return /* @__PURE__ */ jsx(
95
95
  InputContainer,
96
96
  {
97
97
  label,
@@ -100,67 +100,65 @@ function FormSelect({
100
100
  fullWidth,
101
101
  error,
102
102
  helpText,
103
+ helpTextAddition,
103
104
  orientation,
104
105
  labelWidth,
105
106
  required,
106
107
  modified,
107
- children: [
108
- /* @__PURE__ */ jsxs(
109
- "div",
110
- {
111
- className: [
112
- styles.container,
113
- fullWidth ? styles.fullWidth : "",
114
- canClear ? styles.withButton : ""
115
- ].filter(Boolean).join(" "),
116
- children: [
117
- /* @__PURE__ */ jsxs("div", { className: styles.field, children: [
118
- /* @__PURE__ */ jsxs(
119
- "select",
120
- {
121
- ...tooltipEnabled ? triggerProps : {},
122
- id: controlId,
123
- name,
124
- className: [styles.input, styles[size], styles[variant]].filter(Boolean).join(" "),
125
- value: nativeValue,
126
- onChange: handleNativeChange,
127
- disabled,
128
- "aria-invalid": Boolean(error) || void 0,
129
- "aria-describedby": describedBy,
130
- "data-cy": dataCy != null ? dataCy : "formselect",
131
- "data-forminput": true,
132
- children: [
133
- includePlaceholderOption && /* @__PURE__ */ jsx("option", { value: "", disabled: placeholderDisabled, children: placeholder }),
134
- options.map((opt) => {
135
- const v = serializeValue(opt.value, datakey);
136
- return /* @__PURE__ */ jsx("option", { value: v, children: opt.label }, v);
137
- })
138
- ]
139
- }
140
- ),
141
- /* @__PURE__ */ jsx("span", { className: styles.chevron, "aria-hidden": "true", children: /* @__PURE__ */ jsx(ChevronDown, { size: 20 }) })
142
- ] }),
143
- canClear && /* @__PURE__ */ jsx(
144
- "button",
108
+ children: /* @__PURE__ */ jsxs(
109
+ "div",
110
+ {
111
+ className: [
112
+ styles.container,
113
+ fullWidth ? styles.fullWidth : "",
114
+ canClear ? styles.withButton : ""
115
+ ].filter(Boolean).join(" "),
116
+ children: [
117
+ /* @__PURE__ */ jsxs("div", { className: styles.field, children: [
118
+ /* @__PURE__ */ jsxs(
119
+ "select",
145
120
  {
146
- type: "button",
147
- className: styles.trailingButton,
148
- onClick: (e) => {
149
- e.preventDefault();
150
- e.stopPropagation();
151
- onClear == null ? void 0 : onClear();
152
- },
153
- "aria-label": "Ryd valg",
154
- disabled: !showClear,
155
- "data-cy": dataCy ? `${dataCy}-clear` : "formselect-clear",
156
- children: /* @__PURE__ */ jsx(X, { size: 18, "aria-hidden": "true" })
121
+ ...tooltipEnabled ? triggerProps : {},
122
+ id: controlId,
123
+ name,
124
+ className: [styles.input, styles[size], styles[variant]].filter(Boolean).join(" "),
125
+ value: nativeValue,
126
+ onChange: handleNativeChange,
127
+ disabled,
128
+ "aria-invalid": Boolean(error) || void 0,
129
+ "aria-describedby": describedBy,
130
+ "data-cy": dataCy != null ? dataCy : "formselect",
131
+ "data-forminput": true,
132
+ children: [
133
+ includePlaceholderOption && /* @__PURE__ */ jsx("option", { value: "", disabled: placeholderDisabled, children: placeholder }),
134
+ options.map((opt) => {
135
+ const v = serializeValue(opt.value, datakey);
136
+ return /* @__PURE__ */ jsx("option", { value: v, children: opt.label }, v);
137
+ })
138
+ ]
157
139
  }
158
- )
159
- ]
160
- }
161
- ),
162
- (error || helpText) && /* @__PURE__ */ jsx("span", { id: describedById, style: { display: "none" }, children: error != null ? error : helpText })
163
- ]
140
+ ),
141
+ /* @__PURE__ */ jsx("span", { className: styles.chevron, "aria-hidden": "true", children: /* @__PURE__ */ jsx(ChevronDown, { size: 20 }) })
142
+ ] }),
143
+ canClear && /* @__PURE__ */ jsx(
144
+ "button",
145
+ {
146
+ type: "button",
147
+ className: styles.trailingButton,
148
+ onClick: (e) => {
149
+ e.preventDefault();
150
+ e.stopPropagation();
151
+ onClear == null ? void 0 : onClear();
152
+ },
153
+ "aria-label": "Ryd valg",
154
+ disabled: !showClear,
155
+ "data-cy": dataCy ? `${dataCy}-clear` : "formselect-clear",
156
+ children: /* @__PURE__ */ jsx(X, { size: 18, "aria-hidden": "true" })
157
+ }
158
+ )
159
+ ]
160
+ }
161
+ )
164
162
  }
165
163
  );
166
164
  }
@@ -253,3 +253,13 @@
253
253
  .trailingButton:disabled svg {
254
254
  opacity: 0.4;
255
255
  }
256
+
257
+ /* Error */
258
+ .input[aria-invalid='true'],
259
+ .input[aria-invalid='true']:hover {
260
+ border-color: var(--color-status-error);
261
+ }
262
+
263
+ .container:has(.input[aria-invalid='true']):focus-within {
264
+ box-shadow: 0 0 0 2px var(--color-status-error);
265
+ }
@@ -8,6 +8,7 @@ var ClearButton = require('../../../components/clear-button/ClearButton');
8
8
  var useTooltipTrigger = require('../../../components/overlay/tooltip/useTooltipTrigger');
9
9
  var styles = require('../input/Input.module.css');
10
10
  var InputContainer = require('../input-container/InputContainer');
11
+ var messageIds = require('../input-container/messageIds');
11
12
 
12
13
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
13
14
 
@@ -27,6 +28,7 @@ const Input = react.forwardRef(function Input2({
27
28
  labelAction,
28
29
  error,
29
30
  helpText,
31
+ helpTextAddition,
30
32
  orientation = "vertical",
31
33
  labelWidth = "160px",
32
34
  fullWidth = false,
@@ -97,6 +99,7 @@ const Input = react.forwardRef(function Input2({
97
99
  fullWidth,
98
100
  error,
99
101
  helpText,
102
+ helpTextAddition,
100
103
  orientation,
101
104
  labelWidth,
102
105
  required,
@@ -123,7 +126,7 @@ const Input = react.forwardRef(function Input2({
123
126
  styles__default.default[variant],
124
127
  icon ? styles__default.default.fieldWithIcon : "",
125
128
  inputSize ? styles__default.default[inputSize] : "",
126
- modified ? styles__default.default.modified : "",
129
+ error ? styles__default.default.invalid : "",
127
130
  fieldClassName != null ? fieldClassName : ""
128
131
  ].filter(Boolean).join(" "),
129
132
  "data-forminput": "field",
@@ -138,6 +141,12 @@ const Input = react.forwardRef(function Input2({
138
141
  {
139
142
  ...inputProps,
140
143
  id: inputId,
144
+ "aria-invalid": error ? true : inputProps["aria-invalid"],
145
+ "aria-describedby": messageIds.getDescribedBy(
146
+ inputId,
147
+ { error, helpText },
148
+ inputProps["aria-describedby"]
149
+ ),
141
150
  ref: mergeRefs(inputRef, ref),
142
151
  className: [styles__default.default.input, inputSize ? styles__default.default[inputSize] : "", inputClassName != null ? inputClassName : ""].filter(Boolean).join(" ")
143
152
  }