@navikt/ds-react 7.28.0 → 7.29.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 (96) hide show
  1. package/cjs/accordion/Accordion.d.ts +1 -0
  2. package/cjs/accordion/Accordion.js.map +1 -1
  3. package/cjs/form/fieldset/Fieldset.js +4 -3
  4. package/cjs/form/fieldset/Fieldset.js.map +1 -1
  5. package/cjs/form/fieldset/useFieldset.d.ts +3 -3
  6. package/cjs/form/fieldset/useFieldset.js +11 -4
  7. package/cjs/form/fieldset/useFieldset.js.map +1 -1
  8. package/cjs/form/useFormField.d.ts +1 -0
  9. package/cjs/form/useFormField.js +53 -4
  10. package/cjs/form/useFormField.js.map +1 -1
  11. package/cjs/index.d.ts +1 -0
  12. package/cjs/index.js +4 -2
  13. package/cjs/index.js.map +1 -1
  14. package/cjs/layout/box/Box.js +2 -1
  15. package/cjs/layout/box/Box.js.map +1 -1
  16. package/cjs/link-card/LinkCard.d.ts +5 -0
  17. package/cjs/link-card/LinkCard.js +6 -6
  18. package/cjs/link-card/LinkCard.js.map +1 -1
  19. package/cjs/process/Process.d.ts +90 -0
  20. package/cjs/process/Process.js +184 -0
  21. package/cjs/process/Process.js.map +1 -0
  22. package/cjs/process/index.d.ts +1 -0
  23. package/cjs/process/index.js +8 -0
  24. package/cjs/process/index.js.map +1 -0
  25. package/cjs/stepper/Stepper.d.ts +1 -0
  26. package/cjs/stepper/Stepper.js.map +1 -1
  27. package/cjs/toggle-group/ToggleGroup.js +3 -4
  28. package/cjs/toggle-group/ToggleGroup.js.map +1 -1
  29. package/cjs/util/i18n/locales/en.d.ts +3 -0
  30. package/cjs/util/i18n/locales/en.js +3 -0
  31. package/cjs/util/i18n/locales/en.js.map +1 -1
  32. package/cjs/util/i18n/locales/nb.d.ts +4 -0
  33. package/cjs/util/i18n/locales/nb.js +4 -0
  34. package/cjs/util/i18n/locales/nb.js.map +1 -1
  35. package/cjs/util/i18n/locales/nn.d.ts +3 -0
  36. package/cjs/util/i18n/locales/nn.js +3 -0
  37. package/cjs/util/i18n/locales/nn.js.map +1 -1
  38. package/cjs/util/renderStoriesForChromatic.d.ts +13 -0
  39. package/cjs/util/renderStoriesForChromatic.js +21 -0
  40. package/cjs/util/renderStoriesForChromatic.js.map +1 -0
  41. package/esm/accordion/Accordion.d.ts +1 -0
  42. package/esm/accordion/Accordion.js.map +1 -1
  43. package/esm/form/fieldset/Fieldset.js +5 -4
  44. package/esm/form/fieldset/Fieldset.js.map +1 -1
  45. package/esm/form/fieldset/useFieldset.d.ts +3 -3
  46. package/esm/form/fieldset/useFieldset.js +9 -5
  47. package/esm/form/fieldset/useFieldset.js.map +1 -1
  48. package/esm/form/useFormField.d.ts +1 -0
  49. package/esm/form/useFormField.js +19 -4
  50. package/esm/form/useFormField.js.map +1 -1
  51. package/esm/index.d.ts +1 -0
  52. package/esm/index.js +1 -0
  53. package/esm/index.js.map +1 -1
  54. package/esm/layout/box/Box.js +2 -1
  55. package/esm/layout/box/Box.js.map +1 -1
  56. package/esm/link-card/LinkCard.d.ts +5 -0
  57. package/esm/link-card/LinkCard.js +6 -6
  58. package/esm/link-card/LinkCard.js.map +1 -1
  59. package/esm/process/Process.d.ts +90 -0
  60. package/esm/process/Process.js +148 -0
  61. package/esm/process/Process.js.map +1 -0
  62. package/esm/process/index.d.ts +1 -0
  63. package/esm/process/index.js +3 -0
  64. package/esm/process/index.js.map +1 -0
  65. package/esm/stepper/Stepper.d.ts +1 -0
  66. package/esm/stepper/Stepper.js.map +1 -1
  67. package/esm/toggle-group/ToggleGroup.js +3 -4
  68. package/esm/toggle-group/ToggleGroup.js.map +1 -1
  69. package/esm/util/i18n/locales/en.d.ts +3 -0
  70. package/esm/util/i18n/locales/en.js +3 -0
  71. package/esm/util/i18n/locales/en.js.map +1 -1
  72. package/esm/util/i18n/locales/nb.d.ts +4 -0
  73. package/esm/util/i18n/locales/nb.js +4 -0
  74. package/esm/util/i18n/locales/nb.js.map +1 -1
  75. package/esm/util/i18n/locales/nn.d.ts +3 -0
  76. package/esm/util/i18n/locales/nn.js +3 -0
  77. package/esm/util/i18n/locales/nn.js.map +1 -1
  78. package/esm/util/renderStoriesForChromatic.d.ts +13 -0
  79. package/esm/util/renderStoriesForChromatic.js +15 -0
  80. package/esm/util/renderStoriesForChromatic.js.map +1 -0
  81. package/package.json +14 -4
  82. package/src/accordion/Accordion.tsx +1 -0
  83. package/src/form/fieldset/Fieldset.tsx +5 -3
  84. package/src/form/fieldset/useFieldset.ts +15 -5
  85. package/src/form/useFormField.ts +21 -3
  86. package/src/index.ts +1 -0
  87. package/src/layout/box/Box.tsx +2 -1
  88. package/src/link-card/LinkCard.tsx +14 -7
  89. package/src/process/Process.tsx +358 -0
  90. package/src/process/index.ts +7 -0
  91. package/src/stepper/Stepper.tsx +1 -0
  92. package/src/toggle-group/ToggleGroup.tsx +2 -5
  93. package/src/util/i18n/locales/en.ts +3 -0
  94. package/src/util/i18n/locales/nb.ts +3 -0
  95. package/src/util/i18n/locales/nn.ts +3 -0
  96. package/src/util/renderStoriesForChromatic.tsx +24 -0
@@ -1,5 +1,6 @@
1
1
  import cl from "clsx";
2
2
  import React, { useContext } from "react";
3
+ import { ReadMore } from "../read-more/ReadMore";
3
4
  import { useId } from "../util/hooks";
4
5
  import { FieldsetContext } from "./fieldset/context";
5
6
 
@@ -84,7 +85,7 @@ export const useFormField = (
84
85
  "Aksel: Use of 'required' in form-elements is heavily discuouraged. Docs about why here:",
85
86
  );
86
87
  console.warn(
87
- "https://aksel.nav.no/god-praksis/artikler/obligatoriske-og-valgfrie-skjemafelter#h3bfe00453471",
88
+ "https://aksel.nav.no/god-praksis/artikler/obligatoriske-og-valgfrie-skjemafelter#dc7a536235fa",
88
89
  );
89
90
  }
90
91
 
@@ -101,12 +102,29 @@ export const useFormField = (
101
102
  "aria-describedby":
102
103
  cl(props["aria-describedby"], {
103
104
  [inputDescriptionId]:
104
- !!props?.description && typeof props?.description === "string",
105
+ props.description && !containsReadMore(props.description),
105
106
  [errorId]: showErrorMsg,
106
- [fieldset?.errorId ?? ""]: hasError && !!fieldset?.error,
107
+ [fieldset?.errorId ?? ""]: hasError && fieldset?.error,
107
108
  }) || undefined,
108
109
 
109
110
  disabled,
110
111
  },
111
112
  };
112
113
  };
114
+
115
+ export function containsReadMore(
116
+ children: React.ReactNode,
117
+ checkNested = true,
118
+ ): boolean {
119
+ if (React.isValidElement(children)) {
120
+ if (children.type === ReadMore) {
121
+ return true;
122
+ }
123
+ if (children.props.children && checkNested) {
124
+ return containsReadMore(children.props.children, false);
125
+ }
126
+ } else if (Array.isArray(children)) {
127
+ return children.some((child) => containsReadMore(child, checkNested));
128
+ }
129
+ return false;
130
+ }
package/src/index.ts CHANGED
@@ -58,6 +58,7 @@ export { Modal, type ModalProps } from "./modal";
58
58
  export { Pagination, type PaginationProps } from "./pagination";
59
59
  export { Popover, type PopoverProps } from "./popover";
60
60
  export { Portal, type PortalProps } from "./portal";
61
+ export { Process, type ProcessProps } from "./process";
61
62
  export { ProgressBar, type ProgressBarProps } from "./progress-bar";
62
63
  export { Provider, type ProviderProps } from "./provider";
63
64
  export { ReadMore, type ReadMoreProps } from "./read-more";
@@ -173,7 +173,8 @@ export const BoxComponent: OverridableComponent<BoxProps, HTMLDivElement> =
173
173
  "navds-box-bg": background,
174
174
  "navds-box-border-color": borderColor,
175
175
  "navds-box-border-width": borderWidth,
176
- "navds-box-border-radius": borderRadius,
176
+ "navds-box-border-radius": borderRadius && !themeContext,
177
+ "navds-box-radius": borderRadius && themeContext,
177
178
  "navds-box-shadow": shadow,
178
179
  })}
179
180
  >
@@ -15,6 +15,11 @@ interface LinkCardProps extends HTMLAttributes<HTMLDivElement> {
15
15
  * @default true
16
16
  */
17
17
  arrow?: boolean;
18
+ /**
19
+ * Adjusts arrow position.
20
+ * @default "baseline"
21
+ */
22
+ arrowPosition?: "baseline" | "center";
18
23
  /**
19
24
  * Changes padding and typo sizes.
20
25
  * @default "medium"
@@ -24,7 +29,6 @@ interface LinkCardProps extends HTMLAttributes<HTMLDivElement> {
24
29
 
25
30
  type LinkCardContextProps = {
26
31
  size: LinkCardProps["size"];
27
- arrow: LinkCardProps["arrow"];
28
32
  };
29
33
 
30
34
  const [LinkCardContextProvider, useLinkCardContext] =
@@ -93,6 +97,7 @@ export const LinkCard = forwardRef<HTMLDivElement, LinkCardProps>(
93
97
  children,
94
98
  className,
95
99
  arrow = true,
100
+ arrowPosition = "baseline",
96
101
  size = "medium",
97
102
  ...restProps
98
103
  }: LinkCardProps,
@@ -101,7 +106,7 @@ export const LinkCard = forwardRef<HTMLDivElement, LinkCardProps>(
101
106
  const { cn } = useRenameCSS();
102
107
 
103
108
  return (
104
- <LinkCardContextProvider size={size} arrow={arrow}>
109
+ <LinkCardContextProvider size={size}>
105
110
  <LinkAnchorOverlay asChild>
106
111
  <BodyLong
107
112
  as="div"
@@ -113,9 +118,16 @@ export const LinkCard = forwardRef<HTMLDivElement, LinkCardProps>(
113
118
  className,
114
119
  `navds-link-card--${size}`,
115
120
  )}
121
+ data-align-arrow={arrowPosition}
116
122
  {...restProps}
117
123
  >
118
124
  {children}
125
+ {arrow && (
126
+ <LinkAnchorArrow
127
+ fontSize={size === "medium" ? "1.75rem" : "1.5rem"}
128
+ className={cn("navds-link-card__arrow")}
129
+ />
130
+ )}
119
131
  </BodyLong>
120
132
  </LinkAnchorOverlay>
121
133
  </LinkCardContextProvider>
@@ -155,11 +167,6 @@ export const LinkCardTitle = forwardRef<HTMLHeadingElement, LinkCardTitleProps>(
155
167
  {...restProps}
156
168
  >
157
169
  {children}
158
- {context.arrow && (
159
- <LinkAnchorArrow
160
- fontSize={context.size === "medium" ? "1.75rem" : "1.5rem"}
161
- />
162
- )}
163
170
  </Heading>
164
171
  );
165
172
  },
@@ -0,0 +1,358 @@
1
+ import React, {
2
+ forwardRef,
3
+ useCallback,
4
+ useEffect,
5
+ useRef,
6
+ useState,
7
+ } from "react";
8
+ import { useRenameCSS } from "../theme/Theme";
9
+ import { BodyLong, BodyShort, Heading } from "../typography";
10
+ import { useId } from "../util";
11
+ import { createContext } from "../util/create-context";
12
+ import { useMergeRefs } from "../util/hooks";
13
+ import { useI18n } from "../util/i18n/i18n.hooks";
14
+
15
+ interface ProcessProps extends React.HTMLAttributes<HTMLOListElement> {
16
+ /**
17
+ * `<Process.Event />` elements.
18
+ */
19
+ children: React.ReactElement<typeof ProcessEvent>[];
20
+ /**
21
+ * Hides the "aktiv"-text when the event is active.
22
+ * @default false
23
+ */
24
+ hideStatusText?: boolean;
25
+ }
26
+
27
+ type ProcessContextProps = Pick<ProcessProps, "hideStatusText"> & {
28
+ rootId: string;
29
+ syncAriaControls: () => void;
30
+ };
31
+
32
+ const [ProcessContextProvider, useProcessContext] =
33
+ createContext<ProcessContextProps>({
34
+ providerName: "ProcessContextProvider",
35
+ hookName: "useProcessContext",
36
+ name: "ProcessContext",
37
+ errorMessage:
38
+ "`<Process.Event />` must be used within a `<Process />` component.",
39
+ });
40
+
41
+ interface ProcessComponent
42
+ extends React.ForwardRefExoticComponent<
43
+ ProcessProps & React.RefAttributes<HTMLOListElement>
44
+ > {
45
+ /**
46
+ * @see 🏷️ {@link ProcessEventProps}
47
+ */
48
+ Event: typeof ProcessEvent;
49
+ }
50
+
51
+ /**
52
+ * A component that presents a Process as a vertical line of events.
53
+ * Each event can contain information, actions, links or status indicators.
54
+ *
55
+ * @see [📝 Documentation](https://aksel.nav.no/komponenter/core/process)
56
+ * @see 🏷️ {@link ProcessProps}
57
+ *
58
+ * @example
59
+ * ```jsx
60
+ * <>
61
+ * <Heading size="medium" spacing level="2" id="Process-heading">
62
+ * Søknadssteg
63
+ * </Heading>
64
+ * <Process
65
+ * aria-labelledby="Process-heading"
66
+ * activeStep={activeStep}
67
+ * >
68
+ * <Process.Event title="Start søknad" timestamp="21. august 2025" />
69
+ * <Process.Event
70
+ * title="Saksopplysninger"
71
+ * timestamp="22. august 2025"
72
+ * icon={<PaperclipIcon />}
73
+ * >
74
+ * Saksopplysninger er sendt inn
75
+ * </Process.Event>
76
+ * <Process.Event
77
+ * title="Vedlegg"
78
+ * timestamp="25. august 2025"
79
+ * >
80
+ * <h3> Vedlegg er lastet opp </h3>
81
+ * <p>
82
+ * Dokumentasjon av saksopplysninger er lastet opp og tilgjengelig for
83
+ * saksbehandler.
84
+ * </p>
85
+ * </Process.Event>
86
+ * <Process.Event title="Vedtak" timestamp="8. september 2025">
87
+ * Det er gjort endelig vedtak i saken
88
+ * </Process.Event>
89
+ * </Process>
90
+ * </>
91
+ * ```
92
+ */
93
+ export const Process: ProcessComponent = forwardRef<
94
+ HTMLOListElement,
95
+ ProcessProps
96
+ >(
97
+ (
98
+ {
99
+ children,
100
+ className,
101
+ hideStatusText = false,
102
+ id,
103
+ ...restProps
104
+ }: ProcessProps,
105
+ forwardedRef,
106
+ ) => {
107
+ const { cn } = useRenameCSS();
108
+
109
+ const rootId = useId(id);
110
+
111
+ const rootRef = useRef<HTMLOListElement>(null);
112
+ const mergedRef = useMergeRefs(forwardedRef, rootRef);
113
+
114
+ const [activeChildId, setActiveChildId] = useState<string | undefined>(
115
+ undefined,
116
+ );
117
+
118
+ const syncAriaControls = useCallback(() => {
119
+ const activeChildren = rootRef.current?.querySelectorAll(
120
+ '[data-process-event][aria-current="true"]',
121
+ );
122
+
123
+ if (!activeChildren) {
124
+ setActiveChildId(undefined);
125
+ return;
126
+ }
127
+
128
+ if (activeChildren.length > 1) {
129
+ if (process.env.NODE_ENV !== "production") {
130
+ console.warn(
131
+ "Aksel: Found multiple `<Process.Event />` elements with `status='active'`. Only one event should be active at a time.",
132
+ rootRef.current,
133
+ );
134
+ }
135
+ setActiveChildId(undefined);
136
+ return;
137
+ }
138
+
139
+ if (activeChildren.length === 1) {
140
+ const lastActiveChild = activeChildren[activeChildren.length - 1];
141
+ setActiveChildId(lastActiveChild.id);
142
+ } else {
143
+ setActiveChildId(undefined);
144
+ }
145
+ }, []);
146
+
147
+ return (
148
+ // `<ol />` elements with `list-style: none;` tends to be ignored by voiceover on Safari.
149
+ // To resolve this, we add `role="list"` to the `<ol />` element.
150
+ // eslint-disable-next-line jsx-a11y/no-redundant-roles
151
+ <ol
152
+ ref={mergedRef}
153
+ data-color="info"
154
+ // biome-ignore lint/a11y/noRedundantRoles: See comment above
155
+ role="list"
156
+ {...restProps}
157
+ className={cn("navds-process", className)}
158
+ id={rootId}
159
+ aria-controls={activeChildId}
160
+ >
161
+ <ProcessContextProvider
162
+ hideStatusText={hideStatusText}
163
+ rootId={rootId}
164
+ syncAriaControls={syncAriaControls}
165
+ >
166
+ {children}
167
+ </ProcessContextProvider>
168
+ </ol>
169
+ );
170
+ },
171
+ ) as ProcessComponent;
172
+
173
+ /* ------------------------------ Process Event ------------------------------ */
174
+ interface ProcessEventProps extends React.HTMLAttributes<HTMLLIElement> {
175
+ /**
176
+ * Rich content to display under the title and timestamp if provided.
177
+ */
178
+ children?: React.ReactNode;
179
+ /**
180
+ * Hide the content section of the event.
181
+ */
182
+ hideContent?: boolean;
183
+ /**
184
+ * Step title.
185
+ */
186
+ title?: string;
187
+ /**
188
+ * Timestamp or date to display for event.
189
+ */
190
+ timestamp?: string;
191
+ /**
192
+ * Icon or number to display inside the bullet.
193
+ */
194
+ bullet?: React.ReactNode;
195
+ /**
196
+ * Current event status.
197
+ * @default "uncompleted"
198
+ */
199
+ status?: "active" | "completed" | "uncompleted";
200
+ }
201
+
202
+ export const ProcessEvent = forwardRef<HTMLLIElement, ProcessEventProps>(
203
+ (
204
+ {
205
+ title,
206
+ timestamp,
207
+ children,
208
+ bullet,
209
+ hideContent,
210
+ className,
211
+ id,
212
+ status = "uncompleted",
213
+ ...restProps
214
+ }: ProcessEventProps,
215
+ forwardedRef,
216
+ ) => {
217
+ const translate = useI18n("Process");
218
+ const { cn } = useRenameCSS();
219
+ const eventId = useId();
220
+ const { syncAriaControls, hideStatusText, rootId } = useProcessContext();
221
+
222
+ // syncAriaControls is already memoized with useCallback
223
+ // biome-ignore lint/correctness/useExhaustiveDependencies: We want to run this only when status changes
224
+ useEffect(syncAriaControls, [status]); // eslint-disable-line react-hooks/exhaustive-deps
225
+
226
+ const isActive = status === "active";
227
+
228
+ return (
229
+ <li
230
+ ref={forwardedRef}
231
+ aria-current={isActive}
232
+ id={id ?? eventId}
233
+ {...restProps}
234
+ aria-controls={isActive ? rootId : undefined}
235
+ className={cn("navds-process__event", className)}
236
+ data-dot={bullet === undefined}
237
+ data-process-event=""
238
+ data-status={status}
239
+ >
240
+ <div className={cn("navds-process__item")}>
241
+ <ProcessBullet>{bullet}</ProcessBullet>
242
+
243
+ <div className={cn("navds-process__body")}>
244
+ {title && <ProcessTitle>{title}</ProcessTitle>}
245
+ {isActive && !hideStatusText && (
246
+ <BodyShort
247
+ size="small"
248
+ className={cn("navds-process__active-label")}
249
+ >
250
+ {translate("active")}
251
+ </BodyShort>
252
+ )}
253
+ {timestamp && <ProcessTimestamp>{timestamp}</ProcessTimestamp>}
254
+ {!hideContent && !!children && (
255
+ <ProcessContent>{children}</ProcessContent>
256
+ )}
257
+ </div>
258
+ </div>
259
+ <ProcessLine />
260
+ </li>
261
+ );
262
+ },
263
+ );
264
+
265
+ /* ------------------------------ Process Title ----------------------------- */
266
+ interface ProcessTitleProps {
267
+ /**
268
+ * Title content.
269
+ */
270
+ children: React.ReactNode;
271
+ }
272
+
273
+ const ProcessTitle = ({ children }: ProcessTitleProps) => {
274
+ const { cn } = useRenameCSS();
275
+
276
+ return (
277
+ <Heading size="small" as="div" className={cn("navds-process__title")}>
278
+ {children}
279
+ </Heading>
280
+ );
281
+ };
282
+
283
+ /* ---------------------------- Process timestamp --------------------------- */
284
+ interface ProcessTimestampProps {
285
+ /**
286
+ * Timestamp content.
287
+ */
288
+ children: React.ReactNode;
289
+ }
290
+
291
+ const ProcessTimestamp = ({ children }: ProcessTimestampProps) => {
292
+ const { cn } = useRenameCSS();
293
+
294
+ return (
295
+ <BodyShort
296
+ spacing
297
+ as="div"
298
+ size="small"
299
+ textColor="subtle"
300
+ className={cn("navds-process__timestamp")}
301
+ >
302
+ {children}
303
+ </BodyShort>
304
+ );
305
+ };
306
+
307
+ /* ----------------------------- Process Content ---------------------------- */
308
+ interface ProcessContentProps {
309
+ /**
310
+ * Content content.
311
+ */
312
+ children: React.ReactNode;
313
+ }
314
+
315
+ const ProcessContent = ({ children }: ProcessContentProps) => {
316
+ const { cn } = useRenameCSS();
317
+
318
+ return (
319
+ <BodyLong as="div" className={cn("navds-process__content")}>
320
+ {children}
321
+ </BodyLong>
322
+ );
323
+ };
324
+
325
+ /* ----------------------------- Process Bullet ----------------------------- */
326
+ interface ProcessBulletProps {
327
+ /**
328
+ * Bullet content.
329
+ */
330
+ children: React.ReactNode;
331
+ }
332
+
333
+ const ProcessBullet = ({ children }: ProcessBulletProps) => {
334
+ const { cn } = useRenameCSS();
335
+
336
+ return (
337
+ <BodyShort
338
+ as="span"
339
+ weight="semibold"
340
+ className={cn("navds-process__bullet")}
341
+ aria-hidden
342
+ >
343
+ {children}
344
+ </BodyShort>
345
+ );
346
+ };
347
+
348
+ /* ------------------------------ Process Line ------------------------------ */
349
+ const ProcessLine = () => {
350
+ const { cn } = useRenameCSS();
351
+
352
+ return <span className={cn("navds-process__line")} />;
353
+ };
354
+
355
+ /* -------------------------- Process exports ------------------------- */
356
+ Process.Event = ProcessEvent;
357
+
358
+ export type { ProcessEventProps, ProcessProps };
@@ -0,0 +1,7 @@
1
+ "use client";
2
+ export {
3
+ Process,
4
+ type ProcessProps,
5
+ ProcessEvent,
6
+ type ProcessEventProps,
7
+ } from "./Process";
@@ -27,6 +27,7 @@ export interface StepperProps extends React.HTMLAttributes<HTMLOListElement> {
27
27
  onStepChange?: (step: number) => void;
28
28
  /**
29
29
  * Makes stepper non-interactive if false.
30
+ * @deprecated Use `interactive` prop on `<Stepper.Step />` instead for individual steps. For completely static steppers, use `Process` component instead.
30
31
  * @default true
31
32
  */
32
33
  interactive?: boolean;
@@ -1,4 +1,3 @@
1
- import cl from "clsx";
2
1
  import React, { forwardRef } from "react";
3
2
  import { useRenameCSS, useThemeInternal } from "../theme/Theme";
4
3
  import { AkselColor } from "../types";
@@ -48,7 +47,6 @@ export const ToggleGroup = forwardRef<HTMLDivElement, ToggleGroupProps>(
48
47
  label,
49
48
  value,
50
49
  defaultValue,
51
- "aria-describedby": userDescribedby,
52
50
  variant,
53
51
  fill = false,
54
52
  "data-color": color,
@@ -103,6 +101,7 @@ export const ToggleGroup = forwardRef<HTMLDivElement, ToggleGroupProps>(
103
101
  >
104
102
  {label && (
105
103
  <Label
104
+ as="div"
106
105
  size={size}
107
106
  className={cn("navds-toggle-group__label")}
108
107
  id={labelId}
@@ -111,6 +110,7 @@ export const ToggleGroup = forwardRef<HTMLDivElement, ToggleGroupProps>(
111
110
  </Label>
112
111
  )}
113
112
  <div
113
+ aria-labelledby={label ? labelId : undefined}
114
114
  {...rest}
115
115
  ref={ref}
116
116
  className={cn(
@@ -118,9 +118,6 @@ export const ToggleGroup = forwardRef<HTMLDivElement, ToggleGroupProps>(
118
118
  `navds-toggle-group--${size}`,
119
119
  { [`navds-toggle-group--${localVariant}`]: localVariant },
120
120
  )}
121
- aria-describedby={
122
- cl(userDescribedby, !!label && labelId) || undefined
123
- }
124
121
  role="radiogroup"
125
122
  >
126
123
  {children}
@@ -93,6 +93,9 @@ export default {
93
93
  previous: "Previous",
94
94
  next: "Next",
95
95
  },
96
+ Process: {
97
+ active: "Active",
98
+ },
96
99
  ProgressBar: {
97
100
  progress: "{current} of {max}",
98
101
  progressUnknown:
@@ -99,6 +99,9 @@ export default {
99
99
  previous: "Forrige",
100
100
  next: "Neste",
101
101
  },
102
+ Process: {
103
+ active: "Aktiv",
104
+ },
102
105
  ProgressBar: {
103
106
  progress: "{current} av {max}",
104
107
  progressUnknown:
@@ -93,6 +93,9 @@ export default {
93
93
  previous: "Førre",
94
94
  next: "Neste",
95
95
  },
96
+ Process: {
97
+ active: "Aktiv",
98
+ },
96
99
  ProgressBar: {
97
100
  progress: "{current} av {max}",
98
101
  progressUnknown:
@@ -0,0 +1,24 @@
1
+ import { Args } from "@storybook/react";
2
+ import React from "react";
3
+ import { Renderer, StoryContext } from "storybook/internal/types";
4
+
5
+ export function renderStoriesForChromatic(
6
+ stories: Record<
7
+ string,
8
+ | { render?: (...args: any[]) => React.ReactNode }
9
+ | React.FunctionComponent<void>
10
+ >,
11
+ ) {
12
+ return {
13
+ render: (...args: [Args, StoryContext<Renderer, Args>]) =>
14
+ Object.entries(stories).map(([storyName, story]) => (
15
+ <div key={storyName}>
16
+ <h2 className="storyheading">{storyName}</h2>
17
+ {typeof story === "function" ? story() : story.render?.(...args)}
18
+ </div>
19
+ )),
20
+ parameters: {
21
+ chromatic: { disable: false },
22
+ },
23
+ };
24
+ }