@patternfly/chatbot 6.6.0-prerelease.4 → 6.6.0-prerelease.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,13 +4,16 @@ import {
4
4
  ExternalLinkAltIcon,
5
5
  VolumeUpIcon,
6
6
  OutlinedThumbsUpIcon,
7
+ ThumbsUpIcon,
7
8
  OutlinedThumbsDownIcon,
9
+ ThumbsDownIcon,
8
10
  OutlinedCopyIcon,
9
11
  DownloadIcon,
10
12
  PencilAltIcon
11
13
  } from '@patternfly/react-icons';
12
14
  import ResponseActionButton from './ResponseActionButton';
13
15
  import { ButtonProps, TooltipProps } from '@patternfly/react-core';
16
+ import { css } from '@patternfly/react-styles';
14
17
 
15
18
  export interface ActionProps extends Omit<ButtonProps, 'ref'> {
16
19
  /** Aria-label for the button */
@@ -49,6 +52,8 @@ type ExtendedActionProps = ActionProps & {
49
52
  */
50
53
 
51
54
  export interface ResponseActionProps {
55
+ /** Additional classes for the response actions container. */
56
+ className?: string;
52
57
  /** Props for message actions, such as feedback (positive or negative), copy button, share, and listen */
53
58
  actions: Record<string, ExtendedActionProps | undefined> & {
54
59
  positive?: ActionProps;
@@ -62,11 +67,22 @@ export interface ResponseActionProps {
62
67
  /** When true, the selected action will persist even when clicking outside the component.
63
68
  * When false (default), clicking outside or clicking another action will deselect the current selection. */
64
69
  persistActionSelection?: boolean;
70
+ /** When true, automatically swaps to filled icon variants when predefined actions are clicked.
71
+ * Predefined actions will use filled variants (e.g., ThumbsUpIcon) when clicked and outline variants (e.g., OutlinedThumbsUpIcon) when not clicked. */
72
+ useFilledIconsOnClick?: boolean;
73
+ /** Flag indicating whether the actions container is only visible when a message is hovered or an action would receive focus. Note
74
+ * that setting this to true will append tooltips inline instead of the document.body.
75
+ */
76
+ showActionsOnInteraction?: boolean;
65
77
  }
66
78
 
67
79
  export const ResponseActions: FunctionComponent<ResponseActionProps> = ({
80
+ className,
68
81
  actions,
69
- persistActionSelection = false
82
+ persistActionSelection = false,
83
+ useFilledIconsOnClick = false,
84
+ showActionsOnInteraction = false,
85
+ ...props
70
86
  }) => {
71
87
  const [activeButton, setActiveButton] = useState<string>();
72
88
  const [clickStatePersisted, setClickStatePersisted] = useState<boolean>(false);
@@ -129,6 +145,7 @@ export const ResponseActions: FunctionComponent<ResponseActionProps> = ({
129
145
  id: string,
130
146
  onClick?: (event: MouseEvent | MouseEvent<Element, MouseEvent> | KeyboardEvent) => void
131
147
  ) => {
148
+ e.stopPropagation();
132
149
  if (persistActionSelection) {
133
150
  if (activeButton === id) {
134
151
  // Toggle off if clicking the same button
@@ -145,8 +162,44 @@ export const ResponseActions: FunctionComponent<ResponseActionProps> = ({
145
162
  onClick && onClick(e);
146
163
  };
147
164
 
165
+ const iconMap = {
166
+ positive: {
167
+ filled: <ThumbsUpIcon />,
168
+ outlined: <OutlinedThumbsUpIcon />
169
+ },
170
+ negative: {
171
+ filled: <ThumbsDownIcon />,
172
+ outlined: <OutlinedThumbsDownIcon />
173
+ }
174
+ };
175
+
176
+ const getIcon = (actionName: string) => {
177
+ const isClicked = activeButton === actionName;
178
+
179
+ if (isClicked && useFilledIconsOnClick) {
180
+ return iconMap[actionName].filled;
181
+ }
182
+
183
+ return iconMap[actionName].outlined;
184
+ };
185
+
186
+ // We want to append the tooltip inline so that hovering the tooltip keeps the actions container visible
187
+ // when showActionsOnInteraction is true. Otherwise hovering the tooltip causes the actions container
188
+ // to disappear but the tooltip will remain visible.
189
+ const getTooltipContainer = (): HTMLElement => responseActions.current || document.body;
190
+
191
+ const getTooltipProps = (tooltipProps?: TooltipProps) =>
192
+ ({
193
+ ...(showActionsOnInteraction && { appendTo: getTooltipContainer }),
194
+ ...tooltipProps
195
+ }) as TooltipProps;
196
+
148
197
  return (
149
- <div ref={responseActions} className="pf-chatbot__response-actions">
198
+ <div
199
+ ref={responseActions}
200
+ className={css('pf-chatbot__response-actions', showActionsOnInteraction && 'pf-m-visible-interaction', className)}
201
+ {...props}
202
+ >
150
203
  {positive && (
151
204
  <ResponseActionButton
152
205
  {...positive}
@@ -157,8 +210,8 @@ export const ResponseActions: FunctionComponent<ResponseActionProps> = ({
157
210
  isDisabled={positive.isDisabled}
158
211
  tooltipContent={positive.tooltipContent ?? 'Good response'}
159
212
  clickedTooltipContent={positive.clickedTooltipContent ?? 'Good response recorded'}
160
- tooltipProps={positive.tooltipProps}
161
- icon={<OutlinedThumbsUpIcon />}
213
+ tooltipProps={getTooltipProps(positive.tooltipProps)}
214
+ icon={getIcon('positive')}
162
215
  isClicked={activeButton === 'positive'}
163
216
  ref={positive.ref}
164
217
  aria-expanded={positive['aria-expanded']}
@@ -175,8 +228,8 @@ export const ResponseActions: FunctionComponent<ResponseActionProps> = ({
175
228
  isDisabled={negative.isDisabled}
176
229
  tooltipContent={negative.tooltipContent ?? 'Bad response'}
177
230
  clickedTooltipContent={negative.clickedTooltipContent ?? 'Bad response recorded'}
178
- tooltipProps={negative.tooltipProps}
179
- icon={<OutlinedThumbsDownIcon />}
231
+ tooltipProps={getTooltipProps(negative.tooltipProps)}
232
+ icon={getIcon('negative')}
180
233
  isClicked={activeButton === 'negative'}
181
234
  ref={negative.ref}
182
235
  aria-expanded={negative['aria-expanded']}
@@ -193,7 +246,7 @@ export const ResponseActions: FunctionComponent<ResponseActionProps> = ({
193
246
  isDisabled={copy.isDisabled}
194
247
  tooltipContent={copy.tooltipContent ?? 'Copy'}
195
248
  clickedTooltipContent={copy.clickedTooltipContent ?? 'Copied'}
196
- tooltipProps={copy.tooltipProps}
249
+ tooltipProps={getTooltipProps(copy.tooltipProps)}
197
250
  icon={<OutlinedCopyIcon />}
198
251
  isClicked={activeButton === 'copy'}
199
252
  ref={copy.ref}
@@ -211,7 +264,7 @@ export const ResponseActions: FunctionComponent<ResponseActionProps> = ({
211
264
  isDisabled={edit.isDisabled}
212
265
  tooltipContent={edit.tooltipContent ?? 'Edit '}
213
266
  clickedTooltipContent={edit.clickedTooltipContent ?? 'Editing'}
214
- tooltipProps={edit.tooltipProps}
267
+ tooltipProps={getTooltipProps(edit.tooltipProps)}
215
268
  icon={<PencilAltIcon />}
216
269
  isClicked={activeButton === 'edit'}
217
270
  ref={edit.ref}
@@ -229,7 +282,7 @@ export const ResponseActions: FunctionComponent<ResponseActionProps> = ({
229
282
  isDisabled={share.isDisabled}
230
283
  tooltipContent={share.tooltipContent ?? 'Share'}
231
284
  clickedTooltipContent={share.clickedTooltipContent ?? 'Shared'}
232
- tooltipProps={share.tooltipProps}
285
+ tooltipProps={getTooltipProps(share.tooltipProps)}
233
286
  icon={<ExternalLinkAltIcon />}
234
287
  isClicked={activeButton === 'share'}
235
288
  ref={share.ref}
@@ -247,7 +300,7 @@ export const ResponseActions: FunctionComponent<ResponseActionProps> = ({
247
300
  isDisabled={download.isDisabled}
248
301
  tooltipContent={download.tooltipContent ?? 'Download'}
249
302
  clickedTooltipContent={download.clickedTooltipContent ?? 'Downloaded'}
250
- tooltipProps={download.tooltipProps}
303
+ tooltipProps={getTooltipProps(download.tooltipProps)}
251
304
  icon={<DownloadIcon />}
252
305
  isClicked={activeButton === 'download'}
253
306
  ref={download.ref}
@@ -265,7 +318,7 @@ export const ResponseActions: FunctionComponent<ResponseActionProps> = ({
265
318
  isDisabled={listen.isDisabled}
266
319
  tooltipContent={listen.tooltipContent ?? 'Listen'}
267
320
  clickedTooltipContent={listen.clickedTooltipContent ?? 'Listening'}
268
- tooltipProps={listen.tooltipProps}
321
+ tooltipProps={getTooltipProps(listen.tooltipProps)}
269
322
  icon={<VolumeUpIcon />}
270
323
  isClicked={activeButton === 'listen'}
271
324
  ref={listen.ref}
@@ -284,7 +337,7 @@ export const ResponseActions: FunctionComponent<ResponseActionProps> = ({
284
337
  className={additionalActions[action]?.className}
285
338
  isDisabled={additionalActions[action]?.isDisabled}
286
339
  tooltipContent={additionalActions[action]?.tooltipContent}
287
- tooltipProps={additionalActions[action]?.tooltipProps}
340
+ tooltipProps={getTooltipProps(additionalActions[action]?.tooltipProps)}
288
341
  clickedTooltipContent={additionalActions[action]?.clickedTooltipContent}
289
342
  icon={additionalActions[action]?.icon}
290
343
  isClicked={activeButton === action}