@navikt/ds-react 7.5.2 → 7.6.0

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 (169) hide show
  1. package/cjs/date/datepicker/DatePicker.js +5 -3
  2. package/cjs/date/datepicker/DatePicker.js.map +1 -1
  3. package/cjs/date/datepicker/DatePickerStandalone.js +5 -3
  4. package/cjs/date/datepicker/DatePickerStandalone.js.map +1 -1
  5. package/cjs/date/datepicker/parts/Caption.js +6 -5
  6. package/cjs/date/datepicker/parts/Caption.js.map +1 -1
  7. package/cjs/date/datepicker/parts/DropdownCaption.js +10 -13
  8. package/cjs/date/datepicker/parts/DropdownCaption.js.map +1 -1
  9. package/cjs/date/datepicker/parts/WeekNumber.d.ts +1 -2
  10. package/cjs/date/datepicker/parts/WeekNumber.js +8 -19
  11. package/cjs/date/datepicker/parts/WeekNumber.js.map +1 -1
  12. package/cjs/date/datepicker/parts/WeekRow.js +5 -3
  13. package/cjs/date/datepicker/parts/WeekRow.js.map +1 -1
  14. package/cjs/date/hooks/useDatepicker.js +4 -2
  15. package/cjs/date/hooks/useDatepicker.js.map +1 -1
  16. package/cjs/date/hooks/useMonthPicker.js +4 -2
  17. package/cjs/date/hooks/useMonthPicker.js.map +1 -1
  18. package/cjs/date/hooks/useRangeDatepicker.js +4 -2
  19. package/cjs/date/hooks/useRangeDatepicker.js.map +1 -1
  20. package/cjs/date/monthpicker/MonthCaption.js +6 -4
  21. package/cjs/date/monthpicker/MonthCaption.js.map +1 -1
  22. package/cjs/date/monthpicker/MonthPicker.js +6 -2
  23. package/cjs/date/monthpicker/MonthPicker.js.map +1 -1
  24. package/cjs/date/parts/DateInput.js +5 -5
  25. package/cjs/date/parts/DateInput.js.map +1 -1
  26. package/cjs/date/parts/DateWrapper.d.ts +2 -1
  27. package/cjs/date/parts/DateWrapper.js +11 -3
  28. package/cjs/date/parts/DateWrapper.js.map +1 -1
  29. package/cjs/date/utils/index.d.ts +1 -2
  30. package/cjs/date/utils/index.js +2 -7
  31. package/cjs/date/utils/index.js.map +1 -1
  32. package/cjs/date/utils/locale.d.ts +24 -0
  33. package/cjs/date/utils/locale.js +22 -1
  34. package/cjs/date/utils/locale.js.map +1 -1
  35. package/cjs/form/combobox/Combobox.d.ts +1 -1
  36. package/cjs/form/combobox/Input/InputController.d.ts +1 -1
  37. package/cjs/form/combobox/SelectedOptions/SelectedOptions.js +1 -1
  38. package/cjs/form/combobox/SelectedOptions/SelectedOptions.js.map +1 -1
  39. package/cjs/form/switch/Switch.js +8 -3
  40. package/cjs/form/switch/Switch.js.map +1 -1
  41. package/cjs/internal-header/InternalHeader.js +9 -0
  42. package/cjs/internal-header/InternalHeader.js.map +1 -1
  43. package/cjs/overlays/action-menu/ActionMenu.d.ts +2 -1
  44. package/cjs/overlays/action-menu/ActionMenu.js +8 -4
  45. package/cjs/overlays/action-menu/ActionMenu.js.map +1 -1
  46. package/cjs/provider/theme/AkselTheme.d.ts +12 -1
  47. package/cjs/provider/theme/AkselTheme.js +6 -4
  48. package/cjs/provider/theme/AkselTheme.js.map +1 -1
  49. package/cjs/read-more/ReadMore.d.ts +1 -1
  50. package/cjs/read-more/ReadMore.js +6 -3
  51. package/cjs/read-more/ReadMore.js.map +1 -1
  52. package/cjs/stepper/Step.js +1 -1
  53. package/cjs/stepper/Step.js.map +1 -1
  54. package/cjs/stepper/Stepper.js +3 -2
  55. package/cjs/stepper/Stepper.js.map +1 -1
  56. package/cjs/util/TextareaAutoSize.js +1 -1
  57. package/cjs/util/TextareaAutoSize.js.map +1 -1
  58. package/cjs/util/i18n/locales/en.d.ts +20 -0
  59. package/cjs/util/i18n/locales/en.js +20 -0
  60. package/cjs/util/i18n/locales/en.js.map +1 -1
  61. package/cjs/util/i18n/locales/nb.d.ts +20 -0
  62. package/cjs/util/i18n/locales/nb.js +20 -0
  63. package/cjs/util/i18n/locales/nb.js.map +1 -1
  64. package/cjs/util/i18n/locales/nn.d.ts +20 -0
  65. package/cjs/util/i18n/locales/nn.js +20 -0
  66. package/cjs/util/i18n/locales/nn.js.map +1 -1
  67. package/esm/date/datepicker/DatePicker.js +6 -4
  68. package/esm/date/datepicker/DatePicker.js.map +1 -1
  69. package/esm/date/datepicker/DatePickerStandalone.js +6 -4
  70. package/esm/date/datepicker/DatePickerStandalone.js.map +1 -1
  71. package/esm/date/datepicker/parts/Caption.js +6 -5
  72. package/esm/date/datepicker/parts/Caption.js.map +1 -1
  73. package/esm/date/datepicker/parts/DropdownCaption.js +8 -11
  74. package/esm/date/datepicker/parts/DropdownCaption.js.map +1 -1
  75. package/esm/date/datepicker/parts/WeekNumber.d.ts +1 -2
  76. package/esm/date/datepicker/parts/WeekNumber.js +8 -19
  77. package/esm/date/datepicker/parts/WeekNumber.js.map +1 -1
  78. package/esm/date/datepicker/parts/WeekRow.js +5 -3
  79. package/esm/date/datepicker/parts/WeekRow.js.map +1 -1
  80. package/esm/date/hooks/useDatepicker.js +4 -2
  81. package/esm/date/hooks/useDatepicker.js.map +1 -1
  82. package/esm/date/hooks/useMonthPicker.js +4 -2
  83. package/esm/date/hooks/useMonthPicker.js.map +1 -1
  84. package/esm/date/hooks/useRangeDatepicker.js +4 -2
  85. package/esm/date/hooks/useRangeDatepicker.js.map +1 -1
  86. package/esm/date/monthpicker/MonthCaption.js +7 -5
  87. package/esm/date/monthpicker/MonthCaption.js.map +1 -1
  88. package/esm/date/monthpicker/MonthPicker.js +6 -2
  89. package/esm/date/monthpicker/MonthPicker.js.map +1 -1
  90. package/esm/date/parts/DateInput.js +5 -5
  91. package/esm/date/parts/DateInput.js.map +1 -1
  92. package/esm/date/parts/DateWrapper.d.ts +2 -1
  93. package/esm/date/parts/DateWrapper.js +11 -3
  94. package/esm/date/parts/DateWrapper.js.map +1 -1
  95. package/esm/date/utils/index.d.ts +1 -2
  96. package/esm/date/utils/index.js +1 -2
  97. package/esm/date/utils/index.js.map +1 -1
  98. package/esm/date/utils/locale.d.ts +24 -0
  99. package/esm/date/utils/locale.js +17 -0
  100. package/esm/date/utils/locale.js.map +1 -1
  101. package/esm/form/combobox/Combobox.d.ts +1 -1
  102. package/esm/form/combobox/Input/InputController.d.ts +1 -1
  103. package/esm/form/combobox/SelectedOptions/SelectedOptions.js +1 -1
  104. package/esm/form/combobox/SelectedOptions/SelectedOptions.js.map +1 -1
  105. package/esm/form/switch/Switch.js +8 -3
  106. package/esm/form/switch/Switch.js.map +1 -1
  107. package/esm/internal-header/InternalHeader.js +9 -0
  108. package/esm/internal-header/InternalHeader.js.map +1 -1
  109. package/esm/overlays/action-menu/ActionMenu.d.ts +2 -1
  110. package/esm/overlays/action-menu/ActionMenu.js +8 -4
  111. package/esm/overlays/action-menu/ActionMenu.js.map +1 -1
  112. package/esm/provider/theme/AkselTheme.d.ts +12 -1
  113. package/esm/provider/theme/AkselTheme.js +6 -4
  114. package/esm/provider/theme/AkselTheme.js.map +1 -1
  115. package/esm/read-more/ReadMore.d.ts +1 -1
  116. package/esm/read-more/ReadMore.js +6 -3
  117. package/esm/read-more/ReadMore.js.map +1 -1
  118. package/esm/stepper/Step.js +1 -1
  119. package/esm/stepper/Step.js.map +1 -1
  120. package/esm/stepper/Stepper.js +3 -2
  121. package/esm/stepper/Stepper.js.map +1 -1
  122. package/esm/util/TextareaAutoSize.js +1 -1
  123. package/esm/util/TextareaAutoSize.js.map +1 -1
  124. package/esm/util/i18n/locales/en.d.ts +20 -0
  125. package/esm/util/i18n/locales/en.js +20 -0
  126. package/esm/util/i18n/locales/en.js.map +1 -1
  127. package/esm/util/i18n/locales/nb.d.ts +20 -0
  128. package/esm/util/i18n/locales/nb.js +20 -0
  129. package/esm/util/i18n/locales/nb.js.map +1 -1
  130. package/esm/util/i18n/locales/nn.d.ts +20 -0
  131. package/esm/util/i18n/locales/nn.js +20 -0
  132. package/esm/util/i18n/locales/nn.js.map +1 -1
  133. package/package.json +4 -4
  134. package/src/date/datepicker/DatePicker.tsx +5 -4
  135. package/src/date/datepicker/DatePickerStandalone.tsx +5 -4
  136. package/src/date/datepicker/parts/Caption.tsx +5 -6
  137. package/src/date/datepicker/parts/DropdownCaption.tsx +7 -12
  138. package/src/date/datepicker/parts/WeekNumber.tsx +12 -35
  139. package/src/date/datepicker/parts/WeekRow.tsx +5 -8
  140. package/src/date/hooks/useDatepicker.tsx +4 -2
  141. package/src/date/hooks/useMonthPicker.tsx +4 -2
  142. package/src/date/hooks/useRangeDatepicker.tsx +4 -2
  143. package/src/date/monthpicker/MonthCaption.tsx +9 -10
  144. package/src/date/monthpicker/MonthPicker.tsx +6 -2
  145. package/src/date/parts/DateInput.tsx +8 -9
  146. package/src/date/parts/DateWrapper.tsx +14 -4
  147. package/src/date/utils/index.ts +1 -8
  148. package/src/date/utils/locale.ts +18 -0
  149. package/src/form/combobox/SelectedOptions/SelectedOptions.tsx +5 -1
  150. package/src/form/switch/Switch.tsx +30 -24
  151. package/src/internal-header/InternalHeader.tsx +28 -8
  152. package/src/overlays/action-menu/ActionMenu.tsx +90 -56
  153. package/src/provider/theme/AkselTheme.tsx +22 -4
  154. package/src/react-css.d.ts +2 -0
  155. package/src/read-more/ReadMore.tsx +10 -2
  156. package/src/stepper/Step.tsx +3 -0
  157. package/src/stepper/Stepper.tsx +5 -2
  158. package/src/util/TextareaAutoSize.tsx +1 -0
  159. package/src/util/i18n/locales/en.ts +20 -0
  160. package/src/util/i18n/locales/nb.ts +20 -0
  161. package/src/util/i18n/locales/nn.ts +20 -0
  162. package/src/util/i18n/locales.test.tsx +44 -12
  163. package/cjs/date/utils/labels.d.ts +0 -18
  164. package/cjs/date/utils/labels.js +0 -201
  165. package/cjs/date/utils/labels.js.map +0 -1
  166. package/esm/date/utils/labels.d.ts +0 -18
  167. package/esm/date/utils/labels.js +0 -189
  168. package/esm/date/utils/labels.js.map +0 -1
  169. package/src/date/utils/labels.ts +0 -219
@@ -5,6 +5,7 @@ import { ReadOnlyIcon } from "../../form/ReadOnlyIcon";
5
5
  import { FormFieldProps, useFormField } from "../../form/useFormField";
6
6
  import { BodyShort, ErrorMessage, Label } from "../../typography";
7
7
  import { omit } from "../../util";
8
+ import { useI18n } from "../../util/i18n/i18n.context";
8
9
  import { useDateInputContext } from "../context";
9
10
 
10
11
  export interface DateInputProps
@@ -46,16 +47,17 @@ const DateInput = forwardRef<HTMLInputElement, DateInputProps>((props, ref) => {
46
47
  } = props;
47
48
 
48
49
  const buttonRef = useRef<HTMLButtonElement>(null);
50
+ const translate = useI18n("DatePicker");
49
51
 
50
52
  const isDatepickerVariant = variant === "datepicker";
51
53
 
52
54
  const conditionalVariables = {
53
55
  prefix: isDatepickerVariant ? "datepicker-input" : "monthpicker-input",
54
56
  iconTitle: {
55
- open: isDatepickerVariant ? "Åpne datovelger" : "Åpne månedsvelger",
56
- close: isDatepickerVariant ? "Lukk datovelger" : "Lukk månedsvelger",
57
+ open: isDatepickerVariant ? "openDatePicker" : "openMonthPicker",
58
+ close: isDatepickerVariant ? "closeDatePicker" : "closeMonthPicker",
57
59
  },
58
- };
60
+ } as const;
59
61
 
60
62
  const context = useDateInputContext();
61
63
 
@@ -137,12 +139,9 @@ const DateInput = forwardRef<HTMLInputElement, DateInputProps>((props, ref) => {
137
139
  ref={buttonRef}
138
140
  >
139
141
  <CalendarIcon
140
- pointerEvents="none"
141
- title={
142
- context?.open
143
- ? conditionalVariables.iconTitle.close
144
- : conditionalVariables.iconTitle.open
145
- }
142
+ title={translate(
143
+ conditionalVariables.iconTitle[context?.open ? "close" : "open"],
144
+ )}
146
145
  />
147
146
  </button>
148
147
  </div>
@@ -5,14 +5,23 @@ import { Modal } from "../../modal";
5
5
  import { useModalContext } from "../../modal/Modal.context";
6
6
  import { Popover } from "../../popover";
7
7
  import { useMedia } from "../../util/hooks";
8
- import { modalCloseButtonLabel, modalLabel } from "../utils/labels";
8
+ import { useI18n } from "../../util/i18n/i18n.context";
9
+ import { getTranslations } from "../utils";
10
+
11
+ const variantToLabel = {
12
+ single: "chooseDate",
13
+ multiple: "chooseDates",
14
+ range: "chooseDateRange",
15
+ month: "chooseMonth",
16
+ } as const;
9
17
 
10
18
  type DateWrapperProps = {
11
19
  open: boolean;
12
20
  children: React.ReactNode;
13
21
  onClose: () => void;
14
22
  anchor: HTMLDivElement | null;
15
- locale: "nb" | "nn" | "en";
23
+ /** @deprecated Temporary to support locale prop */
24
+ locale: "nb" | "nn" | "en" | undefined;
16
25
  variant: "single" | "multiple" | "range" | "month";
17
26
  popoverProps: {
18
27
  id?: string;
@@ -29,6 +38,7 @@ export const DateWrapper = ({
29
38
  variant,
30
39
  popoverProps,
31
40
  }: DateWrapperProps) => {
41
+ const translate = useI18n("DatePicker", getTranslations(locale));
32
42
  const modalRef = useRef<HTMLDialogElement>(null);
33
43
  const isInModal = useModalContext(false) !== undefined;
34
44
  const hideModal =
@@ -61,7 +71,7 @@ export const DateWrapper = ({
61
71
  event.stopPropagation();
62
72
  onClose();
63
73
  }}
64
- aria-label={modalLabel(locale, variant)}
74
+ aria-label={translate(variantToLabel[variant])}
65
75
  className={cl("navds-date__modal", {
66
76
  "navds-date__nested-modal": isInModal,
67
77
  "navds-date": variant === "month",
@@ -76,7 +86,7 @@ export const DateWrapper = ({
76
86
  size="small"
77
87
  type="button"
78
88
  >
79
- {modalCloseButtonLabel(locale)}
89
+ {translate("close")}
80
90
  </Button>
81
91
  </div>
82
92
  </Modal>
@@ -1,18 +1,11 @@
1
1
  export { formatDateForInput } from "./format-date";
2
2
  export { getMonths, getYears } from "./get-dates";
3
- export {
4
- labelMonthDropdown,
5
- labelYearDropdown,
6
- labels,
7
- labelNextYear,
8
- labelPrevYear,
9
- } from "./labels";
10
3
  export {
11
4
  INPUT_DATE_STRING_FORMAT_DATE,
12
5
  INPUT_DATE_STRING_FORMAT_MONTH,
13
6
  parseDate,
14
7
  } from "./parse-date";
15
- export { getLocaleFromString } from "./locale";
8
+ export { getLocaleFromString, getTranslations } from "./locale";
16
9
  export { disableDate } from "./dates-disabled";
17
10
 
18
11
  export { dateIsInCurrentMonth, isValidDate } from "./check-dates";
@@ -1,4 +1,6 @@
1
1
  import { enGB, nb, nn } from "date-fns/locale";
2
+ import en_translations from "../../util/i18n/locales/en";
3
+ import nn_translations from "../../util/i18n/locales/nn";
2
4
 
3
5
  /** @private */
4
6
  export const getLocaleFromString = (locale: "nb" | "nn" | "en" = "nb") => {
@@ -11,3 +13,19 @@ export const getLocaleFromString = (locale: "nb" | "nn" | "en" = "nb") => {
11
13
  return nb;
12
14
  }
13
15
  };
16
+
17
+ /**
18
+ * @private
19
+ * Temporary for backwards compatibility with locale prop
20
+ */
21
+ export const getTranslations = (locale: string | undefined) => {
22
+ switch (locale) {
23
+ case "nn":
24
+ return nn_translations.DatePicker;
25
+ case "en":
26
+ case "en-GB":
27
+ return en_translations.DatePicker;
28
+ default:
29
+ return undefined;
30
+ }
31
+ };
@@ -45,7 +45,11 @@ const SelectedOptions: React.FC<SelectedOptionsProps> = ({
45
45
  const { value } = useInputContext();
46
46
  const { isMultiSelect } = useSelectedOptionsContext();
47
47
  return (
48
- <Chips className="navds-combobox__selected-options" size={size}>
48
+ <Chips
49
+ className="navds-combobox__selected-options"
50
+ size={size}
51
+ data-type={isMultiSelect ? "multiple" : "single"}
52
+ >
49
53
  {value.length === 0 || (isMultiSelect && selectedOptions.length)
50
54
  ? selectedOptions.map((option, i) => (
51
55
  <Option key={option.label + i} option={option} />
@@ -6,31 +6,12 @@ import React, {
6
6
  useState,
7
7
  } from "react";
8
8
  import { Loader } from "../../loader";
9
+ import { UNSAFE_useAkselTheme } from "../../provider";
9
10
  import { BodyShort } from "../../typography";
10
11
  import { omit } from "../../util";
11
12
  import { ReadOnlyIconWithTitle } from "../ReadOnlyIcon";
12
13
  import { FormFieldProps, useFormField } from "../useFormField";
13
14
 
14
- const SelectedIcon = () => (
15
- <svg
16
- width="12"
17
- height="10"
18
- viewBox="0 0 12 10"
19
- fill="none"
20
- xmlns="http://www.w3.org/2000/svg"
21
- focusable={false}
22
- role="img"
23
- aria-hidden
24
- >
25
- <path
26
- fillRule="evenodd"
27
- clipRule="evenodd"
28
- d="M11.2674 0.647802C11.8762 1.20971 11.9141 2.1587 11.3522 2.76743L5.35221 9.26743C5.07531 9.56739 4.68813 9.74155 4.27998 9.74971C3.87184 9.75787 3.478 9.59933 3.18934 9.31067L0.68934 6.81067C0.103553 6.22488 0.103553 5.27513 0.68934 4.68935C1.27513 4.10356 2.22487 4.10356 2.81066 4.68935L4.20673 6.08541L9.14779 0.732587C9.7097 0.123856 10.6587 0.0858967 11.2674 0.647802Z"
29
- fill="currentColor"
30
- />
31
- </svg>
32
- );
33
-
34
15
  export interface SwitchProps
35
16
  extends Omit<FormFieldProps, "error" | "errorId">,
36
17
  Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
@@ -88,6 +69,8 @@ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(
88
69
  defaultChecked ?? checkedProp ?? false,
89
70
  );
90
71
 
72
+ const themeContext = UNSAFE_useAkselTheme(false);
73
+
91
74
  useEffect(() => {
92
75
  checkedProp !== undefined && setChecked(checkedProp);
93
76
  }, [checkedProp]);
@@ -138,11 +121,34 @@ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(
138
121
  <Loader
139
122
  size="xsmall"
140
123
  aria-live="polite"
141
- variant={checked ? "interaction" : "neutral"}
124
+ variant={
125
+ checked
126
+ ? "interaction"
127
+ : themeContext
128
+ ? "inverted"
129
+ : "neutral"
130
+ }
142
131
  />
143
- ) : checked ? (
144
- <SelectedIcon />
145
- ) : null}
132
+ ) : (
133
+ <svg
134
+ width="12"
135
+ height="10"
136
+ viewBox="0 0 12 10"
137
+ fill="none"
138
+ xmlns="http://www.w3.org/2000/svg"
139
+ focusable={false}
140
+ role="img"
141
+ aria-hidden
142
+ className="navds-switch__checkmark"
143
+ >
144
+ <path
145
+ fillRule="evenodd"
146
+ clipRule="evenodd"
147
+ d="M11.2674 0.647802C11.8762 1.20971 11.9141 2.1587 11.3522 2.76743L5.35221 9.26743C5.07531 9.56739 4.68813 9.74155 4.27998 9.74971C3.87184 9.75787 3.478 9.59933 3.18934 9.31067L0.68934 6.81067C0.103553 6.22488 0.103553 5.27513 0.68934 4.68935C1.27513 4.10356 2.22487 4.10356 2.81066 4.68935L4.20673 6.08541L9.14779 0.732587C9.7097 0.123856 10.6587 0.0858967 11.2674 0.647802Z"
148
+ fill="currentColor"
149
+ />
150
+ </svg>
151
+ )}
146
152
  </span>
147
153
  </span>
148
154
  <label htmlFor={inputProps.id} className="navds-switch__label-wrapper">
@@ -1,5 +1,6 @@
1
1
  import cl from "clsx";
2
2
  import React, { HTMLAttributes, forwardRef } from "react";
3
+ import { UNSAFE_AkselTheme, UNSAFE_useAkselTheme } from "../provider";
3
4
  import { OverridableComponent } from "../util/types";
4
5
  import InternalHeaderButton, {
5
6
  InternalHeaderButtonProps,
@@ -76,14 +77,33 @@ interface InternalHeaderComponent
76
77
  * </InternalHeader>
77
78
  * ```
78
79
  */
79
- export const InternalHeader = forwardRef(({ className, ...rest }, ref) => (
80
- <header
81
- data-theme="dark"
82
- {...rest}
83
- ref={ref}
84
- className={cl("navds-internalheader", className)}
85
- />
86
- )) as InternalHeaderComponent;
80
+ export const InternalHeader = forwardRef(({ className, ...rest }, ref) => {
81
+ const themeContext = UNSAFE_useAkselTheme(false);
82
+
83
+ /*
84
+ * Component is always in "dark" mode, so we manually override global theme.
85
+ */
86
+ if (themeContext) {
87
+ return (
88
+ <UNSAFE_AkselTheme theme="dark" asChild>
89
+ <header
90
+ {...rest}
91
+ ref={ref}
92
+ className={cl("navds-internalheader", className)}
93
+ />
94
+ </UNSAFE_AkselTheme>
95
+ );
96
+ }
97
+
98
+ return (
99
+ <header
100
+ data-theme="dark"
101
+ {...rest}
102
+ ref={ref}
103
+ className={cl("navds-internalheader", className)}
104
+ />
105
+ );
106
+ }) as InternalHeaderComponent;
87
107
 
88
108
  InternalHeader.Title = InternalHeaderTitle;
89
109
  InternalHeader.User = InternalHeaderUser;
@@ -2,6 +2,7 @@ import cl from "clsx";
2
2
  import React, { forwardRef, useRef } from "react";
3
3
  import { ChevronRightIcon } from "@navikt/aksel-icons";
4
4
  import { useModalContext } from "../../modal/Modal.context";
5
+ import { UNSAFE_useAkselTheme } from "../../provider";
5
6
  import { Slot } from "../../slot/Slot";
6
7
  import { OverridableComponent, useId } from "../../util";
7
8
  import { composeEventHandlers } from "../../util/composeEventHandlers";
@@ -332,44 +333,56 @@ export const ActionMenuTrigger = forwardRef<
332
333
  interface ActionMenuContentProps
333
334
  extends Omit<React.HTMLAttributes<HTMLDivElement>, "id"> {
334
335
  children?: React.ReactNode;
336
+ align?: "start" | "end";
335
337
  }
336
338
 
337
339
  export const ActionMenuContent = forwardRef<
338
340
  HTMLDivElement,
339
341
  ActionMenuContentProps
340
- >(({ children, className, style, ...rest }: ActionMenuContentProps, ref) => {
341
- const context = useActionMenuContext();
342
+ >(
343
+ (
344
+ {
345
+ children,
346
+ className,
347
+ style,
348
+ align = "start",
349
+ ...rest
350
+ }: ActionMenuContentProps,
351
+ ref,
352
+ ) => {
353
+ const context = useActionMenuContext();
342
354
 
343
- return (
344
- <Menu.Portal rootElement={context.rootElement} asChild>
345
- <Menu.Content
346
- ref={ref}
347
- id={context.contentId}
348
- aria-labelledby={context.triggerId}
349
- className={cl("navds-action-menu__content", className)}
350
- {...rest}
351
- align="start"
352
- sideOffset={4}
353
- collisionPadding={10}
354
- onCloseAutoFocus={() => {
355
- context.triggerRef.current?.focus();
356
- }}
357
- safeZone={{ anchor: context.triggerRef.current }}
358
- style={{
359
- ...style,
360
- ...{
361
- "--__ac-action-menu-content-transform-origin":
362
- "var(--ac-floating-transform-origin)",
363
- "--__ac-action-menu-content-available-height":
364
- "var(--ac-floating-available-height)",
365
- },
366
- }}
367
- >
368
- <div className="navds-action-menu__content-inner">{children}</div>
369
- </Menu.Content>
370
- </Menu.Portal>
371
- );
372
- });
355
+ return (
356
+ <Menu.Portal rootElement={context.rootElement} asChild>
357
+ <Menu.Content
358
+ ref={ref}
359
+ id={context.contentId}
360
+ aria-labelledby={context.triggerId}
361
+ className={cl("navds-action-menu__content", className)}
362
+ {...rest}
363
+ align={align}
364
+ sideOffset={4}
365
+ collisionPadding={10}
366
+ onCloseAutoFocus={() => {
367
+ context.triggerRef.current?.focus();
368
+ }}
369
+ safeZone={{ anchor: context.triggerRef.current }}
370
+ style={{
371
+ ...style,
372
+ ...{
373
+ "--__ac-action-menu-content-transform-origin":
374
+ "var(--ac-floating-transform-origin)",
375
+ "--__ac-action-menu-content-available-height":
376
+ "var(--ac-floating-available-height)",
377
+ },
378
+ }}
379
+ >
380
+ <div className="navds-action-menu__content-inner">{children}</div>
381
+ </Menu.Content>
382
+ </Menu.Portal>
383
+ );
384
+ },
385
+ );
373
386
 
374
387
  /* -------------------------------------------------------------------------- */
375
388
  /* ActionMenuLabel */
@@ -723,6 +736,8 @@ export const ActionMenuRadioItem = forwardRef<
723
736
  { children, className, onSelect, ...rest }: ActionMenuRadioItemProps,
724
737
  ref,
725
738
  ) => {
739
+ const themeContext = UNSAFE_useAkselTheme(false);
740
+
726
741
  return (
727
742
  <Menu.RadioItem
728
743
  ref={ref}
@@ -768,29 +783,48 @@ export const ActionMenuRadioItem = forwardRef<
768
783
  fill="var(--ax-bg-default, var(--a-surface-default))"
769
784
  />
770
785
  </g>
771
- <g className="navds-action-menu__indicator-icon--checked">
772
- <rect
773
- x="1"
774
- y="1"
775
- width="22"
776
- height="22"
777
- rx="11"
778
- fill="var(--ax-bg-default, var(--a-surface-default))"
779
- />
780
- <rect
781
- x="1"
782
- y="1"
783
- width="22"
784
- height="22"
785
- rx="11"
786
- stroke="var(--ax-bg-accent-strong-pressed, var(--a-surface-action-selected))"
787
- strokeWidth="2"
788
- />
789
- <path
790
- d="M20 12C20 16.4178 16.4178 20 12 20C7.58222 20 4 16.4178 4 12C4 7.58222 7.58222 4 12 4C16.4178 4 20 7.58222 20 12Z"
791
- fill="var(--ax-bg-accent-strong-pressed, var(--a-surface-action-selected))"
792
- />
793
- </g>
786
+ {themeContext ? (
787
+ <g className="navds-action-menu__indicator-icon--checked">
788
+ <rect
789
+ width="24"
790
+ height="24"
791
+ rx="12"
792
+ fill="var(--ax-bg-accent-strong-pressed)"
793
+ />
794
+ <rect
795
+ x="8"
796
+ y="8"
797
+ width="8"
798
+ height="8"
799
+ rx="4"
800
+ fill="var(--ax-bg-default, var(--a-surface-default))"
801
+ />
802
+ </g>
803
+ ) : (
804
+ <g className="navds-action-menu__indicator-icon--checked">
805
+ <rect
806
+ x="1"
807
+ y="1"
808
+ width="22"
809
+ height="22"
810
+ rx="11"
811
+ fill="var(--ax-bg-default, var(--a-surface-default))"
812
+ />
813
+ <rect
814
+ x="1"
815
+ y="1"
816
+ width="22"
817
+ height="22"
818
+ rx="11"
819
+ stroke="var(--ax-bg-accent-strong-pressed, var(--a-surface-action-selected))"
820
+ strokeWidth="2"
821
+ />
822
+ <path
823
+ d="M20 12C20 16.4178 16.4178 20 12 20C7.58222 20 4 16.4178 4 12C4 7.58222 7.58222 4 12 4C16.4178 4 20 7.58222 20 12Z"
824
+ fill="var(--ax-bg-accent-strong-pressed, var(--a-surface-action-selected))"
825
+ />
826
+ </g>
827
+ )}
794
828
  </svg>
795
829
  </Menu.ItemIndicator>
796
830
  </Marker>
@@ -955,11 +989,11 @@ ActionMenu.SubTrigger = ActionMenuSubTrigger;
955
989
  ActionMenu.SubContent = ActionMenuSubContent;
956
990
 
957
991
  export type {
958
- ActionMenuItemProps,
959
992
  ActionMenuCheckboxItemProps,
960
993
  ActionMenuContentProps,
961
994
  ActionMenuDividerProps,
962
995
  ActionMenuGroupProps,
996
+ ActionMenuItemProps,
963
997
  ActionMenuLabelProps,
964
998
  ActionMenuProps,
965
999
  ActionMenuRadioGroupProps,
@@ -1,9 +1,20 @@
1
1
  import cl from "clsx";
2
2
  import React, { forwardRef } from "react";
3
+ import { Slot } from "../../slot/Slot";
3
4
  import { createContext } from "../../util/create-context";
4
5
 
5
6
  type AkselThemeContext = {
6
- theme: "light" | "dark";
7
+ /**
8
+ * Color theme
9
+ * @default "light"
10
+ */
11
+ theme?: "light" | "dark";
12
+ /**
13
+ * Brand volume
14
+ * @default "low"
15
+ * This is experimental and subject to changes
16
+ */
17
+ volume?: "high" | "low";
7
18
  };
8
19
 
9
20
  const [ThemeProvider, useAkselTheme] = createContext<AkselThemeContext>({
@@ -17,6 +28,8 @@ type AkselThemeProps = {
17
28
  children: React.ReactNode;
18
29
  className?: string;
19
30
  hasBackground?: boolean;
31
+ /* TODO: Handle this correctly with types */
32
+ asChild?: boolean;
20
33
  } & AkselThemeContext;
21
34
 
22
35
  const AkselTheme = forwardRef<HTMLDivElement, AkselThemeProps>(
@@ -26,7 +39,9 @@ const AkselTheme = forwardRef<HTMLDivElement, AkselThemeProps>(
26
39
  const {
27
40
  children,
28
41
  className,
42
+ asChild = false,
29
43
  theme = context?.theme ?? "light",
44
+ volume = context?.volume ?? "low",
30
45
  hasBackground: hasBackgroundProp = true,
31
46
  } = props;
32
47
 
@@ -35,15 +50,18 @@ const AkselTheme = forwardRef<HTMLDivElement, AkselThemeProps>(
35
50
  const hasBackground =
36
51
  hasBackgroundProp ?? (isRoot || props.theme !== undefined);
37
52
 
53
+ const SlotElement = asChild ? Slot : "div";
54
+
38
55
  return (
39
- <ThemeProvider theme={theme}>
40
- <div
56
+ <ThemeProvider theme={theme} volume={volume}>
57
+ <SlotElement
41
58
  ref={ref}
42
59
  className={cl("navds-theme", className, theme)}
43
60
  data-background={hasBackground}
61
+ data-volume={volume}
44
62
  >
45
63
  {children}
46
- </div>
64
+ </SlotElement>
47
65
  </ThemeProvider>
48
66
  );
49
67
  },
@@ -4,5 +4,7 @@ declare module "react" {
4
4
  interface CSSProperties {
5
5
  [key: `--ac-${string}`]: string | number | undefined;
6
6
  [key: `--__ac-${string}`]: string | number | undefined;
7
+ [key: `--axc-${string}`]: string | number | undefined;
8
+ [key: `--__axc-${string}`]: string | number | undefined;
7
9
  }
8
10
  }
@@ -1,6 +1,7 @@
1
1
  import cl from "clsx";
2
2
  import React, { forwardRef } from "react";
3
3
  import { ChevronDownIcon } from "@navikt/aksel-icons";
4
+ import { UNSAFE_useAkselTheme } from "../provider";
4
5
  import { BodyLong } from "../typography";
5
6
  import { composeEventHandlers } from "../util/composeEventHandlers";
6
7
  import { useControllableState } from "../util/hooks/useControllableState";
@@ -33,7 +34,7 @@ export interface ReadMoreProps
33
34
  * Changes fontsize for content.
34
35
  * @default "medium"
35
36
  */
36
- size?: "medium" | "small";
37
+ size?: "large" | "medium" | "small";
37
38
  }
38
39
 
39
40
  /**
@@ -74,6 +75,10 @@ export const ReadMore = forwardRef<HTMLButtonElement, ReadMoreProps>(
74
75
  onChange: onOpenChange,
75
76
  });
76
77
 
78
+ const themeContext = UNSAFE_useAkselTheme(false);
79
+
80
+ const typoSize = size === "small" ? "small" : "medium";
81
+
77
82
  return (
78
83
  <div
79
84
  className={cl(
@@ -82,6 +87,7 @@ export const ReadMore = forwardRef<HTMLButtonElement, ReadMoreProps>(
82
87
  className,
83
88
  { "navds-read-more--open": _open },
84
89
  )}
90
+ data-volume={themeContext?.volume}
85
91
  >
86
92
  <button
87
93
  {...rest}
@@ -92,6 +98,7 @@ export const ReadMore = forwardRef<HTMLButtonElement, ReadMoreProps>(
92
98
  })}
93
99
  onClick={composeEventHandlers(onClick, () => _setOpen((x) => !x))}
94
100
  aria-expanded={_open}
101
+ data-state={_open ? "open" : "closed"}
95
102
  >
96
103
  <ChevronDownIcon
97
104
  className="navds-read-more__expand-icon"
@@ -106,7 +113,8 @@ export const ReadMore = forwardRef<HTMLButtonElement, ReadMoreProps>(
106
113
  className={cl("navds-read-more__content", {
107
114
  "navds-read-more__content--closed": !_open,
108
115
  })}
109
- size={size}
116
+ size={typoSize}
117
+ data-state={_open ? "open" : "closed"}
110
118
  >
111
119
  {children}
112
120
  </BodyLong>
@@ -60,6 +60,9 @@ export const Step: OverridableComponent<StepperStepProps, HTMLAnchorElement> =
60
60
  "navds-stepper__step--non-interactive": !isInteractive,
61
61
  "navds-stepper__step--completed": completed,
62
62
  })}
63
+ data-active={activeStep === context.index}
64
+ data-completed={completed}
65
+ data-interactive={isInteractive}
63
66
  onClick={composeEventHandlers(onClick, handleStepClick)}
64
67
  >
65
68
  {completed ? (
@@ -93,6 +93,7 @@ export const Stepper: StepperComponent = forwardRef<
93
93
  orientation === "horizontal" ? "navds-stepper--horizontal" : "",
94
94
  className,
95
95
  )}
96
+ data-orientation={orientation}
96
97
  >
97
98
  {React.Children.map(children, (step, index) => {
98
99
  const stepProps: Partial<StepperStepProps> =
@@ -101,10 +102,12 @@ export const Stepper: StepperComponent = forwardRef<
101
102
  return (
102
103
  <li
103
104
  className={cl("navds-stepper__item", {
105
+ /* TODO: Remove these 3 classNames in darkmode update */
104
106
  "navds-stepper__item--behind": activeStep > index,
105
107
  "navds-stepper__item--completed": stepProps.completed,
106
- "navds-stepper__item--non-interactive":
107
- stepProps.interactive ?? interactive,
108
+ "navds-stepper__item--non-interactive": !(
109
+ stepProps.interactive ?? interactive
110
+ ),
108
111
  })}
109
112
  key={index + (children?.toString?.() ?? "")}
110
113
  >
@@ -224,6 +224,7 @@ const TextareaAutosize = forwardRef<HTMLTextAreaElement, TextareaAutosizeProps>(
224
224
 
225
225
  const mainStyle: React.CSSProperties = {
226
226
  "--__ac-textarea-height": state.outerHeightStyle + "px",
227
+ "--__axc-textarea-height": state.outerHeightStyle + "px",
227
228
  // Need a large enough difference to allow scrolling.
228
229
  // This prevents infinite rendering loop.
229
230
  overflow:
@@ -97,4 +97,24 @@ export default {
97
97
  reset: "Reset zoom",
98
98
  },
99
99
  },
100
+ DatePicker: {
101
+ close: "Close",
102
+ chooseDate: "Choose date",
103
+ chooseDates: "Choose dates",
104
+ chooseDateRange: "Choose start and end date",
105
+ chooseMonth: "Choose month",
106
+ week: "Week",
107
+ weekNumber: "Week {week}",
108
+ selectWeekNumber: "Select week {week}",
109
+ month: "Month",
110
+ goToNextMonth: "Go to next month",
111
+ goToPreviousMonth: "Go to previous month",
112
+ year: "Year",
113
+ goToNextYear: "Go to next year",
114
+ goToPreviousYear: "Go to previous year",
115
+ openDatePicker: "Open date picker",
116
+ openMonthPicker: "Open month picker",
117
+ closeDatePicker: "Close date picker",
118
+ closeMonthPicker: "Close month picker",
119
+ },
100
120
  } satisfies Translations;