Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
## [Unreleased]

### BREAKING CHANGES
- Fixed `Divider` wrong usage of the `typeSecondary{color, backgroundColor}` and `default{color, backgroundColor}` variables; renamed `default{color, backgroundColor}` variables to `color` and `backgroundColor` @mnajdova ([#234](https://github.com/stardust-ui/react/pull/234))
- Restrict the `styles` prop to styling the root element only @levithomason ([#238](https://github.com/stardust-ui/react/pull/238))

### Features
- Add `author` and `timestamp` props for `Chat.Message` component @Bugaa92 ([#242](https://github.com/stardust-ui/react/pull/242))

<!--------------------------------[ v0.5.2 ]------------------------------- -->
## [v0.5.2](https://github.com/stardust-ui/react/tree/v0.5.2) (2018-09-14)
[Compare changes](https://github.com/stardust-ui/react/compare/v0.5.1...v0.5.2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,22 @@ import React from 'react'
import { Chat } from '@stardust-ui/react'

const messages = [
{ key: 1, content: 'Hello', mine: true },
{ key: 2, content: 'Hi' },
{ key: 3, content: "Let's go get some lunch!", mine: true },
{ key: 4, content: 'Sure thing. I was thinking we should try the new place downtown.' },
{ 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' },
{
key: 3,
content: "Let's go get some lunch!",
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',
},
]

const ChatExampleShorthand = () => <Chat messages={messages} />
Expand Down
17 changes: 0 additions & 17 deletions docs/src/examples/components/Chat/Types/ChatExample.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,31 @@ const busyStatus = { color: 'red', title: 'Busy' }
const messages = [
{
key: 1,
author: 'Matt Doe',
timestamp: 'Yesterday, 10:15 PM',
content: 'Hello',
mine: true,
avatar: { src: 'public/images/avatar/small/matt.jpg', status: availableStatus },
},
{
key: 2,
author: 'Jenny Doe',
timestamp: 'Yesterday, 10:17 PM',
content: 'Hi',
avatar: { src: '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: { src: '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: { src: 'public/images/avatar/small/jenny.jpg', status: busyStatus },
},
Expand Down
86 changes: 76 additions & 10 deletions src/components/Chat/ChatMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,33 @@ import * as React from 'react'
import * as PropTypes from 'prop-types'
import * as cx from 'classnames'

import { childrenExist, createShorthandFactory, customPropTypes, UIComponent } from '../../lib'
import {
childrenExist,
createShorthandFactory,
customPropTypes,
UIComponent,
IRenderResultConfig,
} from '../../lib'
import {
ComponentVariablesInput,
ComponentPartStyle,
IComponentPartStylesInput,
} from '../../../types/theme'
import { Extendable, ReactChildren, ItemShorthand } from '../../../types/utils'
import Avatar from '../Avatar'
import Layout from '../Layout'
import Text from '../Text'

export interface IChatMessageProps {
as?: any
author?: ItemShorthand
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

avatar?: ItemShorthand
children?: ReactChildren
className?: string
content?: any
mine?: boolean
styles?: ComponentPartStyle
timestamp?: ItemShorthand
variables?: ComponentVariablesInput
}

Expand All @@ -32,6 +42,9 @@ class ChatMessage extends UIComponent<Extendable<IChatMessageProps>, any> {
static propTypes = {
as: customPropTypes.as,

/** Author of the message. */
author: customPropTypes.itemShorthand,

/** Chat messages can have an avatar */
avatar: customPropTypes.itemShorthand,

Expand All @@ -50,50 +63,103 @@ class ChatMessage extends UIComponent<Extendable<IChatMessageProps>, any> {
/** Custom styles to be applied for component. */
styles: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),

/** Timestamp of the message. */
timestamp: customPropTypes.itemShorthand,

/** Custom variables to be applied for component. */
variables: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
}

static handledProps = [
'as',
'author',
'avatar',
'children',
'className',
'content',
'mine',
'styles',
'timestamp',
'variables',
]

static defaultProps = {
as: 'li',
}

renderComponent({ ElementType, classes, rest, styles, variables }) {
const { avatar, children, content, mine } = this.props
renderComponent({
ElementType,
classes,
rest,
styles,
variables,
}: IRenderResultConfig<IChatMessageProps>) {
const { as, avatar, children, mine } = this.props

return childrenExist(children) ? (
<ElementType {...rest} className={cx(classes.root, classes.content)}>
{children}
</ElementType>
) : (
<ElementType {...rest} className={classes.root}>
{!mine && this.renderAvatar(avatar, styles, variables)}
<div className={classes.content}>{content}</div>
{mine && this.renderAvatar(avatar, styles, variables)}
</ElementType>
<Layout
as={as}
{...rest}
className={classes.root}
start={!mine && this.renderAvatar(avatar, styles.avatar, variables)}
main={this.renderContent(classes.content, styles, variables)}
end={mine && this.renderAvatar(avatar, styles.avatar, variables)}
/>
)
}

private renderContent = (
contentClass: string,
styles: IComponentPartStylesInput,
variables: ComponentVariablesInput,
) => {
const { author, content, mine, timestamp } = this.props

const authorComponent = Text.create(author, {
defaultProps: {
size: 'sm',
styles: styles.author,
variables: variables.author,
},
})

const timestampComponent = Text.create(timestamp, {
defaultProps: {
size: 'sm',
timestamp: true,
styles: styles.timestamp,
variables: variables.timestamp,
},
})

return (
<Layout
className={contentClass}
vertical
start={
<>
{!mine && authorComponent}
{timestampComponent}
</>
}
main={content}
/>
)
}

private renderAvatar = (
avatar: ItemShorthand,
styles: IComponentPartStylesInput,
avatarStyles: ComponentPartStyle,
variables: ComponentVariablesInput,
) =>
avatar &&
Avatar.create(avatar, {
defaultProps: {
styles: styles.avatar,
styles: avatarStyles,
variables: variables.avatar,
},
})
Expand Down
6 changes: 5 additions & 1 deletion src/components/Text/Text.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as PropTypes from 'prop-types'
import * as React from 'react'

import { childrenExist, customPropTypes, UIComponent } from '../../lib'
import { childrenExist, createShorthandFactory, customPropTypes, UIComponent } from '../../lib'

import { Extendable } from '../../../types/utils'
import { ComponentVariablesInput, ComponentPartStyle } from '../../../types/theme'
Expand Down Expand Up @@ -31,6 +31,8 @@ export interface ITextProps {
* Ensure that a contrast ratio of at least 4.5:1 exists between text and the background behind the text.
*/
class Text extends UIComponent<Extendable<ITextProps>, any> {
static create: Function

static className = 'ui-text'

static displayName = 'Text'
Expand Down Expand Up @@ -114,4 +116,6 @@ class Text extends UIComponent<Extendable<ITextProps>, any> {
}
}

Text.create = createShorthandFactory(Text, content => ({ content }))

export default Text
2 changes: 2 additions & 0 deletions src/themes/teams/componentVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export { default as Avatar } from './components/Avatar/avatarVariables'
export { default as Button } from './components/Button/buttonVariables'
export { default as ButtonGroup } from './components/Button/buttonVariables'

export { default as Chat } from './components/Chat/chatVariables'

export { default as ChatMessage } from './components/Chat/chatMessageVariables'

export { default as Divider } from './components/Divider/dividerVariables'
Expand Down
13 changes: 9 additions & 4 deletions src/themes/teams/components/Chat/chatMessageStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { IChatMessageProps } from '../../../../components/Chat/ChatMessage'
import { IChatMessageVariables } from './chatMessageVariables'
import { pxToRem } from '../../../../lib'

const px10asRem = pxToRem(10)
const chatMessageStyles = {
root: ({
props: p,
Expand All @@ -11,7 +12,6 @@ const chatMessageStyles = {
props: IChatMessageProps
variables: IChatMessageVariables
}): ICSSInJSStyle => ({
display: 'flex',
position: 'relative',
marginTop: '1rem',
marginBottom: '1rem',
Expand All @@ -25,8 +25,11 @@ const chatMessageStyles = {
maxWidth: v.messageWidth,
}),

avatar: (): ICSSInJSStyle => ({
margin: pxToRem(10),
avatar: ({ props: p }: { props: IChatMessageProps }): ICSSInJSStyle => ({
marginTop: px10asRem,
marginBottom: px10asRem,
marginLeft: p.mine ? px10asRem : 0,
marginRight: p.mine ? 0 : px10asRem,
}),

content: ({
Expand All @@ -36,12 +39,14 @@ const chatMessageStyles = {
props: IChatMessageProps
variables: IChatMessageVariables
}): ICSSInJSStyle => ({
flex: 1,
padding: '1rem',
color: 'rgb(64, 64, 64)',
backgroundColor: p.mine ? v.messageColorMine : v.messageColor,
borderRadius: '0.3rem',
}),
author: {
marginRight: px10asRem,
},
}

export default chatMessageStyles
8 changes: 6 additions & 2 deletions src/themes/teams/components/Chat/chatMessageVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ export interface IChatMessageVariables {
messageWidth: string
messageColor: string
messageColorMine: string
avatar: { statusBorderColor: string }
}

export default (): IChatMessageVariables => ({
export default (siteVars): IChatMessageVariables => ({
messageWidth: '80%',
messageColor: 'rgba(0,0,0,0.1)',
messageColor: siteVars.white,
messageColorMine: '#E0E0ED',
avatar: {
statusBorderColor: siteVars.gray10,
},
})
8 changes: 6 additions & 2 deletions src/themes/teams/components/Chat/chatStyles.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { ICSSInJSStyle } from '../../../../../types/theme'
import { IChatVariables } from './chatVariables'
import { pxToRem } from '../../../../lib'

const chatStyles = {
root: (): ICSSInJSStyle => ({
root: ({ variables: v }: { variables: IChatVariables }): ICSSInJSStyle => ({
backgroundColor: v.backgroundColor,
border: `1px solid ${v.backgroundColor}`,
display: 'flex',
flexDirection: 'column',
listStyle: 'none',
padding: 0,
padding: `0 ${pxToRem(10)} 0 ${pxToRem(10)}`,
margin: 0,
}),
}
Expand Down
7 changes: 7 additions & 0 deletions src/themes/teams/components/Chat/chatVariables.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface IChatVariables {
backgroundColor: string
Copy link
Contributor

Choose a reason for hiding this comment

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

this is better to be handled by the code of examples for now - more than that, we could adjust padding aspects there as well

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, I added the backgroundColor and the padding to the variables with some defaults that would match the Team's theme, as we are developing this theme, so why not have this look by default. Please share your thoughts on this. Also, I added avatar slot in the ChatMessage, for configuring the statusBorderColor to match the background. Actually I have one thing that I am not 100% sure that should be implement this way. The Chat component has it's own backgroundColor and this color should match the Avatar's statusBorderColor. The problem is that, the Avatar is inside the ChatMessage component, and I am not confident that the Chat component should define the avatar's slot in the ChatMessage component. For now, those colors are independent variables in the Chat, and the ChatMessage's avatar slot component. What do you think about this @kuzhelov? This is how the default look of the examples looks now:
image

Copy link
Contributor

Choose a reason for hiding this comment

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

sounds quite reasonable, thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

agreed to not introduce these two as variables for now, just inline them into styles directly

Copy link
Contributor

Choose a reason for hiding this comment

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

We are going to stick with the backgroundColor as variable in order to reuse the siteVariables. Paddings are deleted from variables

}

export default (siteVars): IChatVariables => ({
backgroundColor: siteVars.gray10,
})
3 changes: 3 additions & 0 deletions test/specs/components/Chat/ChatMessage-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ import { mountWithProvider } from '../../../utils'

import ChatMessage from 'src/components/Chat/ChatMessage'
import Avatar from 'src/components/Avatar'
import Text from 'src/components/Text'

describe('ChatMessage', () => {
isConformant(ChatMessage)
implementsShorthandProp(ChatMessage)('avatar', Avatar, { mapsValueToProp: 'name' })
implementsShorthandProp(ChatMessage)('author', Text)
implementsShorthandProp(ChatMessage)('timestamp', Text)

describe('avatar', () => {
it('creates an Avatar component when the avatar shorthand is provided', () => {
Expand Down