diff --git a/packages/module/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx b/packages/module/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx index 004258f57..bb78c2229 100644 --- a/packages/module/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx +++ b/packages/module/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx @@ -1,104 +1,130 @@ import { useState, FunctionComponent } from 'react'; import Message from '@patternfly/chatbot/dist/dynamic/Message'; import patternflyAvatar from './patternfly_avatar.jpg'; -import { Checkbox, FormGroup, Stack } from '@patternfly/react-core'; +import { Checkbox, FormGroup, Flex, FlexItem } from '@patternfly/react-core'; export const MessageWithFeedbackExample: FunctionComponent = () => { const [hasCloseButton, setHasCloseButton] = useState(false); const [hasTextArea, setHasTextArea] = useState(false); + const [hasChildren, setHasChildren] = useState(false); + + const children = <>Do not share any personal or other sensitive information in your feedback.; return ( <> - - - { - setHasTextArea(!hasTextArea); + + + + { + setHasTextArea(!hasTextArea); + }} + name="feedback-card-with-text-area" + label="Has text area" + id="has-text-area" + /> + { + setHasChildren(!hasChildren); + }} + name="feedback-card-with-children" + label="Has additional content" + id="has-children" + /> + + + + + alert(`Selected ${quickResponse} and received the additional feedback: ${additionalFeedback}`), + hasTextArea, + children: hasChildren ? children : undefined, + // eslint-disable-next-line no-console + onClose: () => console.log('closed feedback form'), + focusOnLoad: false }} - name="basic-inline-radio" - label="Has text area" - id="has-text-area" /> - - - alert(`Selected ${quickResponse} and received the additional feedback: ${additionalFeedback}`), - hasTextArea, - // eslint-disable-next-line no-console - onClose: () => console.log('closed feedback form'), - focusOnLoad: false - }} - /> - - alert(`Selected ${quickResponse} and received the additional feedback: ${additionalFeedback}`), - hasTextArea, - // eslint-disable-next-line no-console - onClose: () => console.log('closed feedback form'), - focusOnLoad: false - }} - isCompact - /> - - - - { - setHasCloseButton(!hasCloseButton); + + + + alert(`Selected ${quickResponse} and received the additional feedback: ${additionalFeedback}`), + hasTextArea, + children: hasChildren ? children : undefined, + // eslint-disable-next-line no-console + onClose: () => console.log('closed feedback form'), + focusOnLoad: false }} - name="basic-inline-radio" - label="Has close button" - id="has-close" + isCompact /> - - + + + + + { + setHasCloseButton(!hasCloseButton); + }} + name="basic-inline-radio" + label="Has close button" + id="has-close" + /> + + + + console.log('closed completion message') : undefined, - focusOnLoad: false - }} - /> - console.log('closed completion message') : undefined, + focusOnLoad: false + }} + /> + + + console.log('closed completion message') : undefined, - focusOnLoad: false - }} - isCompact - /> - + userFeedbackComplete={{ + // eslint-disable-next-line no-console + onClose: hasCloseButton ? () => console.log('closed completion message') : undefined, + focusOnLoad: false + }} + isCompact + /> + + ); }; diff --git a/packages/module/src/Message/UserFeedback/UserFeedback.test.tsx b/packages/module/src/Message/UserFeedback/UserFeedback.test.tsx index 7afea5081..953d9eeec 100644 --- a/packages/module/src/Message/UserFeedback/UserFeedback.test.tsx +++ b/packages/module/src/Message/UserFeedback/UserFeedback.test.tsx @@ -245,4 +245,111 @@ describe('UserFeedback', () => { ); expect(screen.getByTestId('card')).toHaveClass('pf-m-compact'); }); + it('should pass buttonProps to submit button', () => { + render( + + ); + const submitButton = screen.getByRole('button', { name: /Submit/i }); + expect(submitButton).toHaveClass('pf-v6-c-button pf-m-secondary'); + expect(submitButton).toBeDisabled(); + }); + it('should pass cardHeaderProps to card header', () => { + render( + + ); + const cardHeader = screen.getByTestId('card-header'); + expect(cardHeader).toHaveClass('custom-header'); + }); + it('should pass cardBodyProps to card body', () => { + render( + + ); + const cardBody = screen.getByTestId('card-body'); + expect(cardBody).toHaveClass('custom-body'); + }); + it('should pass headingLevelProps to title heading', () => { + render( + + ); + const heading = screen.getByRole('heading', { level: 1, name: /Why did you choose this rating?/i }); + expect(heading).toHaveClass('custom-heading'); + expect(heading).toHaveAttribute('id', 'feedback-title'); + }); + + it('should pass formProps to form', () => { + render( + + ); + const form = screen.getByTestId('feedback-form'); + expect(form).toHaveClass('custom-form'); + }); + it('should pass textAreaProps to text area when hasTextArea is true', () => { + render( + + ); + const textArea = screen.getByTestId('custom-textarea'); + expect(textArea).toHaveAttribute('rows', '5'); + expect(textArea).toHaveAttribute('data-testid', 'custom-textarea'); + }); + it('should pass actionGroupProps to action group', () => { + render( + + ); + const actionGroup = screen.getByTestId('action-group'); + expect(actionGroup).toHaveClass('custom-actions'); + }); + it('should render children', () => { + render( + +
Custom feedback content
+

Additional paragraph

+
+ ); + expect(screen.getByTestId('custom-content')).toBeInTheDocument(); + expect(screen.getByText('Custom feedback content')).toBeInTheDocument(); + expect(screen.getByText('Additional paragraph')).toBeInTheDocument(); + }); }); diff --git a/packages/module/src/Message/UserFeedback/UserFeedback.tsx b/packages/module/src/Message/UserFeedback/UserFeedback.tsx index a3300dc39..3ac4885b3 100644 --- a/packages/module/src/Message/UserFeedback/UserFeedback.tsx +++ b/packages/module/src/Message/UserFeedback/UserFeedback.tsx @@ -8,15 +8,21 @@ import { useState, useRef, useEffect } from 'react'; // Import PatternFly components import { ActionGroup, + ActionGroupProps, Button, + ButtonProps, Card, CardBody, + CardBodyProps, CardHeader, + CardHeaderProps, CardProps, Form, + FormProps, LabelGroupProps, OUIAProps, - TextArea + TextArea, + TextAreaProps } from '@patternfly/react-core'; import QuickResponse from '../QuickResponse/QuickResponse'; import CloseButton from './CloseButton'; @@ -54,6 +60,20 @@ export interface UserFeedbackProps extends Omit, OUIAProp focusOnLoad?: boolean; /** Timestamp passed in by Message for more context in aria announcements */ timestamp?: string; + /** Additional props passed to submit button */ + submitButtonProps?: ButtonProps; + /** Additional props passed to card header */ + cardHeaderProps?: CardHeaderProps; + /** Additional props passed to card body */ + cardBodyProps?: CardBodyProps; + /** Additional props passed to title heading */ + headingLevelProps?: React.HTMLAttributes; + /** Additional props passed to form */ + formProps?: FormProps; + /** Additional props passed to text area */ + textAreaProps?: TextAreaProps; + /** Additional props passed to action group */ + actionGroupProps?: ActionGroupProps; } const UserFeedback: FunctionComponent = ({ @@ -74,6 +94,14 @@ const UserFeedback: FunctionComponent = ({ headingLevel: HeadingLevel = 'h1', focusOnLoad = true, isCompact, + children, + cardHeaderProps, + cardBodyProps, + headingLevelProps, + formProps, + textAreaProps, + actionGroupProps, + submitButtonProps, ...props }: UserFeedbackProps) => { const [selectedResponse, setSelectedResponse] = useState(); @@ -94,11 +122,14 @@ const UserFeedback: FunctionComponent = ({ actions={{ actions: }} + {...cardHeaderProps} > - {title} + + {title} + - -
+ + {quickResponses && ( = ({ placeholder={textAreaPlaceholder} aria-label={textAreaAriaLabel} resizeOrientation="vertical" + {...textAreaProps} /> )} - - + {children} + +