Skip to content

Commit fdfe10a

Browse files
authored
feat: Allow arbitrary content in support prompt item content (#114)
* feat: Allow arbitrary content in support prompt item content * feat: add content slot instead of changing text prop type * fix: reset button in dev page * refactor: remove content slot again in favor for text type change in support prompt * chore: update snapshots * refactor: Remove unused css class (dimmed-text)
1 parent ec1bfdd commit fdfe10a

File tree

6 files changed

+140
-8
lines changed

6 files changed

+140
-8
lines changed

pages/support-prompt-group/in-context.page.tsx

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33
import { createRef, useState } from "react";
44

5+
import Badge from "@cloudscape-design/components/badge";
56
import Button from "@cloudscape-design/components/button";
67
import Container from "@cloudscape-design/components/container";
78
import Header from "@cloudscape-design/components/header";
@@ -18,7 +19,9 @@ import styles from "./styles.module.scss";
1819
export default function SupportPromptPage() {
1920
const [text, setText] = useState("");
2021
const [text2, setText2] = useState("");
22+
const [text3, setText3] = useState("");
2123
const [sentText, setSentText] = useState("");
24+
const [sentText2, setSentText2] = useState("");
2225
const ref = createRef<HTMLTextAreaElement>();
2326

2427
const items: Array<SupportPromptGroupProps.Item> = [
@@ -56,6 +59,47 @@ export default function SupportPromptPage() {
5659
ariaLabel: "Summarize this long PDF for me. (edit before submit)",
5760
},
5861
];
62+
const items3PlainText: Record<string, string> = {
63+
image: "Create a really detailed and powerful image.",
64+
brainstorm: "Help me brainstorm for an upcoming sign-off.",
65+
summarize: "Summarize this long PDF for me.",
66+
};
67+
68+
const items3: Array<SupportPromptGroupProps.Item> = [
69+
{
70+
text: (
71+
<SpaceBetween direction="vertical" size="xs">
72+
<b>Create a really detailed and powerful image</b>
73+
<Badge>Generate Image</Badge>
74+
</SpaceBetween>
75+
),
76+
id: "image",
77+
iconName: "edit",
78+
ariaLabel: "Create a really detailed and powerful image. (edit before submit)",
79+
},
80+
{
81+
text: (
82+
<SpaceBetween direction="vertical" size="xs">
83+
<b>Help me brainstorm for an upcoming sign-off</b>
84+
<Badge>Brainstorm</Badge>
85+
</SpaceBetween>
86+
),
87+
id: "brainstorm",
88+
iconName: "edit",
89+
ariaLabel: "Help me brainstorm for an upcoming sign-off. (edit before submit)",
90+
},
91+
{
92+
text: (
93+
<SpaceBetween direction="vertical" size="xs">
94+
<b>Summarize this long PDF for me</b>
95+
<Badge>Summarize</Badge>
96+
</SpaceBetween>
97+
),
98+
id: "summarize",
99+
iconName: "edit",
100+
ariaLabel: "Summarize this long PDF for me. (edit before submit)",
101+
},
102+
];
59103

60104
return (
61105
<Page title="Support prompt group">
@@ -84,8 +128,7 @@ export default function SupportPromptPage() {
84128
alignment="vertical"
85129
onItemClick={({ detail }) => {
86130
const activeItem = items.find((item) => item.id === detail.id);
87-
setText(activeItem?.text || "");
88-
console.log(detail);
131+
setText((activeItem?.text as string) || "");
89132
}}
90133
items={items}
91134
/>
@@ -125,7 +168,7 @@ export default function SupportPromptPage() {
125168
ariaLabel="Test support prompt group 2"
126169
onItemClick={({ detail }) => {
127170
const activeItem = items2.find((item) => item.id === detail.id);
128-
setText2(activeItem?.text || "");
171+
setText2((activeItem?.text as string) || "");
129172
ref.current?.focus();
130173
}}
131174
items={items2}
@@ -145,6 +188,46 @@ export default function SupportPromptPage() {
145188
</SpaceBetween>
146189
</SpaceBetween>
147190
</Container>
191+
<Container
192+
header={
193+
<Header actions={<Button onClick={() => setSentText2("")}>Reset</Button>}>
194+
Support prompt test: react slot
195+
</Header>
196+
}
197+
>
198+
<SpaceBetween direction="vertical" size="m">
199+
<div className={styles.placeholder} />
200+
{sentText2 !== "" && (
201+
<ChatBubble type="outgoing" avatar={<ChatBubbleAvatarUser />} ariaLabel="User at 4:23:20pm">
202+
{sentText2}
203+
</ChatBubble>
204+
)}
205+
<SpaceBetween direction="vertical" size="m">
206+
{sentText2 === "" && (
207+
<SupportPromptGroup
208+
alignment="horizontal"
209+
ariaLabel="Test support prompt group 2"
210+
onItemClick={({ detail }) => {
211+
setText3(items3PlainText[detail.id] || "");
212+
ref.current?.focus();
213+
}}
214+
items={items3}
215+
/>
216+
)}
217+
218+
<PromptInput
219+
ref={ref}
220+
placeholder="Write a prompt"
221+
value={text3}
222+
actionButtonIconName="send"
223+
onAction={() => {
224+
setSentText2(text3);
225+
setText3("");
226+
}}
227+
/>
228+
</SpaceBetween>
229+
</SpaceBetween>
230+
</Container>
148231
</SpaceBetween>
149232
</TestBed>
150233
</main>

pages/support-prompt-group/simple.page.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,38 @@ export default function SupportPromptPage() {
257257
},
258258
]}
259259
/>
260+
<h2>horizontal group with ReactNode content</h2>
261+
<SupportPromptGroup
262+
ariaLabel="Support prompt group with ReactNode content"
263+
alignment="horizontal"
264+
onItemClick={({ detail }) => console.log(detail)}
265+
items={[
266+
{
267+
text: (
268+
<div>
269+
<strong>Create image</strong> - Generate a visual
270+
</div>
271+
),
272+
id: "react-image",
273+
},
274+
{
275+
text: (
276+
<div>
277+
<strong>Brainstorm</strong> - Get creative ideas
278+
</div>
279+
),
280+
id: "react-brainstorm",
281+
},
282+
{
283+
text: (
284+
<div>
285+
<strong>Summarize</strong> - Condense text
286+
</div>
287+
),
288+
id: "react-summarize",
289+
},
290+
]}
291+
/>
260292
</TestBed>
261293
</main>
262294
</Page>

src/__tests__/__snapshots__/documenter.test.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ Use this to provide a unique accessible name for each support prompt group on th
476476
{
477477
"description": "An array of objects representing support prompts.
478478
Each item has the following properties:
479-
- text: The text of the support prompt.
479+
- text: The text or ReactNode content of the support prompt.
480480
- id: The ID of the support prompt.
481481
- iconName (optional): The name of a built-in icon to display.
482482
- iconSvg (optional): A custom SVG icon to display. Takes precedence over iconName.

src/support-prompt-group/__tests__/support-prompt-group.test.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,21 @@ describe("Support prompt group", () => {
128128
expect(warnOnce).toHaveBeenCalledWith("SupportPromptGroup", `No matching ID found to focus.`);
129129
});
130130
});
131+
132+
test("renders ReactNode content with div element", () => {
133+
const wrapper = renderSupportPromptGroup({
134+
items: [
135+
{
136+
text: <div data-testid="custom-div">Custom content</div>,
137+
id: "jsx-item",
138+
},
139+
],
140+
});
141+
142+
const item = wrapper.findItemById("jsx-item")!.getElement();
143+
expect(item.querySelector('[data-testid="custom-div"]')).toHaveTextContent("Custom content");
144+
});
145+
131146
describe("Keyboard navigation", () => {
132147
const ref: { current: SupportPromptGroupProps.Ref | null } = { current: null };
133148
const { KeyCode } = ComponentToolkitInternal;

src/support-prompt-group/interfaces.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
import { ReactNode } from "react";
5+
46
import { IconProps } from "@cloudscape-design/components/icon";
57

68
import { ClickDetail as _ClickDetail, NonCancelableEventHandler } from "../internal/events";
@@ -14,7 +16,7 @@ export interface SupportPromptGroupProps {
1416
/**
1517
* An array of objects representing support prompts.
1618
* Each item has the following properties:
17-
* - text: The text of the support prompt.
19+
* - text: The text or ReactNode content of the support prompt.
1820
* - id: The ID of the support prompt.
1921
* - iconName (optional): The name of a built-in icon to display.
2022
* - iconSvg (optional): A custom SVG icon to display. Takes precedence over iconName.
@@ -40,7 +42,7 @@ export namespace SupportPromptGroupProps {
4042
export type Alignment = "vertical" | "horizontal";
4143

4244
export interface Item {
43-
text: string;
45+
text: ReactNode;
4446
id: string;
4547
iconName?: IconProps.Name;
4648
iconSvg?: React.ReactNode;

src/support-prompt-group/prompt.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
3-
import { forwardRef, Ref, useRef } from "react";
3+
import { forwardRef, ReactNode, Ref, useRef } from "react";
44
import clsx from "clsx";
55

66
import { useSingleTabStopNavigation } from "@cloudscape-design/component-toolkit/internal";
@@ -11,7 +11,7 @@ import useForwardFocus from "../internal/utils/use-forward-focus";
1111
import styles from "./styles.css.js";
1212

1313
export interface PromptProps {
14-
children: string;
14+
children: ReactNode;
1515
id: string;
1616
onClick: (event: React.MouseEvent, id: string) => void;
1717
iconName?: IconProps.Name;

0 commit comments

Comments
 (0)