Skip to content

Commit 07c1e30

Browse files
katiegeorgeKatie George
andauthored
feat: Add SupportPromptGroup (#37)
* feat: Adds basic support prompt interface and styles * feat: Changes from single to group component * feat: Updates API and styles * feat: Adds id back and changes label to text * wip: adds single tab stop focus * wip: Single tab now working * chore: Adds tests * chore: Adds keyboard navigation tests and focus ref * chore: Adds additional test page * chore: Updates tests * chore: Updates snapshots * fix: Update snapshots * fix: Fixes tests and removes utils * chore: Update test data * chore: Update test page * fix: Small page fixes * chore: Removes unused utils * chore: Clean up tests * chore: Adds more test coverage * chore: Adds more test coverage * fix: Fixes import * chore: One more test * Uses component toolkit version of single tab stop * fix: PR comments and fixes * PR comments * fix: Removes unused import * fix: Removes extra argument * chore: Updates documenter --------- Co-authored-by: Katie George <katiegeo@amazon.com>
1 parent 62fec21 commit 07c1e30

File tree

23 files changed

+1309
-1
lines changed

23 files changed

+1309
-1
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"./avatar": "./avatar/index.js",
4343
"./chat-bubble": "./chat-bubble/index.js",
4444
"./loading-bar": "./loading-bar/index.js",
45+
"./support-prompt-group": "./support-prompt-group/index.js",
4546
"./test-utils/dom": "./test-utils/dom/index.js",
4647
"./test-utils/selectors": "./test-utils/selectors/index.js",
4748
"./internal/api-docs/*.js": "./internal/api-docs/*.js"
@@ -120,7 +121,7 @@
120121
],
121122
"*.{scss,css}": [
122123
"stylelint --fix"
123-
],
124+
],
124125
"package-lock.json": [
125126
"./scripts/prepare-package-lock.js"
126127
]
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
import { createRef, useState } from "react";
4+
5+
import Button from "@cloudscape-design/components/button";
6+
import Container from "@cloudscape-design/components/container";
7+
import Header from "@cloudscape-design/components/header";
8+
import PromptInput from "@cloudscape-design/components/prompt-input";
9+
import SpaceBetween from "@cloudscape-design/components/space-between";
10+
11+
import { ChatBubble, SupportPromptGroup } from "../../lib/components";
12+
import { TestBed } from "../app/test-bed";
13+
import { ChatBubbleAvatarGenAI, ChatBubbleAvatarUser } from "../chat-bubble/util-components";
14+
import { ScreenshotArea } from "../screenshot-area";
15+
16+
import styles from "./styles.module.scss";
17+
18+
export default function SupportPromptPage() {
19+
const [text, setText] = useState("");
20+
const [text2, setText2] = useState("");
21+
const [sentText, setSentText] = useState("");
22+
const ref = createRef<HTMLTextAreaElement>();
23+
24+
const items = [
25+
{
26+
text: "Create a really detailed and powerful image. The image should be of a mountain scene with a blue lake and green hills, with a sunset in the background. In the lake, there should be 3 whales leaping out of the water.",
27+
id: "image",
28+
},
29+
{
30+
text: "Help me brainstorm for an upcoming sign-off.",
31+
id: "brainstorm",
32+
},
33+
{
34+
text: "Summarize this long and complex PDF for me. Include a paragraph containing 3-4 sentences that capture the main ideas and overall message of the documents, a list of 5 to 10 key points from the document, and up to 3 follow-up questions that arise from the content of the document.",
35+
id: "summarize",
36+
},
37+
];
38+
39+
const items2 = [
40+
{
41+
text: "Create a really detailed and powerful image.",
42+
id: "image",
43+
},
44+
{
45+
text: "Help me brainstorm for an upcoming sign-off.",
46+
id: "brainstorm",
47+
},
48+
{
49+
text: "Summarize this long PDF for me.",
50+
id: "summarize",
51+
},
52+
];
53+
54+
return (
55+
<ScreenshotArea>
56+
<main className={styles.container}>
57+
<TestBed>
58+
<SpaceBetween size="xl">
59+
<Container
60+
header={
61+
<Header actions={<Button onClick={() => setText("")}>Reset</Button>}>Support prompt test: send</Header>
62+
}
63+
>
64+
<SpaceBetween direction="vertical" size="xxl">
65+
<div>
66+
<ChatBubble type="outgoing" avatar={<ChatBubbleAvatarUser />} ariaLabel="User at 4:23:20pm">
67+
What can I do with Amazon S3?
68+
</ChatBubble>
69+
<SpaceBetween direction="vertical" size="xs">
70+
<ChatBubble avatar={<ChatBubbleAvatarGenAI />} type="incoming" ariaLabel="Gen AI at at 4:23:23pm">
71+
Amazon S3 provides a simple web service interface that you can use to store and retrieve any
72+
amount of data, at any time, from anywhere.
73+
</ChatBubble>
74+
{text === "" && (
75+
<div className={styles["support-prompt-container"]}>
76+
<SupportPromptGroup
77+
ariaLabel="Test support prompt group 1"
78+
alignment="vertical"
79+
onItemClick={({ detail }) => {
80+
const activeItem = items.find((item) => item.id === detail.id);
81+
setText(activeItem?.text || "");
82+
console.log(detail);
83+
}}
84+
items={items}
85+
/>
86+
</div>
87+
)}
88+
</SpaceBetween>
89+
{text !== "" && (
90+
<ChatBubble type="outgoing" avatar={<ChatBubbleAvatarUser />} ariaLabel="User at 4:23:20pm">
91+
{text}
92+
</ChatBubble>
93+
)}
94+
</div>
95+
96+
<SpaceBetween direction="vertical" size="m">
97+
<PromptInput placeholder="Write a prompt" value="" actionButtonIconName="send" />
98+
</SpaceBetween>
99+
</SpaceBetween>
100+
</Container>
101+
<Container
102+
header={
103+
<Header actions={<Button onClick={() => setSentText("")}>Reset</Button>}>
104+
Support prompt test: draft
105+
</Header>
106+
}
107+
>
108+
<SpaceBetween direction="vertical" size="m">
109+
<div className={styles.placeholder} />
110+
{sentText !== "" && (
111+
<ChatBubble type="outgoing" avatar={<ChatBubbleAvatarUser />} ariaLabel="User at 4:23:20pm">
112+
{sentText}
113+
</ChatBubble>
114+
)}
115+
<SpaceBetween direction="vertical" size="m">
116+
{sentText === "" && (
117+
<SupportPromptGroup
118+
alignment="horizontal"
119+
ariaLabel="Test support prompt group 2"
120+
onItemClick={({ detail }) => {
121+
const activeItem = items2.find((item) => item.id === detail.id);
122+
setText2(activeItem?.text || "");
123+
ref.current?.focus();
124+
}}
125+
items={items2}
126+
/>
127+
)}
128+
129+
<PromptInput
130+
ref={ref}
131+
placeholder="Write a prompt"
132+
value={text2}
133+
actionButtonIconName="send"
134+
onAction={() => {
135+
setSentText(text2);
136+
setText2("");
137+
}}
138+
/>
139+
</SpaceBetween>
140+
</SpaceBetween>
141+
</Container>
142+
</SpaceBetween>
143+
</TestBed>
144+
</main>
145+
</ScreenshotArea>
146+
);
147+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { SupportPromptGroup } from "../../lib/components";
5+
import { TestBed } from "../app/test-bed";
6+
import { ScreenshotArea } from "../screenshot-area";
7+
8+
export default function SupportPromptPage() {
9+
return (
10+
<ScreenshotArea>
11+
<h1>Support prompt</h1>
12+
<main>
13+
<TestBed>
14+
<h2>horizontal group</h2>
15+
<SupportPromptGroup
16+
ariaLabel="Horizontal support prompt group"
17+
alignment="horizontal"
18+
onItemClick={({ detail }) => console.log(detail)}
19+
items={[
20+
{
21+
text: "Create image",
22+
id: "image",
23+
},
24+
{
25+
text: "Brainstorm",
26+
id: "brainstorm",
27+
},
28+
{
29+
text: "Summarize text",
30+
id: "summarize",
31+
},
32+
]}
33+
/>
34+
35+
<h2>vertical group</h2>
36+
<SupportPromptGroup
37+
ariaLabel="Vertical support prompt group"
38+
onItemClick={({ detail }) => console.log(detail)}
39+
items={[
40+
{
41+
text: "Create image",
42+
id: "image-2",
43+
},
44+
{
45+
text: "Brainstorm",
46+
id: "brainstorm-2",
47+
},
48+
{
49+
text: "Summarize text",
50+
id: "summarize-2",
51+
},
52+
]}
53+
/>
54+
55+
<h2>Horizontal group with really long text</h2>
56+
<SupportPromptGroup
57+
ariaLabel="Horizontal support prompt group"
58+
alignment="horizontal"
59+
onItemClick={({ detail }) => console.log(detail)}
60+
items={[
61+
{
62+
text: "Create a really detailed and powerful image. The image should be of a mountain scene with a blue lake and green hills, with a sunset in the background. In the lake, there should be 3 whales leaping out of the water.",
63+
id: "image",
64+
},
65+
{
66+
text: "Help me brainstorm for an upcoming sign-off.",
67+
id: "brainstorm",
68+
},
69+
{
70+
text: "Summarize this long and complex PDF for me. Include a paragraph containing 3-4 sentences that capture the main ideas and overall message of the documents, a list of 5 to 10 key points from the document, and up to 3 follow-up questions that arise from the content of the document.",
71+
id: "summarize",
72+
},
73+
{
74+
text: "What questions remain unanswered after reading the document(s)? The response shall consider all current or past uploaded documents.",
75+
id: "image-2",
76+
},
77+
]}
78+
/>
79+
80+
<h2>vertical group with really long text</h2>
81+
<SupportPromptGroup
82+
ariaLabel="Horizontal support prompt group"
83+
onItemClick={({ detail }) => console.log(detail)}
84+
items={[
85+
{
86+
text: "Create a really detailed and powerful image. The image should be of a mountain scene with a blue lake and green hills, with a sunset in the background. In the lake, there should be 3 whales leaping out of the water.",
87+
id: "image",
88+
},
89+
{
90+
text: "Help me brainstorm for an upcoming sign-off.",
91+
id: "brainstorm",
92+
},
93+
{
94+
text: "Summarize this long and complex PDF for me. Include a paragraph containing 3-4 sentences that capture the main ideas and overall message of the documents, a list of 5 to 10 key points from the document, and up to 3 follow-up questions that arise from the content of the document.",
95+
id: "summarize",
96+
},
97+
{
98+
text: "What questions remain unanswered after reading the document(s)? The response shall consider all current or past uploaded documents.",
99+
id: "image-2",
100+
},
101+
]}
102+
/>
103+
</TestBed>
104+
</main>
105+
</ScreenshotArea>
106+
);
107+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
.support-prompt-container {
7+
margin-inline-start: 36px;
8+
}
9+
10+
.container {
11+
max-width: 1000px;
12+
}
13+
14+
.placeholder {
15+
block-size: 150px;
16+
}

scripts/pluralize.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const pluralizationMap = {
44
Avatar: "Avatars",
55
ChatBubble: "ChatBubbles",
66
LoadingBar: "LoadingBars",
7+
SupportPromptGroup: "SupportPromptGroups",
78
};
89

910
function pluralizeComponentName(componentName) {

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

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,3 +183,100 @@ with rounded corners.",
183183
"releaseStatus": "stable",
184184
}
185185
`;
186+
187+
exports[`definition for support-prompt-group matches the snapshot > support-prompt-group 1`] = `
188+
{
189+
"events": [
190+
{
191+
"cancelable": false,
192+
"description": "Called when the user clicks on a support prompt. The event detail object contains the ID of the clicked item.",
193+
"detailInlineType": {
194+
"name": "SupportPromptGroupProps.ItemClickDetail",
195+
"properties": [
196+
{
197+
"name": "altKey",
198+
"optional": false,
199+
"type": "boolean",
200+
},
201+
{
202+
"name": "button",
203+
"optional": false,
204+
"type": "number",
205+
},
206+
{
207+
"name": "ctrlKey",
208+
"optional": false,
209+
"type": "boolean",
210+
},
211+
{
212+
"name": "id",
213+
"optional": false,
214+
"type": "string",
215+
},
216+
{
217+
"name": "metaKey",
218+
"optional": false,
219+
"type": "boolean",
220+
},
221+
{
222+
"name": "shiftKey",
223+
"optional": false,
224+
"type": "boolean",
225+
},
226+
],
227+
"type": "object",
228+
},
229+
"detailType": "SupportPromptGroupProps.ItemClickDetail",
230+
"name": "onItemClick",
231+
},
232+
],
233+
"functions": [
234+
{
235+
"description": "Focuses support prompt group item by ID.",
236+
"name": "focus",
237+
"parameters": [
238+
{
239+
"name": "itemId",
240+
"type": "string",
241+
},
242+
],
243+
"returnType": "void",
244+
},
245+
],
246+
"name": "SupportPromptGroup",
247+
"properties": [
248+
{
249+
"description": "Alignment of the prompts. Defaults to \`vertical\`.",
250+
"inlineType": {
251+
"name": "SupportPromptGroupProps.Alignment",
252+
"type": "union",
253+
"values": [
254+
"vertical",
255+
"horizontal",
256+
],
257+
},
258+
"name": "alignment",
259+
"optional": true,
260+
"type": "string",
261+
},
262+
{
263+
"description": "Adds an aria label to the support prompt group.
264+
Use this to provide a unique accessible name for each support prompt group on the page.",
265+
"name": "ariaLabel",
266+
"optional": false,
267+
"type": "string",
268+
},
269+
{
270+
"description": "An array of objects representing support prompts.
271+
Each item has the following properties:
272+
- text: The text of the support prompt.
273+
- id: The ID of the support prompt.",
274+
"name": "items",
275+
"optional": false,
276+
"type": "ReadonlyArray<SupportPromptGroupProps.Item>",
277+
},
278+
],
279+
"regions": [],
280+
"releaseStatus": "stable",
281+
}
282+
`;

0 commit comments

Comments
 (0)