@kaizen/components 1.48.0 → 1.49.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 (72) hide show
  1. package/dist/cjs/DateInput/DateInput/DateInput.cjs +1 -0
  2. package/dist/cjs/DatePicker/DatePicker.cjs +7 -3
  3. package/dist/cjs/DateRangePicker/DateRangePicker.cjs +7 -2
  4. package/dist/cjs/EmptyState/EmptyState.cjs +0 -1
  5. package/dist/cjs/RichTextEditor/EditableRichTextContent/EditableRichTextContent.cjs +1 -0
  6. package/dist/cjs/RichTextEditor/EditableRichTextContent/EditableRichTextContent.module.scss.cjs +1 -0
  7. package/dist/cjs/RichTextEditor/RichTextEditor/RichTextEditor.cjs +1 -0
  8. package/dist/cjs/RichTextEditor/RichTextEditor/RichTextEditor.module.scss.cjs +1 -0
  9. package/dist/cjs/RichTextEditor/utils/plugins/LinkManager/components/LinkModal/LinkModal.cjs +5 -1
  10. package/dist/cjs/RichTextEditor/utils/plugins/LinkManager/components/LinkModal/LinkModal.module.scss.cjs +6 -0
  11. package/dist/cjs/RichTextEditor/utils/plugins/LinkManager/validation.cjs +8 -1
  12. package/dist/cjs/Select/Select.cjs +6 -2
  13. package/dist/cjs/__future__/Select/Select.cjs +12 -11
  14. package/dist/esm/DateInput/DateInput/DateInput.mjs +1 -0
  15. package/dist/esm/DatePicker/DatePicker.mjs +7 -3
  16. package/dist/esm/DateRangePicker/DateRangePicker.mjs +7 -2
  17. package/dist/esm/EmptyState/EmptyState.mjs +0 -1
  18. package/dist/esm/RichTextEditor/EditableRichTextContent/EditableRichTextContent.mjs +3 -2
  19. package/dist/esm/RichTextEditor/EditableRichTextContent/EditableRichTextContent.module.scss.mjs +1 -0
  20. package/dist/esm/RichTextEditor/RichTextEditor/RichTextEditor.mjs +3 -2
  21. package/dist/esm/RichTextEditor/RichTextEditor/RichTextEditor.module.scss.mjs +1 -0
  22. package/dist/esm/RichTextEditor/utils/plugins/LinkManager/components/LinkModal/LinkModal.mjs +5 -1
  23. package/dist/esm/RichTextEditor/utils/plugins/LinkManager/components/LinkModal/LinkModal.module.scss.mjs +4 -0
  24. package/dist/esm/RichTextEditor/utils/plugins/LinkManager/validation.mjs +2 -1
  25. package/dist/esm/Select/Select.mjs +6 -2
  26. package/dist/esm/__future__/Select/Select.mjs +12 -11
  27. package/dist/styles.css +9 -8
  28. package/dist/types/Input/Input/Input.d.ts +5 -0
  29. package/dist/types/RichTextEditor/utils/plugins/LinkManager/validation.d.ts +1 -0
  30. package/dist/types/Select/Select.d.ts +10 -0
  31. package/dist/types/TextArea/TextArea.d.ts +5 -0
  32. package/dist/types/__future__/Select/Select.d.ts +5 -0
  33. package/dist/types/__future__/Select/subcomponents/SelectToggle/SelectToggle.d.ts +8 -0
  34. package/package.json +6 -6
  35. package/src/DateInput/DateInput/DateInput.tsx +1 -0
  36. package/src/DatePicker/DatePicker.spec.tsx +14 -14
  37. package/src/DatePicker/DatePicker.tsx +20 -11
  38. package/src/DateRangePicker/DateRangePicker.tsx +14 -2
  39. package/src/DateRangePicker/_docs/DateRangePicker.mdx +5 -1
  40. package/src/DateRangePicker/_docs/DateRangePicker.stories.tsx +99 -3
  41. package/src/EmptyState/EmptyState.tsx +1 -4
  42. package/src/FieldGroup/_docs/FieldGroup.stickersheet.stories.tsx +2 -12
  43. package/src/FieldGroup/_docs/FieldGroup.stories.tsx +4 -9
  44. package/src/Input/Input/Input.tsx +5 -0
  45. package/src/Input/InputSearch/InputSearch.spec.tsx +10 -7
  46. package/src/Notification/ToastNotification/ToastNotificationsList/ToastNotificationsList.module.scss +1 -1
  47. package/src/RichTextEditor/EditableRichTextContent/EditableRichTextContent.module.scss +25 -7
  48. package/src/RichTextEditor/EditableRichTextContent/EditableRichTextContent.tsx +3 -1
  49. package/src/RichTextEditor/EditableRichTextContent/_docs/EditableRichTextContent.mdx +6 -4
  50. package/src/RichTextEditor/EditableRichTextContent/_docs/EditableRichTextContent.stickersheet.stories.tsx +98 -0
  51. package/src/RichTextEditor/EditableRichTextContent/_docs/EditableRichTextContent.stories.tsx +8 -5
  52. package/src/RichTextEditor/EditableRichTextContent/_docs/defaultContent.json +11 -0
  53. package/src/RichTextEditor/EditableRichTextContent/_docs/dummyContent.json +44 -39
  54. package/src/RichTextEditor/RichTextContent/_docs/RichTextContent.mdx +11 -1
  55. package/src/RichTextEditor/RichTextContent/_docs/RichTextContent.stories.tsx +47 -2
  56. package/src/RichTextEditor/RichTextEditor/RichTextEditor.module.scss +6 -1
  57. package/src/RichTextEditor/RichTextEditor/RichTextEditor.spec.stories.tsx +48 -0
  58. package/src/RichTextEditor/RichTextEditor/RichTextEditor.tsx +7 -2
  59. package/src/RichTextEditor/RichTextEditor/_docs/RichTextEditor.mdx +66 -7
  60. package/src/RichTextEditor/RichTextEditor/_docs/RichTextEditor.stories.tsx +60 -7
  61. package/src/RichTextEditor/_mixins.scss +1 -0
  62. package/src/RichTextEditor/utils/plugins/LinkManager/components/LinkModal/LinkModal.module.scss +5 -0
  63. package/src/RichTextEditor/utils/plugins/LinkManager/components/LinkModal/LinkModal.spec.stories.tsx +37 -0
  64. package/src/RichTextEditor/utils/plugins/LinkManager/components/LinkModal/LinkModal.stories.tsx +33 -0
  65. package/src/RichTextEditor/utils/plugins/LinkManager/components/LinkModal/LinkModal.tsx +9 -1
  66. package/src/RichTextEditor/utils/plugins/LinkManager/{validation.ts → validation.tsx} +11 -1
  67. package/src/Select/Select.tsx +9 -1
  68. package/src/Select/_docs/Select.stories.tsx +0 -3
  69. package/src/TextArea/TextArea.tsx +5 -0
  70. package/src/__future__/Select/Select.tsx +6 -1
  71. package/src/__future__/Select/_docs/Select.stickersheet.stories.tsx +0 -9
  72. package/src/__future__/Select/subcomponents/SelectToggle/SelectToggle.tsx +4 -0
@@ -16,6 +16,7 @@ import {
16
16
  setFocusInCalendar,
17
17
  } from "~components/Calendar"
18
18
  import { CalendarPopover } from "~components/Calendar/CalendarPopover"
19
+ import { VisuallyHidden } from "~components/VisuallyHidden"
19
20
  import {
20
21
  DateInputField,
21
22
  DateInputFieldProps,
@@ -305,17 +306,25 @@ export const DatePicker = ({
305
306
  </div>
306
307
 
307
308
  {isOpen && (
308
- <CalendarPopover referenceElement={containerRef.current}>
309
- <CalendarSingle
310
- id={calendarId}
311
- selected={selectedDay}
312
- defaultMonth={defaultMonth}
313
- weekStartsOn={weekStartsOn}
314
- disabled={disabledDays}
315
- locale={locale}
316
- onDayClick={handleCalendarDayChange}
317
- onMount={handleCalendarMount}
318
- />
309
+ <CalendarPopover
310
+ referenceElement={containerRef.current}
311
+ aria-labelledby={`${id}-calendar-label ${id}-input-label`}
312
+ >
313
+ <>
314
+ <VisuallyHidden id={`${id}-calendar-label`}>
315
+ Select date from calendar for:
316
+ </VisuallyHidden>
317
+ <CalendarSingle
318
+ id={calendarId}
319
+ selected={selectedDay}
320
+ defaultMonth={defaultMonth}
321
+ weekStartsOn={weekStartsOn}
322
+ disabled={disabledDays}
323
+ locale={locale}
324
+ onDayClick={handleCalendarDayChange}
325
+ onMount={handleCalendarMount}
326
+ />
327
+ </>
319
328
  </CalendarPopover>
320
329
  )}
321
330
  </FocusOn>
@@ -15,6 +15,7 @@ import {
15
15
  } from "~components/Calendar/LegacyCalendarRange"
16
16
  import { DateStartIcon } from "~components/Icon"
17
17
  import { Label } from "~components/Label"
18
+ import { VisuallyHidden } from "~components/VisuallyHidden"
18
19
  import styles from "./DateRangePicker.module.scss"
19
20
 
20
21
  export type DateRangePickerProps = {
@@ -146,7 +147,12 @@ export const DateRangePicker = ({
146
147
  return (
147
148
  <div>
148
149
  <div ref={containerRef} className={classNameOverride}>
149
- <Label disabled={isDisabled} htmlFor={id} labelText={labelText} />
150
+ <Label
151
+ id={`${id}-input-label`}
152
+ disabled={isDisabled}
153
+ htmlFor={id}
154
+ labelText={labelText}
155
+ />
150
156
  <button
151
157
  type="button"
152
158
  id={id}
@@ -178,7 +184,13 @@ export const DateRangePicker = ({
178
184
  onEscapeKey={handleOpenClose}
179
185
  enabled={isOpen}
180
186
  >
181
- <CalendarPopover referenceElement={containerRef.current}>
187
+ <CalendarPopover
188
+ referenceElement={containerRef.current}
189
+ aria-labelledby={`${id}-calendar-label ${id}-input-label`}
190
+ >
191
+ <VisuallyHidden id={`${id}-calendar-label`}>
192
+ Select dates from calendar for:
193
+ </VisuallyHidden>
182
194
  <LegacyCalendarRange
183
195
  selectedRange={selectedDateRange}
184
196
  defaultMonth={defaultMonth}
@@ -1,4 +1,4 @@
1
- import { Canvas, Controls, Meta } from "@storybook/blocks"
1
+ import { Canvas, DocsStory, Controls, Meta } from "@storybook/blocks"
2
2
  import { ResourceLinks, KAIOInstallation } from "~storybook/components"
3
3
  import * as DateRangePickerStories from "./DateRangePicker.stories"
4
4
 
@@ -28,3 +28,7 @@ Date range picker form field.
28
28
  ## Responsive behaviour
29
29
 
30
30
  As both the `DatePicker` and `DateRangePicker` use the `CalendarPopover` component under the hood, they share the same responsive behaviour. You can read more on this [here](/docs/components-date-controls-datepicker--docs#responsive-behaviour).
31
+
32
+ <DocsStory of={DateRangePickerStories.AboveIfAvailable} />
33
+ <DocsStory of={DateRangePickerStories.LimitedViewportHeight} />
34
+ <DocsStory of={DateRangePickerStories.FullViewportHeight} />
@@ -1,6 +1,6 @@
1
1
  import React, { useEffect, useState } from "react"
2
2
  import { Meta, StoryObj } from "@storybook/react"
3
- import { fn } from "@storybook/test"
3
+ import { userEvent, within, expect, fn } from "@storybook/test"
4
4
  import { DateRange } from "react-day-picker"
5
5
  import { DateRangePicker, formatDateRangeValue } from "../index"
6
6
 
@@ -20,8 +20,8 @@ type Story = StoryObj<typeof meta>
20
20
  const DateRangePickerTemplate: Story = {
21
21
  render: args => {
22
22
  const [selectedDateRange, setSelectedDateRange] = useState<DateRange>({
23
- from: undefined,
24
- to: undefined,
23
+ from: args?.selectedDateRange?.from,
24
+ to: args?.selectedDateRange?.to,
25
25
  })
26
26
  const [value, setValue] = useState(args.value)
27
27
 
@@ -58,3 +58,99 @@ export const Playground: Story = {
58
58
  },
59
59
  },
60
60
  }
61
+
62
+ const selectedDateRange = {
63
+ from: new Date(2022, 2, 6),
64
+ to: new Date(2022, 2, 15),
65
+ }
66
+
67
+ export const AboveIfAvailable: Story = {
68
+ ...DateRangePickerTemplate,
69
+ name: "Limited viewport autoplacement above",
70
+ args: {
71
+ labelText: "Calendar with space above",
72
+ selectedDateRange,
73
+ },
74
+ parameters: {
75
+ viewport: {
76
+ viewports: {
77
+ LimitedViewportAutoPlace: {
78
+ name: "Limited vertical space",
79
+ styles: {
80
+ width: "1024px",
81
+ height: "500px",
82
+ },
83
+ },
84
+ },
85
+ defaultViewport: "LimitedViewportAutoPlace",
86
+ },
87
+ },
88
+ decorators: [
89
+ Story => (
90
+ <div className="mt-[350px]">
91
+ <Story />
92
+ </div>
93
+ ),
94
+ ],
95
+ play: async ({ canvasElement }) => {
96
+ const canvas = within(canvasElement)
97
+ await userEvent.click(canvas.getByRole("button", { name: /Change date:/ }))
98
+ await expect(canvas.getByRole("dialog")).toBeInTheDocument()
99
+ },
100
+ }
101
+
102
+ export const LimitedViewportHeight: Story = {
103
+ ...DateRangePickerTemplate,
104
+ name: "Limited viewport height",
105
+ args: {
106
+ labelText: "Calendar with reduced space below",
107
+ selectedDateRange,
108
+ },
109
+ parameters: {
110
+ viewport: {
111
+ viewports: {
112
+ LimitedViewportHeight: {
113
+ name: "Limited vertical space",
114
+ styles: {
115
+ width: "1024px",
116
+ height: "300px",
117
+ },
118
+ },
119
+ },
120
+ defaultViewport: "LimitedViewportHeight",
121
+ },
122
+ },
123
+ decorators: [
124
+ Story => (
125
+ <div className="mb-[150px]">
126
+ <Story />
127
+ </div>
128
+ ),
129
+ ],
130
+ play: async ({ canvasElement }) => {
131
+ const canvas = within(canvasElement)
132
+ await userEvent.click(canvas.getByRole("button", { name: /Change date:/ }))
133
+ await expect(canvas.getByRole("dialog")).toBeInTheDocument()
134
+ },
135
+ }
136
+
137
+ export const FullViewportHeight: Story = {
138
+ ...DateRangePickerTemplate,
139
+ name: "Full viewport height",
140
+ args: {
141
+ labelText: "Calendar with full space below",
142
+ selectedDateRange,
143
+ },
144
+ decorators: [
145
+ Story => (
146
+ <div className="mb-[350px]">
147
+ <Story />
148
+ </div>
149
+ ),
150
+ ],
151
+ play: async ({ canvasElement }) => {
152
+ const canvas = within(canvasElement)
153
+ await userEvent.click(canvas.getByRole("button", { name: /Change date:/ }))
154
+ await expect(canvas.getByRole("dialog")).toBeInTheDocument()
155
+ },
156
+ }
@@ -84,10 +84,7 @@ export const EmptyState = ({
84
84
  classNameOverride={styles.illustration}
85
85
  />
86
86
  ) : (
87
- <IllustrationComponent
88
- alt={illustrationType}
89
- classNameOverride={styles.illustration}
90
- />
87
+ <IllustrationComponent classNameOverride={styles.illustration} />
91
88
  )}
92
89
  </div>
93
90
  <div className={styles.textSide}>
@@ -25,21 +25,11 @@ const FieldGroupTemplate = ({
25
25
  <div>
26
26
  <FieldGroup inline={inline} classNameOverride="mr-6">
27
27
  <Label htmlFor={`id--field-${id}`}>Email</Label>
28
- <input
29
- className="border border-gray-500"
30
- placeholder="Native text input..."
31
- type="text"
32
- id="id--field-2"
33
- />
28
+ <input className="border border-gray-500" type="text" id="id--field-2" />
34
29
  </FieldGroup>
35
30
  <FieldGroup inline={inline}>
36
31
  <Label htmlFor={`id--field-${id}`}>Username</Label>
37
- <input
38
- className="border border-gray-500"
39
- placeholder="Native text input..."
40
- type="text"
41
- id="id--field-2"
42
- />
32
+ <input className="border border-gray-500" type="text" id="id--field-2" />
43
33
  </FieldGroup>
44
34
  </div>
45
35
  )
@@ -12,7 +12,6 @@ const meta = {
12
12
  <Label htmlFor="id--field-1">Email</Label>
13
13
  <input
14
14
  className="ms-6 border border-gray-500"
15
- placeholder="Native text input..."
16
15
  type="text"
17
16
  id="id--field-1"
18
17
  />
@@ -42,16 +41,14 @@ export const Inline: Story = {
42
41
  <Label htmlFor="id--field-1">Email</Label>
43
42
  <input
44
43
  className="ms-6 border border-gray-500"
45
- placeholder="Native text input..."
46
44
  type="text"
47
- id="id--field-2"
45
+ id="id--field-1"
48
46
  />
49
47
  </FieldGroup>
50
48
  <FieldGroup inline>
51
- <Label htmlFor="id--field-1">Username</Label>
49
+ <Label htmlFor="id--field-2">Username</Label>
52
50
  <input
53
51
  className="ms-6 border border-gray-500"
54
- placeholder="Native text input..."
55
52
  type="text"
56
53
  id="id--field-2"
57
54
  />
@@ -67,16 +64,14 @@ export const Default: Story = {
67
64
  <Label htmlFor="id--field-1">Email</Label>
68
65
  <input
69
66
  className="ms-6 border border-gray-500"
70
- placeholder="Native text input..."
71
67
  type="text"
72
- id="id--field-2"
68
+ id="id--field-1"
73
69
  />
74
70
  </FieldGroup>
75
71
  <FieldGroup>
76
- <Label htmlFor="id--field-1">Username</Label>
72
+ <Label htmlFor="id--field-2">Username</Label>
77
73
  <input
78
74
  className="ms-6 border border-gray-500"
79
- placeholder="Native text input..."
80
75
  type="text"
81
76
  id="id--field-2"
82
77
  />
@@ -14,6 +14,11 @@ export type InputProps = {
14
14
  endIconAdornment?: React.ReactNode
15
15
  reversed?: boolean
16
16
  type?: InputType
17
+ /**
18
+ * @deprecated Use of placeholder text goes against our a11y standards.
19
+ * Use the `labelText` prop to provide a concise name, and the `description` prop for any help text.
20
+ */
21
+ placeholder?: string
17
22
  } & OverrideClassName<InputHTMLAttributes<HTMLInputElement>>
18
23
 
19
24
  export const Input = ({
@@ -12,10 +12,12 @@ const defaultInputProps = {
12
12
  onChange: jest.fn(),
13
13
  }
14
14
 
15
- const renderInput = (props?: InputSearchProps): ReturnType<typeof render> => {
15
+ const renderInput = (
16
+ props?: Omit<InputSearchProps, "id">
17
+ ): ReturnType<typeof render> => {
16
18
  const mergedInputProps = { ...defaultInputProps, ...props }
17
19
 
18
- return render(<InputSearch {...mergedInputProps} />)
20
+ return render(<InputSearch {...mergedInputProps} data-testid="someInputId" />)
19
21
  }
20
22
 
21
23
  describe("<InputSearch />", () => {
@@ -28,9 +30,10 @@ describe("<InputSearch />", () => {
28
30
  })
29
31
 
30
32
  it("should call the `onChange` event when text value is updated", async () => {
31
- const placeholder = "someInputPlaceholder"
32
- const utils = renderInput({ value: "", placeholder, id: "someInputId" })
33
- const input = utils.getByPlaceholderText(placeholder)
33
+ const utils = renderInput({
34
+ value: "",
35
+ })
36
+ const input = utils.getByTestId("someInputId")
34
37
 
35
38
  await user.type(input, "Hello")
36
39
  await waitFor(() => {
@@ -39,12 +42,12 @@ describe("<InputSearch />", () => {
39
42
  })
40
43
 
41
44
  it("should render a disabled inside of input", () => {
42
- const { container } = renderInput({ disabled: true, id: "someInputId" })
45
+ const { container } = renderInput({ disabled: true })
43
46
  expect(container.querySelector("[disabled]")).toBeTruthy()
44
47
  })
45
48
 
46
49
  it("should render a reversed input", () => {
47
- const { container } = renderInput({ reversed: true, id: "someInputId" })
50
+ const { container } = renderInput({ reversed: true })
48
51
  expect(container.querySelector(".reversed")).toBeTruthy()
49
52
  })
50
53
  })
@@ -12,7 +12,7 @@
12
12
  right: $spacing-md;
13
13
  top: 0;
14
14
  bottom: 0;
15
- z-index: 1030;
15
+ z-index: 1100;
16
16
  max-width: 100%;
17
17
  pointer-events: none;
18
18
 
@@ -2,25 +2,43 @@
2
2
  @import "~@kaizen/design-tokens/sass/border";
3
3
  @import "~@kaizen/design-tokens/sass/color";
4
4
  @import "~@kaizen/design-tokens/sass/spacing";
5
+ @import "~@kaizen/design-tokens/sass/typography";
6
+
7
+ .editorLabel {
8
+ margin-bottom: $spacing-6;
9
+ display: inline-block;
10
+ }
5
11
 
6
12
  .editableContainer :global(.ProseMirror) {
7
- padding: $spacing-sm;
13
+ padding: calc($spacing-12 - $border-solid-border-width);
8
14
  position: relative;
9
15
  border-radius: $border-solid-border-radius;
10
- border: $border-focus-ring-border-width $border-focus-ring-border-style
11
- transparent;
16
+ border: $border-solid-border-width $border-solid-border-style $color-gray-500;
12
17
  transition:
13
18
  background-color $animation-duration-immediate,
14
19
  border-color $animation-duration-immediate;
15
- background-color: $color-gray-200;
20
+ background-color: $color-white;
21
+ min-height: $typography-paragraph-body-line-height;
16
22
  }
17
23
 
18
24
  .editableContainer:hover :global(.ProseMirror) {
19
25
  background-color: $color-gray-200;
20
- border-color: $color-blue-500;
21
26
  }
22
27
 
23
28
  .editableContainer .hiddenButton:focus-within + * > :global(.ProseMirror) {
24
- border: $border-focus-ring-border-width $border-focus-ring-border-style
25
- $color-blue-500;
29
+ background-color: $color-gray-200;
30
+
31
+ &::before {
32
+ $focus-ring-offset: calc((#{$border-focus-ring-border-width} * 2) + 1px);
33
+
34
+ pointer-events: none;
35
+ content: "";
36
+ position: absolute;
37
+ background: transparent;
38
+ border: $border-focus-ring-border-width $border-focus-ring-border-style
39
+ $color-blue-500;
40
+ border-radius: 10px;
41
+ inset: calc(-1 * #{$focus-ring-offset});
42
+ z-index: 1;
43
+ }
26
44
  }
@@ -37,7 +37,9 @@ export const EditableRichTextContent = ({
37
37
  ...restProps
38
38
  }: EditableRichTextContentProps): JSX.Element => (
39
39
  <>
40
- {!isLabelHidden && <Label labelText={labelText} />}
40
+ {!isLabelHidden && (
41
+ <Label classNameOverride={styles.editorLabel} labelText={labelText} />
42
+ )}
41
43
  {/* Disabling these a11y linting errors because there is a <button> that mitigates these concerns. The onClick here is just an additional layer. */}
42
44
  {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */}
43
45
  <div
@@ -1,5 +1,5 @@
1
1
  import { Canvas, Controls, Meta } from "@storybook/blocks"
2
- import { ResourceLinks, KAIOInstallation, LinkTo } from "~storybook/components"
2
+ import { ResourceLinks, KAIOInstallation } from "~storybook/components"
3
3
  import * as EditableRichTextContentStories from "./EditableRichTextContent.stories"
4
4
 
5
5
  <Meta of={EditableRichTextContentStories} />
@@ -15,15 +15,17 @@ import * as EditableRichTextContentStories from "./EditableRichTextContent.stori
15
15
 
16
16
  ## Overview
17
17
 
18
- To render the contents of your <LinkTo pageId="components-richtexteditor">RichTextEditor</LinkTo> using the same structure for both components.
18
+ To render the contents of your [RichTextEditor](/docs/components-richtexteditor-richtexteditor--docs) using the same structure for both components.
19
19
 
20
20
  <Canvas of={EditableRichTextContentStories.Playground} />
21
21
  <Controls of={EditableRichTextContentStories.Playground} />
22
22
 
23
23
  ## Usage
24
24
 
25
- The general idea is to use this component in combination with the <LinkTo pageId="components-richtexteditor">RichTextEditor</LinkTo> to toggle between a read only state
26
- and an editable state.
25
+ The `EditableRichTextContent` indicates interactivity similar to a `text` or `textarea` input and should be used in combination with the [RichTextEditor](/docs/components-richtexteditor-richtexteditor--docs) to toggle between inactive and editable states.
26
+
27
+ This differs from the [RichTextContent](/docs/components-richtexteditor-richtextcontent--docs) component, which is used to render `RichTextEditor` content as read-only text.
28
+
27
29
 
28
30
  ```tsx
29
31
  const [editMode, setEditMode] = useState<boolean>(false);
@@ -0,0 +1,98 @@
1
+ import React from "react"
2
+ import { action } from "@storybook/addon-actions"
3
+ import { Meta } from "@storybook/react"
4
+ import {
5
+ StickerSheet,
6
+ StickerSheetStory,
7
+ } from "~storybook/components/StickerSheet"
8
+ import { EditableRichTextContent } from "../index"
9
+ import defaultContent from "./defaultContent.json"
10
+
11
+ const meta = {
12
+ title: "Components/RichTextEditor/EditableRichTextContent",
13
+ component: EditableRichTextContent,
14
+ } satisfies Meta<typeof EditableRichTextContent>
15
+
16
+ export default meta
17
+
18
+ const StickerSheetTemplate: StickerSheetStory = {
19
+ render: () => (
20
+ <div>
21
+ <StickerSheet className="" heading="Pseudo states">
22
+ <StickerSheet.Body>
23
+ <StickerSheet.Row rowTitle="Default">
24
+ <StickerSheet.Cell className=" w-1/2">
25
+ <EditableRichTextContent
26
+ onClick={action("Toggle RTE")}
27
+ content={[]}
28
+ labelText="Label"
29
+ />
30
+ </StickerSheet.Cell>
31
+ <StickerSheet.Cell className=" w-1/2">
32
+ <EditableRichTextContent
33
+ onClick={action("Toggle RTE")}
34
+ content={defaultContent}
35
+ labelText="Label"
36
+ />
37
+ </StickerSheet.Cell>
38
+ </StickerSheet.Row>
39
+ <StickerSheet.Row rowTitle="Hover">
40
+ <StickerSheet.Cell className=" w-1/2">
41
+ <EditableRichTextContent
42
+ onClick={action("Toggle RTE")}
43
+ data-sb-pseudo-styles="hover"
44
+ content={[]}
45
+ labelText="Label"
46
+ />
47
+ </StickerSheet.Cell>
48
+ <StickerSheet.Cell className=" w-1/2">
49
+ <EditableRichTextContent
50
+ onClick={action("Toggle RTE")}
51
+ data-sb-pseudo-styles="hover"
52
+ content={defaultContent}
53
+ labelText="Label"
54
+ />
55
+ </StickerSheet.Cell>
56
+ </StickerSheet.Row>
57
+ <StickerSheet.Row rowTitle="Focus">
58
+ <StickerSheet.Cell className=" w-1/2">
59
+ <EditableRichTextContent
60
+ onClick={action("Toggle RTE")}
61
+ data-sb-pseudo-styles="focusWithin"
62
+ content={[]}
63
+ labelText="Label"
64
+ />
65
+ </StickerSheet.Cell>
66
+ <StickerSheet.Cell className=" w-1/2">
67
+ <EditableRichTextContent
68
+ onClick={action("Toggle RTE")}
69
+ data-sb-pseudo-styles="focusWithin"
70
+ content={defaultContent}
71
+ labelText="Label"
72
+ />
73
+ </StickerSheet.Cell>
74
+ </StickerSheet.Row>
75
+ </StickerSheet.Body>
76
+ </StickerSheet>
77
+ </div>
78
+ ),
79
+ parameters: {
80
+ pseudo: {
81
+ hover: ['[data-sb-pseudo-styles="hover"]'],
82
+ focusWithin: [
83
+ '[data-sb-pseudo-styles="focusWithin"] > [class^="VisuallyHidden"]',
84
+ ],
85
+ },
86
+ },
87
+ }
88
+
89
+ export const StickerSheetDefault: StickerSheetStory = {
90
+ ...StickerSheetTemplate,
91
+ name: "Sticker Sheet (Default)",
92
+ }
93
+
94
+ export const StickerSheetRTL: StickerSheetStory = {
95
+ ...StickerSheetTemplate,
96
+ name: "Sticker Sheet (RTL)",
97
+ parameters: { textDirection: "rtl" },
98
+ }
@@ -8,14 +8,14 @@ import {
8
8
  RichTextEditorProps,
9
9
  } from "../../index"
10
10
  import { EditableRichTextContent } from "../index"
11
- import dummyContent from "./dummyContent.json"
11
+ import defaultContent from "./defaultContent.json"
12
12
 
13
13
  const meta = {
14
14
  title: "Components/RichTextEditor/EditableRichTextContent",
15
15
  component: EditableRichTextContent,
16
16
  args: {
17
- content: dummyContent,
18
- labelText: "Editable rich text content",
17
+ content: [],
18
+ labelText: "Label",
19
19
  onClick: fn(),
20
20
  },
21
21
  argTypes: {
@@ -32,7 +32,7 @@ const EditableRichTextContentTemplate: Story = {
32
32
  render: props => {
33
33
  const [editMode, setEditMode] = useState<boolean>(false)
34
34
  const [readRteData, setReadRTEData] = useState<EditorContentArray>(
35
- props.content || dummyContent
35
+ props.content
36
36
  )
37
37
  const [editRteData, setEditRTEData] = useState<EditorContentArray>([])
38
38
 
@@ -65,7 +65,7 @@ const EditableRichTextContentTemplate: Story = {
65
65
  defaultValue={editRteData}
66
66
  onChange={handleOnChange}
67
67
  />
68
- <div className="flex justify-end mt-8">
68
+ <div className="flex justify-end mt-12 gap-8">
69
69
  <Button label="Cancel" secondary onClick={handleCancel} />
70
70
  <Button label="Save" primary onClick={handleSave} />
71
71
  </div>
@@ -81,6 +81,9 @@ const EditableRichTextContentTemplate: Story = {
81
81
  />
82
82
  )
83
83
  },
84
+ args: {
85
+ content: defaultContent,
86
+ },
84
87
  }
85
88
 
86
89
  export const Playground: Story = {
@@ -0,0 +1,11 @@
1
+ [
2
+ {
3
+ "type": "paragraph",
4
+ "content": [
5
+ {
6
+ "type": "text",
7
+ "text": "User text goes here"
8
+ }
9
+ ]
10
+ }
11
+ ]