@navikt/ds-react 6.0.0-alpha.7 → 6.0.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 (124) hide show
  1. package/cjs/date/parts/DateWrapper.js +2 -2
  2. package/cjs/date/parts/DateWrapper.js.map +1 -1
  3. package/cjs/form/error-summary/ErrorSummary.d.ts +3 -9
  4. package/cjs/form/error-summary/ErrorSummary.js +9 -4
  5. package/cjs/form/error-summary/ErrorSummary.js.map +1 -1
  6. package/cjs/form/error-summary/ErrorSummaryItem.d.ts +1 -1
  7. package/cjs/form/error-summary/ErrorSummaryItem.js +1 -2
  8. package/cjs/form/error-summary/ErrorSummaryItem.js.map +1 -1
  9. package/cjs/form/search/Search.d.ts +1 -1
  10. package/cjs/form/search/Search.js +1 -1
  11. package/cjs/index.js +1 -0
  12. package/cjs/index.js.map +1 -1
  13. package/cjs/modal/Modal.context.d.ts +9 -0
  14. package/cjs/modal/Modal.context.js +10 -0
  15. package/cjs/modal/Modal.context.js.map +1 -0
  16. package/cjs/modal/Modal.js +3 -6
  17. package/cjs/modal/Modal.js.map +1 -1
  18. package/cjs/modal/ModalHeader.js +2 -6
  19. package/cjs/modal/ModalHeader.js.map +1 -1
  20. package/cjs/modal/types.d.ts +24 -3
  21. package/cjs/panel/Panel.d.ts +9 -16
  22. package/cjs/panel/Panel.js +6 -16
  23. package/cjs/panel/Panel.js.map +1 -1
  24. package/cjs/popover/Popover.js +2 -2
  25. package/cjs/popover/Popover.js.map +1 -1
  26. package/cjs/table/types.d.ts +1 -1
  27. package/cjs/tooltip/Tooltip.js +3 -3
  28. package/cjs/tooltip/Tooltip.js.map +1 -1
  29. package/cjs/util/create-context.d.ts +2 -5
  30. package/cjs/util/create-context.js +9 -5
  31. package/cjs/util/create-context.js.map +1 -1
  32. package/cjs/util/types/OverridableComponent.d.ts +1 -1
  33. package/esm/date/parts/DateWrapper.js +3 -3
  34. package/esm/date/parts/DateWrapper.js.map +1 -1
  35. package/esm/form/error-summary/ErrorSummary.d.ts +3 -9
  36. package/esm/form/error-summary/ErrorSummary.js +10 -5
  37. package/esm/form/error-summary/ErrorSummary.js.map +1 -1
  38. package/esm/form/error-summary/ErrorSummaryItem.d.ts +1 -1
  39. package/esm/form/error-summary/ErrorSummaryItem.js +1 -2
  40. package/esm/form/error-summary/ErrorSummaryItem.js.map +1 -1
  41. package/esm/form/search/Search.d.ts +1 -1
  42. package/esm/form/search/Search.js +1 -1
  43. package/esm/index.js +1 -0
  44. package/esm/index.js.map +1 -1
  45. package/esm/modal/Modal.context.d.ts +9 -0
  46. package/esm/modal/Modal.context.js +6 -0
  47. package/esm/modal/Modal.context.js.map +1 -0
  48. package/esm/modal/Modal.js +3 -6
  49. package/esm/modal/Modal.js.map +1 -1
  50. package/esm/modal/ModalHeader.js +3 -7
  51. package/esm/modal/ModalHeader.js.map +1 -1
  52. package/esm/modal/types.d.ts +24 -3
  53. package/esm/panel/Panel.d.ts +9 -16
  54. package/esm/panel/Panel.js +6 -16
  55. package/esm/panel/Panel.js.map +1 -1
  56. package/esm/popover/Popover.js +2 -2
  57. package/esm/popover/Popover.js.map +1 -1
  58. package/esm/table/types.d.ts +1 -1
  59. package/esm/tooltip/Tooltip.js +4 -4
  60. package/esm/tooltip/Tooltip.js.map +1 -1
  61. package/esm/util/create-context.d.ts +2 -5
  62. package/esm/util/create-context.js +10 -6
  63. package/esm/util/create-context.js.map +1 -1
  64. package/esm/util/types/OverridableComponent.d.ts +1 -1
  65. package/package.json +6 -6
  66. package/src/accordion/accordion.stories.tsx +121 -135
  67. package/src/button/button.stories.tsx +88 -185
  68. package/src/chat/chat.stories.tsx +285 -186
  69. package/src/date/datepicker/datepicker.stories.tsx +6 -2
  70. package/src/date/monthpicker/monthpicker.stories.tsx +2 -1
  71. package/src/date/parts/DateWrapper.tsx +3 -3
  72. package/src/dropdown/dropdown.stories.tsx +1 -1
  73. package/src/form/error-summary/ErrorSummary.tsx +11 -15
  74. package/src/form/error-summary/ErrorSummaryItem.tsx +8 -10
  75. package/src/form/error-summary/error-summary.stories.tsx +2 -56
  76. package/src/form/search/Search.tsx +4 -4
  77. package/src/form/stories/confirmation-panel.stories.tsx +1 -1
  78. package/src/form/stories/textarea.stories.tsx +1 -1
  79. package/src/help-text/help-text.stories.tsx +2 -1
  80. package/src/index.ts +1 -0
  81. package/src/internal-header/header.stories.tsx +2 -1
  82. package/src/layout/bleed/Bleed.stories.tsx +2 -1
  83. package/src/layout/box/Box.stories.tsx +2 -1
  84. package/src/layout/sidemal-test/navno-sidemal.stories.tsx +4 -1
  85. package/src/link/stories/link.stories.tsx +20 -22
  86. package/src/link-panel/link-panel.stories.tsx +1 -1
  87. package/src/list/list.stories.tsx +2 -1
  88. package/src/loader/loader.stories.tsx +1 -1
  89. package/src/modal/Modal.context.ts +13 -0
  90. package/src/modal/Modal.test.tsx +2 -2
  91. package/src/modal/Modal.tsx +6 -8
  92. package/src/modal/ModalHeader.tsx +3 -7
  93. package/src/modal/modal.stories.tsx +33 -6
  94. package/src/modal/types.ts +21 -4
  95. package/src/panel/Panel.tsx +9 -16
  96. package/src/popover/Popover.tsx +2 -2
  97. package/src/stepper/stepper.stories.tsx +1 -1
  98. package/src/table/stories/{table.stories.tsx → table-1.stories.tsx} +118 -92
  99. package/src/table/stories/{table-expandable.stories.tsx → table-2-expandable.stories.tsx} +10 -34
  100. package/src/table/stories/{table-async.stories.tsx → table-3-async.stories.tsx} +5 -3
  101. package/src/table/stories/tests/table.stories.tsx +4 -1
  102. package/src/table/types.ts +1 -1
  103. package/src/tabs/Tabs.test.tsx +109 -0
  104. package/src/toggle-group/ToggleGroup.test.tsx +54 -0
  105. package/src/tooltip/Tooltip.tsx +4 -10
  106. package/src/tooltip/tooltip.stories.tsx +4 -1
  107. package/src/typography/stories/bodylong.stories.tsx +49 -3
  108. package/src/typography/stories/bodyshort.stories.tsx +50 -4
  109. package/src/typography/stories/detail.stories.tsx +32 -3
  110. package/src/typography/stories/error-message.stories.tsx +34 -3
  111. package/src/typography/stories/heading.stories.tsx +32 -3
  112. package/src/typography/stories/label.stories.tsx +38 -3
  113. package/src/util/create-context.tsx +26 -15
  114. package/src/util/types/OverridableComponent.ts +1 -1
  115. package/_docs.json +0 -20247
  116. package/cjs/modal/ModalContext.d.ts +0 -7
  117. package/cjs/modal/ModalContext.js +0 -9
  118. package/cjs/modal/ModalContext.js.map +0 -1
  119. package/esm/modal/ModalContext.d.ts +0 -7
  120. package/esm/modal/ModalContext.js +0 -3
  121. package/esm/modal/ModalContext.js.map +0 -1
  122. package/src/modal/ModalContext.ts +0 -7
  123. package/src/panel/panel.stories.tsx +0 -63
  124. package/src/typography/stories/ingress.stories.tsx +0 -50
@@ -1,7 +1,6 @@
1
1
  import { Meta } from "@storybook/react";
2
- import { expect, userEvent, within } from "@storybook/test";
3
- import React, { useRef } from "react";
4
- import { ErrorSummary } from "..";
2
+ import React from "react";
3
+ import { ErrorSummary } from "./ErrorSummary";
5
4
 
6
5
  export default {
7
6
  title: "ds-react/Errorsummary",
@@ -44,56 +43,3 @@ export const Small = () => (
44
43
  </ErrorSummary.Item>
45
44
  </ErrorSummary>
46
45
  );
47
-
48
- export const A11yDemo = {
49
- render: () => {
50
- // eslint-disable-next-line react-hooks/rules-of-hooks
51
- const ref = useRef<HTMLHeadingElement>(null);
52
- return (
53
- <div>
54
- <button onClick={() => ref.current?.focus()}>
55
- Fokuser Errorsummary på klikk
56
- </button>
57
- <ErrorSummary heading="Feiloppsummering tittel" focusTargetRef={ref}>
58
- <ErrorSummary.Item href="#1">Checkbox må fylles ut</ErrorSummary.Item>
59
- <ErrorSummary.Item href="#2">
60
- Tekstfeltet må ha en godkjent e-mail
61
- </ErrorSummary.Item>
62
- </ErrorSummary>
63
- </div>
64
- );
65
- },
66
- };
67
-
68
- export const FocusDemo = {
69
- render: () => {
70
- // eslint-disable-next-line react-hooks/rules-of-hooks
71
- const ref = useRef<HTMLHeadingElement>(null);
72
- return (
73
- <div>
74
- <button onClick={() => ref.current?.focus()}>Focus summary</button>
75
- <ErrorSummary heading="Feiloppsummering tittel" focusTargetRef={ref}>
76
- <ErrorSummary.Item href="#1">Checkbox må fylles ut</ErrorSummary.Item>
77
- <ErrorSummary.Item href="#2">
78
- Tekstfeltet må ha en godkjent e-mail
79
- </ErrorSummary.Item>
80
- </ErrorSummary>
81
- </div>
82
- );
83
- },
84
- play: async ({ canvasElement, step }) => {
85
- const canvas = within(canvasElement);
86
-
87
- const button = canvas.getByText("Focus summary");
88
- const heading = canvas.getByText("Feiloppsummering tittel");
89
-
90
- await step("click button", async () => {
91
- await userEvent.click(button);
92
- });
93
-
94
- expect(heading).toHaveFocus();
95
- },
96
- parameters: {
97
- chromatic: { disableSnapshot: true },
98
- },
99
- };
@@ -23,7 +23,7 @@ export type SearchClearEvent =
23
23
 
24
24
  export interface SearchProps
25
25
  extends Omit<FormFieldProps, "readOnly">,
26
- Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "onChange"> {
26
+ Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "onChange" | "type"> {
27
27
  children?: React.ReactNode;
28
28
  /**
29
29
  * Search label
@@ -66,10 +66,10 @@ export interface SearchProps
66
66
  * Exposes the HTML size attribute
67
67
  */
68
68
  htmlSize?: number | string;
69
- /*
69
+ /*
70
70
  * Exposes role attribute
71
71
  */
72
- role?: string
72
+ role?: string;
73
73
  }
74
74
 
75
75
  interface SearchComponent
@@ -210,7 +210,7 @@ export const Search = forwardRef<HTMLInputElement, SearchProps>(
210
210
  value={value ?? internalValue}
211
211
  onChange={(e) => handleChange(e.target.value)}
212
212
  type="search"
213
- role={role ?? 'searchbox'}
213
+ role={role ?? "searchbox"}
214
214
  className={cl(
215
215
  className,
216
216
  "navds-search__input",
@@ -1,6 +1,6 @@
1
1
  import { Meta } from "@storybook/react";
2
2
  import React, { useState } from "react";
3
- import { Link } from "../..";
3
+ import { Link } from "../../link";
4
4
  import { ConfirmationPanel } from "../index";
5
5
 
6
6
  export default {
@@ -212,7 +212,7 @@ export const ModalStrictMode: StoryFn<typeof Textarea> = () => {
212
212
  // and set the height to 2px when used in StrictMode in a Modal that is initially open.
213
213
  return (
214
214
  <React.StrictMode>
215
- <Modal open>
215
+ <Modal open onClose={() => null} aria-label="Modal med textarea">
216
216
  <Modal.Body>
217
217
  <Textarea label="Har du noen tilbakemeldinger?" />
218
218
  </Modal.Body>
@@ -1,6 +1,7 @@
1
1
  import { Meta, StoryFn, StoryObj } from "@storybook/react";
2
2
  import React, { useEffect, useRef } from "react";
3
- import { BodyLong, Heading, HelpText } from "..";
3
+ import { BodyLong, Heading } from "../typography";
4
+ import HelpText from "./HelpText";
4
5
 
5
6
  const meta: Meta<typeof HelpText> = {
6
7
  title: "ds-react/HelpText",
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  export * from "./accordion";
2
3
  export * from "./alert";
3
4
  export * from "./button";
@@ -6,7 +6,8 @@ import {
6
6
  MenuGridIcon,
7
7
  } from "@navikt/aksel-icons";
8
8
  import { BodyLong, BodyShort, Detail } from "@navikt/ds-react";
9
- import { Dropdown, InternalHeader } from "..";
9
+ import { Dropdown } from "../dropdown";
10
+ import InternalHeader from "./InternalHeader";
10
11
 
11
12
  export default {
12
13
  title: "ds-react/InternalHeader",
@@ -1,7 +1,8 @@
1
1
  import type { Meta } from "@storybook/react";
2
2
  import React from "react";
3
- import { Box, HStack, VStack } from "../..";
4
3
  import { BodyLong } from "../../typography";
4
+ import { Box } from "../box";
5
+ import { HStack, VStack } from "../stack";
5
6
  import { Bleed } from "./Bleed";
6
7
 
7
8
  export default {
@@ -1,8 +1,9 @@
1
1
  import type { Meta } from "@storybook/react";
2
2
  import React, { ReactNode } from "react";
3
3
  import { ChevronRightIcon } from "@navikt/aksel-icons";
4
- import { HGrid, HStack, VStack } from "../..";
5
4
  import { BodyLong, Detail, Heading } from "../../typography";
5
+ import { HGrid } from "../grid";
6
+ import { HStack, VStack } from "../stack";
6
7
  import { BackgroundToken, BorderRadiiToken } from "../utilities/types";
7
8
  import { Box } from "./Box";
8
9
 
@@ -1,6 +1,9 @@
1
1
  import type { Meta, StoryObj } from "@storybook/react";
2
2
  import React from "react";
3
- import { Box, HGrid, Hide, Show, VStack } from "../..";
3
+ import { Box } from "../box";
4
+ import { HGrid } from "../grid";
5
+ import { Hide, Show } from "../responsive";
6
+ import { VStack } from "../stack";
4
7
  import { Content } from "./Content";
5
8
  import { FilterCard } from "./Filter";
6
9
  import { Header } from "./Header";
@@ -1,11 +1,9 @@
1
1
  import React from "react";
2
2
  import { PlusCircleFillIcon } from "@navikt/aksel-icons";
3
- import {
4
- BodyLong,
5
- Alert as DsAlert,
6
- ConfirmationPanel as DsConfirmationPanel,
7
- Link,
8
- } from "../..";
3
+ import { Alert } from "../../alert";
4
+ import { ConfirmationPanel } from "../../form";
5
+ import { BodyLong } from "../../typography";
6
+ import Link from "../Link";
9
7
  import { RandomIcon } from "./RandomIcon";
10
8
 
11
9
  export default {
@@ -139,37 +137,37 @@ const DemoLink = () => (
139
137
 
140
138
  export const Icon = () => <DemoLink />;
141
139
 
142
- export const Alert = () => {
140
+ export const InAlert = () => {
143
141
  return (
144
142
  <div className="colgap">
145
- <DsAlert variant="info">
143
+ <Alert variant="info">
146
144
  <DemoLink />
147
- </DsAlert>
148
- <DsAlert variant="success">
145
+ </Alert>
146
+ <Alert variant="success">
149
147
  <DemoLink />
150
- </DsAlert>
151
- <DsAlert variant="warning">
148
+ </Alert>
149
+ <Alert variant="warning">
152
150
  <DemoLink />
153
- </DsAlert>
154
- <DsAlert variant="error">
151
+ </Alert>
152
+ <Alert variant="error">
155
153
  <DemoLink />
156
- </DsAlert>
154
+ </Alert>
157
155
  </div>
158
156
  );
159
157
  };
160
158
 
161
- export const ConfirmationPanel = () => {
159
+ export const InConfirmationPanel = () => {
162
160
  return (
163
161
  <div className="colgap">
164
- <DsConfirmationPanel label="demo">
162
+ <ConfirmationPanel label="demo">
165
163
  <DemoLink />
166
- </DsConfirmationPanel>
167
- <DsConfirmationPanel checked label="demo">
164
+ </ConfirmationPanel>
165
+ <ConfirmationPanel checked label="demo">
168
166
  <DemoLink />
169
- </DsConfirmationPanel>
170
- <DsConfirmationPanel error="demo" label="demo">
167
+ </ConfirmationPanel>
168
+ <ConfirmationPanel error="demo" label="demo">
171
169
  <DemoLink />
172
- </DsConfirmationPanel>
170
+ </ConfirmationPanel>
173
171
  </div>
174
172
  );
175
173
  };
@@ -1,6 +1,6 @@
1
1
  import { Meta } from "@storybook/react";
2
2
  import React from "react";
3
- import { LinkPanel } from "..";
3
+ import LinkPanel from "./LinkPanel";
4
4
 
5
5
  export default {
6
6
  title: "ds-react/LinkPanel",
@@ -6,7 +6,8 @@ import {
6
6
  HeadHeartIcon,
7
7
  RecycleIcon,
8
8
  } from "@navikt/aksel-icons";
9
- import { List, VStack } from "..";
9
+ import { VStack } from "../layout/stack";
10
+ import List from "./List";
10
11
 
11
12
  export default {
12
13
  title: "ds-react/List",
@@ -1,6 +1,6 @@
1
1
  import { Meta } from "@storybook/react";
2
2
  import React from "react";
3
- import { Loader, LoaderProps } from "..";
3
+ import Loader, { LoaderProps } from "./Loader";
4
4
 
5
5
  export default {
6
6
  title: "ds-react/Loader",
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ import { createContext } from "../util/create-context";
3
+
4
+ interface ModalContextProps {
5
+ closeHandler?: React.MouseEventHandler<HTMLButtonElement>;
6
+ ref: React.RefObject<HTMLDialogElement>;
7
+ }
8
+
9
+ export const [ModalContextProvider, useModalContext] =
10
+ createContext<ModalContextProps>({
11
+ name: "ModalContext",
12
+ errorMessage: "<Modal.Header> must be used within a <Modal>",
13
+ });
@@ -7,7 +7,7 @@ const Test = () => {
7
7
  const [open, setOpen] = useState(true);
8
8
 
9
9
  return (
10
- <Modal open={open}>
10
+ <Modal open={open} onClose={() => null} aria-label="Test">
11
11
  <Modal.Body>
12
12
  <p>Foobar</p>
13
13
  <Button onClick={() => setOpen(false)}>Close</Button>
@@ -40,7 +40,7 @@ describe("Modal", () => {
40
40
 
41
41
  test("should toggle body class when using portal", async () => {
42
42
  render(
43
- <Modal portal open>
43
+ <Modal portal open onClose={() => null} aria-label="Test">
44
44
  <Modal.Header />
45
45
  </Modal>,
46
46
  );
@@ -8,8 +8,8 @@ import { Detail, Heading } from "../typography";
8
8
  import { composeEventHandlers } from "../util/composeEventHandlers";
9
9
  import { useId } from "../util/hooks";
10
10
  import { useMergeRefs } from "../util/hooks/useMergeRefs";
11
+ import { ModalContextProvider, useModalContext } from "./Modal.context";
11
12
  import ModalBody from "./ModalBody";
12
- import { ModalContext } from "./ModalContext";
13
13
  import ModalFooter from "./ModalFooter";
14
14
  import ModalHeader from "./ModalHeader";
15
15
  import { getCloseHandler, useBodyScrollLock } from "./ModalUtils";
@@ -98,7 +98,7 @@ export const Modal = forwardRef<HTMLDialogElement, ModalProps>(
98
98
  const portalNode = useFloatingPortalNode({ root: rootElement });
99
99
 
100
100
  const dateContext = useContext(DateContext);
101
- const modalContext = useContext(ModalContext);
101
+ const modalContext = useModalContext(false);
102
102
  if (modalContext && !dateContext) {
103
103
  console.error("Modals should not be nested");
104
104
  }
@@ -185,11 +185,9 @@ export const Modal = forwardRef<HTMLDialogElement, ModalProps>(
185
185
  onClick={composeEventHandlers(onClick, handleModalClick)}
186
186
  aria-labelledby={mergedAriaLabelledBy}
187
187
  >
188
- <ModalContext.Provider
189
- value={{
190
- closeHandler: getCloseHandler(modalRef, header, onBeforeClose),
191
- ref: modalRef,
192
- }}
188
+ <ModalContextProvider
189
+ closeHandler={getCloseHandler(modalRef, header, onBeforeClose)}
190
+ ref={modalRef}
193
191
  >
194
192
  {header && (
195
193
  <ModalHeader>
@@ -208,7 +206,7 @@ export const Modal = forwardRef<HTMLDialogElement, ModalProps>(
208
206
  )}
209
207
 
210
208
  {children}
211
- </ModalContext.Provider>
209
+ </ModalContextProvider>
212
210
  </dialog>
213
211
  );
214
212
 
@@ -1,8 +1,8 @@
1
1
  import cl from "clsx";
2
- import React, { forwardRef, useContext } from "react";
2
+ import React, { forwardRef } from "react";
3
3
  import { XMarkIcon } from "@navikt/aksel-icons";
4
4
  import { Button } from "../button";
5
- import { ModalContext } from "./ModalContext";
5
+ import { useModalContext } from "./Modal.context";
6
6
 
7
7
  export interface ModalHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
8
8
  children?: React.ReactNode;
@@ -15,11 +15,7 @@ export interface ModalHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
15
15
 
16
16
  const ModalHeader = forwardRef<HTMLDivElement, ModalHeaderProps>(
17
17
  ({ children, className, closeButton = true, ...rest }, ref) => {
18
- const context = useContext(ModalContext);
19
- if (context === null) {
20
- console.error("<Modal.Header> has to be used within a <Modal>");
21
- return null;
22
- }
18
+ const context = useModalContext();
23
19
 
24
20
  return (
25
21
  <div {...rest} ref={ref} className={cl("navds-modal__header", className)}>
@@ -1,9 +1,11 @@
1
1
  import { Meta, StoryFn } from "@storybook/react";
2
2
  import React, { useRef, useState } from "react";
3
3
  import { FileIcon } from "@navikt/aksel-icons";
4
- import { BodyLong, Button, Heading, Tooltip } from "..";
4
+ import { Button } from "../button";
5
5
  import { Checkbox, CheckboxGroup } from "../form/checkbox";
6
6
  import { VStack } from "../layout/stack";
7
+ import { Tooltip } from "../tooltip";
8
+ import { BodyLong, Heading } from "../typography";
7
9
  import Modal from "./Modal";
8
10
 
9
11
  const meta: Meta<typeof Modal> = {
@@ -24,6 +26,7 @@ export const WithUseRef: StoryFn = () => {
24
26
  <Button onClick={() => ref.current?.showModal()}>Open Modal</Button>
25
27
  <Modal
26
28
  open={ref.current ? undefined : true /* initially open */}
29
+ onClose={() => null}
27
30
  ref={ref}
28
31
  header={{
29
32
  label: "Optional label",
@@ -145,7 +148,7 @@ export const WithUseState: StoryFn = () => {
145
148
  WithUseState.storyName = "With useState";
146
149
 
147
150
  export const EmptyHeader: StoryFn = () => (
148
- <Modal open>
151
+ <Modal open onClose={() => null} aria-label="Modal with empty header">
149
152
  <Modal.Header />
150
153
  <Modal.Body>
151
154
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
@@ -160,21 +163,37 @@ export const EmptyHeader: StoryFn = () => (
160
163
  );
161
164
 
162
165
  export const Small: StoryFn = () => (
163
- <Modal open width="small" header={{ heading: "Simple header" }}>
166
+ <Modal
167
+ open
168
+ onClose={() => null}
169
+ width="small"
170
+ header={{ heading: "Simple header" }}
171
+ >
164
172
  <Modal.Body>Lorem ipsum dolor sit amet.</Modal.Body>
165
173
  </Modal>
166
174
  );
167
175
  Small.storyName = "Size = Small";
168
176
 
169
177
  export const MediumWithPortal: StoryFn = () => (
170
- <Modal open portal width="medium" header={{ heading: "Simple header" }}>
178
+ <Modal
179
+ open
180
+ onClose={() => null}
181
+ portal
182
+ width="medium"
183
+ header={{ heading: "Simple header" }}
184
+ >
171
185
  <Modal.Body>Lorem ipsum dolor sit amet.</Modal.Body>
172
186
  </Modal>
173
187
  );
174
188
  MediumWithPortal.storyName = "Size = Medium (with portal)";
175
189
 
176
190
  export const Large800: StoryFn = () => (
177
- <Modal open width={800} header={{ heading: "Simple header" }}>
191
+ <Modal
192
+ open
193
+ onClose={() => null}
194
+ width={800}
195
+ header={{ heading: "Simple header" }}
196
+ >
178
197
  <Modal.Body>Lorem ipsum dolor sit amet.</Modal.Body>
179
198
  </Modal>
180
199
  );
@@ -188,7 +207,9 @@ export const WithTooltip: StoryFn = () => {
188
207
  <Button onClick={() => ref.current?.showModal()}>Open Modal</Button>
189
208
  <Modal
190
209
  open={ref.current ? undefined : true /* initially open */}
210
+ onClose={() => null}
191
211
  ref={ref}
212
+ aria-label="Tooltip test"
192
213
  >
193
214
  <Modal.Body>
194
215
  <div style={{ marginBottom: "1rem" }}>
@@ -206,7 +227,12 @@ export const WithTooltip: StoryFn = () => {
206
227
  };
207
228
 
208
229
  export const WithSrOnlyElement: StoryFn = () => (
209
- <Modal open width={300} header={{ heading: "Simple header" }}>
230
+ <Modal
231
+ open
232
+ onClose={() => null}
233
+ width={300}
234
+ header={{ heading: "Simple header" }}
235
+ >
210
236
  <Modal.Body>
211
237
  <VStack gap="16">
212
238
  <BodyLong>
@@ -255,6 +281,7 @@ export const ChromaticViewportTesting: StoryFn = () => (
255
281
  <style>{`#storybook-root { padding: 0 !important }`}</style>
256
282
  <Modal
257
283
  open
284
+ onClose={() => null}
258
285
  header={{ heading: "Chromatic Viewports Testing", label: "Test" }}
259
286
  >
260
287
  <Modal.Body>
@@ -1,5 +1,4 @@
1
- export interface ModalProps
2
- extends React.DialogHTMLAttributes<HTMLDialogElement> {
1
+ interface ModalPropsBase extends React.DialogHTMLAttributes<HTMLDialogElement> {
3
2
  /**
4
3
  * Content for the header. Alteratively you can use <Modal.Header> instead for more control,
5
4
  * but then you have to set `aria-label` or `aria-labelledby` on the modal manually.
@@ -39,7 +38,7 @@ export interface ModalProps
39
38
  * @warning Will not always be called when pressing Esc. See `onCancel` for more info.
40
39
  * @returns Whether to close the modal
41
40
  */
42
- onBeforeClose?: () => boolean | void;
41
+ onBeforeClose?: () => boolean;
43
42
  /**
44
43
  * *Sometimes** called when the user presses the Esc key.
45
44
  * @warning *Some browsers does not always trigger this event. Chrome only triggers it if you have
@@ -66,9 +65,27 @@ export interface ModalProps
66
65
  */
67
66
  className?: string;
68
67
  /**
69
- * Sets aria-labelledby on modal.
68
+ * ID of the element that labels the modal.
70
69
  * No need to set this manually if the `header` prop is used. A reference to `header.heading` will be created automatically.
71
70
  * @warning If not using `header`, you should set either `aria-labelledby` or `aria-label`.
72
71
  */
73
72
  "aria-labelledby"?: string;
73
+ /**
74
+ * String value that labels the modal.
75
+ * No need to set this if the `header` prop is used.
76
+ * @warning If not using `header`, you should set either `aria-labelledby` or `aria-label`.
77
+ */
78
+ "aria-label"?: string;
74
79
  }
80
+
81
+ // Require onClose if you use open & Require either header, aria-labelledby or aria-label
82
+ export type ModalProps = ModalPropsBase &
83
+ (
84
+ | { open?: never }
85
+ | { open: boolean | undefined; onClose: ModalPropsBase["onClose"] }
86
+ ) &
87
+ (
88
+ | { header: ModalPropsBase["header"] }
89
+ | { "aria-labelledby": string; "aria-label"?: never }
90
+ | { "aria-labelledby"?: never; "aria-label": string }
91
+ );
@@ -2,6 +2,9 @@ import cl from "clsx";
2
2
  import React, { forwardRef } from "react";
3
3
  import { OverridableComponent } from "../util/types";
4
4
 
5
+ /**
6
+ * @deprecated Use Box with padding and border instead
7
+ */
5
8
  export interface PanelProps extends React.HTMLAttributes<HTMLElement> {
6
9
  /**
7
10
  * Panel content
@@ -17,23 +20,13 @@ export interface PanelProps extends React.HTMLAttributes<HTMLElement> {
17
20
  export type PanelType = OverridableComponent<PanelProps, HTMLElement>;
18
21
 
19
22
  /**
20
- * A component that displays a bordered panel with heading and body.
21
- *
22
- * @see [📝 Documentation](https://aksel.nav.no/komponenter/core/panel)
23
- * @see 🏷️ {@link PanelProps}
24
- * @see [🤖 OverridableComponent](https://aksel.nav.no/grunnleggende/kode/overridablecomponent) support
25
- *
26
- * @example
27
- * ```jsx
28
- * <Panel border>
29
- * <Heading spacing level="2" size="large">
30
- * Søk om økonomisk sosialhjelp
31
- * </Heading>
32
- * <BodyLong>
33
- * Du kan søke om det du trenger økonomisk støtte til.
34
- * </BodyLong>
35
- * </Panel>
23
+ * @deprecated
24
+ * Use Box with padding and border instead
25
+ * ```
26
+ * <Box padding="4" borderRadius="small" />
27
+ * <Box padding="4" borderWidth="1" borderRadius="small" />
36
28
  * ```
29
+ * Component will be removed in a future major release
37
30
  */
38
31
  export const Panel: PanelType = forwardRef(
39
32
  (
@@ -18,7 +18,7 @@ import React, {
18
18
  useRef,
19
19
  } from "react";
20
20
  import { DateContext } from "../date/context";
21
- import { ModalContext } from "../modal/ModalContext";
21
+ import { useModalContext } from "../modal/Modal.context";
22
22
  import { useClientLayoutEffect, useEventListener } from "../util/hooks";
23
23
  import { useMergeRefs } from "../util/hooks/useMergeRefs";
24
24
  import PopoverContent, { PopoverContentType } from "./PopoverContent";
@@ -126,7 +126,7 @@ export const Popover = forwardRef<HTMLDivElement, PopoverProps>(
126
126
  ref,
127
127
  ) => {
128
128
  const arrowRef = useRef<HTMLDivElement | null>(null);
129
- const isInModal = useContext(ModalContext) !== null;
129
+ const isInModal = useModalContext(false) !== undefined;
130
130
  const isInDatepicker = useContext(DateContext) !== null;
131
131
  const chosenStrategy = userStrategy ?? (isInModal ? "fixed" : "absolute");
132
132
  const chosenFlip = isInDatepicker ? false : _flip;
@@ -1,6 +1,6 @@
1
1
  import { Meta } from "@storybook/react";
2
2
  import React, { useState } from "react";
3
- import { BodyLong } from "..";
3
+ import { BodyLong } from "../typography";
4
4
  import Stepper from "./Stepper";
5
5
 
6
6
  const meta: Meta<typeof Stepper> = {