Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

Commit 53da689

Browse files
author
Alexandru Buliga
authored
feat(chat): remove layout component and allow styling slots (#518)
* feat(chat): remove layout component and allow styling slots * changelog * fix console error * addressed PR comments * addressed PR comments * - removed unnecessary arguments for shorthand - added correct modifiers for methods * reverted change
1 parent 83bccfb commit 53da689

File tree

10 files changed

+231
-41
lines changed

10 files changed

+231
-41
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
1818
## [Unreleased]
1919

2020
### Features
21-
- Add `renderComponent` function in the public API @mnajdova ([#503](https://github.com/stardust-ui/react/pull/503))
21+
- Add `createComponent` function in the public API @mnajdova ([#503](https://github.com/stardust-ui/react/pull/503))
2222
- Apply `dir=auto` attribute to string content of `Text` @kuzhelov ([#5](https://github.com/stardust-ui/react/pull/5))
2323
- Improve `Menu` accessibility behaviors @sophieH29 ([#523](https://github.com/stardust-ui/react/pull/523))
24+
- Add ability to style every slot of `Chat.Message` and remove dependency on `Layout` component @Bugaa92 ([#518](https://github.com/stardust-ui/react/pull/518))
2425

2526
### Fixes
2627
- Fix the behaviour of `AutoControlledComponent` when `undefined` is passed as a prop value @layershifter ([#499](https://github.com/stardust-ui/react/pull/499))

docs/src/components/ComponentDoc/ComponentSidebar/ComponentSidebar.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ class ComponentSidebar extends React.Component<any, any> {
4444
return (
4545
<Sticky context={examplesRef} offset={15}>
4646
<Menu as={Accordion} fluid style={sidebarStyle} text vertical>
47-
{_.map(sections, ({ examples, sectionName }) => (
47+
{_.map(sections, ({ examples, sectionName }, index) => (
4848
<ComponentSidebarSection
4949
activePath={activePath}
5050
examples={examples}
51-
key={sectionName}
51+
key={`${sectionName}-${index}`}
5252
sectionName={sectionName}
5353
onItemClick={onItemClick}
5454
/>

docs/src/examples/components/Chat/Types/ChatExample.shorthand.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const items = [
1111
content: (
1212
<Chat.Message content="Hello" author="John Doe" timestamp="Yesterday, 10:15 PM" mine />
1313
),
14+
key: 'message-id-1',
1415
},
1516
{
1617
content: (
@@ -21,6 +22,7 @@ const items = [
2122
avatar={janeAvatar}
2223
/>
2324
),
25+
key: 'message-id-2',
2426
},
2527
{
2628
content: (
@@ -31,6 +33,7 @@ const items = [
3133
mine
3234
/>
3335
),
36+
key: 'message-id-3',
3437
},
3538
{
3639
content: (
@@ -41,9 +44,11 @@ const items = [
4144
avatar={janeAvatar}
4245
/>
4346
),
47+
key: 'message-id-4',
4448
},
4549
{
4650
content: <Divider content="Today" type="primary" important />,
51+
key: 'message-id-5',
4752
},
4853
{
4954
content: (
@@ -54,6 +59,7 @@ const items = [
5459
mine
5560
/>
5661
),
62+
key: 'message-id-6',
5763
},
5864
]
5965

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import React from 'react'
2+
import { Chat, Provider } from '@stardust-ui/react'
3+
4+
const janeAvatar = {
5+
image: 'public/images/avatar/small/ade.jpg',
6+
status: { color: 'green', icon: 'check' },
7+
}
8+
9+
const content = (
10+
<div>
11+
Sure! Try one of these places:<br />
12+
<a href="#">www.goodFood1.com</a>,<br />
13+
<a href="#">www.goodFood2.com</a> or<br />
14+
<a href="#">www.goodFood3.com</a>
15+
</div>
16+
)
17+
18+
const slotLabelStyles: any = (label, beforeStyles) => ({
19+
position: 'relative',
20+
border: '1px solid #000',
21+
padding: '12px',
22+
':before': {
23+
content: `'${label}'`,
24+
position: 'absolute',
25+
background: '#000',
26+
paddingBottom: '2px',
27+
bottom: '-1px',
28+
right: '-1px',
29+
color: 'white',
30+
fontSize: '11px',
31+
letterSpacing: '0.1px',
32+
lineHeight: '9px',
33+
...beforeStyles,
34+
},
35+
})
36+
37+
const ChatMessageExampleStyled = () => (
38+
<Provider
39+
theme={{
40+
componentStyles: {
41+
ChatMessage: {
42+
root: { ...slotLabelStyles('root'), backgroundColor: '#2E8B57' },
43+
avatar: {
44+
...slotLabelStyles('avatar', { bottom: '-11px' }),
45+
backgroundColor: '#FF00FF',
46+
padding: 0,
47+
},
48+
messageBody: { ...slotLabelStyles('messageBody'), backgroundColor: '#87CEFA' },
49+
author: { ...slotLabelStyles('author'), backgroundColor: '#E0FFFF' },
50+
content: { ...slotLabelStyles('content'), backgroundColor: '#F08080' },
51+
timestamp: { ...slotLabelStyles('timestamp'), backgroundColor: '#FFFFE0' },
52+
},
53+
},
54+
componentVariables: {
55+
ChatMessage: siteVars => ({
56+
messageBody: {
57+
focusOutlineColor: siteVars.white,
58+
},
59+
}),
60+
},
61+
}}
62+
>
63+
<Chat
64+
items={[
65+
{
66+
content: (
67+
<Chat.Message
68+
content="Hey, do you know any restaurants with good food?"
69+
author="John Doe"
70+
timestamp="Yesterday, 10:15 PM"
71+
mine
72+
/>
73+
),
74+
key: 'message-id-1',
75+
},
76+
{
77+
key: 'message-id-2',
78+
content: (
79+
<Chat.Message
80+
content={{ content }}
81+
author="Jane Doe"
82+
timestamp="Yesterday, 10:15 PM"
83+
avatar={janeAvatar}
84+
/>
85+
),
86+
},
87+
]}
88+
/>
89+
</Provider>
90+
)
91+
92+
export default ChatMessageExampleStyled
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import React from 'react'
2+
import { Chat, Provider } from '@stardust-ui/react'
3+
4+
const janeAvatar = {
5+
image: 'public/images/avatar/small/ade.jpg',
6+
status: { color: 'green', icon: 'check' },
7+
}
8+
9+
const content = (
10+
<div>
11+
Sure! Try one of these places:<br />
12+
<a href="#">www.goodFood1.com</a>,<br />
13+
<a href="#">www.goodFood2.com</a> or<br />
14+
<a href="#">www.goodFood3.com</a>
15+
</div>
16+
)
17+
18+
const slotLabelStyles: any = (label, beforeStyles) => ({
19+
position: 'relative',
20+
border: '1px solid #000',
21+
padding: '12px',
22+
':before': {
23+
content: `'${label}'`,
24+
position: 'absolute',
25+
background: '#000',
26+
paddingBottom: '2px',
27+
bottom: '-1px',
28+
right: '-1px',
29+
color: 'white',
30+
fontSize: '11px',
31+
letterSpacing: '0.1px',
32+
lineHeight: '9px',
33+
...beforeStyles,
34+
},
35+
})
36+
37+
const ChatMessageExampleStyled = () => (
38+
<Provider
39+
theme={{
40+
componentStyles: {
41+
ChatMessage: {
42+
root: { ...slotLabelStyles('root'), backgroundColor: '#2E8B57' },
43+
avatar: {
44+
...slotLabelStyles('avatar', { bottom: '-11px' }),
45+
backgroundColor: '#FF00FF',
46+
padding: 0,
47+
},
48+
messageBody: { ...slotLabelStyles('messageBody'), backgroundColor: '#87CEFA' },
49+
author: { ...slotLabelStyles('author'), backgroundColor: '#E0FFFF' },
50+
content: { ...slotLabelStyles('content'), backgroundColor: '#F08080' },
51+
timestamp: { ...slotLabelStyles('timestamp'), backgroundColor: '#FFFFE0' },
52+
},
53+
},
54+
componentVariables: {
55+
ChatMessage: siteVars => ({
56+
messageBody: {
57+
focusOutlineColor: siteVars.white,
58+
},
59+
}),
60+
},
61+
}}
62+
>
63+
<Chat>
64+
<Chat.Item>
65+
<Chat.Message
66+
content="Hey, do you know any restaurants with good food?"
67+
author="John Doe"
68+
timestamp="Yesterday, 10:15 PM"
69+
mine
70+
/>
71+
</Chat.Item>
72+
<Chat.Item>
73+
<Chat.Message
74+
content={{ content }}
75+
author="Jane Doe"
76+
timestamp="Yesterday, 10:15 PM"
77+
avatar={janeAvatar}
78+
/>
79+
</Chat.Item>
80+
</Chat>
81+
</Provider>
82+
)
83+
84+
export default ChatMessageExampleStyled

docs/src/examples/components/Chat/Types/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ const Types = () => (
99
description="A default Chat."
1010
examplePath="components/Chat/Types/ChatExample"
1111
/>
12+
<ComponentExample
13+
title="Styled Chat Item"
14+
description="A Chat item with custom styles for every slot."
15+
examplePath="components/Chat/Types/ChatMessageExampleStyled"
16+
/>
1217
</ExampleSection>
1318
)
1419

src/components/Chat/Chat.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ class Chat extends UIComponent<Extendable<ChatProps>, any> {
4848
renderItem: PropTypes.func,
4949
}
5050

51-
static defaultProps = { accessibility: chatBehavior as Accessibility, as: 'ul' }
51+
static defaultProps = { accessibility: chatBehavior, as: 'ul' }
5252

5353
static Item = ChatItem
5454
static Message = ChatMessage
5555

56-
actionHandlers: AccessibilityActionHandlers = {
57-
focus: event => this.focusZone && this.focusZone.focus(),
56+
protected actionHandlers: AccessibilityActionHandlers = {
57+
focus: () => this.focusZone && this.focusZone.focus(),
5858
}
5959

6060
renderComponent({ ElementType, classes, accessibility, rest }) {

src/components/Chat/ChatMessage.tsx

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,14 @@ import { Extendable, ShorthandRenderFunction, ShorthandValue } from '../../../ty
1818
import Avatar from '../Avatar/Avatar'
1919
import { chatMessageBehavior } from '../../lib/accessibility'
2020
import { Accessibility, AccessibilityActionHandlers } from '../../lib/accessibility/types'
21-
import Layout from '../Layout/Layout'
2221
import Text from '../Text/Text'
2322
import Slot from '../Slot/Slot'
2423
import {
2524
UIComponentProps,
2625
ChildrenComponentProps,
2726
ContentComponentProps,
2827
} from '../../lib/commonPropInterfaces'
29-
import {
30-
commonUIComponentPropTypes,
31-
childrenComponentPropTypes,
32-
contentComponentPropsTypes,
33-
} from '../../lib/commonPropTypes'
28+
import { commonUIComponentPropTypes, childrenComponentPropTypes } from '../../lib/commonPropTypes'
3429

3530
export interface ChatMessageProps
3631
extends UIComponentProps<any, any>,
@@ -104,10 +99,10 @@ class ChatMessage extends UIComponent<Extendable<ChatMessageProps>, any> {
10499
static propTypes = {
105100
...commonUIComponentPropTypes,
106101
...childrenComponentPropTypes,
107-
...contentComponentPropsTypes,
108102
accessibility: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
109103
author: customPropTypes.itemShorthand,
110104
avatar: customPropTypes.itemShorthand,
105+
content: customPropTypes.itemShorthand,
111106
mine: PropTypes.bool,
112107
renderAuthor: PropTypes.func,
113108
renderAvatar: PropTypes.func,
@@ -117,11 +112,11 @@ class ChatMessage extends UIComponent<Extendable<ChatMessageProps>, any> {
117112
}
118113

119114
static defaultProps = {
120-
accessibility: chatMessageBehavior as Accessibility,
115+
accessibility: chatMessageBehavior,
121116
as: 'div',
122117
}
123118

124-
actionHandlers: AccessibilityActionHandlers = {
119+
protected actionHandlers: AccessibilityActionHandlers = {
125120
// prevents default FocusZone behavior, e.g., in ChatMessageBehavior, it prevents FocusZone from using arrow keys as navigation (only Tab key should work)
126121
preventDefault: event => {
127122
event.preventDefault()
@@ -137,7 +132,6 @@ class ChatMessage extends UIComponent<Extendable<ChatMessageProps>, any> {
137132
variables,
138133
}: RenderResultConfig<ChatMessageProps>) {
139134
const { children } = this.props
140-
141135
const childrenPropExists = childrenExist(children)
142136
const className = childrenPropExists ? cx(classes.root, classes.content) : classes.root
143137

@@ -153,7 +147,7 @@ class ChatMessage extends UIComponent<Extendable<ChatMessageProps>, any> {
153147
)
154148
}
155149

156-
renderContent = (
150+
private renderContent = (
157151
classes: ComponentSlotClasses,
158152
styles: ComponentSlotStylesInput,
159153
variables: ComponentVariablesInput,
@@ -182,45 +176,34 @@ class ChatMessage extends UIComponent<Extendable<ChatMessageProps>, any> {
182176
defaultProps: {
183177
size: 'small',
184178
styles: styles.author,
185-
variables: variables.author,
186179
},
187180
render: renderAuthor,
188181
})
189182

190183
const timestampElement = Text.create(timestamp, {
191184
defaultProps: {
192185
size: 'small',
193-
timestamp: true,
194186
styles: styles.timestamp,
195-
variables: variables.timestamp,
187+
timestamp: true,
196188
},
197189
render: renderTimestamp,
198190
})
199191

200192
const contentElement = Slot.create(content, {
201-
styles: styles.content,
202-
variables: variables.content,
193+
defaultProps: { styles: styles.content },
203194
render: renderContent,
204195
})
205196

206197
return (
207-
<Layout
208-
start={!mine && avatarElement}
209-
main={
210-
<Layout
211-
className={classes.content}
212-
vertical
213-
start={
214-
<>
215-
{!mine && authorElement}
216-
{timestampElement}
217-
</>
218-
}
219-
main={contentElement}
220-
/>
221-
}
222-
end={mine && avatarElement}
223-
/>
198+
<>
199+
{!mine && avatarElement}
200+
<Slot className={cx('ui-chat__message__messageBody', classes.messageBody)}>
201+
{!mine && authorElement}
202+
{timestampElement}
203+
{contentElement}
204+
</Slot>
205+
{mine && avatarElement}
206+
</>
224207
)
225208
}
226209
}

0 commit comments

Comments
 (0)