@navikt/ds-react 7.0.1 → 7.1.1

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 (133) hide show
  1. package/cjs/collapsible/Collapsible.context.d.ts +1 -1
  2. package/cjs/form/combobox/Combobox.js +5 -2
  3. package/cjs/form/combobox/Combobox.js.map +1 -1
  4. package/cjs/form/combobox/ComboboxProvider.js +2 -1
  5. package/cjs/form/combobox/ComboboxProvider.js.map +1 -1
  6. package/cjs/form/combobox/ComboboxWrapper.d.ts +1 -0
  7. package/cjs/form/combobox/ComboboxWrapper.js +3 -1
  8. package/cjs/form/combobox/ComboboxWrapper.js.map +1 -1
  9. package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.js +6 -1
  10. package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.js.map +1 -1
  11. package/cjs/form/combobox/Input/Input.context.d.ts +1 -0
  12. package/cjs/form/combobox/Input/Input.context.js +2 -1
  13. package/cjs/form/combobox/Input/Input.context.js.map +1 -1
  14. package/cjs/form/combobox/Input/Input.js +6 -2
  15. package/cjs/form/combobox/Input/Input.js.map +1 -1
  16. package/cjs/form/combobox/Input/InputController.js +3 -3
  17. package/cjs/form/combobox/Input/InputController.js.map +1 -1
  18. package/cjs/form/combobox/SelectedOptions/SelectedOptions.js +2 -2
  19. package/cjs/form/combobox/SelectedOptions/SelectedOptions.js.map +1 -1
  20. package/cjs/form/combobox/SelectedOptions/selectedOptionsContext.d.ts +2 -2
  21. package/cjs/form/combobox/types.d.ts +10 -11
  22. package/cjs/form/error-summary/ErrorSummary.d.ts +3 -3
  23. package/cjs/form/error-summary/ErrorSummary.js +6 -7
  24. package/cjs/form/error-summary/ErrorSummary.js.map +1 -1
  25. package/cjs/form/file-upload/FileUpload.context.d.ts +1 -1
  26. package/cjs/form/form-summary/FormSummaryEditLink.js +2 -2
  27. package/cjs/form/form-summary/FormSummaryEditLink.js.map +1 -1
  28. package/cjs/layout/page/parts/PageBlock.js +1 -1
  29. package/cjs/layout/page/parts/PageBlock.js.map +1 -1
  30. package/cjs/layout/stack/HStack.js +14 -2
  31. package/cjs/layout/stack/HStack.js.map +1 -1
  32. package/cjs/layout/stack/VStack.js +14 -2
  33. package/cjs/layout/stack/VStack.js.map +1 -1
  34. package/cjs/list/List.d.ts +4 -1
  35. package/cjs/list/List.js +6 -12
  36. package/cjs/list/List.js.map +1 -1
  37. package/cjs/list/ListItem.d.ts +1 -1
  38. package/cjs/list/ListItem.js +3 -3
  39. package/cjs/list/ListItem.js.map +1 -1
  40. package/cjs/list/context.d.ts +2 -3
  41. package/cjs/list/context.js +0 -1
  42. package/cjs/list/context.js.map +1 -1
  43. package/cjs/list/types.d.ts +1 -1
  44. package/cjs/overlays/floating/Floating.utils.d.ts +1 -1
  45. package/cjs/pagination/Pagination.js +6 -7
  46. package/cjs/pagination/Pagination.js.map +1 -1
  47. package/cjs/pagination/PaginationItem.d.ts +3 -2
  48. package/cjs/pagination/PaginationItem.js +1 -1
  49. package/cjs/pagination/PaginationItem.js.map +1 -1
  50. package/cjs/stepper/context.d.ts +1 -1
  51. package/cjs/tabs/Tabs.context.d.ts +1 -1
  52. package/cjs/toggle-group/ToggleGroup.context.d.ts +1 -1
  53. package/cjs/util/create-context.js.map +1 -1
  54. package/cjs/util/virtualfocus/Context.d.ts +1 -1
  55. package/esm/collapsible/Collapsible.context.d.ts +1 -1
  56. package/esm/form/combobox/Combobox.js +5 -2
  57. package/esm/form/combobox/Combobox.js.map +1 -1
  58. package/esm/form/combobox/ComboboxProvider.js +2 -1
  59. package/esm/form/combobox/ComboboxProvider.js.map +1 -1
  60. package/esm/form/combobox/ComboboxWrapper.d.ts +1 -0
  61. package/esm/form/combobox/ComboboxWrapper.js +3 -1
  62. package/esm/form/combobox/ComboboxWrapper.js.map +1 -1
  63. package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js +6 -1
  64. package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js.map +1 -1
  65. package/esm/form/combobox/Input/Input.context.d.ts +1 -0
  66. package/esm/form/combobox/Input/Input.context.js +2 -1
  67. package/esm/form/combobox/Input/Input.context.js.map +1 -1
  68. package/esm/form/combobox/Input/Input.js +6 -2
  69. package/esm/form/combobox/Input/Input.js.map +1 -1
  70. package/esm/form/combobox/Input/InputController.js +3 -3
  71. package/esm/form/combobox/Input/InputController.js.map +1 -1
  72. package/esm/form/combobox/SelectedOptions/SelectedOptions.js +2 -2
  73. package/esm/form/combobox/SelectedOptions/SelectedOptions.js.map +1 -1
  74. package/esm/form/combobox/SelectedOptions/selectedOptionsContext.d.ts +2 -2
  75. package/esm/form/combobox/types.d.ts +10 -11
  76. package/esm/form/error-summary/ErrorSummary.d.ts +3 -3
  77. package/esm/form/error-summary/ErrorSummary.js +7 -8
  78. package/esm/form/error-summary/ErrorSummary.js.map +1 -1
  79. package/esm/form/file-upload/FileUpload.context.d.ts +1 -1
  80. package/esm/form/form-summary/FormSummaryEditLink.js +2 -2
  81. package/esm/form/form-summary/FormSummaryEditLink.js.map +1 -1
  82. package/esm/layout/page/parts/PageBlock.js +1 -1
  83. package/esm/layout/page/parts/PageBlock.js.map +1 -1
  84. package/esm/layout/stack/HStack.js +14 -2
  85. package/esm/layout/stack/HStack.js.map +1 -1
  86. package/esm/layout/stack/VStack.js +14 -2
  87. package/esm/layout/stack/VStack.js.map +1 -1
  88. package/esm/list/List.d.ts +4 -1
  89. package/esm/list/List.js +7 -13
  90. package/esm/list/List.js.map +1 -1
  91. package/esm/list/ListItem.d.ts +1 -1
  92. package/esm/list/ListItem.js +3 -3
  93. package/esm/list/ListItem.js.map +1 -1
  94. package/esm/list/context.d.ts +2 -3
  95. package/esm/list/context.js +0 -1
  96. package/esm/list/context.js.map +1 -1
  97. package/esm/list/types.d.ts +1 -1
  98. package/esm/overlays/floating/Floating.utils.d.ts +1 -1
  99. package/esm/pagination/Pagination.js +6 -7
  100. package/esm/pagination/Pagination.js.map +1 -1
  101. package/esm/pagination/PaginationItem.d.ts +3 -2
  102. package/esm/pagination/PaginationItem.js +1 -1
  103. package/esm/pagination/PaginationItem.js.map +1 -1
  104. package/esm/stepper/context.d.ts +1 -1
  105. package/esm/tabs/Tabs.context.d.ts +1 -1
  106. package/esm/toggle-group/ToggleGroup.context.d.ts +1 -1
  107. package/esm/util/create-context.js.map +1 -1
  108. package/esm/util/virtualfocus/Context.d.ts +1 -1
  109. package/package.json +3 -3
  110. package/src/date/datepicker/datepicker.test.tsx +1 -1
  111. package/src/date/utils/__tests__/parse-dates.test.ts +12 -12
  112. package/src/form/combobox/Combobox.tsx +3 -0
  113. package/src/form/combobox/ComboboxProvider.tsx +2 -0
  114. package/src/form/combobox/ComboboxWrapper.tsx +4 -1
  115. package/src/form/combobox/FilteredOptions/filteredOptionsContext.tsx +7 -1
  116. package/src/form/combobox/Input/Input.context.tsx +3 -0
  117. package/src/form/combobox/Input/Input.tsx +6 -0
  118. package/src/form/combobox/Input/InputController.tsx +3 -0
  119. package/src/form/combobox/SelectedOptions/SelectedOptions.tsx +8 -2
  120. package/src/form/combobox/SelectedOptions/selectedOptionsContext.tsx +2 -2
  121. package/src/form/combobox/types.ts +10 -12
  122. package/src/form/error-summary/ErrorSummary.tsx +9 -15
  123. package/src/form/form-summary/FormSummaryEditLink.tsx +12 -9
  124. package/src/layout/page/parts/PageBlock.tsx +1 -1
  125. package/src/layout/stack/HStack.tsx +2 -2
  126. package/src/layout/stack/VStack.tsx +4 -2
  127. package/src/list/List.tsx +15 -25
  128. package/src/list/ListItem.tsx +6 -6
  129. package/src/list/context.ts +2 -4
  130. package/src/list/types.ts +1 -1
  131. package/src/pagination/Pagination.tsx +7 -22
  132. package/src/pagination/PaginationItem.tsx +4 -3
  133. package/src/util/create-context.tsx +2 -2
@@ -4,29 +4,29 @@ import { describe, expect, test } from "vitest";
4
4
  import { isValidDate, parseDate } from "..";
5
5
 
6
6
  const check = (inp: string) =>
7
- // eslint-disable-next-line vitest/valid-expect
7
+ // eslint-disable-next-line @vitest/valid-expect
8
8
  expect(isValidDate(parseDate(inp, new Date(), nb, "date", false)));
9
9
 
10
10
  const checkTwoDigit = (inp: string) =>
11
- // eslint-disable-next-line vitest/valid-expect
11
+ // eslint-disable-next-line @vitest/valid-expect
12
12
  expect(isValidDate(parseDate(inp, new Date(), nb, "date", true)));
13
13
 
14
14
  const parse = (inp: string) => parseDate(inp, new Date(), nb, "date", false);
15
15
 
16
16
  describe("Parse date-inputs with 4-digit years", () => {
17
- // eslint-disable-next-line vitest/expect-expect
17
+ // eslint-disable-next-line @vitest/expect-expect
18
18
  test("No spaces", () => {
19
19
  check("11052022").toBeTruthy();
20
20
  check("15052022").toBeTruthy();
21
21
  });
22
22
 
23
- // eslint-disable-next-line vitest/expect-expect
23
+ // eslint-disable-next-line @vitest/expect-expect
24
24
  test(". divider", () => {
25
25
  check("1.5.2022").toBeTruthy();
26
26
  check("11.05.2022").toBeTruthy();
27
27
  });
28
28
 
29
- // eslint-disable-next-line vitest/expect-expect
29
+ // eslint-disable-next-line @vitest/expect-expect
30
30
  test("/ divider", () => {
31
31
  check("1/5/2022").toBeTruthy();
32
32
  check("10/5/2022").toBeTruthy();
@@ -34,7 +34,7 @@ describe("Parse date-inputs with 4-digit years", () => {
34
34
  check("10/05/2022").toBeTruthy();
35
35
  });
36
36
 
37
- // eslint-disable-next-line vitest/expect-expect
37
+ // eslint-disable-next-line @vitest/expect-expect
38
38
  test("- divider", () => {
39
39
  check("1-5-2022").toBeTruthy();
40
40
  check("10-5-2022").toBeTruthy();
@@ -44,19 +44,19 @@ describe("Parse date-inputs with 4-digit years", () => {
44
44
  });
45
45
 
46
46
  describe("Parse date-inputs with 2-digit years", () => {
47
- // eslint-disable-next-line vitest/expect-expect
47
+ // eslint-disable-next-line @vitest/expect-expect
48
48
  test("No spaces", () => {
49
49
  checkTwoDigit("110522").toBeTruthy();
50
50
  checkTwoDigit("150522").toBeTruthy();
51
51
  });
52
52
 
53
- // eslint-disable-next-line vitest/expect-expect
53
+ // eslint-disable-next-line @vitest/expect-expect
54
54
  test(". divider", () => {
55
55
  checkTwoDigit("1.5.22").toBeTruthy();
56
56
  checkTwoDigit("11.05.22").toBeTruthy();
57
57
  });
58
58
 
59
- // eslint-disable-next-line vitest/expect-expect
59
+ // eslint-disable-next-line @vitest/expect-expect
60
60
  test("/ divider", () => {
61
61
  checkTwoDigit("1/5/22").toBeTruthy();
62
62
  checkTwoDigit("10/5/22").toBeTruthy();
@@ -64,7 +64,7 @@ describe("Parse date-inputs with 2-digit years", () => {
64
64
  checkTwoDigit("10/05/22").toBeTruthy();
65
65
  });
66
66
 
67
- // eslint-disable-next-line vitest/expect-expect
67
+ // eslint-disable-next-line @vitest/expect-expect
68
68
  test("- divider", () => {
69
69
  checkTwoDigit("1-5-22").toBeTruthy();
70
70
  checkTwoDigit("10-5-22").toBeTruthy();
@@ -72,14 +72,14 @@ describe("Parse date-inputs with 2-digit years", () => {
72
72
  checkTwoDigit("10-05-22").toBeTruthy();
73
73
  });
74
74
 
75
- // eslint-disable-next-line vitest/expect-expect
75
+ // eslint-disable-next-line @vitest/expect-expect
76
76
  test("Dissallow 1 and 3 digit years", () => {
77
77
  checkTwoDigit("11052").toBeFalsy();
78
78
  checkTwoDigit("1105222").toBeFalsy();
79
79
  checkTwoDigit("1105999").toBeFalsy();
80
80
  });
81
81
 
82
- // eslint-disable-next-line vitest/expect-expect
82
+ // eslint-disable-next-line @vitest/expect-expect
83
83
  test("Dissallow date before year 1000", () => {
84
84
  checkTwoDigit("11050999").toBeFalsy();
85
85
  checkTwoDigit("11050010").toBeFalsy();
@@ -1,6 +1,7 @@
1
1
  import cl from "clsx";
2
2
  import React, { forwardRef } from "react";
3
3
  import { BodyShort, ErrorMessage, Label } from "../../typography";
4
+ import { ReadOnlyIcon } from "../ReadOnlyIcon";
4
5
  import ComboboxWrapper from "./ComboboxWrapper";
5
6
  import FilteredOptions from "./FilteredOptions/FilteredOptions";
6
7
  import { useFilteredOptionsContext } from "./FilteredOptions/filteredOptionsContext";
@@ -27,6 +28,7 @@ export const Combobox = forwardRef<
27
28
  inputProps,
28
29
  showErrorMsg,
29
30
  size = "medium",
31
+ readOnly,
30
32
  } = useInputContext();
31
33
 
32
34
  return (
@@ -44,6 +46,7 @@ export const Combobox = forwardRef<
44
46
  "navds-sr-only": hideLabel,
45
47
  })}
46
48
  >
49
+ <ReadOnlyIcon nativeReadOnly={false} readOnly={readOnly} />
47
50
  {label}
48
51
  </Label>
49
52
  {!!description && (
@@ -36,6 +36,7 @@ const ComboboxProvider = forwardRef<HTMLInputElement, ComboboxProps>(
36
36
  children,
37
37
  defaultValue,
38
38
  disabled,
39
+ readOnly,
39
40
  error,
40
41
  errorId,
41
42
  filteredOptions: externalFilteredOptions,
@@ -63,6 +64,7 @@ const ComboboxProvider = forwardRef<HTMLInputElement, ComboboxProps>(
63
64
  defaultValue,
64
65
  description: rest.description,
65
66
  disabled,
67
+ readOnly,
66
68
  error,
67
69
  errorId,
68
70
  id,
@@ -9,6 +9,7 @@ type ComboboxWrapperProps = {
9
9
  inputProps: {
10
10
  disabled?: boolean;
11
11
  };
12
+ readOnly?: boolean;
12
13
  inputSize: string;
13
14
  toggleIsListOpen: (isListOpen: boolean) => void;
14
15
  };
@@ -21,7 +22,7 @@ const ComboboxWrapper = ({
21
22
  inputSize,
22
23
  toggleIsListOpen,
23
24
  }: ComboboxWrapperProps) => {
24
- const { toggleOpenButtonRef, clearInput } = useInputContext();
25
+ const { toggleOpenButtonRef, clearInput, readOnly } = useInputContext();
25
26
 
26
27
  const wrapperRef = useRef<HTMLDivElement | null>(null);
27
28
  const [hasFocusWithin, setHasFocusWithin] = useState(false);
@@ -55,6 +56,8 @@ const ComboboxWrapper = ({
55
56
  "navds-combobox--error": hasError,
56
57
  "navds-combobox--disabled": !!inputProps.disabled,
57
58
  "navds-combobox--focused": hasFocusWithin,
59
+ "navds-combobox--readonly": readOnly,
60
+ "navds-form-field--readonly": readOnly,
58
61
  },
59
62
  )}
60
63
  onFocus={onFocusInsideWrapper}
@@ -58,7 +58,8 @@ const FilteredOptionsProvider = ({
58
58
  useState<HTMLUListElement | null>(null);
59
59
  const virtualFocus = useVirtualFocus(filteredOptionsRef);
60
60
  const {
61
- inputProps: { "aria-describedby": partialAriaDescribedBy, id },
61
+ inputProps: { "aria-describedby": partialAriaDescribedBy, id, disabled },
62
+ readOnly,
62
63
  value,
63
64
  searchTerm,
64
65
  setValue,
@@ -136,6 +137,9 @@ const FilteredOptionsProvider = ({
136
137
 
137
138
  const toggleIsListOpen = useCallback(
138
139
  (newState?: boolean) => {
140
+ if (disabled || readOnly) {
141
+ return;
142
+ }
139
143
  virtualFocus.moveFocusToTop();
140
144
  if (newState ?? !isInternalListOpen) {
141
145
  setHideCaret(!!maxSelected?.isLimitReached);
@@ -147,6 +151,8 @@ const FilteredOptionsProvider = ({
147
151
  maxSelected?.isLimitReached,
148
152
  isInternalListOpen,
149
153
  setHideCaret,
154
+ disabled,
155
+ readOnly,
150
156
  ],
151
157
  );
152
158
 
@@ -32,6 +32,7 @@ interface Props {
32
32
  defaultValue: ComboboxProps["defaultValue"];
33
33
  description: ComboboxProps["description"];
34
34
  disabled: ComboboxProps["disabled"];
35
+ readOnly: ComboboxProps["readOnly"];
35
36
  error: ComboboxProps["error"];
36
37
  errorId: ComboboxProps["errorId"];
37
38
  id: ComboboxProps["id"];
@@ -48,6 +49,7 @@ const InputProvider = ({ children, value: props }: Props) => {
48
49
  defaultValue = "",
49
50
  description,
50
51
  disabled,
52
+ readOnly,
51
53
  error,
52
54
  errorId,
53
55
  id: externalId,
@@ -61,6 +63,7 @@ const InputProvider = ({ children, value: props }: Props) => {
61
63
  {
62
64
  description,
63
65
  disabled,
66
+ readOnly,
64
67
  error,
65
68
  errorId,
66
69
  id: externalId,
@@ -49,6 +49,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
49
49
  setValue,
50
50
  hideCaret,
51
51
  setHideCaret,
52
+ readOnly,
52
53
  } = useInputContext();
53
54
  const {
54
55
  selectedOptions,
@@ -149,6 +150,9 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
149
150
  const handleKeyDown = useCallback(
150
151
  (e: React.KeyboardEvent<HTMLInputElement>) => {
151
152
  setIsMouseLastUsedInputDevice(false);
153
+ if (readOnly) {
154
+ return;
155
+ }
152
156
  if (e.key === "Backspace") {
153
157
  if (value === "" && shouldShowSelectedOptions) {
154
158
  const lastSelectedOption =
@@ -214,6 +218,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
214
218
  setValue,
215
219
  searchTerm,
216
220
  shouldShowSelectedOptions,
221
+ readOnly,
217
222
  ],
218
223
  );
219
224
 
@@ -262,6 +267,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
262
267
  aria-activedescendant={activeDecendantId}
263
268
  aria-describedby={ariaDescribedBy}
264
269
  aria-invalid={inputProps["aria-invalid"]}
270
+ readOnly={readOnly}
265
271
  />
266
272
  );
267
273
  },
@@ -45,6 +45,7 @@ export const InputController = forwardRef<
45
45
  size = "medium",
46
46
  inputRef,
47
47
  toggleOpenButtonRef,
48
+ readOnly,
48
49
  } = useInputContext();
49
50
 
50
51
  const { activeDecendantId } = useFilteredOptionsContext();
@@ -65,6 +66,7 @@ export const InputController = forwardRef<
65
66
  id={inputProps.id}
66
67
  ref={mergedInputRef}
67
68
  inputClassName={inputClassName}
69
+ readOnly={readOnly}
68
70
  {...rest}
69
71
  />
70
72
  ) : (
@@ -74,6 +76,7 @@ export const InputController = forwardRef<
74
76
  ref={mergedInputRef}
75
77
  inputClassName={inputClassName}
76
78
  shouldShowSelectedOptions={shouldShowSelectedOptions}
79
+ readOnly={readOnly}
77
80
  {...rest}
78
81
  />
79
82
  </SelectedOptions>
@@ -12,7 +12,7 @@ interface SelectedOptionsProps {
12
12
 
13
13
  const Option = ({ option }: { option: ComboboxOption }) => {
14
14
  const { isMultiSelect, removeSelectedOption } = useSelectedOptionsContext();
15
- const { focusInput } = useInputContext();
15
+ const { focusInput, readOnly, inputProps } = useInputContext();
16
16
 
17
17
  const onClick = (e) => {
18
18
  e.stopPropagation();
@@ -28,7 +28,13 @@ const Option = ({ option }: { option: ComboboxOption }) => {
28
28
  );
29
29
  }
30
30
 
31
- return <Chips.Removable onClick={onClick}>{option.label}</Chips.Removable>;
31
+ return readOnly || inputProps.disabled ? (
32
+ <Chips.Toggle variant="neutral" checkmark={false} as="div">
33
+ {option.label}
34
+ </Chips.Toggle>
35
+ ) : (
36
+ <Chips.Removable onClick={onClick}>{option.label}</Chips.Removable>
37
+ );
32
38
  };
33
39
 
34
40
  const SelectedOptions: React.FC<SelectedOptionsProps> = ({
@@ -4,7 +4,7 @@ import { usePrevious } from "../../../util/hooks";
4
4
  import { useInputContext } from "../Input/Input.context";
5
5
  import { isInList } from "../combobox-utils";
6
6
  import { useComboboxCustomOptions } from "../customOptionsContext";
7
- import { ComboboxOption, ComboboxProps, MaxSelected } from "../types";
7
+ import { ComboboxOption, ComboboxProps } from "../types";
8
8
 
9
9
  type SelectedOptionsContextValue = {
10
10
  addSelectedOption: (option: ComboboxOption) => void;
@@ -12,7 +12,7 @@ type SelectedOptionsContextValue = {
12
12
  removeSelectedOption: (option: ComboboxOption) => void;
13
13
  prevSelectedOptions?: ComboboxOption[];
14
14
  selectedOptions: ComboboxOption[];
15
- maxSelected?: MaxSelected & { isLimitReached: boolean };
15
+ maxSelected?: ComboboxProps["maxSelected"] & { isLimitReached: boolean };
16
16
  setSelectedOptions: (any) => void;
17
17
  toggleOption: (
18
18
  option: ComboboxOption,
@@ -16,17 +16,6 @@ export type ComboboxOption = {
16
16
  value: string;
17
17
  };
18
18
 
19
- export type MaxSelected = {
20
- /**
21
- * The limit for maximum selected options
22
- */
23
- limit: number;
24
- /**
25
- * Override the message to display when the limit for maximum selected options has been reached
26
- */
27
- message?: string;
28
- };
29
-
30
19
  export interface ComboboxProps
31
20
  extends FormFieldProps,
32
21
  Omit<
@@ -135,7 +124,16 @@ export interface ComboboxProps
135
124
  /**
136
125
  * Options for the maximum number of selected options.
137
126
  */
138
- maxSelected?: MaxSelected;
127
+ maxSelected?: {
128
+ /**
129
+ * The limit for maximum selected options
130
+ */
131
+ limit: number;
132
+ /**
133
+ * Override the message to display when the limit for maximum selected options has been reached
134
+ */
135
+ message?: string;
136
+ };
139
137
  /**
140
138
  * Set to `true` to enable inline autocomplete.
141
139
  *
@@ -2,7 +2,7 @@ import cl from "clsx";
2
2
  import React, { HTMLAttributes, forwardRef, useRef } from "react";
3
3
  import { BodyShort, Heading } from "../../typography";
4
4
  import { composeEventHandlers } from "../../util/composeEventHandlers";
5
- import { useId, useMergeRefs } from "../../util/hooks";
5
+ import { useMergeRefs } from "../../util/hooks";
6
6
  import ErrorSummaryItem from "./ErrorSummaryItem";
7
7
 
8
8
  export interface ErrorSummaryProps
@@ -33,13 +33,13 @@ interface ErrorSummaryComponent
33
33
  ErrorSummaryProps & React.RefAttributes<HTMLDivElement>
34
34
  > {
35
35
  /**
36
- * Link to error.
36
+ * Error message with link to field.
37
37
  *
38
38
  * @see [🤖 OverridableComponent](https://aksel.nav.no/grunnleggende/kode/overridablecomponent) support
39
39
  *
40
40
  * @example
41
41
  * ```jsx
42
- * <ErrorSummary.Item href="#1">
42
+ * <ErrorSummary.Item href="#id-til-alderfelt">
43
43
  * Felt må fylles ut med alder
44
44
  * </ErrorSummary.Item>
45
45
  * ```
@@ -48,7 +48,7 @@ interface ErrorSummaryComponent
48
48
  }
49
49
 
50
50
  /**
51
- * A component that displays a summary of errors.
51
+ * Summary of errors in a form.
52
52
  *
53
53
  * @see [📝 Documentation](https://aksel.nav.no/komponenter/core/errorsummary)
54
54
  * @see 🏷️ {@link ErrorSummaryProps}
@@ -77,15 +77,13 @@ export const ErrorSummary = forwardRef<HTMLDivElement, ErrorSummaryProps>(
77
77
  },
78
78
  ref,
79
79
  ) => {
80
- const headingId = useId();
81
-
82
- const sectionRef = useRef<HTMLDivElement>(null);
80
+ const wrapperRef = useRef<HTMLDivElement>(null);
83
81
  const headingRef = useRef<HTMLHeadingElement>(null);
84
82
 
85
- const mergedRef = useMergeRefs(ref, sectionRef);
83
+ const mergedRef = useMergeRefs(ref, wrapperRef);
86
84
 
87
85
  return (
88
- <section
86
+ <div
89
87
  ref={mergedRef}
90
88
  {...rest}
91
89
  className={cl(
@@ -94,11 +92,8 @@ export const ErrorSummary = forwardRef<HTMLDivElement, ErrorSummaryProps>(
94
92
  `navds-error-summary--${size}`,
95
93
  )}
96
94
  tabIndex={-1}
97
- aria-live="polite"
98
- aria-relevant="all"
99
- aria-labelledby={headingId}
100
95
  onFocus={composeEventHandlers(rest.onFocus, (event) => {
101
- if (event.target === sectionRef.current) {
96
+ if (event.target === wrapperRef.current) {
102
97
  headingRef?.current?.focus();
103
98
  }
104
99
  })}
@@ -107,7 +102,6 @@ export const ErrorSummary = forwardRef<HTMLDivElement, ErrorSummaryProps>(
107
102
  className="navds-error-summary__heading"
108
103
  as={headingTag}
109
104
  size="small"
110
- id={headingId}
111
105
  ref={headingRef}
112
106
  tabIndex={-1}
113
107
  >
@@ -116,7 +110,7 @@ export const ErrorSummary = forwardRef<HTMLDivElement, ErrorSummaryProps>(
116
110
  <BodyShort as="ul" size={size} className="navds-error-summary__list">
117
111
  {children}
118
112
  </BodyShort>
119
- </section>
113
+ </div>
120
114
  );
121
115
  },
122
116
  ) as ErrorSummaryComponent;
@@ -22,14 +22,17 @@ export interface FormSummaryEditProps
22
22
  export const FormSummaryEditLink: OverridableComponent<
23
23
  FormSummaryEditProps,
24
24
  HTMLAnchorElement
25
- > = forwardRef(({ children = "Endre svar", className, ...rest }, ref) => (
26
- <Link
27
- ref={ref}
28
- {...rest}
29
- className={cl("navds-form-summary__edit", className)}
30
- >
31
- {children}
32
- </Link>
33
- ));
25
+ > = forwardRef(
26
+ ({ children = "Endre svar", className, as = "a", ...rest }, ref) => (
27
+ <Link
28
+ ref={ref}
29
+ as={as}
30
+ {...rest}
31
+ className={cl("navds-form-summary__edit", className)}
32
+ >
33
+ {children}
34
+ </Link>
35
+ ),
36
+ );
34
37
 
35
38
  export default FormSummaryEditLink;
@@ -63,7 +63,7 @@ export const PageBlock: OverridableComponent<PageBlockProps, HTMLDivElement> =
63
63
  {...rest}
64
64
  className={cl(
65
65
  "navds-pageblock",
66
- `navds-pageblock--${width}`,
66
+ width && `navds-pageblock--${width}`,
67
67
  className,
68
68
  { "navds-pageblock--gutters": gutters },
69
69
  )}
@@ -26,8 +26,8 @@ export type HStackProps = PrimitiveAsChildProps & Omit<StackProps, "direction">;
26
26
  * </HStack>
27
27
  */
28
28
  export const HStack: OverridableComponent<HStackProps, HTMLDivElement> =
29
- forwardRef((props, ref) => {
30
- return <Stack {...props} ref={ref} direction="row" />;
29
+ forwardRef(({ as = "div", ...rest }, ref) => {
30
+ return <Stack as={as} {...rest} ref={ref} direction="row" />;
31
31
  });
32
32
 
33
33
  export default HStack;
@@ -27,8 +27,10 @@ export type VStackProps = PrimitiveAsChildProps &
27
27
  * </VStack>
28
28
  */
29
29
  export const VStack: OverridableComponent<VStackProps, HTMLDivElement> =
30
- forwardRef((props, ref) => {
31
- return <Stack {...props} ref={ref} direction="column" wrap={false} />;
30
+ forwardRef(({ as = "div", ...rest }, ref) => {
31
+ return (
32
+ <Stack as={as} {...rest} ref={ref} direction="column" wrap={false} />
33
+ );
32
34
  });
33
35
 
34
36
  export default VStack;
package/src/list/List.tsx CHANGED
@@ -1,15 +1,18 @@
1
1
  import cl from "clsx";
2
2
  import React, { forwardRef, useContext } from "react";
3
- import { BodyShort, Heading } from "../typography";
4
- import { useId } from "../util/hooks";
3
+ import { BodyLong, BodyShort, Heading } from "../typography";
5
4
  import { ListItem } from "./ListItem";
6
5
  import { ListContext } from "./context";
7
- import { ListProps } from "./types";
6
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
7
+ import type { ListItemProps, ListProps } from "./types";
8
8
 
9
9
  export interface ListComponent
10
10
  extends React.ForwardRefExoticComponent<
11
11
  ListProps & React.RefAttributes<HTMLDivElement>
12
12
  > {
13
+ /**
14
+ * @see 🏷️ {@link ListItemProps}
15
+ */
13
16
  Item: typeof ListItem;
14
17
  }
15
18
 
@@ -42,47 +45,34 @@ export const List = forwardRef<HTMLDivElement, ListProps>(
42
45
  },
43
46
  ref,
44
47
  ) => {
45
- const ariaId = useId();
48
+ const { size: contextSize } = useContext(ListContext);
46
49
 
47
- const { isNested, size: _size } = useContext(ListContext);
48
-
49
- const listSize = size ?? _size ?? "medium";
50
+ const listSize = size ?? contextSize;
50
51
  return (
51
52
  <ListContext.Provider
52
53
  value={{
53
54
  listType: ListTag,
54
- isNested: isNested === null ? false : true,
55
55
  size: listSize,
56
56
  }}
57
57
  >
58
- <div
58
+ <BodyLong
59
+ as="div"
59
60
  {...rest}
61
+ size={size}
60
62
  ref={ref}
61
- className={cl("navds-list", `navds-list--${listSize}`, className, {
62
- "navds-list--nested": isNested === null ? false : true,
63
- })}
63
+ className={cl("navds-list", `navds-list--${listSize}`, className)}
64
64
  >
65
65
  {title && (
66
66
  <Heading
67
- id={`tittel-${ariaId}`}
68
67
  size={listSize === "medium" ? "small" : "xsmall"}
69
68
  as={headingTag}
70
69
  >
71
70
  {title}
72
71
  </Heading>
73
72
  )}
74
- {description && (
75
- <BodyShort size={listSize} id={`description-${ariaId}`}>
76
- {description}
77
- </BodyShort>
78
- )}
79
- <ListTag
80
- aria-labelledby={title && `tittel-${ariaId}`}
81
- aria-describedby={description && `description-${ariaId}`}
82
- >
83
- {children}
84
- </ListTag>
85
- </div>
73
+ {description && <BodyShort size={listSize}>{description}</BodyShort>}
74
+ <ListTag role="list">{children}</ListTag>
75
+ </BodyLong>
86
76
  </ListContext.Provider>
87
77
  );
88
78
  },
@@ -2,7 +2,7 @@ import cl from "clsx";
2
2
  import React, { forwardRef, useContext } from "react";
3
3
  import { BodyLong } from "../typography";
4
4
  import { ListContext } from "./context";
5
- import { ListItemProps } from "./types";
5
+ import type { ListItemProps } from "./types";
6
6
 
7
7
  /**
8
8
  * @see 🏷️ {@link ListItemProps}
@@ -21,7 +21,7 @@ export const ListItem = forwardRef<HTMLLIElement, ListItemProps>(
21
21
  <li {...rest} ref={ref} className={cl("navds-list__item", className)}>
22
22
  {listType === "ul" && (
23
23
  <div
24
- className={cl({
24
+ className={cl("navds-list__item-marker", {
25
25
  "navds-list__item-marker--icon": icon,
26
26
  "navds-list__item-marker--bullet": !icon,
27
27
  })}
@@ -30,8 +30,8 @@ export const ListItem = forwardRef<HTMLLIElement, ListItemProps>(
30
30
  icon
31
31
  ) : (
32
32
  <svg
33
- width="6"
34
- height="6"
33
+ width="0.375rem"
34
+ height="0.375rem"
35
35
  viewBox="0 0 6 6"
36
36
  fill="none"
37
37
  xmlns="http://www.w3.org/2000/svg"
@@ -45,14 +45,14 @@ export const ListItem = forwardRef<HTMLLIElement, ListItemProps>(
45
45
  </div>
46
46
  )}
47
47
 
48
- <BodyLong as="div" size={size} className="navds-list__item-content">
48
+ <div>
49
49
  {title && (
50
50
  <BodyLong as="p" size={size} weight="semibold">
51
51
  {title}
52
52
  </BodyLong>
53
53
  )}
54
54
  {children}
55
- </BodyLong>
55
+ </div>
56
56
  </li>
57
57
  );
58
58
  },
@@ -2,13 +2,11 @@ import { createContext } from "react";
2
2
  import { ListProps } from "./types";
3
3
 
4
4
  interface ListContextProps {
5
- listType: ListProps["as"];
6
- isNested: boolean | null;
7
- size: ListProps["size"];
5
+ listType: Exclude<ListProps["as"], undefined>;
6
+ size: Exclude<ListProps["size"], undefined>;
8
7
  }
9
8
 
10
9
  export const ListContext = createContext<ListContextProps>({
11
10
  listType: "ul",
12
- isNested: null,
13
11
  size: "medium",
14
12
  });
package/src/list/types.ts CHANGED
@@ -19,7 +19,7 @@ export interface ListProps extends React.HTMLAttributes<HTMLDivElement> {
19
19
  */
20
20
  headingTag?: React.ElementType<any>;
21
21
  /**
22
- * Changes padding, height and font-size.
22
+ * Changes margin-block on list and font size on items.
23
23
  * @default "medium"
24
24
  */
25
25
  size?: "medium" | "small";