This repo contains a set of opinionated react component groups used to standardize functionality and look and feel across products. The components are based on PatternFly with some additional functionality.
main - PatternFly 6 implementation
v5 - PatternFly 5 implementation
do-not-delete - do not delete
NOTE: If new features are not needed in
v5,they should be added directly to themainbranch. For bug fixes, it is preferred to fix the bug for both versions (fix in one branch and cherry-pick to another). Pulling new changes from 5 to 6 and vice versa is not recommended usingrebase. Rather, always cherry-pick specific commits.
Migration from RedHatInsights/frontend-components to patternfly/react-component-groups
Please see the migration guide
Please reference PatternFly's AI-assisted development guidelines if you'd like to contribute code generated using AI.
- make sure your use case is new/complex enough to be added to this extension
- the component should bring a value value above and beyond existing PatternFly components
- create a folder in
src/matching its name (for examplesrc/MyComponent) - to the new folder add a new
.tsxfile named after the component (for examplesrc/MyComponent/MyComponent.tsx) - to the same folder include an
index.tswhich will export the component as a default and then all necessary interfaces - if this file structure is not met, your component won't be exposed correctly
import * as React from 'react';
import { Content } from '@patternfly/react-core';
import { createUseStyles } from 'react-jss';
// do not forget to export your component's interface
// always place the component's interface above the component itself in the code
export interface MyComponentProps {
text: String;
}
const useStyles = createUseStyles({
myText: {
fontFamily: 'monospace',
fontSize: 'var(--pf-v6-global--icon--FontSize--md)',
},
})
// do not use the named export of your component, just a default one
import { FunctionComponent } from 'react';
const MyComponent: FunctionComponent<MyComponentProps> = () => {
const classes = useStyles();
return (
<Content className={classes.myText}>
This is my new reusable component
</Content>
);
};
export default MyComponent;
export { default } from './MyComponent';
export * from './MyComponent';
src
|- MyComponent
|- index.ts
|- MyComponent.tsx
- prop names comply with PatternFly components naming standards (
variant,onClick,position, etc.) - the API is maximally simplified and all props are provided with a description
- it is built on top of existing PatternFly types without prop omitting
- it is well documented using the PatternFly documentation (
/packages/module/patternfly-docs/content/extensions/component-groups/examples/MyComponent/MyComponent.md) with examples of all possible use cases (packages/module/patternfly-docs/content/extensions/component-groups/examples/MyComponent/MyComponent[...]Example.tsx) - do not unnecessarily use external libraries in your component - rather, delegate the necessary logic to the component's user using the component's API
import { FunctionComponent } from 'react';
// when possible, extend available PatternFly types
export interface MyComponentProps extends ButtonProps {
customLabel: Boolean
};
export const MyComponent: FunctionComponent<MyComponentProps> = ({ customLabel, ...props }) => ( ... );
---
section: Component groups
subsection: My component's category
id: MyComponent
propComponents: ['MyComponent']
---
import MyComponent from "@patternfly/react-component-groups/dist/dynamic/MyComponent";
## Component usage
MyComponent has been created to demo contributing to this repository.
### MyComponent component example label
```js file="./MyComponentExample.tsx"```
import { FunctionComponent } from 'react';
const MyComponentExample: FunctionComponent = () => (
<MyComponent customLabel="My label">
);
export default MyComponentExample;
When adding a component for which it is advantageous to divide it into several sub-components make sure:
- component and all its sub-components are located in separate files and directories straight under the
src/folder - sub-components are exported and documented separately from their parent
- parent component should provide a way to pass props to all its sub-components
The aim is to enable the user of our "complex" component to use either complete or take advantage of its sub-components and manage their composition independently.
When adding/making changes to a component, always make sure your code is tested:
- use React Testing Library for unit testing
- add unit tests to a
[ComponentName].test.tsxfile to your component's directory - make sure all the core functionality is covered using Cypress component or E2E tests
- add component tests to
cypress/component/[ComponentName].cy.tsxfile and E2E tests tocypress/e2e/[ComponentName].spec.cy.ts - add
ouiaIdto the component props definition with a default value of the component name (for subcomponents, let's useComponentName-element-specificationnaming convention e.g.ouiaId="WarningModal-confirm-button")
- for styling always use JSS
- new classNames should be named in camelCase starting with the name of a given component and following with more details clarifying its purpose/component's subsection to which the class is applied (
actionMenu,actionMenuDropdown,actionMenuDropdownToggle, etc.) - do not use
pf-v6-u-XXXclasses, use CSS variables in a custom class instead (styles for the utility classes are not bundled with the standard patternfly.css - it would require the consumer to import also addons.css)
- run
npm install - run
npm run build
- run
npm install - run
npm run startto build and start the development server
- run
npm run testto run the unit tests - run
npm run cypress:run:cpto run Cypress component tests - run
npm run cypress:run:e2eto run Cypress E2E tests - run
npm run lintto run the linter
- run
npm run build:docsfollowed bynpm run serve:docs, then runnpm run test:a11yin a new terminal window to run our accessibility tests for the components. Once the accessibility tests have finished running you can runnpm run serve:a11yto locally view the generated report.