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
96 changes: 14 additions & 82 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"@babel/preset-react": "^7.23.3",
"@babel/preset-typescript": "^7.23.3",
"@octokit/rest": "^18.0.0",
"@patternfly/documentation-framework": "6.28.6",
"@patternfly/documentation-framework": "6.28.9",
"@patternfly/patternfly": "^6.1.0",
"@patternfly/react-icons": "^6.1.0",
"@patternfly/react-table": "^6.1.0",
Expand Down
3 changes: 2 additions & 1 deletion packages/module/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"@patternfly/react-core": "^6.1.0",
"@patternfly/react-icons": "^6.1.0",
"@patternfly/react-table": "^6.1.0",
"@patternfly/react-styles": "^6.1.0",
"@segment/analytics-next": "^1.76.0",
"clsx": "^2.1.0",
"path-browserify": "^1.0.1",
Expand All @@ -55,7 +56,7 @@
},
"devDependencies": {
"@octokit/rest": "^18.0.0",
"@patternfly/documentation-framework": "6.28.6",
"@patternfly/documentation-framework": "6.28.9",
"@patternfly/patternfly": "^6.1.0",
"@patternfly/patternfly-a11y": "^5.0.0",
"@types/dom-speech-recognition": "^0.0.4",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { FunctionComponent, useState } from 'react';
import { MessageBar } from '@patternfly/chatbot/dist/dynamic/MessageBar';

export const ChatbotMessageBarIndicatorThinking: FunctionComponent = () => {
const [isThinking, setIsThinking] = useState(false);
const handleSend = (_message: string | number) => {
setIsThinking(true);

setTimeout(() => {
setIsThinking(false);
}, 10000);
};

return <MessageBar onSendMessage={handleSend} hasAiIndicator isThinking={isThinking} />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,16 @@ To enable the stop button, set `hasStopButton` to `true` and pass in a `handleSt

```

### Message bar with AI indicator styles

To add a more pronounced AI indicator style to the message bar, pass `hasAiIndicator` to the `<MessageBar>` component. You can also enable a "thinking" animation by passing in `isThinking`.

This example shows a simplified method of handling the "thinking" animation: after a user sends a message, the `isThinking` property is set to `true` to trigger the animation, then returns to `false` after 10 seconds to halt the animation.

```ts file="./ChatbotMessageBarIndicatorThinking.tsx" isBeta

```

## Navigation

### Side nav in a drawer
Expand Down
18 changes: 10 additions & 8 deletions packages/module/src/MessageBar/MessageBar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,18 @@

overflow: hidden;

&.pf-m-primary {
box-shadow: inset 0 0 0 1px var(--pf-t--global--border--color--default);
}
&:not(.pf-v6-m-thinking) {
&.pf-m-primary {
box-shadow: inset 0 0 0 1px var(--pf-t--global--border--color--default);
}

&:hover {
box-shadow: inset 0 0 0 1px var(--pf-t--global--border--color--default);
}
&:hover {
box-shadow: inset 0 0 0 1px var(--pf-t--global--border--color--default);
}

&:focus-within {
box-shadow: inset 0 0 0 2px var(--pf-t--global--color--brand--default);
&:focus-within {
box-shadow: inset 0 0 0 2px var(--pf-t--global--color--brand--default);
}
Comment on lines +29 to +40
Copy link
Contributor Author

@thatblindgeye thatblindgeye Oct 31, 2025

Choose a reason for hiding this comment

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

@mcoker this is to prevent box-shadows from blocking out the animation. Was also thinking we could apply some static class to indicate "this message bar will think" ("pf-m-think", sorta like how PF has pf-m-progress and pf-m-in-progress?), which we could have some prop for. Would we want to recommend something like that, though?

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm... just curious - do you know why that style was created as a box shadow and not a border? I wonder if it's because the border width needs to change dynamically and you don't want it to cause the message bar to shift?

If we want to keep that border from showing up when it has -m-thinking (or it's wrapped in something with -m-thinking), this looks like a good candidate for a plain variation since we're effectively creating a separate border for it. Would that work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There were issues that arose when using a border I believe, @rebeccaalpert could explain that better, but yeah the border width changing would at least be one reason.

Do you mean apply a plain variation to the MessageBar wrapper? Then from the consumer end, they'd need to pass aprop to apply that plain styling/class as well as the thinking class?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh sorry I had this and the ai-indicator class confused and thought this was a border style. I think your style block is fine. Having a "will think" class could be good, but the only benefit I can think of is that if we end up needing a .pf-m-think down the road and users will need to add it to get the correct thinking classes, that's already a requirement now (not breaking) instead of a new requirement later on (probably breaking?).

Another thing it could do is create a single .pf-m-think class where you can bundle all of the styles that need to change for .pf-v6-m-thinking instead of sprinkling :not(.pf-v6-m-thinking) throughout existing styles, but you could do that currently by just having a block that uses .pf-v6-m-thinking like this

.pf-chatbot__message-bar {
  &.pf-m-v6-thinking {
    // box-shadow overrides
    // anything else that may come up
  }
}

Can you think of any other benefits of .pf-m-think that I'm not considering?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can you think of any other benefits of .pf-m-think that I'm not considering?

Not off the top of my head no, was just curious about this specific scenario really.

Copy link
Contributor

Choose a reason for hiding this comment

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

Cool, I would just stick with what you have then. FWIW on the border/box-shadow question, @srambach left a comment about that here - https://github.com/patternfly/chatbot/pull/734/files#r2482294423. So we'll probably want to make this a border instead of a box shadow at some point. And if the problem was with the border-width dynamically changing and impacting the message bar layout, you could use a pseudo element to create the border and absolutely position it relative to the message bar.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cool 🫘 , sounds good!

}

&-actions {
Expand Down
12 changes: 12 additions & 0 deletions packages/module/src/MessageBar/MessageBar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -448,4 +448,16 @@ describe('Message bar', () => {
const { container } = render(<MessageBar isPrimary onSendMessage={jest.fn} />);
expect(container.querySelector('.pf-m-primary')).toBeTruthy();
});

it('Renders with class pf-v6-m-ai-indicator when hasAiIndicator is true', () => {
render(<MessageBar onSendMessage={jest.fn} hasAiIndicator />);

expect(screen.getByRole('textbox').closest('.pf-chatbot__message-bar')).toHaveClass('pf-v6-m-ai-indicator');
});

it('Renders with class pf-v6-m-thinking when isThinking is true', () => {
render(<MessageBar onSendMessage={jest.fn} isThinking />);

expect(screen.getByRole('textbox').closest('.pf-chatbot__message-bar')).toHaveClass('pf-v6-m-thinking');
});
});
17 changes: 16 additions & 1 deletion packages/module/src/MessageBar/MessageBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
TextAreaProps,
TooltipProps
} from '@patternfly/react-core';
import { css } from '@patternfly/react-styles';

// Import Chatbot components
import SendButton from './SendButton';
Expand Down Expand Up @@ -120,6 +121,10 @@ export interface MessageBarProps extends Omit<TextAreaProps, 'innerRef'> {
innerRef?: React.Ref<HTMLTextAreaElement>;
/** Sets background color to primary */
isPrimary?: boolean;
/** @beta Flag indicating whether the message bar has an AI indicator border. */
hasAiIndicator?: boolean;
/** @beta Flag indicating whether the chatbot is thinking in response to a query, adding an animation to the message bar. */
isThinking?: boolean;
}

export const MessageBarBase: FunctionComponent<MessageBarProps> = ({
Expand Down Expand Up @@ -151,6 +156,8 @@ export const MessageBarBase: FunctionComponent<MessageBarProps> = ({
dropzoneProps,
innerRef,
isPrimary,
hasAiIndicator,
isThinking,
...props
}: MessageBarProps) => {
// Text Input
Expand Down Expand Up @@ -472,7 +479,15 @@ export const MessageBarBase: FunctionComponent<MessageBarProps> = ({
}

return (
<div className={`pf-chatbot__message-bar ${isPrimary ? 'pf-m-primary' : ''} ${className ?? ''}`}>
<div
className={css(
'pf-chatbot__message-bar',
isPrimary && 'pf-m-primary',
hasAiIndicator && 'pf-v6-m-ai-indicator',
isThinking && 'pf-v6-m-thinking',
className
)}
>
{messageBarContents}
</div>
);
Expand Down
Loading