diff --git a/packages/react-core/src/components/Form/ActionGroup.tsx b/packages/react-core/src/components/Form/ActionGroup.tsx index f01e78a3074..45ed3307d31 100644 --- a/packages/react-core/src/components/Form/ActionGroup.tsx +++ b/packages/react-core/src/components/Form/ActionGroup.tsx @@ -1,6 +1,7 @@ import styles from '@patternfly/react-styles/css/components/Form/form'; import { css } from '@patternfly/react-styles'; +/** @deprecated Use ActionList, ActionListGroup, and ActionListItem in a FormGroup instead. */ export interface ActionGroupProps extends React.HTMLProps { /** Anything that can be rendered as ActionGroup content. */ children?: React.ReactNode; @@ -8,6 +9,7 @@ export interface ActionGroupProps extends React.HTMLProps { className?: string; } +/** @deprecated Use ActionList, ActionListGroup, and ActionListItem in a FormGroup instead. */ export const ActionGroup: React.FunctionComponent = ({ children = null, className = '', diff --git a/packages/react-core/src/components/Form/FormGroup.tsx b/packages/react-core/src/components/Form/FormGroup.tsx index abde71667e0..d20aa842a70 100644 --- a/packages/react-core/src/components/Form/FormGroup.tsx +++ b/packages/react-core/src/components/Form/FormGroup.tsx @@ -21,6 +21,8 @@ export interface FormGroupProps extends Omit, 'l isInline?: boolean; /** Sets the FormGroupControl to be stacked */ isStack?: boolean; + /** Sets the FormGroup action modifier. Used to contain form action buttons. */ + isAction?: boolean; /** Removes top spacer from label. */ hasNoPaddingTop?: boolean; /** ID of an individual field or a group of multiple fields. Required when a role of "group" or "radiogroup" is passed in. @@ -47,6 +49,7 @@ export const FormGroup: React.FunctionComponent = ({ isInline = false, hasNoPaddingTop = false, isStack = false, + isAction = false, fieldId, role, ouiaId, @@ -75,7 +78,7 @@ export const FormGroup: React.FunctionComponent = ({ return (
{ expect(screen.getByTestId('form-group-test-id').firstElementChild).toHaveClass('pf-m-no-padding-top'); }); + test('should render action form group variant', () => { + render( + + + + ); + expect(screen.getByTestId('form-group-test-id')).toHaveClass('pf-m-action'); + }); + test('should render form group variant with required label', () => { const { asFragment } = render( diff --git a/packages/react-core/src/components/Form/__tests__/__snapshots__/FormGroup.test.tsx.snap b/packages/react-core/src/components/Form/__tests__/__snapshots__/FormGroup.test.tsx.snap index 9c61b9cfb36..963cdc3e163 100644 --- a/packages/react-core/src/components/Form/__tests__/__snapshots__/FormGroup.test.tsx.snap +++ b/packages/react-core/src/components/Form/__tests__/__snapshots__/FormGroup.test.tsx.snap @@ -4,7 +4,7 @@ exports[`FormGroup should render correctly when label is not a string with Child
@@ -78,7 +78,7 @@ exports[`FormGroup should render form group variant with node label 1`] = `
@@ -114,7 +114,7 @@ exports[`FormGroup should render form group variant with required label 1`] = `
@@ -154,7 +154,7 @@ exports[`FormGroup should render form group variant without label 1`] = `
@@ -173,7 +173,7 @@ exports[`FormGroup should render form group with additional label info 1`] = `
@@ -218,14 +218,14 @@ exports[`FormGroup should render horizontal form group variant 1`] = `
@@ -260,14 +260,14 @@ exports[`FormGroup should render stacked horizontal form group variant 1`] = `
diff --git a/packages/react-core/src/components/Form/examples/Form.md b/packages/react-core/src/components/Form/examples/Form.md index 8efa6679b1f..5b38dd1e4ef 100644 --- a/packages/react-core/src/components/Form/examples/Form.md +++ b/packages/react-core/src/components/Form/examples/Form.md @@ -6,6 +6,9 @@ cssPrefix: pf-v6-c-form propComponents: [ 'ActionGroup', + 'ActionList', + 'ActionListGroup', + 'ActionListItem', 'Form', 'FormGroup', 'FormGroupLabelHelp', diff --git a/packages/react-core/src/components/Form/examples/FormBasic.tsx b/packages/react-core/src/components/Form/examples/FormBasic.tsx index 93af5d17cb2..a6f8b397923 100644 --- a/packages/react-core/src/components/Form/examples/FormBasic.tsx +++ b/packages/react-core/src/components/Form/examples/FormBasic.tsx @@ -5,7 +5,9 @@ import { TextInput, Checkbox, Popover, - ActionGroup, + ActionList, + ActionListGroup, + ActionListItem, Button, Radio, HelperText, @@ -123,10 +125,18 @@ export const FormBasic: React.FunctionComponent = () => { - - - - + + + + + + + + + + + + ); }; diff --git a/packages/react-core/src/components/Form/examples/FormHorizontal.tsx b/packages/react-core/src/components/Form/examples/FormHorizontal.tsx index aaf4b02b43f..4cb679880e1 100644 --- a/packages/react-core/src/components/Form/examples/FormHorizontal.tsx +++ b/packages/react-core/src/components/Form/examples/FormHorizontal.tsx @@ -7,7 +7,9 @@ import { FormSelect, FormSelectOption, Checkbox, - ActionGroup, + ActionList, + ActionListGroup, + ActionListItem, Button, Radio, HelperText, @@ -112,10 +114,18 @@ export const FormHorizontal: React.FunctionComponent = () => { - - - - + + + + + + + + + + + + ); }; diff --git a/packages/react-core/src/components/Form/examples/FormLimitWidth.tsx b/packages/react-core/src/components/Form/examples/FormLimitWidth.tsx index ac3cfe2faf2..0ba83999389 100644 --- a/packages/react-core/src/components/Form/examples/FormLimitWidth.tsx +++ b/packages/react-core/src/components/Form/examples/FormLimitWidth.tsx @@ -5,7 +5,9 @@ import { TextInput, Checkbox, Popover, - ActionGroup, + ActionList, + ActionListGroup, + ActionListItem, Button, Radio, HelperText, @@ -123,10 +125,18 @@ export const FormLimitWidth: React.FunctionComponent = () => { - - - - + + + + + + + + + + + + ); }; diff --git a/packages/react-core/src/components/Form/examples/FormState.tsx b/packages/react-core/src/components/Form/examples/FormState.tsx index bf47aa95cac..717809f540f 100644 --- a/packages/react-core/src/components/Form/examples/FormState.tsx +++ b/packages/react-core/src/components/Form/examples/FormState.tsx @@ -1,6 +1,8 @@ import { useState } from 'react'; import { - ActionGroup, + ActionList, + ActionListGroup, + ActionListItem, Button, ButtonType, ButtonVariant, @@ -89,25 +91,36 @@ export const FormState = () => { - - - - + if (!values['input-id']) { + setError('input-id', 'Input value is required.'); + } else { + alert(`Form submitted with: \n ${JSON.stringify(values)}`); + } + }} + > + Submit + + + + + + + + {formStateExpanded && ( <> diff --git a/packages/react-core/src/components/LoginPage/LoginForm.tsx b/packages/react-core/src/components/LoginPage/LoginForm.tsx index c237e79dc66..c6ce6ae3087 100644 --- a/packages/react-core/src/components/LoginPage/LoginForm.tsx +++ b/packages/react-core/src/components/LoginPage/LoginForm.tsx @@ -1,5 +1,6 @@ import { useState } from 'react'; -import { Form, FormGroup, ActionGroup, FormHelperText } from '../Form'; +import { Form, FormGroup, FormHelperText } from '../Form'; +import { ActionList, ActionListGroup, ActionListItem } from '../ActionList'; import { TextInput } from '../TextInput'; import { Button } from '../Button'; import { Checkbox } from '../Checkbox'; @@ -147,11 +148,23 @@ export const LoginForm: React.FunctionComponent = ({ /> )} - - - + + + + + + + + + ); }; diff --git a/packages/react-core/src/components/LoginPage/__tests__/__snapshots__/LoginForm.test.tsx.snap b/packages/react-core/src/components/LoginPage/__tests__/__snapshots__/LoginForm.test.tsx.snap index 0238714fa10..cd9659d36ca 100644 --- a/packages/react-core/src/components/LoginPage/__tests__/__snapshots__/LoginForm.test.tsx.snap +++ b/packages/react-core/src/components/LoginPage/__tests__/__snapshots__/LoginForm.test.tsx.snap @@ -4,14 +4,14 @@ exports[`LoginForm LoginForm with rememberMeLabel 1`] = `
@@ -44,7 +44,7 @@ exports[`LoginForm LoginForm with rememberMeLabel 1`] = ` >
@@ -91,7 +91,7 @@ exports[`LoginForm LoginForm with rememberMeLabel 1`] = ` >
@@ -118,7 +118,7 @@ exports[`LoginForm LoginForm with rememberMeLabel 1`] = `
- + +
+
@@ -166,14 +177,14 @@ exports[`LoginForm LoginForm with show password 1`] = `
@@ -206,7 +217,7 @@ exports[`LoginForm LoginForm with show password 1`] = ` >
@@ -259,7 +270,7 @@ exports[`LoginForm LoginForm with show password 1`] = ` >
- + +
+
@@ -437,26 +459,37 @@ exports[`LoginForm should render Login form 1`] = `
- + +
+
diff --git a/packages/react-core/src/components/SearchInput/AdvancedSearchMenu.tsx b/packages/react-core/src/components/SearchInput/AdvancedSearchMenu.tsx index 05617c59f2f..67095d29d71 100644 --- a/packages/react-core/src/components/SearchInput/AdvancedSearchMenu.tsx +++ b/packages/react-core/src/components/SearchInput/AdvancedSearchMenu.tsx @@ -1,6 +1,7 @@ import { useEffect, useRef, useState } from 'react'; import { Button } from '../Button'; -import { ActionGroup, Form, FormGroup } from '../Form'; +import { ActionList, ActionListGroup, ActionListItem } from '../ActionList'; +import { Form, FormGroup } from '../Form'; import { TextInput } from '../TextInput'; import { useSSRSafeId } from '../../helpers'; import { SearchInputSearchAttribute } from './SearchInput'; @@ -202,16 +203,24 @@ export const AdvancedSearchMenu: React.FunctionComponent {buildFormGroups()} {formAdditionalItems ? formAdditionalItems : null} - - - {!!onClear && ( - - )} - + + + + + + + {!!onClear && ( + + + + )} + + + diff --git a/packages/react-core/src/components/SearchInput/__tests__/__snapshots__/SearchInput.test.tsx.snap b/packages/react-core/src/components/SearchInput/__tests__/__snapshots__/SearchInput.test.tsx.snap index 3d7348cd8cb..c8783dc12bc 100644 --- a/packages/react-core/src/components/SearchInput/__tests__/__snapshots__/SearchInput.test.tsx.snap +++ b/packages/react-core/src/components/SearchInput/__tests__/__snapshots__/SearchInput.test.tsx.snap @@ -442,28 +442,40 @@ exports[`SearchInput advanced search with custom attributes 1`] = ` class="pf-v6-c-form__group-control" >
- - +
+
- Reset - - + +
+
diff --git a/packages/react-core/src/demos/Button/examples/ButtonProgress.tsx b/packages/react-core/src/demos/Button/examples/ButtonProgress.tsx index 6b6bb25a306..01ca43e7173 100644 --- a/packages/react-core/src/demos/Button/examples/ButtonProgress.tsx +++ b/packages/react-core/src/demos/Button/examples/ButtonProgress.tsx @@ -1,5 +1,13 @@ import { useState } from 'react'; -import { Form, FormGroup, ActionGroup, TextInput, Button } from '@patternfly/react-core'; +import { + Form, + FormGroup, + TextInput, + Button, + ActionListItem, + ActionListGroup, + ActionList +} from '@patternfly/react-core'; import RhUiCheckCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-check-circle-fill-icon'; export const ButtonProgress: React.FunctionComponent = () => { @@ -27,28 +35,34 @@ export const ButtonProgress: React.FunctionComponent = () => { aria-label="password input" /> - - - + isLoading={loginState === 'loading'} + icon={loginState === 'loggedIn' ? : null} + spinnerAriaValueText="Loading..." + > + {loginState === 'notLoggedIn' && 'Link account and log in'} + {loginState === 'loading' && 'Linking account'} + {loginState === 'loggedIn' && 'Logged in'} + + + + + ); }; diff --git a/packages/react-core/src/demos/SearchInput/examples/SearchInputAdvancedComposable.tsx b/packages/react-core/src/demos/SearchInput/examples/SearchInputAdvancedComposable.tsx index 6c784d6e873..e547067c993 100644 --- a/packages/react-core/src/demos/SearchInput/examples/SearchInputAdvancedComposable.tsx +++ b/packages/react-core/src/demos/SearchInput/examples/SearchInputAdvancedComposable.tsx @@ -1,6 +1,8 @@ import { useEffect, useRef, useState } from 'react'; import { - ActionGroup, + ActionList, + ActionListGroup, + ActionListItem, Button, DatePicker, Form, @@ -290,16 +292,24 @@ export const SearchInputAdvancedComposable: React.FunctionComponent = () => { - - - {!!onClear && ( - - )} - + + + + + + + + {!!onClear && ( + + )} + + + + diff --git a/packages/react-integration/cypress/integration/searchinput.spec.ts b/packages/react-integration/cypress/integration/searchinput.spec.ts index d522616efcf..5fda7d997c3 100644 --- a/packages/react-integration/cypress/integration/searchinput.spec.ts +++ b/packages/react-integration/cypress/integration/searchinput.spec.ts @@ -62,13 +62,13 @@ describe('Search Input Demo Test', () => { cy.get('#enabled-search .pf-v6-c-form-control > input').eq(1).should('have.value', 'hi'); cy.get('#enabled-search .pf-v6-c-form-control > input').eq(2).should('have.value', 'another test'); - cy.get('#enabled-search .pf-v6-c-form__actions button').eq(1).click({ force: true }); + cy.get('#enabled-search .pf-v6-c-action-list button').eq(1).click({ force: true }); cy.get('#enabled-search .pf-v6-c-text-input-group__text-input').should('have.value', ''); cy.get('#enabled-search .pf-v6-c-form-control > input').eq(1).should('have.value', ''); cy.get('#enabled-search .pf-v6-c-form-control > input').eq(2).should('have.value', ''); cy.get('#enabled-search .pf-v6-c-form-control > input').eq(0).type('test'); - cy.get('#enabled-search .pf-v6-c-form__actions button').eq(0).click({ force: true }); + cy.get('#enabled-search .pf-v6-c-action-list button').eq(0).click({ force: true }); cy.get('#enabled-search .pf-v6-c-form input').should('not.exist'); cy.get('#enabled-search .pf-v6-c-text-input-group__text-input').should('have.value', 'username:test'); });