Skip to content

feat: add components to ChatComposer #3964

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 81 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
83f6275
chore(chat-composer): add fontSize and lineHeight to props
krisantrobus Jun 18, 2024
3ddda45
feat(composer): wip base elements
krisantrobus Jun 20, 2024
9fe61d0
feat(composer): addition of all attatchment components
krisantrobus Jun 20, 2024
b482492
feat(composer): lint fix
krisantrobus Jun 20, 2024
2b244c5
Merge branch 'main' of github.com:twilio-labs/paste into chore/chat-c…
krisantrobus Jun 20, 2024
48e1f47
feat(composer): fix disabled styling
krisantrobus Jun 21, 2024
3abd117
feat(composer): customization stories
krisantrobus Jun 21, 2024
ea302d0
feat(composer): testing
krisantrobus Jun 21, 2024
6e47e71
feat(composer): import cleanup
krisantrobus Jun 24, 2024
9ff59ce
feat(composer): build changes
krisantrobus Jun 25, 2024
8bcfc2a
feat(composer): responsive columns and JS doc
krisantrobus Jun 25, 2024
583d758
feat(anchor): border radius
krisantrobus Jun 25, 2024
3993a04
feat(composer): changesets
krisantrobus Jun 25, 2024
a16718c
chore(composer): update typedocs
krisantrobus Jun 25, 2024
eb46fc4
chore(composer): fix lint
krisantrobus Jun 25, 2024
1f8de1a
chore(composer): missing codemod
krisantrobus Jun 25, 2024
cccafd4
feat(composer): add new plugin to access state
krisantrobus Jun 28, 2024
5caf933
feat(composer): fix lint issues
krisantrobus Jun 28, 2024
fec0c84
chore(chat-composer): fix spellings
krisantrobus Jul 1, 2024
15f7020
chore(chat-composer): styling updates from PR comments
krisantrobus Jul 1, 2024
8bfa07e
Merge branch 'main' of github.com:twilio-labs/paste into chore/chat-c…
krisantrobus Jul 1, 2024
b87b86d
chore(chat-composer): udpate typedocs
krisantrobus Jul 2, 2024
019f6d5
chore(lexical-library): added changeset for export
krisantrobus Jul 2, 2024
6bdf523
chore(lexical-library): update changeset
krisantrobus Jul 2, 2024
6dc1f8f
chore(chat-composer): naming updates
krisantrobus Jul 8, 2024
8390eb8
chore(chat-composer): chnage stlying types
krisantrobus Jul 8, 2024
ad6c2b7
chore(ai-chatl-log): added changeset
krisantrobus Jul 8, 2024
d0d5b67
chore(ai-chatl-log): updated changeset
krisantrobus Jul 9, 2024
a0636ef
chore(chat-composer): pr cleanup
krisantrobus Jul 9, 2024
5eea7a2
chore(chat-composer): refactor ChatCompaserAttachment
krisantrobus Jul 10, 2024
54d6687
chore(chat-composer): add fontSize and lineHeight to props
krisantrobus Jun 18, 2024
202b839
feat(composer): wip base elements
krisantrobus Jun 20, 2024
d043493
feat(composer): addition of all attatchment components
krisantrobus Jun 20, 2024
bfc94a2
feat(composer): lint fix
krisantrobus Jun 20, 2024
e56b225
feat(composer): fix disabled styling
krisantrobus Jun 21, 2024
7523621
feat(composer): customization stories
krisantrobus Jun 21, 2024
8df066b
feat(composer): testing
krisantrobus Jun 21, 2024
3b5e92d
feat(composer): import cleanup
krisantrobus Jun 24, 2024
a22dda5
feat(composer): build changes
krisantrobus Jun 25, 2024
535dec8
feat(composer): responsive columns and JS doc
krisantrobus Jun 25, 2024
dc003a4
feat(anchor): border radius
krisantrobus Jun 25, 2024
c0e275c
feat(composer): changesets
krisantrobus Jun 25, 2024
dff1e1f
chore(composer): update typedocs
krisantrobus Jun 25, 2024
d9d73ec
chore(composer): fix lint
krisantrobus Jun 25, 2024
587d4f2
chore(composer): missing codemod
krisantrobus Jun 25, 2024
eec0ec1
feat(composer): add new plugin to access state
krisantrobus Jun 28, 2024
0e30560
feat(composer): fix lint issues
krisantrobus Jun 28, 2024
80f3976
chore(chat-composer): fix spellings
krisantrobus Jul 1, 2024
0f2a179
chore(chat-composer): styling updates from PR comments
krisantrobus Jul 1, 2024
7fe1db9
chore(chat-composer): udpate typedocs
krisantrobus Jul 2, 2024
b63e78a
chore(lexical-library): added changeset for export
krisantrobus Jul 2, 2024
425b802
chore(lexical-library): update changeset
krisantrobus Jul 2, 2024
e722acf
chore(chat-composer): naming updates
krisantrobus Jul 8, 2024
e84f02a
chore(chat-composer): chnage stlying types
krisantrobus Jul 8, 2024
9ef9f03
chore(ai-chatl-log): added changeset
krisantrobus Jul 8, 2024
3405cb6
chore(ai-chatl-log): updated changeset
krisantrobus Jul 9, 2024
8253df1
chore(chat-composer): pr cleanup
krisantrobus Jul 9, 2024
018849a
chore(chat-composer): refactor ChatCompaserAttachment
krisantrobus Jul 10, 2024
c975bc6
chore(chat-composer): rename editorRef in stories
krisantrobus Jul 10, 2024
c46e9a9
Merge branch 'chore/chat-composer-contained' of github.com:twilio-lab…
krisantrobus Jul 10, 2024
97a1759
chore(chat-composer): change CSS grid so rowGap conditionally applied…
krisantrobus Jul 10, 2024
283362d
chore(chat-composer): add fontSize and lineHeight to props
krisantrobus Jun 18, 2024
096614b
feat(composer): wip base elements
krisantrobus Jun 20, 2024
6b270db
feat(composer): addition of all attatchment components
krisantrobus Jun 20, 2024
1581013
feat(composer): lint fix
krisantrobus Jun 20, 2024
51dbff4
feat(composer): fix disabled styling
krisantrobus Jun 21, 2024
d17b508
feat(composer): responsive columns and JS doc
krisantrobus Jun 25, 2024
e305b2d
feat(composer): add new plugin to access state
krisantrobus Jun 28, 2024
9fa1d7f
feat(composer): fix lint issues
krisantrobus Jun 28, 2024
f6dc5a1
chore(chat-composer): fix spellings
krisantrobus Jul 1, 2024
4769dae
chore(chat-composer): styling updates from PR comments
krisantrobus Jul 1, 2024
fe959e3
chore(chat-composer): chnage stlying types
krisantrobus Jul 8, 2024
4d8cde5
chore(chat-composer): pr cleanup
krisantrobus Jul 9, 2024
330e644
chore(chat-composer): refactor ChatCompaserAttachment
krisantrobus Jul 10, 2024
d03b038
chore(chat-composer): change CSS grid so rowGap conditionally applied…
krisantrobus Jul 10, 2024
2779501
chore(chat-composer): changeset update
krisantrobus Jul 10, 2024
ef8b92e
Merge branch 'chore/chat-composer-contained' of github.com:twilio-lab…
krisantrobus Jul 10, 2024
8acef8f
chore(chat-composer): codemods& lint
krisantrobus Jul 10, 2024
a1a20ab
chore(lexical): changeset
krisantrobus Jul 10, 2024
e5c74fe
chore(chat-composer): flex attachments group to full width
krisantrobus Jul 10, 2024
d197b63
Merge branch 'main' into chore/chat-composer-contained
kodiakhq[bot] Jul 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fair-beds-exist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@twilio-paste/codemods": minor
---

[ChatComposer] Added new components to allow contained variants, actions buttons and attachments
6 changes: 6 additions & 0 deletions .changeset/great-coins-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@twilio-paste/chat-composer": minor
"@twilio-paste/core": minor
---

[ChatComposer] Added new components to allow contained variants, actions buttons and attachments
6 changes: 6 additions & 0 deletions .changeset/khaki-boats-help.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@twilio-paste/ai-chat-log": patch
"@twilio-paste/core": patch
---

[AIChatLog] Updated internal styling types
6 changes: 6 additions & 0 deletions .changeset/nasty-beans-fetch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@twilio-paste/lexical-library": minor
"@twilio-paste/core": minor
---

[Lexical] added export for EditorRefPlugin
6 changes: 6 additions & 0 deletions .changeset/serious-kings-wink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@twilio-paste/anchor": patch
"@twilio-paste/core": patch
---

[Anchor] Added border radius to focus styling
6 changes: 6 additions & 0 deletions packages/paste-codemods/tools/.cache/mappings.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@
"CalloutText": "@twilio-paste/core/callout",
"Card": "@twilio-paste/core/card",
"ChatComposer": "@twilio-paste/core/chat-composer",
"ChatComposerActionGroup": "@twilio-paste/core/chat-composer",
"ChatComposerAttachmentCard": "@twilio-paste/core/chat-composer",
"ChatComposerAttachmentDescription": "@twilio-paste/core/chat-composer",
"ChatComposerAttachmentGroup": "@twilio-paste/core/chat-composer",
"ChatComposerAttachmentLink": "@twilio-paste/core/chat-composer",
"ChatComposerContainer": "@twilio-paste/core/chat-composer",
"ChatAttachment": "@twilio-paste/core/chat-log",
"ChatAttachmentDescription": "@twilio-paste/core/chat-log",
"ChatAttachmentLink": "@twilio-paste/core/chat-log",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { Box, safelySpreadBoxProps } from "@twilio-paste/box";
import type { BoxElementProps } from "@twilio-paste/box";
import type { ThemeShape } from "@twilio-paste/theme";
import type { BoxElementProps, BoxStyleProps } from "@twilio-paste/box";
import type { HTMLPasteProps } from "@twilio-paste/types";
import * as React from "react";

import { AIMessageContext } from "./AIMessageContext";

const Sizes = {
const Sizes: Record<string, BoxStyleProps> = {
default: {
fontSize: "fontSize30" as ThemeShape["fontSizes"],
lineHeight: "lineHeight30" as ThemeShape["lineHeights"],
fontSize: "fontSize30",
lineHeight: "lineHeight30",
},
fullScreen: {
fontSize: "fontSize40" as ThemeShape["fontSizes"],
lineHeight: "lineHeight40" as ThemeShape["lineHeights"],
fontSize: "fontSize40",
lineHeight: "lineHeight40",
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import type { AIChat } from "@twilio-paste/ai-chat-log";
import { Box } from "@twilio-paste/box";
import { Button } from "@twilio-paste/button";
import { ButtonGroup } from "@twilio-paste/button-group";
import { ChatComposer } from "@twilio-paste/chat-composer";
import { ChatComposer, ChatComposerActionGroup, ChatComposerContainer } from "@twilio-paste/chat-composer";
import { AttachIcon } from "@twilio-paste/icons/esm/AttachIcon";
import { SendIcon } from "@twilio-paste/icons/esm/SendIcon";
import { ThumbsDownIcon } from "@twilio-paste/icons/esm/ThumbsDownIcon";
import { ThumbsUpIcon } from "@twilio-paste/icons/esm/ThumbsUpIcon";
Expand All @@ -14,6 +15,7 @@ import {
COMMAND_PRIORITY_HIGH,
ClearEditorPlugin,
KEY_ENTER_COMMAND,
LexicalEditor,
useLexicalComposerContext,
} from "@twilio-paste/lexical-library";
import * as React from "react";
Expand Down Expand Up @@ -202,22 +204,15 @@ export const AIChatLogComposer = (): React.ReactNode => {
if (message === "") return;
push(createNewMessage(message));
};

const editorInstanceRef = React.useRef<LexicalEditor>(null);

return (
<Box>
<Box ref={scrollerRef} overflowX="hidden" overflowY="auto" maxHeight="size50" tabIndex={0}>
<AIChatLogger ref={loggerRef} aiChats={aiChats} />
</Box>
<Box
borderStyle="solid"
borderWidth="borderWidth0"
borderTopWidth="borderWidth10"
borderColor="colorBorderWeak"
display="flex"
flexDirection="row"
columnGap="space30"
paddingX="space70"
paddingTop="space50"
>
<ChatComposerContainer variant="contained">
<ChatComposer
maxHeight="size10"
config={{
Expand All @@ -229,12 +224,27 @@ export const AIChatLogComposer = (): React.ReactNode => {
ariaLabel="Message"
placeholder="Type here..."
onChange={handleComposerChange}
editorInstanceRef={editorInstanceRef}
>
<ClearEditorPlugin />
<SendButtonPlugin onClick={submitMessage} />
<EnterKeySubmitPlugin onKeyDown={submitMessage} />
</ChatComposer>
</Box>
<ChatComposerActionGroup>
<Button variant="secondary_icon" size="reset">
<AttachIcon decorative={false} title="attach a file to your message" />
</Button>
<Button
variant="primary_icon"
size="reset"
onClick={() => {
submitMessage();
editorInstanceRef.current?.dispatchCommand(CLEAR_EDITOR_COMMAND, undefined);
}}
>
<SendIcon decorative={false} title="Send" />
</Button>
</ChatComposerActionGroup>
</ChatComposerContainer>
</Box>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const DefaultAnchor = React.forwardRef<HTMLAnchorElement, AnchorProps>((props, r
boxShadow: "shadowFocus",
color: "colorTextLink",
textDecoration: "underline",
borderRadius: "borderRadius20",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

praise: nice design improvement

}}
_hover={{
color: "colorTextLinkStronger",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const InverseAnchor = React.forwardRef<HTMLAnchorElement, AnchorProps>((props, r
boxShadow: "shadowFocusInverse",
color: "colorTextInverse",
textDecoration: "underline",
borderRadius: "borderRadius20",
}}
_hover={{
color: "colorTextInverse",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { $createParagraphNode, $createTextNode, $getRoot } from "@twilio-paste/lexical-library";
import { Theme } from "@twilio-paste/theme";
import * as React from "react";

import { ChatComposer } from "../src";

const initialText = (): void => {
const root = $getRoot();

if (root.getFirstChild() === null) {
const paragraph = $createParagraphNode();
paragraph.append($createTextNode("Hello"));

root.append(paragraph);
}
};

const baseConfig = {
namespace: "foo",
onError: (error: Error) => {
throw error;
},
};

describe("ChatComposer", () => {
it("should render with placeholder text", () => {
render(<ChatComposer data-testid="my-composer" placeholder="Type here.." config={baseConfig} />);
expect(screen.getByRole("textbox")).toBeDefined();
expect(screen.getByText("Type here..")).toBeDefined();
});

it("should pass props to the content editable", async () => {
render(
<ChatComposer
data-testid="my-composer"
ariaLabel="Feedback"
ariaDescribedBy="foo"
ariaOwns="foo"
ariaActiveDescendant="foo"
config={baseConfig}
/>,
);

const contentEditable = screen.getByRole("textbox");
await waitFor(() => {
expect(contentEditable).toHaveAttribute("aria-label", "Feedback");
expect(contentEditable).toHaveAttribute("aria-activedescendant", "foo");
expect(contentEditable).toHaveAttribute("aria-owns", "foo");
expect(contentEditable).toHaveAttribute("aria-describedby", "foo");
expect(contentEditable.dataset.testid).toEqual("my-composer");
});
});

it("should render initial value with the initialValue prop", async () => {
render(<ChatComposer initialValue="Type here.." config={baseConfig} />);

const contentEditable = screen.getByRole("textbox");
await waitFor(() => {
expect(contentEditable).toHaveTextContent("Type here..");
});
});

it("should render custom initial value with the config prop", async () => {
render(
<ChatComposer
config={{
...baseConfig,
editorState: initialText,
}}
/>,
);

const contentEditable = screen.getByRole("textbox");
await waitFor(() => {
expect(contentEditable).toHaveTextContent("Hello");
});
});

it("should set maxHeight with the maxHeight prop", async () => {
render(
<Theme.Provider theme="default">
<ChatComposer maxHeight="size10" config={baseConfig} />
</Theme.Provider>,
);

const wrapper = screen.getByRole("textbox").parentElement;
await waitFor(() => {
expect(wrapper).toHaveStyleRule("max-height", "5.5rem");
});
});

it("should call onChange function", async () => {
const onChangeMock: jest.Mock = jest.fn();

render(<ChatComposer onChange={onChangeMock} config={baseConfig} />);

const contentEditable = screen.getByRole("textbox");

userEvent.type(contentEditable, "foo bar");
waitFor(() => {
expect(onChangeMock).toHaveBeenCalledTimes(1);
});
});
});
Loading
Loading