Skip to content

Commit 5ec1749

Browse files
authored
Merge pull request #440 from rebeccaalpert/image-message
feat(Message): Add styles for messages with images
2 parents 2b67fa7 + cada5e6 commit 5ec1749

File tree

11 files changed

+158
-4
lines changed

11 files changed

+158
-4
lines changed

package-lock.json

Lines changed: 96 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"@patternfly/documentation-framework": "^6.5.0",
4343
"@patternfly/patternfly": "^6.1.0",
4444
"@patternfly/react-icons": "^6.1.0",
45+
"@patternfly/react-table": "^6.1.0",
4546
"@swc/core": "1.3.96",
4647
"@testing-library/dom": "^9.3.4",
4748
"@testing-library/jest-dom": "^6.4.2",
@@ -90,7 +91,6 @@
9091
"puppeteer-cluster": "^0.24.0"
9192
},
9293
"dependencies": {
93-
"@patternfly/react-table": "^6.1.0",
9494
"dompurify": "^3.2.0",
9595
"react-dropzone": "^14.2.3"
9696
},

packages/module/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"react-markdown": "^9.0.1",
4040
"react-syntax-highlighter": "^15.5.0",
4141
"remark-gfm": "^4.0.0",
42+
"rehype-unwrap-images": "^1.0.0",
4243
"path-browserify": "^1.0.1"
4344
},
4445
"peerDependencies": {

packages/module/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export const BotMessageExample: React.FunctionComponent = () => {
3030
return link;
3131
case 'table':
3232
return table;
33+
case 'image':
34+
return image;
3335
default:
3436
return;
3537
}
@@ -136,6 +138,8 @@ _Italic text, formatted with single underscores_
136138
| 3.0 | April 1, 2025 | Administrator
137139
`;
138140

141+
const image = `![Multi-colored wavy lines on a black background](https://cdn.dribbble.com/userupload/10651749/file/original-8a07b8e39d9e8bf002358c66fce1223e.gif)`;
142+
139143
return (
140144
<>
141145
<Message name="Bot" role="bot" avatar={patternflyAvatar} content={`Text-based message from a bot named "Bot"`} />
@@ -234,6 +238,13 @@ _Italic text, formatted with single underscores_
234238
label="Table"
235239
id="table"
236240
/>
241+
<Radio
242+
isChecked={variant === 'image'}
243+
onChange={() => setVariant('image')}
244+
name="bot-message-type"
245+
label="Image"
246+
id="image"
247+
/>
237248
</FormGroup>
238249
</Form>
239250
<Message

packages/module/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export const UserMessageExample: React.FunctionComponent = () => {
3030
return link;
3131
case 'table':
3232
return table;
33+
case 'image':
34+
return image;
3335
default:
3436
return;
3537
}
@@ -136,6 +138,8 @@ _Italic text, formatted with single underscores_
136138
| 3.0 | April 1, 2025 | Administrator
137139
`;
138140

141+
const image = `![Multi-colored wavy lines on a black background](https://cdn.dribbble.com/userupload/10651749/file/original-8a07b8e39d9e8bf002358c66fce1223e.gif)`;
142+
139143
return (
140144
<>
141145
<Message
@@ -224,6 +228,13 @@ _Italic text, formatted with single underscores_
224228
label="Table"
225229
id="user-table"
226230
/>
231+
<Radio
232+
isChecked={variant === 'image'}
233+
onChange={() => setVariant('image')}
234+
name="user-message-type"
235+
label="Image"
236+
id="user-image"
237+
/>
227238
</FormGroup>
228239
</Form>
229240
<Message
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.pf-chatbot__message-image {
2+
border-radius: var(--pf-t--global--border--radius--small);
3+
max-width: 37.5rem; // 600px
4+
max-height: 25rem; // 400px
5+
min-height: 6.25rem; // 100px
6+
// with rehypePlugins={[rehypeUnwrapImages]}, image is not wrapped in p if it is by itself
7+
// however, if in a paragraph tag as part of other content, it should be a block element
8+
display: block;
9+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// ============================================================================
2+
// Chatbot Main - Message - Content - Image
3+
// ============================================================================
4+
5+
import React from 'react';
6+
import { ExtraProps } from 'react-markdown';
7+
8+
const ImageMessage = ({ children, ...props }: JSX.IntrinsicElements['img'] & ExtraProps) => (
9+
<img className="pf-chatbot__message-image" {...props}>
10+
{children}
11+
</img>
12+
);
13+
14+
export default ImageMessage;

packages/module/src/Message/Message.test.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ const EMPTY_TABLE = `
138138
139139
`;
140140

141+
const IMAGE = `![Multi-colored wavy lines on a black background](https://cdn.dribbble.com/userupload/10651749/file/original-8a07b8e39d9e8bf002358c66fce1223e.gif)`;
142+
141143
const checkListItemsRendered = () => {
142144
const items = ['Item 1', 'Item 2', 'Item 3'];
143145
expect(screen.getAllByRole('listitem')).toHaveLength(3);
@@ -741,4 +743,8 @@ describe('Message', () => {
741743
expect(screen.getByTestId('after-main-content')).toContainHTML('<strong>Bold after content</strong>');
742744
expect(screen.getByTestId('end-main-content')).toContainHTML('<strong>Bold end content</strong>');
743745
});
746+
it('should handle image correctly', () => {
747+
render(<Message avatar="./img" role="user" name="User" content={IMAGE} />);
748+
expect(screen.getByRole('img', { name: /Multi-colored wavy lines on a black background/i })).toBeTruthy();
749+
});
744750
});

packages/module/src/Message/Message.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ import TbodyMessage from './TableMessage/TbodyMessage';
3636
import TheadMessage from './TableMessage/TheadMessage';
3737
import ThMessage from './TableMessage/ThMessage';
3838
import { TableProps } from '@patternfly/react-table';
39+
import ImageMessage from './ImageMessage/ImageMessage';
40+
import rehypeUnwrapImages from 'rehype-unwrap-images';
3941

4042
export interface MessageAttachment {
4143
/** Name of file attached to the message */
@@ -234,9 +236,11 @@ export const MessageBase: React.FunctionComponent<MessageProps> = ({
234236
const { width, ...rest } = props;
235237
return <TdMessage {...rest} />;
236238
},
237-
th: (props) => <ThMessage {...props} />
239+
th: (props) => <ThMessage {...props} />,
240+
img: (props) => <ImageMessage {...props} />
238241
}}
239242
remarkPlugins={[remarkGfm]}
243+
rehypePlugins={[rehypeUnwrapImages]}
240244
>
241245
{content}
242246
</Markdown>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const RehypeUnwrapImages = () => null;
2+
3+
export default RehypeUnwrapImages;

0 commit comments

Comments
 (0)