diff --git a/CHANGELOG.md b/CHANGELOG.md
index b0896e292f..b2f3ec4cd4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### BREAKING CHANGES
- Change font ramp and Text size API @codepretty ([#214](https://github.com/stardust-ui/react/pull/214))
+- Add `ChatItem` component that can be used inside the `Chat` via the Children API or the `items` prop, instead of the `Chat.Message` used directly in the previous `messages` prop @mnajdova ([#255](https://github.com/stardust-ui/react/pull/255))
### Features
- Add embed mode for `FocusZone` and use it in newly added Chat behaviors @tomasiser ([#233](https://github.com/stardust-ui/react/pull/233))
diff --git a/docs/src/examples/components/Chat/Types/ChatExample.shorthand.tsx b/docs/src/examples/components/Chat/Types/ChatExample.shorthand.tsx
index 508b1307c1..a1c2431309 100644
--- a/docs/src/examples/components/Chat/Types/ChatExample.shorthand.tsx
+++ b/docs/src/examples/components/Chat/Types/ChatExample.shorthand.tsx
@@ -1,30 +1,62 @@
import React from 'react'
+import { Chat, Divider } from '@stardust-ui/react'
-import { Chat } from '@stardust-ui/react'
+const janeAvatar = {
+ image: 'public/images/avatar/small/ade.jpg',
+ status: { color: 'green', icon: 'check' },
+}
-const messages = [
- { key: 1, content: 'Hello', author: 'John Doe', timestamp: 'Yesterday, 10:15 PM', mine: true },
- { key: 2, content: 'Hi', author: 'Jane Doe', timestamp: 'Yesterday, 10:15 PM' },
+const items = [
{
- key: 3,
content: (
- <>
- Let's go get some lunch! I suggest the new Downtown Burgers or Chef's Finest.
- >
+
),
- author: 'John Doe',
- timestamp: 'Yesterday, 10:15 PM',
- mine: true,
},
{
- key: 4,
- content:
- 'Sure thing. I was thinking we should try the new place downtown. The name of its chief promises a delicious food being offered.',
- author: 'Jane Doe',
- timestamp: 'Yesterday, 10:15 PM',
+ content: (
+
+ ),
+ },
+ {
+ content: (
+
+ ),
+ },
+ {
+ content: (
+
+ ),
+ },
+ {
+ content: ,
+ },
+ {
+ content: (
+
+ ),
},
]
-const ChatExampleShorthand = () =>
+const ChatExample = () =>
-export default ChatExampleShorthand
+export default ChatExample
diff --git a/docs/src/examples/components/Chat/Types/ChatExample.tsx b/docs/src/examples/components/Chat/Types/ChatExample.tsx
new file mode 100644
index 0000000000..2ffaf98d08
--- /dev/null
+++ b/docs/src/examples/components/Chat/Types/ChatExample.tsx
@@ -0,0 +1,52 @@
+import React from 'react'
+import { Chat, Divider } from '@stardust-ui/react'
+
+const janeAvatar = {
+ image: 'public/images/avatar/small/ade.jpg',
+ status: { color: 'green', icon: 'check' },
+}
+
+const ChatExample = () => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)
+
+export default ChatExample
diff --git a/docs/src/examples/components/Chat/Variations/ChatExampleAvatar.shorthand.tsx b/docs/src/examples/components/Chat/Variations/ChatExampleAvatar.shorthand.tsx
deleted file mode 100644
index ff066ff8b8..0000000000
--- a/docs/src/examples/components/Chat/Variations/ChatExampleAvatar.shorthand.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import React from 'react'
-import { Chat } from '@stardust-ui/react'
-
-const availableStatus = { color: 'green', icon: 'check', title: 'Available' }
-const busyStatus = { color: 'red', title: 'Busy' }
-
-const messages = [
- {
- key: 1,
- author: 'Matt Doe',
- timestamp: 'Yesterday, 10:15 PM',
- content: 'Hello',
- mine: true,
- avatar: { image: 'public/images/avatar/small/matt.jpg', status: availableStatus },
- },
- {
- key: 2,
- author: 'Jenny Doe',
- timestamp: 'Yesterday, 10:17 PM',
- content: 'Hi',
- avatar: { image: 'public/images/avatar/small/jenny.jpg', status: busyStatus },
- },
- {
- key: 3,
- author: 'Matt Doe',
- timestamp: 'Yesterday, 10:18 PM',
- content: "Let's go get some lunch!",
- mine: true,
- avatar: { image: 'public/images/avatar/small/matt.jpg', status: availableStatus },
- },
- {
- key: 4,
- author: 'Jenny Doe',
- timestamp: 'Yesterday, 10:20 PM',
- content: 'Sure thing. I was thinking we should try the new place downtown.',
- avatar: { image: 'public/images/avatar/small/jenny.jpg', status: busyStatus },
- },
-]
-
-const ChatExampleAvatar = () =>
-
-export default ChatExampleAvatar
diff --git a/docs/src/examples/components/Chat/Variations/index.tsx b/docs/src/examples/components/Chat/Variations/index.tsx
deleted file mode 100644
index f9c4f4532e..0000000000
--- a/docs/src/examples/components/Chat/Variations/index.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import React from 'react'
-import ComponentExample from 'docs/src/components/ComponentDoc/ComponentExample'
-import ExampleSection from 'docs/src/components/ComponentDoc/ExampleSection'
-
-const Variations = () => (
-
-
-
-)
-
-export default Variations
diff --git a/docs/src/examples/components/Chat/index.tsx b/docs/src/examples/components/Chat/index.tsx
index bd1a7330ac..0b24f2fae9 100644
--- a/docs/src/examples/components/Chat/index.tsx
+++ b/docs/src/examples/components/Chat/index.tsx
@@ -1,12 +1,10 @@
import React from 'react'
import Types from './Types'
-import Variations from './Variations'
-const MessageExamples = () => (
+const ChatExamples = () => (
-
)
-export default MessageExamples
+export default ChatExamples
diff --git a/src/components/Chat/Chat.tsx b/src/components/Chat/Chat.tsx
index 1abb69097d..79bcd3c88e 100644
--- a/src/components/Chat/Chat.tsx
+++ b/src/components/Chat/Chat.tsx
@@ -3,9 +3,10 @@ import * as PropTypes from 'prop-types'
import * as React from 'react'
import { childrenExist, customPropTypes, UIComponent } from '../../lib'
+import ChatItem from './ChatItem'
import ChatMessage from './ChatMessage'
-import { ComponentVariablesInput, ComponentPartStyle } from '../../../types/theme'
-import { Extendable, ReactChildren, ItemShorthand } from '../../../types/utils'
+import { ComponentPartStyle, ComponentVariablesInput } from '../../../types/theme'
+import { Extendable, ItemShorthand, ReactChildren } from '../../../types/utils'
import { Accessibility, AccessibilityActionHandlers } from '../../lib/accessibility/interfaces'
import ChatBehavior from '../../lib/accessibility/Behaviors/Chat/ChatBehavior'
@@ -14,7 +15,7 @@ export interface IChatProps {
as?: any
className?: string
children?: ReactChildren
- messages?: ItemShorthand[]
+ items?: ItemShorthand[]
styles?: ComponentPartStyle
variables?: ComponentVariablesInput
}
@@ -28,15 +29,17 @@ class Chat extends UIComponent, any> {
/** Accessibility behavior if overridden by the user. */
accessibility: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
+ /** An element type to render as (string or function). */
as: customPropTypes.as,
/** Additional CSS class name(s) to apply. */
className: PropTypes.string,
+ /** Child content. */
children: PropTypes.node,
- /** Shorthand array of messages. */
- messages: PropTypes.arrayOf(PropTypes.any),
+ /** Shorthand array of the items inside the chat. */
+ items: PropTypes.arrayOf(customPropTypes.itemShorthand),
/** Additional CSS styles to apply to the component instance. */
styles: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
@@ -47,6 +50,7 @@ class Chat extends UIComponent, any> {
static defaultProps = { accessibility: ChatBehavior as Accessibility, as: 'ul' }
+ static Item = ChatItem
static Message = ChatMessage
actionHandlers: AccessibilityActionHandlers = {
@@ -54,7 +58,7 @@ class Chat extends UIComponent, any> {
}
renderComponent({ ElementType, classes, accessibility, rest }) {
- const { children, messages } = this.props
+ const { children, items } = this.props
return (
, any> {
{...accessibility.keyHandlers.root}
{...rest}
>
- {childrenExist(children)
- ? children
- : _.map(messages, message => ChatMessage.create(message))}
+ {childrenExist(children) ? children : _.map(items, item => ChatItem.create(item))}
)
}
diff --git a/src/components/Chat/ChatItem.tsx b/src/components/Chat/ChatItem.tsx
new file mode 100644
index 0000000000..0635664797
--- /dev/null
+++ b/src/components/Chat/ChatItem.tsx
@@ -0,0 +1,64 @@
+import * as React from 'react'
+import * as PropTypes from 'prop-types'
+
+import {
+ createShorthandFactory,
+ customPropTypes,
+ IRenderResultConfig,
+ UIComponent,
+} from '../../lib'
+import { ComponentPartStyle, ComponentVariablesInput } from '../../../types/theme'
+import { Extendable, ReactChildren } from '../../../types/utils'
+import childrenExist from '../../lib/childrenExist'
+
+export interface IChatItemProps {
+ as?: any
+ content?: React.ReactNode
+ children?: ReactChildren
+ className?: string
+ styles?: ComponentPartStyle
+ variables?: ComponentVariablesInput
+}
+
+class ChatItem extends UIComponent, any> {
+ static className = 'ui-chat__item'
+
+ static create: Function
+
+ static displayName = 'ChatItem'
+
+ static propTypes = {
+ /** An element type to render as (string or function). */
+ as: customPropTypes.as,
+
+ /** Child content. */
+ children: PropTypes.node,
+
+ /** Additional CSS class name(s) to apply. */
+ className: PropTypes.string,
+
+ /** Custom styles to be applied for component. */
+ styles: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
+
+ /** Custom variables to be applied for component. */
+ variables: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
+ }
+
+ static defaultProps = {
+ as: 'li',
+ }
+
+ renderComponent({ ElementType, classes, rest }: IRenderResultConfig) {
+ const { children, content } = this.props
+
+ return (
+
+ {childrenExist(children) ? children : content}
+
+ )
+ }
+}
+
+ChatItem.create = createShorthandFactory(ChatItem, content => ({ content }))
+
+export default ChatItem
diff --git a/src/components/Chat/ChatMessage.tsx b/src/components/Chat/ChatMessage.tsx
index ef3db222c2..4ed2b1a616 100644
--- a/src/components/Chat/ChatMessage.tsx
+++ b/src/components/Chat/ChatMessage.tsx
@@ -6,15 +6,15 @@ import {
childrenExist,
createShorthandFactory,
customPropTypes,
- UIComponent,
IRenderResultConfig,
+ UIComponent,
} from '../../lib'
import {
- ComponentVariablesInput,
ComponentPartStyle,
+ ComponentVariablesInput,
IComponentPartStylesInput,
} from '../../../types/theme'
-import { Extendable, ReactChildren, ItemShorthand } from '../../../types/utils'
+import { Extendable, ItemShorthand, ReactChildren } from '../../../types/utils'
import Avatar from '../Avatar'
import ChatMessageBehavior from '../../lib/accessibility/Behaviors/Chat/ChatMessageBehavior'
import { Accessibility, AccessibilityActionHandlers } from '../../lib/accessibility/interfaces'
@@ -46,12 +46,13 @@ class ChatMessage extends UIComponent, any> {
/** Accessibility behavior if overridden by the user. */
accessibility: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
+ /** An element type to render as (string or function). */
as: customPropTypes.as,
/** Author of the message. */
author: customPropTypes.itemShorthand,
- /** Chat messages can have an avatar */
+ /** Chat messages can have an avatar. */
avatar: customPropTypes.itemShorthand,
/** Child content. */
@@ -78,7 +79,7 @@ class ChatMessage extends UIComponent, any> {
static defaultProps = {
accessibility: ChatMessageBehavior as Accessibility,
- as: 'li',
+ as: 'div',
}
actionHandlers: AccessibilityActionHandlers = {
diff --git a/src/components/Chat/index.ts b/src/components/Chat/index.ts
index bb2bea9087..d0af733955 100644
--- a/src/components/Chat/index.ts
+++ b/src/components/Chat/index.ts
@@ -1,2 +1,3 @@
export { default } from './Chat'
+export { default as ChatItem } from './ChatItem'
export { default as ChatMessage } from './ChatMessage'
diff --git a/src/components/Grid/Grid.tsx b/src/components/Grid/Grid.tsx
index 9c82028213..26d2b7d547 100644
--- a/src/components/Grid/Grid.tsx
+++ b/src/components/Grid/Grid.tsx
@@ -1,9 +1,9 @@
import * as PropTypes from 'prop-types'
import * as React from 'react'
-import ReactNode = React.ReactNode
import { UIComponent, childrenExist, customPropTypes, IRenderResultConfig } from '../../lib'
import { ComponentVariablesInput, ComponentPartStyle } from '../../../types/theme'
import { Extendable, ItemShorthand, ReactChildren } from '../../../types/utils'
+import ReactNode = React.ReactNode
export interface IGridProps {
as?: any
diff --git a/src/index.ts b/src/index.ts
index 20744af6bb..edaa4f56bf 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,4 +1,5 @@
import * as themes from './themes'
+
export { themes }
export { default as Accordion } from './components/Accordion'
@@ -7,6 +8,7 @@ export { default as Avatar } from './components/Avatar'
export { default as Button } from './components/Button'
export { ButtonGroup } from './components/Button'
export { default as Chat } from './components/Chat'
+export { ChatItem } from './components/Chat'
export { ChatMessage } from './components/Chat'
export { default as Divider } from './components/Divider'
export { default as Grid } from './components/Grid'
diff --git a/src/lib/accessibility/Behaviors/Popup/PopupBehavior.ts b/src/lib/accessibility/Behaviors/Popup/PopupBehavior.ts
index 379e76db06..17e5351426 100644
--- a/src/lib/accessibility/Behaviors/Popup/PopupBehavior.ts
+++ b/src/lib/accessibility/Behaviors/Popup/PopupBehavior.ts
@@ -1,6 +1,5 @@
import { Accessibility } from '../../interfaces'
import * as keyboardKey from 'keyboard-key'
-import _ from 'lodash'
/**
* @description
diff --git a/src/themes/teams/componentStyles.ts b/src/themes/teams/componentStyles.ts
index 3153625033..b136c379f4 100644
--- a/src/themes/teams/componentStyles.ts
+++ b/src/themes/teams/componentStyles.ts
@@ -10,6 +10,7 @@ export { default as Button } from './components/Button/buttonStyles'
export { default as ButtonGroup } from './components/Button/buttonGroupStyles'
export { default as Chat } from './components/Chat/chatStyles'
+export { default as ChatItem } from './components/Chat/chatItemStyles'
export { default as ChatMessage } from './components/Chat/chatMessageStyles'
export { default as Divider } from './components/Divider/dividerStyles'
diff --git a/src/themes/teams/componentVariables.ts b/src/themes/teams/componentVariables.ts
index a056a5e647..df10e0a02a 100644
--- a/src/themes/teams/componentVariables.ts
+++ b/src/themes/teams/componentVariables.ts
@@ -9,6 +9,8 @@ export { default as ButtonGroup } from './components/Button/buttonVariables'
export { default as Chat } from './components/Chat/chatVariables'
+export { default as ChatItem } from './components/Chat/chatItemVariables'
+
export { default as ChatMessage } from './components/Chat/chatMessageVariables'
export { default as Divider } from './components/Divider/dividerVariables'
diff --git a/src/themes/teams/components/Chat/chatItemStyles.ts b/src/themes/teams/components/Chat/chatItemStyles.ts
new file mode 100644
index 0000000000..b5231f2c3d
--- /dev/null
+++ b/src/themes/teams/components/Chat/chatItemStyles.ts
@@ -0,0 +1,7 @@
+import { ICSSInJSStyle } from '../../../../../types/theme'
+
+const chatItemStyles = {
+ root: (): ICSSInJSStyle => ({}),
+}
+
+export default chatItemStyles
diff --git a/src/themes/teams/components/Chat/chatItemVariables.ts b/src/themes/teams/components/Chat/chatItemVariables.ts
new file mode 100644
index 0000000000..a78a27d1e7
--- /dev/null
+++ b/src/themes/teams/components/Chat/chatItemVariables.ts
@@ -0,0 +1,15 @@
+export interface IChatItemVariables {
+ messageWidth: string
+ messageColor: string
+ messageColorMine: string
+ avatar: { statusBorderColor: string }
+}
+
+export default (siteVars): IChatItemVariables => ({
+ messageWidth: '80%',
+ messageColor: siteVars.white,
+ messageColorMine: '#E0E0ED',
+ avatar: {
+ statusBorderColor: siteVars.gray10,
+ },
+})
diff --git a/src/themes/teams/components/Chat/chatMessageStyles.ts b/src/themes/teams/components/Chat/chatMessageStyles.ts
index ff9dbd6b3b..c777ac5f80 100644
--- a/src/themes/teams/components/Chat/chatMessageStyles.ts
+++ b/src/themes/teams/components/Chat/chatMessageStyles.ts
@@ -6,18 +6,16 @@ import { pxToRem } from '../../../../lib'
const px10asRem = pxToRem(10)
const chatMessageStyles: IComponentPartStylesInput = {
root: ({ props: p, variables: v }): ICSSInJSStyle => ({
- display: 'flex',
+ display: 'inline-block',
position: 'relative',
marginTop: '1rem',
marginBottom: '1rem',
- ...(p.mine
- ? {
- marginLeft: 'auto',
- }
- : {
- marginRight: 'auto',
- }),
+ ...(p.mine && {
+ float: 'right',
+ }),
maxWidth: v.messageWidth,
+ wordBreak: 'break-word',
+ wordWrap: 'break-word',
}),
avatar: ({ props: p }: { props: IChatMessageProps }): ICSSInJSStyle => ({
diff --git a/test/specs/components/Chat/Chat-test.ts b/test/specs/components/Chat/Chat-test.ts
index 29e58b36bc..419c15ff79 100644
--- a/test/specs/components/Chat/Chat-test.ts
+++ b/test/specs/components/Chat/Chat-test.ts
@@ -1,11 +1,16 @@
-import { isConformant, handlesAccessibility } from 'test/specs/commonTests'
+import { handlesAccessibility, isConformant } from 'test/specs/commonTests'
import Chat from 'src/components/Chat'
+import implementsCollectionShorthandProp from '../../commonTests/implementsCollectionShorthandProp'
+import ChatItem from 'src/components/Chat/ChatItem'
import ChatBehavior from 'src/lib/accessibility/Behaviors/Chat/ChatBehavior'
import { IAccessibilityDefinition } from 'src/lib/accessibility/interfaces'
+const chatImplementsCollectionShorthandProp = implementsCollectionShorthandProp(Chat)
+
describe('Chat', () => {
isConformant(Chat)
+ chatImplementsCollectionShorthandProp('items', ChatItem)
describe('accessibility', () => {
handlesAccessibility(Chat, {
diff --git a/test/specs/components/Chat/ChatItem-test.tsx b/test/specs/components/Chat/ChatItem-test.tsx
new file mode 100644
index 0000000000..dd6e78f310
--- /dev/null
+++ b/test/specs/components/Chat/ChatItem-test.tsx
@@ -0,0 +1,7 @@
+import { isConformant } from 'test/specs/commonTests'
+
+import ChatItem from 'src/components/Chat/ChatItem'
+
+describe('ChatItem', () => {
+ isConformant(ChatItem)
+})
diff --git a/test/specs/components/Chat/ChatMessage-test.tsx b/test/specs/components/Chat/ChatMessage-test.tsx
index b234b4f12f..84144bc935 100644
--- a/test/specs/components/Chat/ChatMessage-test.tsx
+++ b/test/specs/components/Chat/ChatMessage-test.tsx
@@ -1,5 +1,5 @@
import * as React from 'react'
-import { isConformant, implementsShorthandProp, handlesAccessibility } from 'test/specs/commonTests'
+import { handlesAccessibility, implementsShorthandProp, isConformant } from 'test/specs/commonTests'
import { mountWithProvider } from '../../../utils'
import ChatMessage from 'src/components/Chat/ChatMessage'
@@ -24,9 +24,9 @@ describe('ChatMessage', () => {
describe('avatar', () => {
it('creates an Avatar component when the avatar shorthand is provided', () => {
const name = 'John Doe'
- const chatMsg = mountWithProvider()
+ const chatMessage = mountWithProvider()
- expect(chatMsg.find('Avatar').prop('name')).toEqual(name)
+ expect(chatMessage.find('Avatar').prop('name')).toEqual(name)
})
})
})