Skip to content
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
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ const MessageLoading = () => (
export default MessageLoading;

~~~

Here is a table:

| Version | GA date | User role
|-|-|-|
| 2.5 | September 30, 2024 | Administrator |
| 2.5 | June 27, 2023 | Editor |
| 3.0 | April 1, 2025 | Administrator
`;

// It's important to set a date and timestamp prop since the Message components re-render.
Expand All @@ -111,7 +119,8 @@ const initialMessages: MessageProps[] = [
name: 'User',
avatar: userAvatar,
timestamp: date.toLocaleString(),
avatarProps: { isBordered: true }
avatarProps: { isBordered: true },
isPrimary: true
},
{
id: '2',
Expand All @@ -131,7 +140,9 @@ const initialMessages: MessageProps[] = [
download: { onClick: () => console.log('Download') },
// eslint-disable-next-line no-console
listen: { onClick: () => console.log('Listen') }
}
},
isPrimary: true,
attachments: [{ name: 'auth-operator.yml', id: '1' }]
}
];

Expand Down Expand Up @@ -220,7 +231,8 @@ export const EmbeddedChatbotDemo: FunctionComponent = () => {
name: 'User',
avatar: userAvatar,
timestamp: date.toLocaleString(),
avatarProps: { isBordered: true }
avatarProps: { isBordered: true },
isPrimary: true
});
newMessages.push({
id: generateId(),
Expand All @@ -229,7 +241,8 @@ export const EmbeddedChatbotDemo: FunctionComponent = () => {
name: 'Bot',
avatar: patternflyAvatar,
isLoading: true,
timestamp: date.toLocaleString()
timestamp: date.toLocaleString(),
isPrimary: true
});
setMessages(newMessages);
// make announcement to assistive devices that new messages have been added
Expand Down Expand Up @@ -261,7 +274,8 @@ export const EmbeddedChatbotDemo: FunctionComponent = () => {
// eslint-disable-next-line no-console
listen: { onClick: () => console.log('Listen') }
},
timestamp: date.toLocaleString()
timestamp: date.toLocaleString(),
isPrimary: true
});
setMessages(loadedMessages);
// make announcement to assistive devices that new message has loaded
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions packages/module/src/FileDetailsLabel/FileDetailsLabel.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { PropsWithChildren } from 'react';
import { Button, Label } from '@patternfly/react-core';
import { Button, Label, LabelProps } from '@patternfly/react-core';
import FileDetails from '../FileDetails';
import { Spinner } from '@patternfly/react-core';
import { TimesIcon } from '@patternfly/react-icons';

export interface FileDetailsLabelProps {
export interface FileDetailsLabelProps extends Omit<LabelProps, 'onClose' | 'onClick'> {
/** Name of file, including extension */
fileName: string;
/** Unique id of file */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@
--pf-chatbot-message-text-inline-code-font-size: var(--pf-t--global--font--size--body--default);
background-color: var(--pf-t--global--background--color--tertiary--default);
font-size: var(--pf-chatbot-message-text-inline-code-font-size);

&.pf-m-primary {
background-color: var(--pf-t--global--background--color--secondary--default);
}
}

.pf-chatbot__message-code-toggle {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export interface CodeBlockMessageProps {
collapsedText?: string;
/** Custom actions added to header of code block, after any default actions such as the "copy" action. */
customActions?: React.ReactNode;
/** Sets background colors to be appropriate on primary chatbot background */
isPrimary?: boolean;
}

const DEFAULT_EXPANDED_TEXT = 'Show less';
Expand All @@ -54,6 +56,7 @@ const CodeBlockMessage = ({
expandedText = DEFAULT_EXPANDED_TEXT,
collapsedText = DEFAULT_COLLAPSED_TEXT,
customActions,
isPrimary,
...props
}: CodeBlockMessageProps) => {
const [copied, setCopied] = useState(false);
Expand Down Expand Up @@ -108,7 +111,7 @@ const CodeBlockMessage = ({

if (!String(children).includes('\n')) {
return (
<code {...props} className="pf-chatbot__message-inline-code">
<code {...props} className={`pf-chatbot__message-inline-code ${isPrimary ? 'pf-m-primary' : ''}`}>
{children}
</code>
);
Expand Down
37 changes: 37 additions & 0 deletions packages/module/src/Message/Message.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1093,4 +1093,41 @@ describe('Message', () => {
expect(screen.getByText('Thought for 3 seconds')).toBeTruthy();
expect(screen.getByText("Here's why I said this.")).toBeTruthy();
});
it('should handle isPrimary correctly for inline code when it is true', () => {
const { container } = render(<Message avatar="./img" role="user" name="User" content={INLINE_CODE} isPrimary />);
expect(container.querySelector('.pf-m-primary')).toBeTruthy();
});
it('should handle isPrimary correctly for inline code when it is false', () => {
const { container } = render(<Message avatar="./img" role="user" name="User" content={INLINE_CODE} />);
expect(container.querySelector('.pf-m-primary')).toBeFalsy();
});
it('should handle isPrimary correctly for table when it is true', () => {
const { container } = render(<Message avatar="./img" role="user" name="User" content={TABLE} isPrimary />);
expect(container.querySelector('.pf-m-primary')).toBeTruthy();
});
it('should handle isPrimary correctly for table when it is false', () => {
const { container } = render(<Message avatar="./img" role="user" name="User" content={TABLE} />);
expect(container.querySelector('.pf-m-primary')).toBeFalsy();
});
it('should handle isPrimary correctly for loading when it is true', () => {
const { container } = render(<Message avatar="./img" role="user" name="User" content="" isPrimary isLoading />);
expect(container.querySelector('.pf-m-primary')).toBeTruthy();
});
it('should handle isPrimary correctly for loading when it is false', () => {
const { container } = render(<Message avatar="./img" role="user" name="User" content="" isLoading />);

expect(container.querySelector('.pf-m-primary')).toBeFalsy();
});
it('should handle isPrimary correctly for attachments when it is true', () => {
const { container } = render(
<Message avatar="./img" role="user" name="User" content="" isPrimary attachments={[{ name: 'testAttachment' }]} />
);
expect(container.querySelector('.pf-m-outline')).toBeTruthy();
});
it('should handle isPrimary correctly for attachments when it is false', () => {
const { container } = render(
<Message avatar="./img" role="user" name="User" content="" attachments={[{ name: 'testAttachment' }]} />
);
expect(container.querySelector('.pf-m-outline')).toBeFalsy();
});
});
12 changes: 8 additions & 4 deletions packages/module/src/Message/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
toolCall?: ToolCallProps;
/** Whether user messages default to stripping out images in markdown */
hasNoImagesInUserMessages?: boolean;
/** Sets background colors to be appropriate on primary chatbot background */
isPrimary?: boolean;
}

export const MessageBase: FunctionComponent<MessageProps> = ({
Expand Down Expand Up @@ -236,6 +238,7 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
remarkGfmProps,
toolCall,
hasNoImagesInUserMessages = true,
isPrimary,
...props
}: MessageProps) => {
const [messageText, setMessageText] = useState(content);
Expand Down Expand Up @@ -286,13 +289,13 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
p: (props) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { node, ...rest } = props;
return <TextMessage component={ContentVariants.p} {...rest} />;
return <TextMessage component={ContentVariants.p} {...rest} isPrimary={isPrimary} />;
},
code: ({ children, ...props }) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { node, ...codeProps } = props;
return (
<CodeBlockMessage {...codeProps} {...codeBlockProps}>
<CodeBlockMessage {...codeProps} {...codeBlockProps} isPrimary={isPrimary}>
{children}
</CodeBlockMessage>
);
Expand Down Expand Up @@ -348,7 +351,7 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
return <ListItemMessage {...rest} />;
},
// table requires node attribute for calculating headers for mobile breakpoint
table: (props) => <TableMessage {...props} {...tableProps} />,
table: (props) => <TableMessage {...props} {...tableProps} isPrimary={isPrimary} />,
tbody: (props) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { node, ...rest } = props;
Expand Down Expand Up @@ -416,7 +419,7 @@ export const MessageBase: FunctionComponent<MessageProps> = ({

const renderMessage = () => {
if (isLoading) {
return <MessageLoading loadingWord={loadingWord} />;
return <MessageLoading loadingWord={loadingWord} isPrimary={isPrimary} />;
}
if (isEditable) {
return (
Expand Down Expand Up @@ -522,6 +525,7 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
closeButtonAriaLabel={attachment.closeButtonAriaLabel}
languageTestId={attachment.languageTestId}
spinnerTestId={attachment.spinnerTestId}
variant={isPrimary ? 'outline' : undefined}
/>
</div>
))}
Expand Down
4 changes: 4 additions & 0 deletions packages/module/src/Message/MessageLoading.scss
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@
background-color: rgba(41, 41, 41, 0.25);
}
}

&.pf-m-primary {
background-color: var(--pf-t--global--background--color--secondary--default);
}
}
4 changes: 2 additions & 2 deletions packages/module/src/Message/MessageLoading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Chatbot Main - Message - Processing
// ============================================================================

const MessageLoading = ({ loadingWord }) => (
<div className="pf-chatbot__message-loading">
const MessageLoading = ({ loadingWord, isPrimary }) => (
<div className={`pf-chatbot__message-loading ${isPrimary ? 'pf-m-primary' : ''}`}>
<span className="pf-chatbot__message-loading-dots">
<span className="pf-v6-screen-reader">{loadingWord}</span>
</span>
Expand Down
4 changes: 4 additions & 0 deletions packages/module/src/Message/TableMessage/TableMessage.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
border-block-start: 0;
}

&.pf-m-primary {
--pf-v6-c-table--BackgroundColor: var(--pf-t--global--background--color--secondary--default) !important;
}

tbody {
border-radius: var(--pf-t--global--border--radius--small);
}
Expand Down
8 changes: 6 additions & 2 deletions packages/module/src/Message/TableMessage/TableMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ export interface TableNode {
type: string;
}

const TableMessage = ({ children, ...props }: Omit<TableProps, 'ref'> & ExtraProps) => {
export interface TableMessageProps {
isPrimary?: boolean;
}

const TableMessage = ({ children, isPrimary, ...props }: Omit<TableProps, 'ref'> & ExtraProps & TableMessageProps) => {
const { className, ...rest } = props;

// This allows us to parse the nested data we get back from the 3rd party Markdown parser
Expand Down Expand Up @@ -72,7 +76,7 @@ const TableMessage = ({ children, ...props }: Omit<TableProps, 'ref'> & ExtraPro
<Table
aria-label={props['aria-label']}
gridBreakPoint="grid"
className={`pf-chatbot__message-table ${className ? className : ''}`}
className={`pf-chatbot__message-table ${isPrimary ? 'pf-m-primary' : ''} ${className ? className : ''}`}
{...rest}
>
{modifyChildren(children)}
Expand Down
6 changes: 6 additions & 0 deletions packages/module/src/Message/TextMessage/TextMessage.scss
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@
white-space: nowrap;
width: 1px;
}

&.pf-m-primary {
code {
background-color: var(--pf-t--global--background--color--secondary--default);
}
}
}

// ============================================================================
Expand Down
13 changes: 11 additions & 2 deletions packages/module/src/Message/TextMessage/TextMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,17 @@
import { ExtraProps } from 'react-markdown';
import { Content, ContentProps } from '@patternfly/react-core';

const TextMessage = ({ component, children, ...props }: Omit<ContentProps, 'ref'> & ExtraProps) => (
<span className="pf-chatbot__message-text">
export interface TextMessageProps {
isPrimary?: boolean;
}

const TextMessage = ({
component,
children,
isPrimary,
...props
}: Omit<ContentProps, 'ref'> & ExtraProps & TextMessageProps) => (
<span className={`pf-chatbot__message-text ${isPrimary ? 'pf-m-primary' : ''}`}>
<Content component={component} {...props}>
{children}
</Content>
Expand Down
Loading