Skip to content

Commit 9b93f0a

Browse files
committed
add component for chat area
1 parent a1ec630 commit 9b93f0a

4 files changed

Lines changed: 144 additions & 1 deletion

File tree

src/components/Chat/ChatArea.tsx

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import React from "react";
2+
3+
import { TestableComponent } from "../../components/interfaces";
4+
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
5+
6+
import { FlexibleLayoutContainer, FlexibleLayoutContainerProps, FlexibleLayoutItem } from "./../FlexibleLayout";
7+
import { Spacing, SpacingProps } from "./../Separation/Spacing";
8+
import { ChatFieldProps } from "./ChatField";
9+
10+
export interface ChatAreaProps
11+
extends Omit<FlexibleLayoutContainerProps, "vertical" | "noEqualItemSpace">,
12+
TestableComponent {
13+
/**
14+
* The inut field for the chat.
15+
*/
16+
chatField?: React.ReactElement<ChatFieldProps>;
17+
/**
18+
* Set the position of the chat field.
19+
*/
20+
chatFieldPosition?: "top" | "bottom";
21+
/**
22+
* Sets the maximum width for chat contents and input.
23+
*/
24+
contentWidth?: "small" | "medium" | "large" | "full";
25+
/**
26+
* Put in chat content in a list and add spacings automatically.
27+
* Works best if each child represents one chat content item.
28+
*/
29+
autoSpacingSize?: SpacingProps["size"];
30+
}
31+
32+
/**
33+
* Component to display a full chat, containing chat content bubbles and text input.
34+
*/
35+
export const ChatArea = ({
36+
children,
37+
className,
38+
chatField,
39+
chatFieldPosition = "bottom",
40+
contentWidth = "medium",
41+
autoSpacingSize,
42+
gapSize = "medium",
43+
...otherFlexibleLayoutContainerProps
44+
}: ChatAreaProps) => {
45+
return (
46+
<FlexibleLayoutContainer
47+
className={
48+
`${eccgui}-chat__area` + ` ${eccgui}-chat__area--${contentWidth}` + (className ? ` ${className}` : "")
49+
}
50+
vertical
51+
noEqualItemSpace
52+
gapSize={gapSize}
53+
{...otherFlexibleLayoutContainerProps}
54+
>
55+
{chatField && (
56+
<FlexibleLayoutItem
57+
className={`${eccgui}-chat__area-contents`}
58+
growFactor={0}
59+
shrinkFactor={0}
60+
style={chatFieldPosition === "bottom" ? { order: 1 } : undefined}
61+
>
62+
{chatField}
63+
</FlexibleLayoutItem>
64+
)}
65+
<FlexibleLayoutItem
66+
className={`${eccgui}-chat__area-contents`}
67+
style={
68+
otherFlexibleLayoutContainerProps.useAbsoluteSpace
69+
? {
70+
overflow: "auto",
71+
minHeight: 0,
72+
paddingRight: "0.25rem",
73+
}
74+
: undefined
75+
}
76+
>
77+
{autoSpacingSize && children ? (
78+
<ul>
79+
{React.Children.toArray(children).map((child) => (
80+
<li>
81+
{child}
82+
<Spacing size={autoSpacingSize} />
83+
</li>
84+
))}
85+
</ul>
86+
) : (
87+
children
88+
)}
89+
</FlexibleLayoutItem>
90+
</FlexibleLayoutContainer>
91+
);
92+
};
93+
94+
export default ChatArea;

src/components/Chat/_chat.scss

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,23 @@
5959
max-height: 50vh;
6060
}
6161

62-
.eccgui-chat__inputfield {
62+
.#{$eccgui}-chat__inputfield {
6363
min-height: mini-units(9);
6464
max-height: 39vh;
6565
resize: none !important;
6666
}
67+
68+
.#{$eccgui}-chat__area-contents {
69+
width: 100%;
70+
margin: 0 auto;
71+
72+
.#{$eccgui}-chat__area--small > & {
73+
max-width: 40rem;
74+
}
75+
.#{$eccgui}-chat__area--medium > & {
76+
max-width: 60rem;
77+
}
78+
.#{$eccgui}-chat__area--large > & {
79+
max-width: 80rem;
80+
}
81+
}

src/components/Chat/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
export * from "./ChatArea";
12
export * from "./ChatContent";
23
export * from "./ChatField";
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from "react";
2+
import { Meta, StoryFn } from "@storybook/react";
3+
4+
import { ChatArea, ChatContent, ChatField } from "../../../index";
5+
6+
import { Default as ShortChatBubble, LongChatBubble } from "./ChatContent.stories";
7+
import { Default as ChatFieldExample } from "./ChatField.stories";
8+
9+
export default {
10+
title: "Components/Chat/ChatArea",
11+
component: ChatArea,
12+
argTypes: {},
13+
} as Meta<typeof ChatArea>;
14+
15+
let forceupdate = 0;
16+
const TemplateFull: StoryFn<typeof ChatArea> = (args) => (
17+
<div style={args.useAbsoluteSpace ? { position: "relative", height: "75vh" } : undefined}>
18+
<ChatArea {...args} key={forceupdate++} />
19+
</div>
20+
);
21+
22+
export const Default = TemplateFull.bind({});
23+
Default.args = {
24+
chatField: <ChatField {...ChatFieldExample.args} />,
25+
children: [
26+
<ChatContent {...ShortChatBubble.args} alignment="right" indentationSize="medium" />,
27+
<ChatContent {...ShortChatBubble.args} avatar={undefined} displayType="free" />,
28+
<ChatContent {...ShortChatBubble.args} alignment="right" indentationSize="medium" />,
29+
<ChatContent {...LongChatBubble.args} />,
30+
<ChatContent {...ShortChatBubble.args} alignment="right" indentationSize="medium" />,
31+
<ChatContent {...ShortChatBubble.args} />,
32+
],
33+
};

0 commit comments

Comments
 (0)