From 140d089c993624147610b8c92b9bf0dd270e8be4 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Wed, 8 Jul 2026 16:00:58 -0400 Subject: [PATCH 01/37] feat(Tearsheet): Initial scaffolding from sample impl in core patternfly --- README.md | 2 +- packages/module/src/Tearsheet/Tearsheet.tsx | 72 +++++++++++++++ packages/module/src/Tearsheet/index.ts | 2 + packages/module/src/Tearsheet/tearsheet.css | 87 +++++++++++++++++++ .../src/TearsheetBody/TearsheetBody.tsx | 15 ++++ packages/module/src/TearsheetBody/index.ts | 2 + .../src/TearsheetFooter/TearsheetFooter.tsx | 16 ++++ packages/module/src/TearsheetFooter/index.ts | 2 + .../src/TearsheetGroup/TearsheetGroup.tsx | 82 +++++++++++++++++ packages/module/src/TearsheetGroup/index.ts | 2 + .../src/TearsheetHeader/TearsheetHeader.tsx | 16 ++++ packages/module/src/TearsheetHeader/index.ts | 2 + 12 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 packages/module/src/Tearsheet/Tearsheet.tsx create mode 100644 packages/module/src/Tearsheet/index.ts create mode 100644 packages/module/src/Tearsheet/tearsheet.css create mode 100644 packages/module/src/TearsheetBody/TearsheetBody.tsx create mode 100644 packages/module/src/TearsheetBody/index.ts create mode 100644 packages/module/src/TearsheetFooter/TearsheetFooter.tsx create mode 100644 packages/module/src/TearsheetFooter/index.ts create mode 100644 packages/module/src/TearsheetGroup/TearsheetGroup.tsx create mode 100644 packages/module/src/TearsheetGroup/index.ts create mode 100644 packages/module/src/TearsheetHeader/TearsheetHeader.tsx create mode 100644 packages/module/src/TearsheetHeader/index.ts diff --git a/README.md b/README.md index b76a7e5b..b6507124 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Please reference [PatternFly's AI-assisted development guidelines](https://githu ### Before adding a new component: - 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 +- the component should bring a value above and beyond existing PatternFly components ### To add a new component: diff --git a/packages/module/src/Tearsheet/Tearsheet.tsx b/packages/module/src/Tearsheet/Tearsheet.tsx new file mode 100644 index 00000000..dd75e100 --- /dev/null +++ b/packages/module/src/Tearsheet/Tearsheet.tsx @@ -0,0 +1,72 @@ +import type { ReactNode, HTMLProps, FunctionComponent, MouseEvent } from 'react'; +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/Tearsheet/tearsheet'; +import { Modal, ModalVariant } from '@patternfly/react-core'; + +export interface TearsheetProps extends HTMLProps { + /** Content rendered inside the tearsheet. Should be TearsheetHeader, TearsheetBody, and/or TearsheetFooter. */ + children: ReactNode; + /** Additional classes added to the tearsheet. */ + className?: string; + /** Flag to show the tearsheet. */ + isOpen?: boolean; + /** Visual stack level of the tearsheet. Managed automatically by TearsheetGroup. + * When used standalone: 0 (back), 1 (middle), 2 (front). + * TearsheetGroup may also assign -1 (hidden behind the stack). */ + stackLevel?: number; + /** A callback for when the close button is clicked. This prop needs to be passed to render the close button. */ + onClose?: (event: KeyboardEvent | MouseEvent) => void; + /** A callback for when the tearsheet is closed via the escape key. */ + onEscapePress?: (event: KeyboardEvent) => void; + /** The parent container to append the tearsheet to. Defaults to document.body. */ + appendTo?: HTMLElement | (() => HTMLElement); + /** Accessible label for the tearsheet. */ + 'aria-label'?: string; + /** ID of the element that labels the tearsheet. */ + 'aria-labelledby'?: string; + /** ID of the element that describes the tearsheet. */ + 'aria-describedby'?: string; + /** Flag to disable focus trap. */ + disableFocusTrap?: boolean; +} + +const Tearsheet: FunctionComponent = ({ + children, + className, + isOpen = false, + stackLevel: stackLevelProp, + onClose, + onEscapePress, + appendTo, + 'aria-label': ariaLabel, + 'aria-labelledby': ariaLabelledBy, + 'aria-describedby': ariaDescribedBy, + disableFocusTrap, + ...props +}: TearsheetProps) => { + const stackLevel = stackLevelProp ?? 0; + const stackLevelClassname = stackLevel < 0 ? 'pf-m-stack-hidden' : `pf-m-stack-level-${stackLevel}`; + + return ( + +
+ {children} +
+
+ ); +}; +Tearsheet.displayName = 'Tearsheet'; + +export default Tearsheet; diff --git a/packages/module/src/Tearsheet/index.ts b/packages/module/src/Tearsheet/index.ts new file mode 100644 index 00000000..4342d637 --- /dev/null +++ b/packages/module/src/Tearsheet/index.ts @@ -0,0 +1,2 @@ +export { default } from './Tearsheet'; +export * from './Tearsheet'; diff --git a/packages/module/src/Tearsheet/tearsheet.css b/packages/module/src/Tearsheet/tearsheet.css new file mode 100644 index 00000000..904ffa25 --- /dev/null +++ b/packages/module/src/Tearsheet/tearsheet.css @@ -0,0 +1,87 @@ +.pf-v6-c-tearsheet { + width: calc(100% - 4rem) !important; + max-width: calc(100% - 4rem) !important; + height: calc(100% - 4rem) !important; + max-height: calc(100% - 4rem) !important; + inset-block-start: 0 !important; + top: 2rem !important; +} + +/* Override the modal animation custom property to compose stack-level transitions + with the existing open/close animation. Specificity 0,2,0 beats the single-class + declarations in modal-animations.css. */ +.pf-v6-c-modal-animated.pf-v6-c-tearsheet { + --pf-v6-c-modal-animated--Transition: + width 300ms ease, + max-width 300ms ease, + height 300ms ease, + max-height 300ms ease, + top 300ms ease, + opacity 240ms cubic-bezier(0.4, 0.14, 1, 1), + transform 240ms cubic-bezier(0.4, 0.14, 1, 1), + visibility 0ms linear 240ms; +} + +.pf-v6-c-modal-animated-open.pf-v6-c-tearsheet { + --pf-v6-c-modal-animated--Transition: + width 300ms ease, + max-width 300ms ease, + height 300ms ease, + max-height 300ms ease, + top 300ms ease, + transform 240ms cubic-bezier(0, 0, 0.2, 1), + visibility 0ms linear 0ms; +} + +.pf-v6-c-tearsheet.pf-m-stack-level-1 { + width: calc(100% - 2rem) !important; + max-width: calc(100% - 2rem) !important; + height: calc(100% - 6rem) !important; + max-height: calc(100% - 6rem) !important; + inset-block-start: 0 !important; + top: 3rem !important; +} + +.pf-v6-c-tearsheet.pf-m-stack-level-2 { + width: calc(100% - 0rem) !important; + max-width: calc(100% - 0rem) !important; + height: calc(100% - 8rem) !important; + max-height: calc(100% - 8rem) !important; + inset-block-start: 0 !important; + top: 4rem !important; +} + +.pf-v6-c-tearsheet.pf-m-stack-hidden { + width: calc(100% - 4rem) !important; + max-width: calc(100% - 4rem) !important; + height: calc(100% - 4rem) !important; + max-height: calc(100% - 4rem) !important; + inset-block-start: 0 !important; + top: 3rem !important; + opacity: 0 !important; + pointer-events: none !important; +} + +.pf-v6-c-tearsheet-inner { + display: flex; + flex-direction: column; + overflow: hidden; + height: 100%; + margin-inline-end: 0; +} + +.pf-v6-c-tearsheet-header { + flex-shrink: 0; +} + +.pf-v6-c-tearsheet-body { + caret-color: red; +} + +.pf-v6-c-tearsheet-footer { + flex-shrink: 0; +} + +.pf-v6-c-tearsheet-group { + caret-color: red; +} diff --git a/packages/module/src/TearsheetBody/TearsheetBody.tsx b/packages/module/src/TearsheetBody/TearsheetBody.tsx new file mode 100644 index 00000000..7103a869 --- /dev/null +++ b/packages/module/src/TearsheetBody/TearsheetBody.tsx @@ -0,0 +1,15 @@ +import type { FunctionComponent } from 'react'; +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/Tearsheet/tearsheet'; +import { ModalBody, type ModalBodyProps } from '@patternfly/react-core'; + +export interface TearsheetBodyProps extends ModalBodyProps { + className: string; +} + +const TearsheetBody: FunctionComponent = ({ className, ...props }: TearsheetBodyProps) => ( + +); +TearsheetBody.displayName = 'TearsheetBody'; + +export default TearsheetBody; \ No newline at end of file diff --git a/packages/module/src/TearsheetBody/index.ts b/packages/module/src/TearsheetBody/index.ts new file mode 100644 index 00000000..7229a1b8 --- /dev/null +++ b/packages/module/src/TearsheetBody/index.ts @@ -0,0 +1,2 @@ +export { default } from './TearsheetBody'; +export * from './TearsheetBody'; diff --git a/packages/module/src/TearsheetFooter/TearsheetFooter.tsx b/packages/module/src/TearsheetFooter/TearsheetFooter.tsx new file mode 100644 index 00000000..2ac25bc9 --- /dev/null +++ b/packages/module/src/TearsheetFooter/TearsheetFooter.tsx @@ -0,0 +1,16 @@ +import type { FunctionComponent } from 'react'; +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/Tearsheet/tearsheet'; +import { ModalFooter, type ModalFooterProps } from '@patternfly/react-core'; + +export interface TearsheetFooterProps extends ModalFooterProps { + className: string; +} + +export const TearsheetFooter: FunctionComponent = ({ + className, + ...props +}: TearsheetFooterProps) => ; +TearsheetFooter.displayName = 'TearsheetFooter'; + +export default TearsheetFooter; diff --git a/packages/module/src/TearsheetFooter/index.ts b/packages/module/src/TearsheetFooter/index.ts new file mode 100644 index 00000000..97946ba7 --- /dev/null +++ b/packages/module/src/TearsheetFooter/index.ts @@ -0,0 +1,2 @@ +export { default } from './TearsheetFooter'; +export * from './TearsheetFooter'; diff --git a/packages/module/src/TearsheetGroup/TearsheetGroup.tsx b/packages/module/src/TearsheetGroup/TearsheetGroup.tsx new file mode 100644 index 00000000..41d61b7e --- /dev/null +++ b/packages/module/src/TearsheetGroup/TearsheetGroup.tsx @@ -0,0 +1,82 @@ +import { Children, cloneElement, isValidElement, useRef, type FunctionComponent, type ReactElement } from 'react'; +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/Tearsheet/tearsheet'; +import { Tearsheet, type TearsheetProps } from '@patternfly/react-core'; + +/** The maximum number of visually distinct stack levels (0, 1, 2). */ +const MAX_VISIBLE_LEVELS = 3; + +export interface TearsheetGroupProps { + /** Set of Tearsheets to render inside the group. Render order determines stacking + * priority — later children stack in front of earlier ones. Only Tearsheets with + * isOpen={true} participate in the visual stack. */ + children?: React.ReactNode; + /** Additional classes added to the Tearsheet group. */ + className?: string; + /** Unique id for the Tearsheet group. */ + id: string; +} + +const TearsheetGroup: FunctionComponent = ({ + children, + className, + id, + ...props +}: TearsheetGroupProps) => { + // Track each child's last assigned stack level so closing tearsheets keep + // their position during the modal exit animation instead of snapping to L0. + const prevLevelsRef = useRef>(new Map()); + + const openIndices: number[] = []; + Children.forEach(children, (child, index) => { + if (isValidElement(child) && child.type === Tearsheet && (child.props as TearsheetProps).isOpen) { + openIndices.push(index); + } + }); + + const totalOpen = openIndices.length; + const hiddenThreshold = Math.max(0, totalOpen - MAX_VISIBLE_LEVELS); + + const enhancedChildren = Children.map(children, (child, index) => { + if (!isValidElement(child) || child.type !== Tearsheet) { + return child; + } + + const openPosition = openIndices.indexOf(index); + + if (openPosition === -1) { + // Use the last known level if this tearsheet was previously open, so the + // modal close animation plays without a conflicting size/position shift. + // For never-opened tearsheets, prime them at the level they'd occupy if + // they opened next (the frontmost slot). The tearsheet is invisible at + // this point, so the pre-sizing has no visual effect — but it prevents a + // width/height/top transition from firing alongside the modal enter + // animation when the tearsheet does open. + const level = prevLevelsRef.current.get(index) ?? Math.min(totalOpen, MAX_VISIBLE_LEVELS - 1); + return cloneElement(child as ReactElement, { + stackLevel: level + }); + } + + // Levels fill from 0 upward: 1 open → L0, 2 open → L0+L1, 3 open → L0+L1+L2. + // Once all 3 visible slots are used, earlier tearsheets hide behind the stack. + const stackLevel = openPosition < hiddenThreshold ? -1 : openPosition - hiddenThreshold; + const isFrontmost = openPosition === totalOpen - 1; + + prevLevelsRef.current.set(index, stackLevel); + + return cloneElement(child as ReactElement, { + stackLevel, + disableFocusTrap: !isFrontmost + }); + }); + + return ( +
+ {enhancedChildren} +
+ ); +}; +TearsheetGroup.displayName = 'TearsheetGroup'; + +export default TearsheetGroup; diff --git a/packages/module/src/TearsheetGroup/index.ts b/packages/module/src/TearsheetGroup/index.ts new file mode 100644 index 00000000..a6827ad9 --- /dev/null +++ b/packages/module/src/TearsheetGroup/index.ts @@ -0,0 +1,2 @@ +export { default } from './TearsheetGroup'; +export * from './TearsheetGroup'; diff --git a/packages/module/src/TearsheetHeader/TearsheetHeader.tsx b/packages/module/src/TearsheetHeader/TearsheetHeader.tsx new file mode 100644 index 00000000..92ca5782 --- /dev/null +++ b/packages/module/src/TearsheetHeader/TearsheetHeader.tsx @@ -0,0 +1,16 @@ +import type { FunctionComponent } from 'react'; +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/Tearsheet/tearsheet'; +import { ModalHeader, type ModalHeaderProps } from '@patternfly/react-core'; + +export interface TearsheetHeaderProps extends ModalHeaderProps { + className: string; +} + +const TearsheetHeader: FunctionComponent = ({ + className, + ...props +}: TearsheetHeaderProps) => ; +TearsheetHeader.displayName = 'TearsheetHeader'; + +export default TearsheetHeader; diff --git a/packages/module/src/TearsheetHeader/index.ts b/packages/module/src/TearsheetHeader/index.ts new file mode 100644 index 00000000..eb954f6d --- /dev/null +++ b/packages/module/src/TearsheetHeader/index.ts @@ -0,0 +1,2 @@ +export { default } from './TearsheetHeader'; +export * from './TearsheetHeader'; From 05ab49f988fb507654a37379bf860a2340806219 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Wed, 8 Jul 2026 16:33:41 -0400 Subject: [PATCH 02/37] chore: Migrate tearsheet.css to proper JSS use Generated-by: Claude Opus 4.6 Co-authored-by: Claude Opus 4.6 --- packages/module/src/Tearsheet/Tearsheet.tsx | 61 +++++++++++++++++-- .../src/TearsheetBody/TearsheetBody.tsx | 15 +++-- .../src/TearsheetFooter/TearsheetFooter.tsx | 13 +++- .../src/TearsheetGroup/TearsheetGroup.tsx | 13 +++- .../src/TearsheetHeader/TearsheetHeader.tsx | 13 +++- 5 files changed, 100 insertions(+), 15 deletions(-) diff --git a/packages/module/src/Tearsheet/Tearsheet.tsx b/packages/module/src/Tearsheet/Tearsheet.tsx index dd75e100..37691d83 100644 --- a/packages/module/src/Tearsheet/Tearsheet.tsx +++ b/packages/module/src/Tearsheet/Tearsheet.tsx @@ -1,8 +1,60 @@ import type { ReactNode, HTMLProps, FunctionComponent, MouseEvent } from 'react'; import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Tearsheet/tearsheet'; +import { createUseStyles } from 'react-jss'; import { Modal, ModalVariant } from '@patternfly/react-core'; +const useStyles = createUseStyles({ + tearsheet: { + width: 'calc(100% - 4rem) !important', + maxWidth: 'calc(100% - 4rem) !important', + height: 'calc(100% - 4rem) !important', + maxHeight: 'calc(100% - 4rem) !important', + insetBlockStart: '0 !important', + top: '2rem !important', + '&.pf-v6-c-modal-animated': { + '--pf-v6-c-modal-animated--Transition': + 'width 300ms ease, max-width 300ms ease, height 300ms ease, max-height 300ms ease, top 300ms ease, opacity 240ms cubic-bezier(0.4, 0.14, 1, 1), transform 240ms cubic-bezier(0.4, 0.14, 1, 1), visibility 0ms linear 240ms', + }, + '&.pf-v6-c-modal-animated-open': { + '--pf-v6-c-modal-animated--Transition': + 'width 300ms ease, max-width 300ms ease, height 300ms ease, max-height 300ms ease, top 300ms ease, transform 240ms cubic-bezier(0, 0, 0.2, 1), visibility 0ms linear 0ms', + }, + '&.pf-m-stack-level-1': { + width: 'calc(100% - 2rem) !important', + maxWidth: 'calc(100% - 2rem) !important', + height: 'calc(100% - 6rem) !important', + maxHeight: 'calc(100% - 6rem) !important', + insetBlockStart: '0 !important', + top: '3rem !important', + }, + '&.pf-m-stack-level-2': { + width: 'calc(100% - 0rem) !important', + maxWidth: 'calc(100% - 0rem) !important', + height: 'calc(100% - 8rem) !important', + maxHeight: 'calc(100% - 8rem) !important', + insetBlockStart: '0 !important', + top: '4rem !important', + }, + '&.pf-m-stack-hidden': { + width: 'calc(100% - 4rem) !important', + maxWidth: 'calc(100% - 4rem) !important', + height: 'calc(100% - 4rem) !important', + maxHeight: 'calc(100% - 4rem) !important', + insetBlockStart: '0 !important', + top: '3rem !important', + opacity: '0 !important', + pointerEvents: 'none !important', + }, + }, + tearsheetInner: { + display: 'flex', + flexDirection: 'column', + overflow: 'hidden', + height: '100%', + marginInlineEnd: 0, + }, +}); + export interface TearsheetProps extends HTMLProps { /** Content rendered inside the tearsheet. Should be TearsheetHeader, TearsheetBody, and/or TearsheetFooter. */ children: ReactNode; @@ -44,13 +96,14 @@ const Tearsheet: FunctionComponent = ({ disableFocusTrap, ...props }: TearsheetProps) => { + const classes = useStyles(); const stackLevel = stackLevelProp ?? 0; const stackLevelClassname = stackLevel < 0 ? 'pf-m-stack-hidden' : `pf-m-stack-level-${stackLevel}`; return ( = ({ appendTo={appendTo} disableFocusTrap={disableFocusTrap} > -
+
{children}
diff --git a/packages/module/src/TearsheetBody/TearsheetBody.tsx b/packages/module/src/TearsheetBody/TearsheetBody.tsx index 7103a869..8ed06efe 100644 --- a/packages/module/src/TearsheetBody/TearsheetBody.tsx +++ b/packages/module/src/TearsheetBody/TearsheetBody.tsx @@ -1,15 +1,22 @@ import type { FunctionComponent } from 'react'; import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Tearsheet/tearsheet'; +import { createUseStyles } from 'react-jss'; import { ModalBody, type ModalBodyProps } from '@patternfly/react-core'; +const useStyles = createUseStyles({ + tearsheetBody: { + caretColor: 'red', + }, +}); + export interface TearsheetBodyProps extends ModalBodyProps { className: string; } -const TearsheetBody: FunctionComponent = ({ className, ...props }: TearsheetBodyProps) => ( - -); +const TearsheetBody: FunctionComponent = ({ className, ...props }: TearsheetBodyProps) => { + const classes = useStyles(); + return ; +}; TearsheetBody.displayName = 'TearsheetBody'; export default TearsheetBody; \ No newline at end of file diff --git a/packages/module/src/TearsheetFooter/TearsheetFooter.tsx b/packages/module/src/TearsheetFooter/TearsheetFooter.tsx index 2ac25bc9..03732aa5 100644 --- a/packages/module/src/TearsheetFooter/TearsheetFooter.tsx +++ b/packages/module/src/TearsheetFooter/TearsheetFooter.tsx @@ -1,8 +1,14 @@ import type { FunctionComponent } from 'react'; import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Tearsheet/tearsheet'; +import { createUseStyles } from 'react-jss'; import { ModalFooter, type ModalFooterProps } from '@patternfly/react-core'; +const useStyles = createUseStyles({ + tearsheetFooter: { + flexShrink: 0, + }, +}); + export interface TearsheetFooterProps extends ModalFooterProps { className: string; } @@ -10,7 +16,10 @@ export interface TearsheetFooterProps extends ModalFooterProps { export const TearsheetFooter: FunctionComponent = ({ className, ...props -}: TearsheetFooterProps) => ; +}: TearsheetFooterProps) => { + const classes = useStyles(); + return ; +}; TearsheetFooter.displayName = 'TearsheetFooter'; export default TearsheetFooter; diff --git a/packages/module/src/TearsheetGroup/TearsheetGroup.tsx b/packages/module/src/TearsheetGroup/TearsheetGroup.tsx index 41d61b7e..34c1f3d8 100644 --- a/packages/module/src/TearsheetGroup/TearsheetGroup.tsx +++ b/packages/module/src/TearsheetGroup/TearsheetGroup.tsx @@ -1,7 +1,13 @@ import { Children, cloneElement, isValidElement, useRef, type FunctionComponent, type ReactElement } from 'react'; import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Tearsheet/tearsheet'; -import { Tearsheet, type TearsheetProps } from '@patternfly/react-core'; +import { createUseStyles } from 'react-jss'; +import Tearsheet, { type TearsheetProps } from '../Tearsheet'; + +const useStyles = createUseStyles({ + tearsheetGroup: { + caretColor: 'red', + }, +}); /** The maximum number of visually distinct stack levels (0, 1, 2). */ const MAX_VISIBLE_LEVELS = 3; @@ -23,6 +29,7 @@ const TearsheetGroup: FunctionComponent = ({ id, ...props }: TearsheetGroupProps) => { + const classes = useStyles(); // Track each child's last assigned stack level so closing tearsheets keep // their position during the modal exit animation instead of snapping to L0. const prevLevelsRef = useRef>(new Map()); @@ -72,7 +79,7 @@ const TearsheetGroup: FunctionComponent = ({ }); return ( -
+
{enhancedChildren}
); diff --git a/packages/module/src/TearsheetHeader/TearsheetHeader.tsx b/packages/module/src/TearsheetHeader/TearsheetHeader.tsx index 92ca5782..457c8a10 100644 --- a/packages/module/src/TearsheetHeader/TearsheetHeader.tsx +++ b/packages/module/src/TearsheetHeader/TearsheetHeader.tsx @@ -1,8 +1,14 @@ import type { FunctionComponent } from 'react'; import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Tearsheet/tearsheet'; +import { createUseStyles } from 'react-jss'; import { ModalHeader, type ModalHeaderProps } from '@patternfly/react-core'; +const useStyles = createUseStyles({ + tearsheetHeader: { + flexShrink: 0, + }, +}); + export interface TearsheetHeaderProps extends ModalHeaderProps { className: string; } @@ -10,7 +16,10 @@ export interface TearsheetHeaderProps extends ModalHeaderProps { const TearsheetHeader: FunctionComponent = ({ className, ...props -}: TearsheetHeaderProps) => ; +}: TearsheetHeaderProps) => { + const classes = useStyles(); + return ; +}; TearsheetHeader.displayName = 'TearsheetHeader'; export default TearsheetHeader; From af55c44a07e89ae538a7a6de9a9969dbd73541a0 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Wed, 8 Jul 2026 16:59:42 -0400 Subject: [PATCH 03/37] chore: Port doc examples --- .../examples/Tearsheet/Tearsheet.md | 49 ++++++++ .../examples/Tearsheet/TearsheetBasic.tsx | 43 +++++++ .../examples/Tearsheet/TearsheetGroup.tsx | 66 ++++++++++ .../examples/Tearsheet/TearsheetLayouts.tsx | 117 ++++++++++++++++++ .../examples/Tearsheet/TearsheetStacked.tsx | 101 +++++++++++++++ 5 files changed, 376 insertions(+) create mode 100644 packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md create mode 100644 packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetBasic.tsx create mode 100644 packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetGroup.tsx create mode 100644 packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetLayouts.tsx create mode 100644 packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetStacked.tsx diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md new file mode 100644 index 00000000..ae68c6e0 --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md @@ -0,0 +1,49 @@ +--- +# Sidenav top-level section +# should be the same for all markdown files +section: extensions +subsection: component-groups +# Sidenav secondary level section +# should be the same for all markdown files +id: Tearsheet +# Tab (react | react-demos | html | html-demos | design-guidelines | accessibility) +source: react +# If you use typescript, the name of the interface to display props for +# These are found through the sourceProps function provided in patternfly-docs.source.js +propComponents: ['Tearsheet'] +sourceLink: https://github.com/patternfly/react-component-groups/blob/main/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md +--- + +import { Fragment, useState } from 'react'; +import spacing from '@patternfly/react-styles/css/utilities/Spacing/spacing'; +import TearsheetGroup from '@patternfly/react-component-groups/dist/dynamic/TearsheetGroup'; +import Tearsheet from '@patternfly/react-component-groups/dist/dynamic/Tearsheet'; +import TearsheetHeader from '@patternfly/react-component-groups/dist/dynamic/TearsheetHeader'; +import TearsheetBody from '@patternfly/react-component-groups/dist/dynamic/TearsheetBody'; +import TearsheetFooter from '@patternfly/react-component-groups/dist/dynamic/TearsheetFooter'; + +Tearsheet is used for ... + +## Examples + +### Basic + +```ts file="./TearsheetBasic.tsx" +``` + +### Stacked + +```ts file="./TearsheetStacked.tsx" +``` + +### Tearsheet group (infinite stacking) + +Use a `TearsheetGroup` to manage an unbounded number of stacked tearsheets. Render order determines stacking priority — later children stack in front of earlier ones. Only the top 3 open tearsheets are visible; earlier ones hide behind the stack and reappear as front tearsheets are closed. + +```ts file="./TearsheetGroup.tsx" +``` + +### Tearsheet layouts + +```ts file="./TearsheetLayouts.tsx" +``` diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetBasic.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetBasic.tsx new file mode 100644 index 00000000..e25e1655 --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetBasic.tsx @@ -0,0 +1,43 @@ +import { Fragment, useState } from 'react'; +import { Button } from '@patternfly/react-core'; +import Tearsheet from '@patternfly/react-component-groups/dist/dynamic/Tearsheet'; +import TearsheetHeader from '@patternfly/react-component-groups/dist/dynamic/TearsheetHeader'; +import TearsheetBody from '@patternfly/react-component-groups/dist/dynamic/TearsheetBody'; +import TearsheetFooter from '@patternfly/react-component-groups/dist/dynamic/TearsheetFooter'; + +export const TearsheetBasic: React.FunctionComponent = () => { + const [ isTearsheetOpen, setIsTearsheetOpen ] = useState(false); + + const toggleTearsheet = (_event: React.MouseEvent | KeyboardEvent | MouseEvent) => { + setIsTearsheetOpen(!isTearsheetOpen); + }; + + return ( + + + | KeyboardEvent | MouseEvent) => toggleTearsheet(e)} + > + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore + magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id + est laborum. + + + + + + + + ); +}; diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetGroup.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetGroup.tsx new file mode 100644 index 00000000..0f10d2f8 --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetGroup.tsx @@ -0,0 +1,66 @@ +import { useState } from 'react'; +import { Button } from '@patternfly/react-core'; +import TearsheetGroup from '@patternfly/react-component-groups/dist/dynamic/TearsheetGroup'; +import Tearsheet from '@patternfly/react-component-groups/dist/dynamic/Tearsheet'; +import TearsheetHeader from '@patternfly/react-component-groups/dist/dynamic/TearsheetHeader'; +import TearsheetBody from '@patternfly/react-component-groups/dist/dynamic/TearsheetBody'; +import TearsheetFooter from '@patternfly/react-component-groups/dist/dynamic/TearsheetFooter'; + +const TOTAL_TEARSHEETS = 10; + +export const TearsheetGroupExample: React.FunctionComponent = () => { + const [ openState, setOpenState ] = useState(Array(TOTAL_TEARSHEETS).fill(false)); + + const open = (index: number) => { + setOpenState((prev) => { + const next = [ ...prev ]; + next[index] = true; + return next; + }); + }; + + const close = (index: number) => { + setOpenState((prev) => { + const next = [ ...prev ]; + next[index] = false; + return next; + }); + }; + + return ( +
+
+ +
+ + + {Array.from({ length: TOTAL_TEARSHEETS }, (_, i) => ( + close(i)} aria-label={`Tearsheet ${i + 1}`}> + + +

+ This is tearsheet #{i + 1} of {TOTAL_TEARSHEETS}. +

+

+ The TearsheetGroup manages stacking automatically. Only the top 3 open tearsheets are visible in the + stack — earlier ones hide behind and reappear as you close the ones in front. +

+
+ + {i < TOTAL_TEARSHEETS - 1 && ( + + )} + + +
+ ))} +
+
+ ); +}; diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetLayouts.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetLayouts.tsx new file mode 100644 index 00000000..50e44503 --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetLayouts.tsx @@ -0,0 +1,117 @@ +import { Fragment, useState } from 'react'; +import { + Button, + Card, + CardBody, + CardHeader, + CardTitle, + Content, + DescriptionList, + DescriptionListDescription, + DescriptionListGroup, + DescriptionListTerm, + Divider, + Title +} from '@patternfly/react-core'; +import Tearsheet from '@patternfly/react-component-groups/dist/dynamic/Tearsheet'; +import TearsheetHeader from '@patternfly/react-component-groups/dist/dynamic/TearsheetHeader'; +import TearsheetBody from '@patternfly/react-component-groups/dist/dynamic/TearsheetBody'; +import TearsheetFooter from '@patternfly/react-component-groups/dist/dynamic/TearsheetFooter'; +import { Flex, FlexItem, Grid, GridItem } from '@patternfly/react-core'; + +type BodyLayout = 'simple' | 'xl-text' | 'grid' | 'long'; + +const LOREM = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore ' + + 'magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo ' + + 'consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla ' + + 'pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id ' + + 'est laborum.'; + +const bodyLayouts: Record React.ReactNode }> = { + simple: { + label: 'Simple text', + render: () => {LOREM} + }, + 'xl-text': { + label: 'XL text', + render: () => ( + <> + {Array.from({ length: 30 }, (_, i) => ( + + {LOREM} + + ))} + + ) + }, + grid: { + label: 'Grid layout', + render: () => ( + + {[ 'Overview', 'Configuration', 'Resources', 'Networking', 'Storage', 'Monitoring' ].map((title) => ( + + + + {title} + + {LOREM.slice(0, 120)}... + + + ))} + + ) + }, + long: { + label: 'Long layout', + render: () => ( + + {[ 'General', 'Details', 'Configuration', 'Permissions', 'Audit log' ].map((section) => ( + + {section} + + + {[ 'Name', 'Status', 'Created', 'Modified' ].map((term) => ( + + {term} + {LOREM.slice(0, 80)} + + ))} + + + ))} + + ) + } +}; + +export const TearsheetLayouts: React.FunctionComponent = () => { + const [ activeLayout, setActiveLayout ] = useState(null); + + const open = (layout: BodyLayout) => () => setActiveLayout(layout); + const close = (_event: React.MouseEvent | KeyboardEvent | MouseEvent) => setActiveLayout(null); + + return ( + + + {(Object.keys(bodyLayouts) as BodyLayout[]).map((key) => ( + + ))} + + + + {activeLayout && bodyLayouts[activeLayout].render()} + + + + + + + ); +}; diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetStacked.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetStacked.tsx new file mode 100644 index 00000000..c2f35398 --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetStacked.tsx @@ -0,0 +1,101 @@ +import { Fragment, useState } from 'react'; +import { Button } from '@patternfly/react-core'; +import Tearsheet from '@patternfly/react-component-groups/dist/dynamic/Tearsheet'; +import TearsheetHeader from '@patternfly/react-component-groups/dist/dynamic/TearsheetHeader'; +import TearsheetBody from '@patternfly/react-component-groups/dist/dynamic/TearsheetBody'; +import TearsheetFooter from '@patternfly/react-component-groups/dist/dynamic/TearsheetFooter'; + +export const TearsheetStacked: React.FunctionComponent = () => { + const [ isTearsheetOpen, setIsTearsheetOpen ] = useState(false); + const [ isStack1TearsheetOpen, setIsStack1TearsheetOpen ] = useState(false); + const [ isStack2TearsheetOpen, setIsStack2TearsheetOpen ] = useState(false); + + const toggleTearsheet = (_event: React.MouseEvent | KeyboardEvent | MouseEvent) => { + setIsTearsheetOpen(!isTearsheetOpen); + }; + const toggleStack1Tearsheet = (_event: React.MouseEvent | KeyboardEvent | MouseEvent) => { + setIsStack1TearsheetOpen(!isStack1TearsheetOpen); + }; + const toggleStack2Tearsheet = (_event: React.MouseEvent | KeyboardEvent | MouseEvent) => { + setIsStack2TearsheetOpen(!isStack2TearsheetOpen); + }; + + return ( + + + | KeyboardEvent | MouseEvent) => toggleTearsheet(e)} + > + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore + magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id + est laborum. + + + + + + + + | KeyboardEvent | MouseEvent) => toggleStack1Tearsheet(e)} + > + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore + magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id + est laborum. + + + + + + + + | KeyboardEvent | MouseEvent) => toggleStack2Tearsheet(e)} + > + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore + magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id + est laborum. + + + + + + + + ); +}; From d93b8fec446abe8e91fa4f1c8d1c2aabebd01b4a Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Wed, 8 Jul 2026 17:52:31 -0400 Subject: [PATCH 04/37] fix: Build os-agnostic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Windows, Node's path.resolve and path.relative produce backslash-separated paths (e.g. C:\src\*\index.ts). glob v10+ treats backslashes as escape characters rather than path separators, so \* becomes a literal asterisk match instead of a wildcard. This caused generate-index.js to find zero source files, producing an empty src/index.ts, which compiled to an empty dist/esm/index.js. The downstream build:fed:packages step then crashed with "Cannot read properties of undefined (reading 'flags')" when the TypeScript checker tried to get exports from a module with no symbol. Even if the index had been populated, generate-fed-package-json.js had the same glob issue — its patterns with process.cwd() backslashes would match nothing on Windows, so no dist/dynamic/*/package.json stubs would be created. The doc examples import from those stubs, so the dev server would still show a blank page. Additionally, path.relative on Windows returns backslash paths, which broke the .replace('/dist', '') calls that strip the dist prefix from relative paths written into generated package.json files. Changes: - Add packages/module/utils.js with cross-platform path utilities: toPosixPath (normalize separators), posixGlobSync (normalize glob pattern + results), and posixRelative (normalize path.relative output). Each function is documented with why it exists. - Refactor generate-index.js to use posixGlobSync from utils.js - Refactor generate-fed-package-json.js to use toPosixPath, posixGlobSync, and posixRelative from utils.js - Normalize basePath and path.relative output inline in scripts/parse-dynamic-modules.mjs (kept inline since it lives in a separate shared scripts directory) All changes are no-ops on Linux/macOS where paths already use forward slashes. Generated-by: Claude Co-authored-by: Claude --- packages/module/generate-fed-package-json.js | 24 ++++++------- packages/module/generate-index.js | 4 +-- packages/module/src/index.ts | 15 ++++++++ packages/module/utils.js | 36 ++++++++++++++++++++ scripts/parse-dynamic-modules.mjs | 6 ++-- 5 files changed, 69 insertions(+), 16 deletions(-) create mode 100644 packages/module/utils.js diff --git a/packages/module/generate-fed-package-json.js b/packages/module/generate-fed-package-json.js index c14056fa..42933f14 100644 --- a/packages/module/generate-fed-package-json.js +++ b/packages/module/generate-fed-package-json.js @@ -1,14 +1,14 @@ const fse = require('fs-extra'); -const { globSync } = require('glob'); const path = require('path'); const { default: getDynamicModuleMap } = require('../../scripts/parse-dynamic-modules.mjs'); +const { toPosixPath, posixGlobSync, posixRelative } = require('./utils'); -const root = process.cwd(); +const root = toPosixPath(process.cwd()); -const sourceFiles = globSync(`${root}/src/*/`) +const sourceFiles = posixGlobSync(`${root}/src/*/`) .map((name) => name.replace(/\/$/, '')); - -const indexTypings = globSync(`${root}/src/index.d.ts`); + +const indexTypings = posixGlobSync(`${root}/src/index.d.ts`); const ENV_AGNOSTIC_ROOT = `${root}/dist/dynamic` @@ -23,9 +23,9 @@ async function copyTypings(files, dest) { async function createPackage(file) { const fileName = file.split('/').pop(); - const esmSource = globSync(`${root}/dist/esm/${fileName}/**/index.js`)[0]; - const cjsSource = globSync(`${root}/dist/cjs/${fileName}/**/index.js`)[0]; - const typingsSource = globSync(`${root}/dist/esm/${fileName}/**/index.d.ts`)[0] + const esmSource = posixGlobSync(`${root}/dist/esm/${fileName}/**/index.js`)[0]; + const cjsSource = posixGlobSync(`${root}/dist/cjs/${fileName}/**/index.js`)[0]; + const typingsSource = posixGlobSync(`${root}/dist/esm/${fileName}/**/index.d.ts`)[0] /** * Prevent creating package.json for directories with no JS files (like CSS directories) */ @@ -39,14 +39,14 @@ async function createPackage(file) { // ensure the directory exists fse.ensureDirSync(destDir) - const esmRelative = path.relative(file, esmSource).replace('/dist', ''); - const cjsRelative = path.relative(file, cjsSource).replace('/dist', ''); - const tsRelative = path.relative(file, typingsSource).replace('/dist', '') + const esmRelative = posixRelative(file, esmSource).replace('/dist', ''); + const cjsRelative = posixRelative(file, cjsSource).replace('/dist', ''); + const tsRelative = posixRelative(file, typingsSource).replace('/dist', '') const content = { main: cjsRelative, module: esmRelative, }; - const typings = globSync(`${root}/src/${fileName}/*.d.ts`); + const typings = posixGlobSync(`${root}/src/${fileName}/*.d.ts`); const cmds = []; content.typings = tsRelative; cmds.push(copyTypings(typings, `${root}/dist/${fileName}`)); diff --git a/packages/module/generate-index.js b/packages/module/generate-index.js index 8ff8b416..3afa0b06 100644 --- a/packages/module/generate-index.js +++ b/packages/module/generate-index.js @@ -1,12 +1,12 @@ const fse = require('fs-extra'); -const { globSync } = require('glob'); const path = require('path'); +const { posixGlobSync } = require('./utils'); const root = process.cwd(); const ENV_AGNOSTIC_ROOT = `${root}/src` -const sourceFiles = globSync(path.resolve(__dirname, './src/*/index.ts')) +const sourceFiles = posixGlobSync(path.resolve(__dirname, './src/*/index.ts')) async function generateIndex(files) { // ensure the dynamic root exists diff --git a/packages/module/src/index.ts b/packages/module/src/index.ts index 4f23c2d4..c1ff0b47 100644 --- a/packages/module/src/index.ts +++ b/packages/module/src/index.ts @@ -9,6 +9,21 @@ export * from './UnavailableContent'; export { default as UnauthorizedAccess } from './UnauthorizedAccess'; export * from './UnauthorizedAccess'; +export { default as TearsheetHeader } from './TearsheetHeader'; +export * from './TearsheetHeader'; + +export { default as TearsheetGroup } from './TearsheetGroup'; +export * from './TearsheetGroup'; + +export { default as TearsheetFooter } from './TearsheetFooter'; +export * from './TearsheetFooter'; + +export { default as TearsheetBody } from './TearsheetBody'; +export * from './TearsheetBody'; + +export { default as Tearsheet } from './Tearsheet'; +export * from './Tearsheet'; + export { default as TagCount } from './TagCount'; export * from './TagCount'; diff --git a/packages/module/utils.js b/packages/module/utils.js new file mode 100644 index 00000000..e88e4ec2 --- /dev/null +++ b/packages/module/utils.js @@ -0,0 +1,36 @@ +/** + * Cross-platform path utilities for build scripts. + * + * On Windows, Node's path.resolve and path.relative produce backslash-separated + * paths. glob v10+ treats backslashes as escape characters (not path separators), + * so a pattern like `C:\src\*\index.ts` silently matches nothing because \* is + * interpreted as a literal asterisk. glob also returns backslash paths on Windows, + * breaking downstream code that splits on '/' to extract path segments. + * + * These utilities normalize paths to POSIX forward slashes for glob input/output + * and for any path strings written into generated package.json files. + */ + +const { globSync } = require('glob'); +const path = require('path'); + +/** Normalize a file path to use POSIX forward slashes. No-op on Linux/macOS. */ +const toPosixPath = (filePath) => filePath.replace(/\\/g, '/'); + +/** + * globSync wrapper that normalizes the pattern and results to POSIX paths. + * Use in place of globSync wherever the pattern includes Node-resolved paths + * (process.cwd(), path.resolve, __dirname, etc.) that may contain backslashes. + */ +const posixGlobSync = (pattern) => + globSync(toPosixPath(pattern)).map(toPosixPath); + +/** + * path.relative wrapper that returns a POSIX-style relative path. + * Use when the result will be written into a generated file (e.g. package.json + * "main"/"module" fields) where forward slashes are expected by consumers. + */ +const posixRelative = (from, to) => + toPosixPath(path.relative(from, to)); + +module.exports = { toPosixPath, posixGlobSync, posixRelative }; diff --git a/scripts/parse-dynamic-modules.mjs b/scripts/parse-dynamic-modules.mjs index 6a35cec7..97c88ba1 100644 --- a/scripts/parse-dynamic-modules.mjs +++ b/scripts/parse-dynamic-modules.mjs @@ -76,8 +76,10 @@ const getDynamicModuleMap = ( return {}; } + const normalizedBasePath = basePath.replace(/\\/g, '/'); + /** @type {Record} */ - const dynamicModulePathToPkgDir = glob.sync(`${basePath}/dist/dynamic/**/package.json`).reduce((acc, pkgFile) => { + const dynamicModulePathToPkgDir = glob.sync(`${normalizedBasePath}/dist/dynamic/**/package.json`).reduce((acc, pkgFile) => { const pkg = require(pkgFile); const pkgModule = pkg[resolutionField]; @@ -86,7 +88,7 @@ const getDynamicModuleMap = ( } const pkgResolvedPath = path.resolve(path.dirname(pkgFile), pkgModule); - const pkgRelativePath = path.dirname(path.relative(basePath, pkgFile)); + const pkgRelativePath = path.dirname(path.relative(basePath, pkgFile)).replace(/\\/g, '/'); acc[pkgResolvedPath] = pkgRelativePath; From 690e2fe080aa3f82b7559e983046e42544807922 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Wed, 8 Jul 2026 18:19:10 -0400 Subject: [PATCH 05/37] fix: Build and props MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Doc site source discovery (patternfly-docs.source.js) passed raw path.join() output into globSync(). On Windows, path.join() produces backslash-separated paths (e.g. patternfly-docs\content\extensions\**\*.md). glob v10+ treats backslashes as escape characters, not path separators, so both the sourceProps and sourceMD globs silently matched zero files. This caused the generated/index.js routes file to be empty, leaving the entire Extensions sidenav blank on Windows dev servers. Fix: wrap glob patterns with the existing toPosixPath() utility from utils.js (created in d93b8fe for the same class of bug in other build scripts). Also mark className as optional in TearsheetBody, TearsheetFooter, and TearsheetHeader props interfaces — className is passed through to PF ModalBody/ModalFooter/ModalHeader which already default it. Generated-by: Claude Opus 4.6 Co-authored-by: Claude Opus 4.6 --- packages/module/patternfly-docs/patternfly-docs.source.js | 5 +++-- packages/module/src/TearsheetBody/TearsheetBody.tsx | 2 +- packages/module/src/TearsheetFooter/TearsheetFooter.tsx | 2 +- packages/module/src/TearsheetHeader/TearsheetHeader.tsx | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/module/patternfly-docs/patternfly-docs.source.js b/packages/module/patternfly-docs/patternfly-docs.source.js index cff7aac9..f0127391 100644 --- a/packages/module/patternfly-docs/patternfly-docs.source.js +++ b/packages/module/patternfly-docs/patternfly-docs.source.js @@ -1,14 +1,15 @@ const path = require('path'); +const { toPosixPath } = require('../utils'); module.exports = (sourceMD, sourceProps) => { // Parse source content for props so that we can display them const propsIgnore = [ '**/*.test.tsx', '**/examples/*.tsx' ]; const extensionPath = path.join(__dirname, '../src'); - sourceProps(path.join(extensionPath, '/**/*.tsx'), propsIgnore); + sourceProps(toPosixPath(path.join(extensionPath, '/**/*.tsx')), propsIgnore); // Parse md files const contentBase = path.join(__dirname, './content'); - sourceMD(path.join(contentBase, 'extensions/**/*.md'), 'extensions'); + sourceMD(toPosixPath(path.join(contentBase, 'extensions/**/*.md')), 'extensions'); /** If you want to parse content from node_modules instead of providing a relative/absolute path, diff --git a/packages/module/src/TearsheetBody/TearsheetBody.tsx b/packages/module/src/TearsheetBody/TearsheetBody.tsx index 8ed06efe..6cf134d1 100644 --- a/packages/module/src/TearsheetBody/TearsheetBody.tsx +++ b/packages/module/src/TearsheetBody/TearsheetBody.tsx @@ -10,7 +10,7 @@ const useStyles = createUseStyles({ }); export interface TearsheetBodyProps extends ModalBodyProps { - className: string; + className?: string; } const TearsheetBody: FunctionComponent = ({ className, ...props }: TearsheetBodyProps) => { diff --git a/packages/module/src/TearsheetFooter/TearsheetFooter.tsx b/packages/module/src/TearsheetFooter/TearsheetFooter.tsx index 03732aa5..75db1d52 100644 --- a/packages/module/src/TearsheetFooter/TearsheetFooter.tsx +++ b/packages/module/src/TearsheetFooter/TearsheetFooter.tsx @@ -10,7 +10,7 @@ const useStyles = createUseStyles({ }); export interface TearsheetFooterProps extends ModalFooterProps { - className: string; + className?: string; } export const TearsheetFooter: FunctionComponent = ({ diff --git a/packages/module/src/TearsheetHeader/TearsheetHeader.tsx b/packages/module/src/TearsheetHeader/TearsheetHeader.tsx index 457c8a10..1c15fdc4 100644 --- a/packages/module/src/TearsheetHeader/TearsheetHeader.tsx +++ b/packages/module/src/TearsheetHeader/TearsheetHeader.tsx @@ -10,7 +10,7 @@ const useStyles = createUseStyles({ }); export interface TearsheetHeaderProps extends ModalHeaderProps { - className: string; + className?: string; } const TearsheetHeader: FunctionComponent = ({ From d0be61708a6d9a6b8bcd8847d6ed2c6c5cf1d44e Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Wed, 8 Jul 2026 18:44:13 -0400 Subject: [PATCH 06/37] fix: top not working with insetBlockStart because of JSS ordering Assisted-by: Claude Co-authored-by: Claude --- packages/module/src/Tearsheet/Tearsheet.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/module/src/Tearsheet/Tearsheet.tsx b/packages/module/src/Tearsheet/Tearsheet.tsx index 37691d83..7aac8604 100644 --- a/packages/module/src/Tearsheet/Tearsheet.tsx +++ b/packages/module/src/Tearsheet/Tearsheet.tsx @@ -9,8 +9,8 @@ const useStyles = createUseStyles({ maxWidth: 'calc(100% - 4rem) !important', height: 'calc(100% - 4rem) !important', maxHeight: 'calc(100% - 4rem) !important', - insetBlockStart: '0 !important', - top: '2rem !important', + insetBlockStart: '2rem !important', + // top: '2rem !important', '&.pf-v6-c-modal-animated': { '--pf-v6-c-modal-animated--Transition': 'width 300ms ease, max-width 300ms ease, height 300ms ease, max-height 300ms ease, top 300ms ease, opacity 240ms cubic-bezier(0.4, 0.14, 1, 1), transform 240ms cubic-bezier(0.4, 0.14, 1, 1), visibility 0ms linear 240ms', @@ -24,24 +24,24 @@ const useStyles = createUseStyles({ maxWidth: 'calc(100% - 2rem) !important', height: 'calc(100% - 6rem) !important', maxHeight: 'calc(100% - 6rem) !important', - insetBlockStart: '0 !important', - top: '3rem !important', + insetBlockStart: '3rem !important', + // top: '3rem !important', }, '&.pf-m-stack-level-2': { width: 'calc(100% - 0rem) !important', maxWidth: 'calc(100% - 0rem) !important', height: 'calc(100% - 8rem) !important', maxHeight: 'calc(100% - 8rem) !important', - insetBlockStart: '0 !important', - top: '4rem !important', + insetBlockStart: '4rem !important', + // top: '4rem !important', }, '&.pf-m-stack-hidden': { width: 'calc(100% - 4rem) !important', maxWidth: 'calc(100% - 4rem) !important', height: 'calc(100% - 4rem) !important', maxHeight: 'calc(100% - 4rem) !important', - insetBlockStart: '0 !important', - top: '3rem !important', + insetBlockStart: '3rem !important', + // top: '3rem !important', opacity: '0 !important', pointerEvents: 'none !important', }, From 97ac9f550933052e75b5b055c34f8ef74792c73b Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Thu, 9 Jul 2026 13:12:30 -0400 Subject: [PATCH 07/37] chore: Tweaks - Bottom border radius, example docs, scrolling Tearsheet component: - Remove bottom border radius so tearsheet sits flush against viewport edge - Change tearsheetInner from height:100% to flex:1 1 auto + minHeight:0 so it participates properly in the ModalBox flex layout TearsheetBody component: - Replace placeholder caretColor:red with flex:1, minHeight:0, overflow:auto so the body fills remaining space and scrolls independently TearsheetGroup component: - Remove placeholder caretColor:red style Documentation (Tearsheet.md): - Expand propComponents to include TearsheetHeader, TearsheetBody, TearsheetFooter, and TearsheetGroup - Add descriptive text for each example section - Reorder examples: Basic, Layouts, Stacked, Group, Comparison TearsheetLayouts example: - Remove 'simple' layout, rename 'xl-text' to 'long-text' - Expand grid layout to 60 randomly sorted cards - Rename 'long' label to 'Flex layout' TearsheetComparison example (new): - Side-by-side Tearsheet vs Modal (ModalVariant.large) demo showing why tearsheets are better for dense content - Body content: sticky search bar (PageSection), vertical JumpLinks in a SidebarPanel, 3-column card grid with DescriptionLists, Labels, and CodeBlocks across 6 sections (36 cards total) - CSS fix for sidebar scrolling: sidebar__main height:100%, sidebar__content overflow:scroll + height:100% Generated-by: Claude Co-authored-by: Claude --- .../examples/Tearsheet/Tearsheet.md | 32 ++- .../Tearsheet/TearsheetComparison.tsx | 259 ++++++++++++++++++ .../examples/Tearsheet/TearsheetLayouts.tsx | 36 +-- packages/module/src/Tearsheet/Tearsheet.tsx | 5 +- .../src/TearsheetBody/TearsheetBody.tsx | 4 +- .../src/TearsheetGroup/TearsheetGroup.tsx | 1 - 6 files changed, 311 insertions(+), 26 deletions(-) create mode 100644 packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetComparison.tsx diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md index ae68c6e0..08e1c00e 100644 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md @@ -10,7 +10,7 @@ id: Tearsheet source: react # If you use typescript, the name of the interface to display props for # These are found through the sourceProps function provided in patternfly-docs.source.js -propComponents: ['Tearsheet'] +propComponents: ['Tearsheet', 'TearsheetHeader', 'TearsheetBody', 'TearsheetFooter', 'TearsheetGroup'] sourceLink: https://github.com/patternfly/react-component-groups/blob/main/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md --- @@ -22,28 +22,50 @@ import TearsheetHeader from '@patternfly/react-component-groups/dist/dynamic/Tea import TearsheetBody from '@patternfly/react-component-groups/dist/dynamic/TearsheetBody'; import TearsheetFooter from '@patternfly/react-component-groups/dist/dynamic/TearsheetFooter'; -Tearsheet is used for ... +**Tearsheet** are a full-screen extension of the `` component allowing more complex experiences to be provided to the user. +While the biggest Modal size (`ModalVariant.large`) may work for some cases, tearsheets allow near the entire real-estate to be leveraged. +This component extends the [modal component](/components/modal) allowing any use of its properties to be provided. ## Examples ### Basic +Typical tearsheets should make use of the entire area, for this basic case some sample text is rendered. + ```ts file="./TearsheetBasic.tsx" ``` +### Tearsheet layouts + +Tearsheets should allow various sorts of layouts to be rendered. +The `` component will handle scrolling for long content. + +```ts file="./TearsheetLayouts.tsx" +``` + ### Stacked +One special use case with tearsheets is stacking. +When a user is using a tearsheet, if another one needs to open it can open one level "on-top" of it in a new stack. +Tearsheets offer 3 stack levels (0,1,2). +A special stack level -1 allows a tearsheet to hide behind others. + ```ts file="./TearsheetStacked.tsx" ``` ### Tearsheet group (infinite stacking) -Use a `TearsheetGroup` to manage an unbounded number of stacked tearsheets. Render order determines stacking priority — later children stack in front of earlier ones. Only the top 3 open tearsheets are visible; earlier ones hide behind the stack and reappear as front tearsheets are closed. +Use a `TearsheetGroup` to manage an unbounded number of stacked tearsheets. +`children` rendering order determines stacking priority with later children stacking in front of earlier ones. +Only the top 3 open tearsheets are visible; earlier ones hide behind the stack and reappear as front tearsheets are closed. ```ts file="./TearsheetGroup.tsx" ``` -### Tearsheet layouts +### Tearsheets vs Modals -```ts file="./TearsheetLayouts.tsx" +To illustrate the difference between a tearsheet and a modal, this example showcases a complex use case with a search bar, side panel, and a number of cards. +In a modal the content is crammed and is not as usable as if it were on a bigger area like the tearsheet. + +```ts file="./TearsheetComparison.tsx" ``` diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetComparison.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetComparison.tsx new file mode 100644 index 00000000..0c761403 --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetComparison.tsx @@ -0,0 +1,259 @@ +import { Fragment, useState } from 'react'; +import { + Button, + Card, + CardBody, + CardHeader, + CardTitle, + CodeBlock, + CodeBlockCode, + Content, + DescriptionList, + DescriptionListDescription, + DescriptionListGroup, + DescriptionListTerm, + Flex, + Grid, + GridItem, + JumpLinks, + JumpLinksItem, + Label, + LabelGroup, + Modal, + ModalBody, + ModalFooter, + ModalHeader, + ModalVariant, + PageSection, + SearchInput, + Sidebar, + SidebarContent, + SidebarPanel +} from '@patternfly/react-core'; +import Tearsheet from '@patternfly/react-component-groups/dist/dynamic/Tearsheet'; +import TearsheetHeader from '@patternfly/react-component-groups/dist/dynamic/TearsheetHeader'; +import TearsheetBody from '@patternfly/react-component-groups/dist/dynamic/TearsheetBody'; +import TearsheetFooter from '@patternfly/react-component-groups/dist/dynamic/TearsheetFooter'; + +const SIDEBAR_FIX_CLASS = 'tearsheet-comparison-sidebar'; +const sidebarFixStyles = ` + .${SIDEBAR_FIX_CLASS} .pf-v6-c-sidebar__main { height: 100%; } + .${SIDEBAR_FIX_CLASS} .pf-v6-c-sidebar__content { overflow: scroll; height: 100%; } +`; + +const LOREM = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore ' + + 'magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo ' + + 'consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla ' + + 'pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id ' + + 'est laborum.'; + +const sections = [ + { + id: 'overview', + title: 'Overview', + description: 'High-level summary of the resource, including its purpose, current state, and key metadata.', + labels: [ 'v1', 'stable', 'core' ], + items: [ + { name: 'ConfigMap', status: 'Active', created: '2025-06-01', owner: 'platform-team' }, + { name: 'Secret', status: 'Active', created: '2025-06-02', owner: 'security-team' }, + { name: 'ServiceAccount', status: 'Active', created: '2025-05-28', owner: 'platform-team' }, + { name: 'Namespace', status: 'Terminating', created: '2025-04-15', owner: 'admin' }, + { name: 'LimitRange', status: 'Active', created: '2025-06-03', owner: 'ops-team' }, + { name: 'ResourceQuota', status: 'Active', created: '2025-06-03', owner: 'ops-team' } + ], + code: `apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: my-config\n namespace: default\n labels:\n app.kubernetes.io/name: my-app\n app.kubernetes.io/version: "1.2.0"\n app.kubernetes.io/managed-by: helm\ndata:\n APP_ENV: production\n LOG_LEVEL: info\n MAX_CONNECTIONS: "100"` + }, + { + id: 'configuration', + title: 'Configuration', + description: 'Runtime parameters, feature flags, and environment-specific settings that control application behavior.', + labels: [ 'apps/v1', 'deployment', 'rolling-update' ], + items: [ + { name: 'Deployment', status: 'Available', created: '2025-06-01', owner: 'dev-team' }, + { name: 'StatefulSet', status: 'Ready', created: '2025-06-01', owner: 'data-team' }, + { name: 'DaemonSet', status: 'Scheduled', created: '2025-05-30', owner: 'infra-team' }, + { name: 'ReplicaSet', status: 'Available', created: '2025-06-01', owner: 'dev-team' }, + { name: 'CronJob', status: 'Suspended', created: '2025-05-20', owner: 'batch-team' }, + { name: 'Job', status: 'Complete', created: '2025-06-04', owner: 'batch-team' } + ], + code: `spec:\n replicas: 3\n selector:\n matchLabels:\n app: my-app\n strategy:\n type: RollingUpdate\n rollingUpdate:\n maxSurge: 1\n maxUnavailable: 0\n template:\n spec:\n containers:\n - name: app\n image: registry.io/my-app:1.2.0\n env:\n - name: DB_HOST\n valueFrom:\n secretKeyRef:\n name: db-credentials\n key: host` + }, + { + id: 'resources', + title: 'Resources', + description: 'CPU, memory, and storage allocations for each container in the workload.', + labels: [ 'requests', 'limits', 'QoS: Burstable' ], + items: [ + { name: 'app', status: 'Running', created: '2025-06-01', owner: 'dev-team' }, + { name: 'sidecar-proxy', status: 'Running', created: '2025-06-01', owner: 'mesh-team' }, + { name: 'log-collector', status: 'Running', created: '2025-06-01', owner: 'observability' }, + { name: 'init-db', status: 'Completed', created: '2025-06-01', owner: 'dev-team' }, + { name: 'init-config', status: 'Completed', created: '2025-06-01', owner: 'platform-team' }, + { name: 'debug', status: 'Waiting', created: '2025-06-05', owner: 'sre-team' } + ], + code: `containers:\n - name: app\n resources:\n requests:\n cpu: "250m"\n memory: "512Mi"\n ephemeral-storage: "1Gi"\n limits:\n cpu: "1"\n memory: "1Gi"\n ephemeral-storage: "2Gi"\n - name: sidecar-proxy\n resources:\n requests:\n cpu: "100m"\n memory: "128Mi"\n limits:\n cpu: "200m"\n memory: "256Mi"` + }, + { + id: 'networking', + title: 'Networking', + description: 'Service exposure, ingress rules, and network policies governing traffic flow.', + labels: [ 'ClusterIP', 'Ingress', 'NetworkPolicy' ], + items: [ + { name: 'my-service', status: 'Active', created: '2025-06-01', owner: 'dev-team' }, + { name: 'my-service-headless', status: 'Active', created: '2025-06-01', owner: 'data-team' }, + { name: 'ingress-main', status: 'Synced', created: '2025-06-02', owner: 'platform-team' }, + { name: 'netpol-deny-all', status: 'Enforcing', created: '2025-05-15', owner: 'security-team' }, + { name: 'netpol-allow-web', status: 'Enforcing', created: '2025-05-15', owner: 'security-team' }, + { name: 'external-dns', status: 'Active', created: '2025-06-03', owner: 'infra-team' } + ], + code: `apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: my-ingress\n annotations:\n nginx.ingress.kubernetes.io/rewrite-target: /\n cert-manager.io/cluster-issuer: letsencrypt\nspec:\n tls:\n - hosts:\n - app.example.com\n secretName: app-tls\n rules:\n - host: app.example.com\n http:\n paths:\n - path: /api\n pathType: Prefix\n backend:\n service:\n name: my-service\n port:\n number: 8080` + }, + { + id: 'storage', + title: 'Storage', + description: 'Persistent volume claims, storage classes, and mount configurations.', + labels: [ 'gp3', 'ReadWriteOnce', 'Retain' ], + items: [ + { name: 'data-pvc', status: 'Bound', created: '2025-06-01', owner: 'data-team' }, + { name: 'logs-pvc', status: 'Bound', created: '2025-06-01', owner: 'observability' }, + { name: 'backup-pvc', status: 'Bound', created: '2025-05-20', owner: 'ops-team' }, + { name: 'tmp-pvc', status: 'Pending', created: '2025-06-05', owner: 'dev-team' }, + { name: 'cache-emptydir', status: 'Mounted', created: '2025-06-01', owner: 'dev-team' }, + { name: 'config-projected', status: 'Mounted', created: '2025-06-01', owner: 'platform-team' } + ], + code: `apiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: data-pvc\nspec:\n accessModes:\n - ReadWriteOnce\n storageClassName: gp3-encrypted\n resources:\n requests:\n storage: 50Gi\n---\nvolumeMounts:\n - name: data\n mountPath: /var/lib/data\n - name: logs\n mountPath: /var/log/app\n - name: cache\n mountPath: /tmp/cache\nvolumes:\n - name: data\n persistentVolumeClaim:\n claimName: data-pvc\n - name: cache\n emptyDir:\n sizeLimit: 500Mi` + }, + { + id: 'monitoring', + title: 'Monitoring', + description: 'Health checks, readiness probes, and metrics endpoints used for observability.', + labels: [ 'prometheus', 'liveness', 'readiness' ], + items: [ + { name: 'liveness-http', status: 'Passing', created: '2025-06-01', owner: 'dev-team' }, + { name: 'readiness-http', status: 'Passing', created: '2025-06-01', owner: 'dev-team' }, + { name: 'startup-tcp', status: 'Passing', created: '2025-06-01', owner: 'dev-team' }, + { name: 'metrics-endpoint', status: 'Scraping', created: '2025-06-02', owner: 'observability' }, + { name: 'alert-high-cpu', status: 'Firing', created: '2025-05-10', owner: 'sre-team' }, + { name: 'alert-error-rate', status: 'Pending', created: '2025-05-10', owner: 'sre-team' } + ], + code: `livenessProbe:\n httpGet:\n path: /healthz\n port: 8080\n initialDelaySeconds: 15\n periodSeconds: 10\n failureThreshold: 3\nreadinessProbe:\n httpGet:\n path: /readyz\n port: 8080\n initialDelaySeconds: 5\n periodSeconds: 5\nstartupProbe:\n tcpSocket:\n port: 8080\n failureThreshold: 30\n periodSeconds: 2\n---\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n name: my-app-monitor\nspec:\n selector:\n matchLabels:\n app: my-app\n endpoints:\n - port: metrics\n interval: 15s\n path: /metrics` + } +]; + +const renderBodyContent = (sidebarClassName = '') => ( + + + + +
+ + + + {sections.map((s) => ( + e.preventDefault()}> + {s.title} + + ))} + + + + + {sections.map((section) => ( + + + + {section.title} + + {section.labels.map((l) => ( + + ))} + + + {section.description} + + {section.items.map((item, i) => ( + + + + {item.name} + + + + + Status + {item.status} + + + Created + {item.created} + + + Owner + {item.owner} + + + {LOREM.slice(0, 120)} + + {section.code} + + + + + ))} + + ))} + + + +
+
+); + +export const TearsheetComparison: React.FunctionComponent = () => { + const [ isTearsheetOpen, setIsTearsheetOpen ] = useState(false); + const [ isModalOpen, setIsModalOpen ] = useState(false); + + const closeTearsheet = () => setIsTearsheetOpen(false); + const closeModal = () => setIsModalOpen(false); + + return ( + + + + + + + + + + {renderBodyContent(SIDEBAR_FIX_CLASS)} + + + + + + + + + {renderBodyContent()} + + + + + + + ); +}; diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetLayouts.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetLayouts.tsx index 50e44503..33095bf7 100644 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetLayouts.tsx +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetLayouts.tsx @@ -19,7 +19,7 @@ import TearsheetBody from '@patternfly/react-component-groups/dist/dynamic/Tears import TearsheetFooter from '@patternfly/react-component-groups/dist/dynamic/TearsheetFooter'; import { Flex, FlexItem, Grid, GridItem } from '@patternfly/react-core'; -type BodyLayout = 'simple' | 'xl-text' | 'grid' | 'long'; +type BodyLayout = 'long-text' | 'grid' | 'long'; const LOREM = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore ' + @@ -29,12 +29,8 @@ const LOREM = 'est laborum.'; const bodyLayouts: Record React.ReactNode }> = { - simple: { - label: 'Simple text', - render: () => {LOREM} - }, - 'xl-text': { - label: 'XL text', + 'long-text': { + label: 'Long text', render: () => ( <> {Array.from({ length: 30 }, (_, i) => ( @@ -49,21 +45,25 @@ const bodyLayouts: Record React.React label: 'Grid layout', render: () => ( - {[ 'Overview', 'Configuration', 'Resources', 'Networking', 'Storage', 'Monitoring' ].map((title) => ( - - - - {title} - - {LOREM.slice(0, 120)}... - - - ))} + {[ 'Overview', 'Configuration', 'Resources', 'Networking', 'Storage', 'Monitoring' ] + .map((title) => new Array(10).fill(title)) + .flat() + .sort(() => Math.random() - 0.5) + .map((title) => ( + + + + {title} + + {LOREM.slice(0, 120)}... + + + ))} ) }, long: { - label: 'Long layout', + label: 'Flex layout', render: () => ( {[ 'General', 'Details', 'Configuration', 'Permissions', 'Audit log' ].map((section) => ( diff --git a/packages/module/src/Tearsheet/Tearsheet.tsx b/packages/module/src/Tearsheet/Tearsheet.tsx index 7aac8604..2a137e01 100644 --- a/packages/module/src/Tearsheet/Tearsheet.tsx +++ b/packages/module/src/Tearsheet/Tearsheet.tsx @@ -11,6 +11,8 @@ const useStyles = createUseStyles({ maxHeight: 'calc(100% - 4rem) !important', insetBlockStart: '2rem !important', // top: '2rem !important', + borderBottomLeftRadius: '0', + borderBottomRightRadius: '0', '&.pf-v6-c-modal-animated': { '--pf-v6-c-modal-animated--Transition': 'width 300ms ease, max-width 300ms ease, height 300ms ease, max-height 300ms ease, top 300ms ease, opacity 240ms cubic-bezier(0.4, 0.14, 1, 1), transform 240ms cubic-bezier(0.4, 0.14, 1, 1), visibility 0ms linear 240ms', @@ -50,7 +52,8 @@ const useStyles = createUseStyles({ display: 'flex', flexDirection: 'column', overflow: 'hidden', - height: '100%', + flex: '1 1 auto', + minHeight: 0, marginInlineEnd: 0, }, }); diff --git a/packages/module/src/TearsheetBody/TearsheetBody.tsx b/packages/module/src/TearsheetBody/TearsheetBody.tsx index 6cf134d1..3fe30e29 100644 --- a/packages/module/src/TearsheetBody/TearsheetBody.tsx +++ b/packages/module/src/TearsheetBody/TearsheetBody.tsx @@ -5,7 +5,9 @@ import { ModalBody, type ModalBodyProps } from '@patternfly/react-core'; const useStyles = createUseStyles({ tearsheetBody: { - caretColor: 'red', + flex: 1, + minHeight: 0, + overflow: 'auto', }, }); diff --git a/packages/module/src/TearsheetGroup/TearsheetGroup.tsx b/packages/module/src/TearsheetGroup/TearsheetGroup.tsx index 34c1f3d8..e25d1246 100644 --- a/packages/module/src/TearsheetGroup/TearsheetGroup.tsx +++ b/packages/module/src/TearsheetGroup/TearsheetGroup.tsx @@ -5,7 +5,6 @@ import Tearsheet, { type TearsheetProps } from '../Tearsheet'; const useStyles = createUseStyles({ tearsheetGroup: { - caretColor: 'red', }, }); From 0047ae8b343a55ed155db911adec2197a97739e9 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Thu, 9 Jul 2026 15:50:12 -0400 Subject: [PATCH 08/37] doc: Update syntax of code blocks --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b6507124..cd74b877 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Please reference [PatternFly's AI-assisted development guidelines](https://githu #### Example component: -``` +``` TSX import * as React from 'react'; import { Content } from '@patternfly/react-core'; import { createUseStyles } from 'react-jss'; @@ -75,7 +75,7 @@ export default MyComponent; #### Index file example: -``` +``` TSX export { default } from './MyComponent'; export * from './MyComponent'; ``` @@ -99,8 +99,7 @@ src #### Component API definition example: -``` - +``` TSX import { FunctionComponent } from 'react'; // when possible, extend available PatternFly types @@ -113,7 +112,7 @@ export const MyComponent: FunctionComponent = ({ customLabel, #### Markdown file example: -```` +```` MDX --- section: Component groups subsection: My component's category @@ -135,7 +134,7 @@ MyComponent has been created to demo contributing to this repository. #### Component usage file example: (`MyComponentExample.tsx`) -``` +``` TSX import { FunctionComponent } from 'react'; const MyComponentExample: FunctionComponent = () => ( From fe6c124eab6bcfe00b49ce9298c4dbcb5237c3b2 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Thu, 9 Jul 2026 20:31:19 -0400 Subject: [PATCH 09/37] chore: Cleanup --- packages/module/src/Tearsheet/tearsheet.css | 87 --------------------- 1 file changed, 87 deletions(-) delete mode 100644 packages/module/src/Tearsheet/tearsheet.css diff --git a/packages/module/src/Tearsheet/tearsheet.css b/packages/module/src/Tearsheet/tearsheet.css deleted file mode 100644 index 904ffa25..00000000 --- a/packages/module/src/Tearsheet/tearsheet.css +++ /dev/null @@ -1,87 +0,0 @@ -.pf-v6-c-tearsheet { - width: calc(100% - 4rem) !important; - max-width: calc(100% - 4rem) !important; - height: calc(100% - 4rem) !important; - max-height: calc(100% - 4rem) !important; - inset-block-start: 0 !important; - top: 2rem !important; -} - -/* Override the modal animation custom property to compose stack-level transitions - with the existing open/close animation. Specificity 0,2,0 beats the single-class - declarations in modal-animations.css. */ -.pf-v6-c-modal-animated.pf-v6-c-tearsheet { - --pf-v6-c-modal-animated--Transition: - width 300ms ease, - max-width 300ms ease, - height 300ms ease, - max-height 300ms ease, - top 300ms ease, - opacity 240ms cubic-bezier(0.4, 0.14, 1, 1), - transform 240ms cubic-bezier(0.4, 0.14, 1, 1), - visibility 0ms linear 240ms; -} - -.pf-v6-c-modal-animated-open.pf-v6-c-tearsheet { - --pf-v6-c-modal-animated--Transition: - width 300ms ease, - max-width 300ms ease, - height 300ms ease, - max-height 300ms ease, - top 300ms ease, - transform 240ms cubic-bezier(0, 0, 0.2, 1), - visibility 0ms linear 0ms; -} - -.pf-v6-c-tearsheet.pf-m-stack-level-1 { - width: calc(100% - 2rem) !important; - max-width: calc(100% - 2rem) !important; - height: calc(100% - 6rem) !important; - max-height: calc(100% - 6rem) !important; - inset-block-start: 0 !important; - top: 3rem !important; -} - -.pf-v6-c-tearsheet.pf-m-stack-level-2 { - width: calc(100% - 0rem) !important; - max-width: calc(100% - 0rem) !important; - height: calc(100% - 8rem) !important; - max-height: calc(100% - 8rem) !important; - inset-block-start: 0 !important; - top: 4rem !important; -} - -.pf-v6-c-tearsheet.pf-m-stack-hidden { - width: calc(100% - 4rem) !important; - max-width: calc(100% - 4rem) !important; - height: calc(100% - 4rem) !important; - max-height: calc(100% - 4rem) !important; - inset-block-start: 0 !important; - top: 3rem !important; - opacity: 0 !important; - pointer-events: none !important; -} - -.pf-v6-c-tearsheet-inner { - display: flex; - flex-direction: column; - overflow: hidden; - height: 100%; - margin-inline-end: 0; -} - -.pf-v6-c-tearsheet-header { - flex-shrink: 0; -} - -.pf-v6-c-tearsheet-body { - caret-color: red; -} - -.pf-v6-c-tearsheet-footer { - flex-shrink: 0; -} - -.pf-v6-c-tearsheet-group { - caret-color: red; -} From dc5872d493becbfc917b0005d3e2dea3838548ec Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Mon, 31 Aug 2026 18:05:22 -0400 Subject: [PATCH 10/37] chore: Update dependencies (PR feedback) ```sh npm install @patternfly/react-drag-drop@6.6.2 npm install @patternfly/react-core@6.6.2 @patternfly/react-table@6.6.2 @patternfly/react-code-editor@6.6.2 @patternfly/react-drag-drop@6.6.2 -w @patternfly/react-component-groups ``` Assisted-by: Claude Co-authored-by: Claude --- package-lock.json | 109 ++++++++++++++++++----------------- package.json | 2 +- packages/module/package.json | 10 ++-- 3 files changed, 62 insertions(+), 59 deletions(-) diff --git a/package-lock.json b/package-lock.json index 72358f3c..efad1fcf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "packages/*" ], "dependencies": { - "@patternfly/react-drag-drop": "^6.0.0", + "@patternfly/react-drag-drop": "^6.6.2", "@patternfly/react-tokens": "^6.0.0", "sharp": "^0.34.0" }, @@ -5422,22 +5422,22 @@ } }, "node_modules/@patternfly/react-code-editor": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@patternfly/react-code-editor/-/react-code-editor-6.2.2.tgz", - "integrity": "sha512-KPnkNP769afD2rvoNQtgCx+SYscamM5QSRmw2FJ9QPHVMksarwTsMvrdMxvu+n6Dhs/T40vQLU5UR7X2yPrURg==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/@patternfly/react-code-editor/-/react-code-editor-6.6.2.tgz", + "integrity": "sha512-opy2UXmSWRJUnssuqNzi5kMxjGyck6n78YCx3sjFLO6uosrSGRJEggQnRlot3jw4/+QmOHBWThlI5lrYpjIInw==", "dev": true, "license": "MIT", "dependencies": { - "@monaco-editor/react": "^4.6.0", - "@patternfly/react-core": "^6.2.2", - "@patternfly/react-icons": "^6.2.2", - "@patternfly/react-styles": "^6.2.2", + "@monaco-editor/react": "^4.7.0", + "@patternfly/react-core": "^6.6.2", + "@patternfly/react-icons": "^6.6.1", + "@patternfly/react-styles": "^6.6.1", "react-dropzone": "14.3.5", "tslib": "^2.8.1" }, "peerDependencies": { - "react": "^17 || ^18", - "react-dom": "^17 || ^18" + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19" } }, "node_modules/@patternfly/react-component-groups": { @@ -5445,15 +5445,15 @@ "link": true }, "node_modules/@patternfly/react-core": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-6.3.1.tgz", - "integrity": "sha512-1qV20nU4M6PA28qnikH9fPLQlkteaZZToFlATjBNBw7aUI6zIvj7U0akkHz8raWcfHAI+tAzGV7dfKjiv035/g==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-6.6.2.tgz", + "integrity": "sha512-FjXUSH+zNUto2Qc6t62nW9aEYdy6n+7njtAcZGFb3HhifMtufzOXGg8jNe4rrBAEYBroB913+xoaaQoK5CUwBA==", "license": "MIT", "dependencies": { - "@patternfly/react-icons": "^6.3.1", - "@patternfly/react-styles": "^6.3.1", - "@patternfly/react-tokens": "^6.3.1", - "focus-trap": "7.6.4", + "@patternfly/react-icons": "^6.6.1", + "@patternfly/react-styles": "^6.6.1", + "@patternfly/react-tokens": "^6.6.1", + "focus-trap": "7.6.6", "react-dropzone": "^14.3.5", "tslib": "^2.8.1" }, @@ -5463,17 +5463,17 @@ } }, "node_modules/@patternfly/react-drag-drop": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@patternfly/react-drag-drop/-/react-drag-drop-6.3.1.tgz", - "integrity": "sha512-lTPTSCtScYm+5NPCbr8hmSMOggOEhvIIzsyoVWF/G+iJBR97u0fdvsBqRvTg95hv2R/bKTXHigSCgixqnE9XdQ==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/@patternfly/react-drag-drop/-/react-drag-drop-6.6.2.tgz", + "integrity": "sha512-JBOF3By3bBnsW7/pogkFbHLHeLh+xSOtHkLFdqjfhDtmOOM0qhdz/fzzRcM3hqYtMFVwj0MiL9m5H2YolnP68g==", "license": "MIT", "dependencies": { "@dnd-kit/core": "^6.3.1", "@dnd-kit/modifiers": "^9.0.0", "@dnd-kit/sortable": "^10.0.0", - "@patternfly/react-core": "^6.3.1", - "@patternfly/react-icons": "^6.3.1", - "@patternfly/react-styles": "^6.3.1", + "@patternfly/react-core": "^6.6.2", + "@patternfly/react-icons": "^6.6.1", + "@patternfly/react-styles": "^6.6.1", "resize-observer-polyfill": "^1.5.1" }, "peerDependencies": { @@ -5482,43 +5482,46 @@ } }, "node_modules/@patternfly/react-icons": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-6.3.1.tgz", - "integrity": "sha512-uiMounSIww1iZLM4pq+X8c3upzwl9iowXRPjR5CA8entb70lwgAXg3PqvypnuTAcilTq1Y3k5sFTqkhz7rgKcQ==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-6.6.1.tgz", + "integrity": "sha512-EUHnTliMlUMNfaueyGTaNcdCDGN4CjLtQpNdSg6iWcl5oloHtUDEAIltP0nbCWnepMJDoM2YgjMlyjwWlkNzXg==", "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + }, "peerDependencies": { "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" } }, "node_modules/@patternfly/react-styles": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-6.3.1.tgz", - "integrity": "sha512-hyb+PlO8YITjKh2wBvjdeZhX6FyB3hlf4r6yG4rPOHk4SgneXHjNSdGwQ3szAxgGqtbENCYtOqwD/8ai72GrxQ==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-6.6.1.tgz", + "integrity": "sha512-hwByXA4wSpOIBJFtrYUdkFDIqvzHRP5yzvip/NHDlG0y/kXausOh5Z4m00SbTA6t7Hzudw5eU1lf+IOPCm5C6Q==", "license": "MIT" }, "node_modules/@patternfly/react-table": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-6.2.2.tgz", - "integrity": "sha512-7CxVKhnpA+f8dLJ0hVvzZOe4Djx/nE+w70ipeAHf4Yi5JwfDWmbK97YvjYPfamp/bsXTLtPcK2n4AoY5DQX6Pg==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-6.6.2.tgz", + "integrity": "sha512-HIxECFB1eiVcAi/DP+FYQMzA7JU4zTg/7idVKuEvWJfILx66ZBwpitwOt27IPxQ3AjCgixLMyh6lTDFAfmd3Kw==", "license": "MIT", "dependencies": { - "@patternfly/react-core": "^6.2.2", - "@patternfly/react-icons": "^6.2.2", - "@patternfly/react-styles": "^6.2.2", - "@patternfly/react-tokens": "^6.2.2", - "lodash": "^4.17.21", + "@patternfly/react-core": "^6.6.2", + "@patternfly/react-icons": "^6.6.1", + "@patternfly/react-styles": "^6.6.1", + "@patternfly/react-tokens": "^6.6.1", + "lodash": "^4.18.1", "tslib": "^2.8.1" }, "peerDependencies": { - "react": "^17 || ^18", - "react-dom": "^17 || ^18" + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19" } }, "node_modules/@patternfly/react-tokens": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-6.3.1.tgz", - "integrity": "sha512-wt/xKU1tGCDXUueFb+8/Cwxlm4vUD/Xl26O8MxbSLm6NZAHOUPwytJ7gugloGSPvc/zcsXxEgKANL8UZNO6DTw==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-6.6.1.tgz", + "integrity": "sha512-t7dDEJMnO3QkdIKyjbyKJznVYki9ONZG27Cn/9RXwaM0lDGCrgQEJXy2XoVUCdYhIdXZu+TGSEqXeNFYUyZECg==", "license": "MIT" }, "node_modules/@pkgjs/parseargs": { @@ -14051,12 +14054,12 @@ } }, "node_modules/focus-trap": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.4.tgz", - "integrity": "sha512-xx560wGBk7seZ6y933idtjJQc1l+ck+pI3sKvhKozdBV1dRZoKhkW5xoCaFv9tQiX5RH1xfSxjuNu6g+lmN/gw==", + "version": "7.6.6", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.6.tgz", + "integrity": "sha512-v/Z8bvMCajtx4mEXmOo7QEsIzlIOqRXTIwgUfsFOF9gEsespdbD0AkPIka1bSXZ8Y8oZ+2IVDQZePkTfEHZl7Q==", "license": "MIT", "dependencies": { - "tabbable": "^6.2.0" + "tabbable": "^6.3.0" } }, "node_modules/follow-redirects": { @@ -25680,9 +25683,9 @@ } }, "node_modules/tabbable": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", - "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.5.0.tgz", + "integrity": "sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA==", "license": "MIT" }, "node_modules/tapable": { @@ -29021,17 +29024,17 @@ "version": "5.0.0-prerelease.0", "license": "MIT", "dependencies": { - "@patternfly/react-core": "^6.0.0", + "@patternfly/react-core": "^6.6.2", "@patternfly/react-icons": "^6.0.0", "@patternfly/react-styles": "^6.0.0", - "@patternfly/react-table": "^6.0.0", + "@patternfly/react-table": "^6.6.2", "react-jss": "^10.10.0" }, "devDependencies": { "@patternfly/documentation-framework": "^6.5.16", "@patternfly/patternfly": "^6.0.0", "@patternfly/patternfly-a11y": "^5.1.0", - "@patternfly/react-code-editor": "^6.0.0", + "@patternfly/react-code-editor": "^6.6.2", "@types/react": "^18.2.33", "@types/react-dom": "^18.3.1", "react": "^18.3.1", @@ -29039,7 +29042,7 @@ "typescript": "^5.8.3" }, "peerDependencies": { - "@patternfly/react-drag-drop": "^6.0.0", + "@patternfly/react-drag-drop": "^6.6.2", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" } diff --git a/package.json b/package.json index c52a5a6b..9ad47556 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "whatwg-fetch": "^3.6.20" }, "dependencies": { - "@patternfly/react-drag-drop": "^6.0.0", + "@patternfly/react-drag-drop": "^6.6.2", "@patternfly/react-tokens": "^6.0.0", "sharp": "^0.34.0" } diff --git a/packages/module/package.json b/packages/module/package.json index e251230c..adc780b0 100644 --- a/packages/module/package.json +++ b/packages/module/package.json @@ -31,22 +31,22 @@ "tag": "alpha" }, "dependencies": { - "@patternfly/react-core": "^6.0.0", + "@patternfly/react-core": "^6.6.2", "@patternfly/react-icons": "^6.0.0", "@patternfly/react-styles": "^6.0.0", - "@patternfly/react-table": "^6.0.0", + "@patternfly/react-table": "^6.6.2", "react-jss": "^10.10.0" }, "peerDependencies": { - "@patternfly/react-drag-drop": "^6.0.0", + "@patternfly/react-drag-drop": "^6.6.2", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "devDependencies": { - "@patternfly/patternfly-a11y": "^5.1.0", "@patternfly/documentation-framework": "^6.5.16", - "@patternfly/react-code-editor": "^6.0.0", "@patternfly/patternfly": "^6.0.0", + "@patternfly/patternfly-a11y": "^5.1.0", + "@patternfly/react-code-editor": "^6.6.2", "@types/react": "^18.2.33", "@types/react-dom": "^18.3.1", "react": "^18.3.1", From 2b15f3a67e63324adf680c27305971407243cb9b Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Mon, 31 Aug 2026 18:07:53 -0400 Subject: [PATCH 11/37] chore: Cleanup Tearsheet.md (PR feedback) Top level comments --- .../component-groups/examples/Tearsheet/Tearsheet.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md index 08e1c00e..ae0a99f3 100644 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md @@ -1,15 +1,8 @@ --- -# Sidenav top-level section -# should be the same for all markdown files section: extensions subsection: component-groups -# Sidenav secondary level section -# should be the same for all markdown files id: Tearsheet -# Tab (react | react-demos | html | html-demos | design-guidelines | accessibility) source: react -# If you use typescript, the name of the interface to display props for -# These are found through the sourceProps function provided in patternfly-docs.source.js propComponents: ['Tearsheet', 'TearsheetHeader', 'TearsheetBody', 'TearsheetFooter', 'TearsheetGroup'] sourceLink: https://github.com/patternfly/react-component-groups/blob/main/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md --- From 8c3a3af56f61f0dc68dfc4289fa784085f3e3f8f Mon Sep 17 00:00:00 2001 From: Gustavo Andres Murcia Date: Mon, 31 Aug 2026 18:10:41 -0400 Subject: [PATCH 12/37] chore: Update Tearsheet prop wording (PR feedback) Update packages/module/src/Tearsheet/Tearsheet.tsx From: @thatblindgeye Co-authored-by: Eric Olkowski <70952936+thatblindgeye@users.noreply.github.com> --- packages/module/src/Tearsheet/Tearsheet.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/module/src/Tearsheet/Tearsheet.tsx b/packages/module/src/Tearsheet/Tearsheet.tsx index 2a137e01..ca280a03 100644 --- a/packages/module/src/Tearsheet/Tearsheet.tsx +++ b/packages/module/src/Tearsheet/Tearsheet.tsx @@ -75,11 +75,11 @@ export interface TearsheetProps extends HTMLProps { onEscapePress?: (event: KeyboardEvent) => void; /** The parent container to append the tearsheet to. Defaults to document.body. */ appendTo?: HTMLElement | (() => HTMLElement); - /** Accessible label for the tearsheet. */ + /** Accessible name for the tearsheet as a human readable string. */ 'aria-label'?: string; - /** ID of the element that labels the tearsheet. */ + /** Space separated list of ID's of the elements that label the tearsheet. */ 'aria-labelledby'?: string; - /** ID of the element that describes the tearsheet. */ + /** ISpace separated list of ID's of the elements that describe the tearsheet. */ 'aria-describedby'?: string; /** Flag to disable focus trap. */ disableFocusTrap?: boolean; From 006ef20ecd8c7b22f0b8ab9f9453db45d5d9de70 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Mon, 31 Aug 2026 18:14:38 -0400 Subject: [PATCH 13/37] chore: Add `modalProps` and spread (PR feedback) Replace explicit `disableFocusTrap` prop with a general `modalProps` spread on Modal in Tearsheet. Update TearsheetGroup to pass `disableFocusTrap` through `modalProps`. Generated-by: Claude Co-authored-by: Claude --- packages/module/src/Tearsheet/Tearsheet.tsx | 10 +++++----- packages/module/src/TearsheetGroup/TearsheetGroup.tsx | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/module/src/Tearsheet/Tearsheet.tsx b/packages/module/src/Tearsheet/Tearsheet.tsx index 2a137e01..fca3ddd4 100644 --- a/packages/module/src/Tearsheet/Tearsheet.tsx +++ b/packages/module/src/Tearsheet/Tearsheet.tsx @@ -1,7 +1,7 @@ import type { ReactNode, HTMLProps, FunctionComponent, MouseEvent } from 'react'; import { css } from '@patternfly/react-styles'; import { createUseStyles } from 'react-jss'; -import { Modal, ModalVariant } from '@patternfly/react-core'; +import { Modal, ModalVariant, type ModalProps } from '@patternfly/react-core'; const useStyles = createUseStyles({ tearsheet: { @@ -81,8 +81,8 @@ export interface TearsheetProps extends HTMLProps { 'aria-labelledby'?: string; /** ID of the element that describes the tearsheet. */ 'aria-describedby'?: string; - /** Flag to disable focus trap. */ - disableFocusTrap?: boolean; + /** Additional props spread to the underlying PatternFly Modal. */ + modalProps?: Omit; } const Tearsheet: FunctionComponent = ({ @@ -96,7 +96,7 @@ const Tearsheet: FunctionComponent = ({ 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, - disableFocusTrap, + modalProps, ...props }: TearsheetProps) => { const classes = useStyles(); @@ -115,7 +115,7 @@ const Tearsheet: FunctionComponent = ({ onClose={onClose} onEscapePress={onEscapePress} appendTo={appendTo} - disableFocusTrap={disableFocusTrap} + {...modalProps} >
{children} diff --git a/packages/module/src/TearsheetGroup/TearsheetGroup.tsx b/packages/module/src/TearsheetGroup/TearsheetGroup.tsx index e25d1246..2a5f0ec3 100644 --- a/packages/module/src/TearsheetGroup/TearsheetGroup.tsx +++ b/packages/module/src/TearsheetGroup/TearsheetGroup.tsx @@ -73,7 +73,7 @@ const TearsheetGroup: FunctionComponent = ({ return cloneElement(child as ReactElement, { stackLevel, - disableFocusTrap: !isFrontmost + modalProps: { disableFocusTrap: !isFrontmost } }); }); From c28bee9e0476a3806216de9790aff3965f4ed435 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Mon, 31 Aug 2026 18:15:36 -0400 Subject: [PATCH 14/37] chore: Remove animated comment (PR feedback) Will be added later once animation support in Modal is added --- packages/module/src/Tearsheet/Tearsheet.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/module/src/Tearsheet/Tearsheet.tsx b/packages/module/src/Tearsheet/Tearsheet.tsx index fca3ddd4..0f44d000 100644 --- a/packages/module/src/Tearsheet/Tearsheet.tsx +++ b/packages/module/src/Tearsheet/Tearsheet.tsx @@ -105,7 +105,6 @@ const Tearsheet: FunctionComponent = ({ return ( Date: Mon, 31 Aug 2026 18:17:21 -0400 Subject: [PATCH 15/37] chore: Remove outdated styles (PR feedback) op was used before the correct insetBlockStart was added. Removing comment as the right property is now being used --- packages/module/src/Tearsheet/Tearsheet.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/module/src/Tearsheet/Tearsheet.tsx b/packages/module/src/Tearsheet/Tearsheet.tsx index 0f44d000..61afd422 100644 --- a/packages/module/src/Tearsheet/Tearsheet.tsx +++ b/packages/module/src/Tearsheet/Tearsheet.tsx @@ -10,7 +10,6 @@ const useStyles = createUseStyles({ height: 'calc(100% - 4rem) !important', maxHeight: 'calc(100% - 4rem) !important', insetBlockStart: '2rem !important', - // top: '2rem !important', borderBottomLeftRadius: '0', borderBottomRightRadius: '0', '&.pf-v6-c-modal-animated': { @@ -27,7 +26,6 @@ const useStyles = createUseStyles({ height: 'calc(100% - 6rem) !important', maxHeight: 'calc(100% - 6rem) !important', insetBlockStart: '3rem !important', - // top: '3rem !important', }, '&.pf-m-stack-level-2': { width: 'calc(100% - 0rem) !important', @@ -35,7 +33,6 @@ const useStyles = createUseStyles({ height: 'calc(100% - 8rem) !important', maxHeight: 'calc(100% - 8rem) !important', insetBlockStart: '4rem !important', - // top: '4rem !important', }, '&.pf-m-stack-hidden': { width: 'calc(100% - 4rem) !important', @@ -43,7 +40,6 @@ const useStyles = createUseStyles({ height: 'calc(100% - 4rem) !important', maxHeight: 'calc(100% - 4rem) !important', insetBlockStart: '3rem !important', - // top: '3rem !important', opacity: '0 !important', pointerEvents: 'none !important', }, From 7e710d6cb9190c1d9ca76c7b7d7b2d5138dd7412 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Mon, 31 Aug 2026 18:20:14 -0400 Subject: [PATCH 16/37] chore: Add `children` prop (PR feedback) Add explicit `children` prop with JSDoc descriptions to TearsheetBody, TearsheetFooter, and TearsheetHeader interfaces. Generated-by: Claude Opus 4.6 Co-authored-by: Claude Opus 4.6 --- packages/module/src/TearsheetBody/TearsheetBody.tsx | 5 ++++- packages/module/src/TearsheetFooter/TearsheetFooter.tsx | 5 ++++- packages/module/src/TearsheetHeader/TearsheetHeader.tsx | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/module/src/TearsheetBody/TearsheetBody.tsx b/packages/module/src/TearsheetBody/TearsheetBody.tsx index 3fe30e29..37d143b2 100644 --- a/packages/module/src/TearsheetBody/TearsheetBody.tsx +++ b/packages/module/src/TearsheetBody/TearsheetBody.tsx @@ -1,4 +1,4 @@ -import type { FunctionComponent } from 'react'; +import type { FunctionComponent, ReactNode } from 'react'; import { css } from '@patternfly/react-styles'; import { createUseStyles } from 'react-jss'; import { ModalBody, type ModalBodyProps } from '@patternfly/react-core'; @@ -12,6 +12,9 @@ const useStyles = createUseStyles({ }); export interface TearsheetBodyProps extends ModalBodyProps { + /** Content rendered inside the tearsheet body. */ + children?: ReactNode; + /** Additional classes applied to the tearsheet body. */ className?: string; } diff --git a/packages/module/src/TearsheetFooter/TearsheetFooter.tsx b/packages/module/src/TearsheetFooter/TearsheetFooter.tsx index 75db1d52..604a0d4d 100644 --- a/packages/module/src/TearsheetFooter/TearsheetFooter.tsx +++ b/packages/module/src/TearsheetFooter/TearsheetFooter.tsx @@ -1,4 +1,4 @@ -import type { FunctionComponent } from 'react'; +import type { FunctionComponent, ReactNode } from 'react'; import { css } from '@patternfly/react-styles'; import { createUseStyles } from 'react-jss'; import { ModalFooter, type ModalFooterProps } from '@patternfly/react-core'; @@ -10,6 +10,9 @@ const useStyles = createUseStyles({ }); export interface TearsheetFooterProps extends ModalFooterProps { + /** Content rendered inside the tearsheet footer. */ + children?: ReactNode; + /** Additional classes applied to the tearsheet footer. */ className?: string; } diff --git a/packages/module/src/TearsheetHeader/TearsheetHeader.tsx b/packages/module/src/TearsheetHeader/TearsheetHeader.tsx index 1c15fdc4..49a8f9fc 100644 --- a/packages/module/src/TearsheetHeader/TearsheetHeader.tsx +++ b/packages/module/src/TearsheetHeader/TearsheetHeader.tsx @@ -1,4 +1,4 @@ -import type { FunctionComponent } from 'react'; +import type { FunctionComponent, ReactNode } from 'react'; import { css } from '@patternfly/react-styles'; import { createUseStyles } from 'react-jss'; import { ModalHeader, type ModalHeaderProps } from '@patternfly/react-core'; @@ -10,6 +10,9 @@ const useStyles = createUseStyles({ }); export interface TearsheetHeaderProps extends ModalHeaderProps { + /** Content rendered inside the tearsheet header. */ + children?: ReactNode; + /** Additional classes applied to the tearsheet header. */ className?: string; } From d49bd2e8446bbfe9b6abf61d58d7b8986ee29277 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Mon, 31 Aug 2026 18:21:16 -0400 Subject: [PATCH 17/37] chore: Remove comment (PR feedback) Comment not needed as const explains intent --- packages/module/src/TearsheetGroup/TearsheetGroup.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/module/src/TearsheetGroup/TearsheetGroup.tsx b/packages/module/src/TearsheetGroup/TearsheetGroup.tsx index 2a5f0ec3..ff96af5b 100644 --- a/packages/module/src/TearsheetGroup/TearsheetGroup.tsx +++ b/packages/module/src/TearsheetGroup/TearsheetGroup.tsx @@ -8,7 +8,6 @@ const useStyles = createUseStyles({ }, }); -/** The maximum number of visually distinct stack levels (0, 1, 2). */ const MAX_VISIBLE_LEVELS = 3; export interface TearsheetGroupProps { From bc162d692d2d800ebee6f428e1b53d6655548c1f Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Mon, 31 Aug 2026 18:27:16 -0400 Subject: [PATCH 18/37] chore: Add better id prop if missing (PR feedback) Make TearsheetGroup `id` optional with a `useId()` fallback so consumers don't need to provide a static, unique ID. Generated-by: Claude Opus 4.6 (1M context) Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/module/src/TearsheetGroup/TearsheetGroup.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/module/src/TearsheetGroup/TearsheetGroup.tsx b/packages/module/src/TearsheetGroup/TearsheetGroup.tsx index ff96af5b..9cf20521 100644 --- a/packages/module/src/TearsheetGroup/TearsheetGroup.tsx +++ b/packages/module/src/TearsheetGroup/TearsheetGroup.tsx @@ -1,4 +1,4 @@ -import { Children, cloneElement, isValidElement, useRef, type FunctionComponent, type ReactElement } from 'react'; +import { Children, cloneElement, isValidElement, useId, useRef, type FunctionComponent, type ReactElement } from 'react'; import { css } from '@patternfly/react-styles'; import { createUseStyles } from 'react-jss'; import Tearsheet, { type TearsheetProps } from '../Tearsheet'; @@ -17,8 +17,8 @@ export interface TearsheetGroupProps { children?: React.ReactNode; /** Additional classes added to the Tearsheet group. */ className?: string; - /** Unique id for the Tearsheet group. */ - id: string; + /** Unique id for the Tearsheet group. A random id is generated when not provided. */ + id?: string; } const TearsheetGroup: FunctionComponent = ({ @@ -28,6 +28,8 @@ const TearsheetGroup: FunctionComponent = ({ ...props }: TearsheetGroupProps) => { const classes = useStyles(); + const generatedId = useId(); + const groupId = id ?? generatedId; // Track each child's last assigned stack level so closing tearsheets keep // their position during the modal exit animation instead of snapping to L0. const prevLevelsRef = useRef>(new Map()); @@ -77,7 +79,7 @@ const TearsheetGroup: FunctionComponent = ({ }); return ( -
+
{enhancedChildren}
); From 57f179bea081ee99c89bacf8c9a298077678fc0f Mon Sep 17 00:00:00 2001 From: Gustavo Andres Murcia Date: Mon, 31 Aug 2026 18:29:25 -0400 Subject: [PATCH 19/37] chore: Update Tearsheet documentation (PR feedback) Update packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md From: @kaylachumley Co-authored-by: Kayla Chumley <150823809+kaylachumley@users.noreply.github.com> --- .../extensions/component-groups/examples/Tearsheet/Tearsheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md index ae0a99f3..1a8ad461 100644 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md @@ -23,7 +23,7 @@ This component extends the [modal component](/components/modal) allowing any use ### Basic -Typical tearsheets should make use of the entire area, for this basic case some sample text is rendered. +Basic tearsheets should make use of the entire container. For this basic example, heading and body text is rendered with an action list placed within the footer area. ```ts file="./TearsheetBasic.tsx" ``` From fdfe55e45aa13295248e9b701160aa05f00e08e5 Mon Sep 17 00:00:00 2001 From: Gustavo Andres Murcia Date: Mon, 31 Aug 2026 18:29:48 -0400 Subject: [PATCH 20/37] chore: Update Tearsheet documentation (PR feedback) Update packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md From: @kaylachumley Co-authored-by: Kayla Chumley <150823809+kaylachumley@users.noreply.github.com> --- .../extensions/component-groups/examples/Tearsheet/Tearsheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md index 1a8ad461..83111e0f 100644 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md @@ -30,7 +30,7 @@ Basic tearsheets should make use of the entire container. For this basic example ### Tearsheet layouts -Tearsheets should allow various sorts of layouts to be rendered. +Tearsheets can be customized to render various layout styles. These layout styles include, [full width text](https://www.patternfly.org/foundations-and-styles/utility-classes/alignment), [flex](https://www.patternfly.org/foundations-and-styles/layouts/flex), and [grid](https://www.patternfly.org/foundations-and-styles/layouts/grid). The `` component will handle scrolling for long content. ```ts file="./TearsheetLayouts.tsx" From b6ec74b464f95d325893f0defdd859d4343fc304 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Mon, 31 Aug 2026 18:33:08 -0400 Subject: [PATCH 21/37] chore: Update Tearsheet documentation (PR feedback) Update packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md From: @kaylachumley Co-authored-by: Kayla Chumley <150823809+kaylachumley@users.noreply.github.com> --- .../component-groups/examples/Tearsheet/Tearsheet.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md index ae0a99f3..fbd86e77 100644 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md @@ -38,10 +38,7 @@ The `` component will handle scrolling for long content. ### Stacked -One special use case with tearsheets is stacking. -When a user is using a tearsheet, if another one needs to open it can open one level "on-top" of it in a new stack. -Tearsheets offer 3 stack levels (0,1,2). -A special stack level -1 allows a tearsheet to hide behind others. +Tearsheets support stacking, allowing new sheets to open on top of active ones. They utilize three visible stack levels (0, 1, and 2) and a background level (-1) to hide inactive sheets. ```ts file="./TearsheetStacked.tsx" ``` From d801d0cf9127364e370e38511b32506607b3c3de Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Mon, 31 Aug 2026 18:36:08 -0400 Subject: [PATCH 22/37] chore: Update Tearsheet documentation (PR feedback) Update packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md From: @kaylachumley Co-authored-by: Kayla Chumley <150823809+kaylachumley@users.noreply.github.com> --- .../component-groups/examples/Tearsheet/Tearsheet.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md index 55c9d3e0..c2d8fcea 100644 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md @@ -54,8 +54,8 @@ Only the top 3 open tearsheets are visible; earlier ones hide behind the stack a ### Tearsheets vs Modals -To illustrate the difference between a tearsheet and a modal, this example showcases a complex use case with a search bar, side panel, and a number of cards. -In a modal the content is crammed and is not as usable as if it were on a bigger area like the tearsheet. +Choose a tearsheet over a modal when users need to process detailed and complex workflows. +This example demonstrates how the expanded surface area of a tearsheet allows users to easily navigate a robust layout without feeling overwhelmed. ```ts file="./TearsheetComparison.tsx" ``` From fb38940d2ab6235454bd73ee335d89f2c271bd19 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Mon, 31 Aug 2026 18:38:43 -0400 Subject: [PATCH 23/37] chore: Remove infinite stacking from Tearsheet doc (PR feedback) To prevent unwanted UX with infinite stacking, remove the example and explicitly ask for up to 3 max in the stacked example doc --- .../examples/Tearsheet/Tearsheet.md | 15 ++--- .../examples/Tearsheet/TearsheetGroup.tsx | 66 ------------------- 2 files changed, 5 insertions(+), 76 deletions(-) delete mode 100644 packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetGroup.tsx diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md index c2d8fcea..021a039a 100644 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md @@ -38,18 +38,13 @@ The `` component will handle scrolling for long content. ### Stacked -Tearsheets support stacking, allowing new sheets to open on top of active ones. They utilize three visible stack levels (0, 1, and 2) and a background level (-1) to hide inactive sheets. +Tearsheets support stacking, allowing new sheets to open on top of active ones. +They utilize three visible stack levels (0, 1, and 2) and a background level (-1) to hide inactive sheets. -```ts file="./TearsheetStacked.tsx" -``` - -### Tearsheet group (infinite stacking) +Limit stacked tearsheets to a maximum of three. +Flows requiring four or more levels should be redesigned using multi-step wizard or dedicates page to prevent loss of user context. -Use a `TearsheetGroup` to manage an unbounded number of stacked tearsheets. -`children` rendering order determines stacking priority with later children stacking in front of earlier ones. -Only the top 3 open tearsheets are visible; earlier ones hide behind the stack and reappear as front tearsheets are closed. - -```ts file="./TearsheetGroup.tsx" +```ts file="./TearsheetStacked.tsx" ``` ### Tearsheets vs Modals diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetGroup.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetGroup.tsx deleted file mode 100644 index 0f10d2f8..00000000 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetGroup.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { useState } from 'react'; -import { Button } from '@patternfly/react-core'; -import TearsheetGroup from '@patternfly/react-component-groups/dist/dynamic/TearsheetGroup'; -import Tearsheet from '@patternfly/react-component-groups/dist/dynamic/Tearsheet'; -import TearsheetHeader from '@patternfly/react-component-groups/dist/dynamic/TearsheetHeader'; -import TearsheetBody from '@patternfly/react-component-groups/dist/dynamic/TearsheetBody'; -import TearsheetFooter from '@patternfly/react-component-groups/dist/dynamic/TearsheetFooter'; - -const TOTAL_TEARSHEETS = 10; - -export const TearsheetGroupExample: React.FunctionComponent = () => { - const [ openState, setOpenState ] = useState(Array(TOTAL_TEARSHEETS).fill(false)); - - const open = (index: number) => { - setOpenState((prev) => { - const next = [ ...prev ]; - next[index] = true; - return next; - }); - }; - - const close = (index: number) => { - setOpenState((prev) => { - const next = [ ...prev ]; - next[index] = false; - return next; - }); - }; - - return ( -
-
- -
- - - {Array.from({ length: TOTAL_TEARSHEETS }, (_, i) => ( - close(i)} aria-label={`Tearsheet ${i + 1}`}> - - -

- This is tearsheet #{i + 1} of {TOTAL_TEARSHEETS}. -

-

- The TearsheetGroup manages stacking automatically. Only the top 3 open tearsheets are visible in the - stack — earlier ones hide behind and reappear as you close the ones in front. -

-
- - {i < TOTAL_TEARSHEETS - 1 && ( - - )} - - -
- ))} -
-
- ); -}; From 11fb33c9544f06b7ee5960817f908be97dcdfce5 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Mon, 31 Aug 2026 18:42:13 -0400 Subject: [PATCH 24/37] chore: Cleanup variant prop use (PR feedback) Adding 'large' variant as the prop has no effect. Removing --- packages/module/src/Tearsheet/Tearsheet.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/module/src/Tearsheet/Tearsheet.tsx b/packages/module/src/Tearsheet/Tearsheet.tsx index 8c224cf1..c23595c5 100644 --- a/packages/module/src/Tearsheet/Tearsheet.tsx +++ b/packages/module/src/Tearsheet/Tearsheet.tsx @@ -103,7 +103,6 @@ const Tearsheet: FunctionComponent = ({ Date: Mon, 31 Aug 2026 18:43:08 -0400 Subject: [PATCH 25/37] chore: Update Tearsheet doc example (PR feedback) Update packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetComparison.tsx From: @mcoker Co-authored-by: Michael Coker <35148959+mcoker@users.noreply.github.com> --- .../examples/Tearsheet/TearsheetComparison.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetComparison.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetComparison.tsx index 0c761403..b756aa4c 100644 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetComparison.tsx +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetComparison.tsx @@ -143,9 +143,7 @@ const sections = [ const renderBodyContent = (sidebarClassName = '') => ( - - - +
From 2bce77b2646fd703fcd621500b42af04d704136f Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Mon, 31 Aug 2026 18:44:33 -0400 Subject: [PATCH 26/37] chore: Cleanup styles (PR feedback) TearsheetFooter styles come for free from ModalFooter --- packages/module/src/TearsheetFooter/TearsheetFooter.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/module/src/TearsheetFooter/TearsheetFooter.tsx b/packages/module/src/TearsheetFooter/TearsheetFooter.tsx index 604a0d4d..a251551f 100644 --- a/packages/module/src/TearsheetFooter/TearsheetFooter.tsx +++ b/packages/module/src/TearsheetFooter/TearsheetFooter.tsx @@ -5,7 +5,6 @@ import { ModalFooter, type ModalFooterProps } from '@patternfly/react-core'; const useStyles = createUseStyles({ tearsheetFooter: { - flexShrink: 0, }, }); From 4d42ce14f1f7ce71f00ee6cb1c6565f51e6a8b45 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Mon, 31 Aug 2026 18:44:57 -0400 Subject: [PATCH 27/37] chore: Cleanup styles (PR feedback) TearsheetHeader styles come for free from ModalHeader --- packages/module/src/TearsheetHeader/TearsheetHeader.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/module/src/TearsheetHeader/TearsheetHeader.tsx b/packages/module/src/TearsheetHeader/TearsheetHeader.tsx index 49a8f9fc..3631754d 100644 --- a/packages/module/src/TearsheetHeader/TearsheetHeader.tsx +++ b/packages/module/src/TearsheetHeader/TearsheetHeader.tsx @@ -5,7 +5,6 @@ import { ModalHeader, type ModalHeaderProps } from '@patternfly/react-core'; const useStyles = createUseStyles({ tearsheetHeader: { - flexShrink: 0, }, }); From 29bc935f96b1c222d40ecc4d4ea946327eae8567 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Mon, 31 Aug 2026 18:48:34 -0400 Subject: [PATCH 28/37] chore: Cleanup styles (PR feedback) TearsheetBody styles largely overlap with ModalBody --- packages/module/src/TearsheetBody/TearsheetBody.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/module/src/TearsheetBody/TearsheetBody.tsx b/packages/module/src/TearsheetBody/TearsheetBody.tsx index 37d143b2..3309c644 100644 --- a/packages/module/src/TearsheetBody/TearsheetBody.tsx +++ b/packages/module/src/TearsheetBody/TearsheetBody.tsx @@ -5,9 +5,6 @@ import { ModalBody, type ModalBodyProps } from '@patternfly/react-core'; const useStyles = createUseStyles({ tearsheetBody: { - flex: 1, - minHeight: 0, - overflow: 'auto', }, }); From c56f4e408277a35cc87aaedc00fa29639513b732 Mon Sep 17 00:00:00 2001 From: Gustavo Andres Murcia Date: Mon, 31 Aug 2026 18:51:03 -0400 Subject: [PATCH 29/37] chore: Update Tearsheet styles (PR feedback) Update packages/module/src/Tearsheet/Tearsheet.tsx From: @mcoker Co-authored-by: Michael Coker <35148959+mcoker@users.noreply.github.com> --- packages/module/src/Tearsheet/Tearsheet.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/module/src/Tearsheet/Tearsheet.tsx b/packages/module/src/Tearsheet/Tearsheet.tsx index c23595c5..25584652 100644 --- a/packages/module/src/Tearsheet/Tearsheet.tsx +++ b/packages/module/src/Tearsheet/Tearsheet.tsx @@ -9,7 +9,8 @@ const useStyles = createUseStyles({ maxWidth: 'calc(100% - 4rem) !important', height: 'calc(100% - 4rem) !important', maxHeight: 'calc(100% - 4rem) !important', - insetBlockStart: '2rem !important', + insetBlockStart: 'auto !important', + alignSelf: 'end !important' borderBottomLeftRadius: '0', borderBottomRightRadius: '0', '&.pf-v6-c-modal-animated': { From bb7a752619f9b495b4939a76a0e532929ff44f08 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Mon, 31 Aug 2026 18:51:50 -0400 Subject: [PATCH 30/37] fix: TS and Imports --- packages/module/src/Tearsheet/Tearsheet.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/module/src/Tearsheet/Tearsheet.tsx b/packages/module/src/Tearsheet/Tearsheet.tsx index 25584652..99b511d6 100644 --- a/packages/module/src/Tearsheet/Tearsheet.tsx +++ b/packages/module/src/Tearsheet/Tearsheet.tsx @@ -1,7 +1,7 @@ import type { ReactNode, HTMLProps, FunctionComponent, MouseEvent } from 'react'; import { css } from '@patternfly/react-styles'; import { createUseStyles } from 'react-jss'; -import { Modal, ModalVariant, type ModalProps } from '@patternfly/react-core'; +import { Modal, type ModalProps } from '@patternfly/react-core'; const useStyles = createUseStyles({ tearsheet: { @@ -10,7 +10,7 @@ const useStyles = createUseStyles({ height: 'calc(100% - 4rem) !important', maxHeight: 'calc(100% - 4rem) !important', insetBlockStart: 'auto !important', - alignSelf: 'end !important' + alignSelf: 'end !important', borderBottomLeftRadius: '0', borderBottomRightRadius: '0', '&.pf-v6-c-modal-animated': { From 1d9a4415d0dd64fa5a998b44071cf16a35373e35 Mon Sep 17 00:00:00 2001 From: Gustavo Andres Murcia Date: Tue, 1 Sep 2026 12:14:39 -0400 Subject: [PATCH 31/37] chore: Update Tearsheet documentation (PR feedback) Apply batched suggestions from code review From: @thatblindgeye Co-authored-by: Eric Olkowski <70952936+thatblindgeye@users.noreply.github.com> --- .../examples/Tearsheet/Tearsheet.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md index 021a039a..37d26b57 100644 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md @@ -15,9 +15,7 @@ import TearsheetHeader from '@patternfly/react-component-groups/dist/dynamic/Tea import TearsheetBody from '@patternfly/react-component-groups/dist/dynamic/TearsheetBody'; import TearsheetFooter from '@patternfly/react-component-groups/dist/dynamic/TearsheetFooter'; -**Tearsheet** are a full-screen extension of the `` component allowing more complex experiences to be provided to the user. -While the biggest Modal size (`ModalVariant.large`) may work for some cases, tearsheets allow near the entire real-estate to be leveraged. -This component extends the [modal component](/components/modal) allowing any use of its properties to be provided. +**Tearsheet** is an extension of the [modal component](/components/modal), allowing more complex experiences to be provided to the user. Additionally, while the biggest `` size (`ModalVariant.large`) may work for some cases, tearsheet allows more of the viewport area to be utilized. ## Examples @@ -30,7 +28,8 @@ Basic tearsheets should make use of the entire container. For this basic example ### Tearsheet layouts -Tearsheets can be customized to render various layout styles. These layout styles include, [full width text](https://www.patternfly.org/foundations-and-styles/utility-classes/alignment), [flex](https://www.patternfly.org/foundations-and-styles/layouts/flex), and [grid](https://www.patternfly.org/foundations-and-styles/layouts/grid). +Tearsheets can be customized to render various layout styles. These layout styles include, [full width text](/foundations-and-styles/utility-classes/alignment), [flex](/foundations-and-styles/layouts/flex), and [grid](/foundations-and-styles/layouts/grid). + The `` component will handle scrolling for long content. ```ts file="./TearsheetLayouts.tsx" @@ -38,11 +37,9 @@ The `` component will handle scrolling for long content. ### Stacked -Tearsheets support stacking, allowing new sheets to open on top of active ones. -They utilize three visible stack levels (0, 1, and 2) and a background level (-1) to hide inactive sheets. +Tearsheets support stacking, allowing new sheets to open on top of active ones. They utilize three visible stack levels (0, 1, and 2) and a background level (-1) to hide inactive sheets. -Limit stacked tearsheets to a maximum of three. -Flows requiring four or more levels should be redesigned using multi-step wizard or dedicates page to prevent loss of user context. +Limit stacked tearsheets to a maximum of 3. Flows requiring 4 or more levels should be redesigned using multi-step wizard or dedicates page to prevent loss of user context. ```ts file="./TearsheetStacked.tsx" ``` From 50eaa859178ca8d3ceccca8e666e5589127dd7e6 Mon Sep 17 00:00:00 2001 From: Gustavo Andres Murcia Date: Tue, 1 Sep 2026 12:16:00 -0400 Subject: [PATCH 32/37] chore: Update Tearsheet prop description (PR feedback) Update packages/module/src/Tearsheet/Tearsheet.tsx From: @thatblindgeye Co-authored-by: Eric Olkowski <70952936+thatblindgeye@users.noreply.github.com> --- packages/module/src/Tearsheet/Tearsheet.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/module/src/Tearsheet/Tearsheet.tsx b/packages/module/src/Tearsheet/Tearsheet.tsx index 99b511d6..230e658f 100644 --- a/packages/module/src/Tearsheet/Tearsheet.tsx +++ b/packages/module/src/Tearsheet/Tearsheet.tsx @@ -76,7 +76,7 @@ export interface TearsheetProps extends HTMLProps { 'aria-label'?: string; /** Space separated list of ID's of the elements that label the tearsheet. */ 'aria-labelledby'?: string; - /** ISpace separated list of ID's of the elements that describe the tearsheet. */ + /** Space separated list of ID's of the elements that describe the tearsheet. */ 'aria-describedby'?: string; /** Additional props spread to the underlying PatternFly Modal. */ modalProps?: Omit; From 4ccb3fc493821764f326205b4928b5f7054d2cf6 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Tue, 1 Sep 2026 12:17:49 -0400 Subject: [PATCH 33/37] chore: Update Tearsheet documentation (PR feedback) --- .../component-groups/examples/Tearsheet/Tearsheet.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md index 37d26b57..43be9bfc 100644 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/Tearsheet.md @@ -46,8 +46,7 @@ Limit stacked tearsheets to a maximum of 3. Flows requiring 4 or more levels sho ### Tearsheets vs Modals -Choose a tearsheet over a modal when users need to process detailed and complex workflows. -This example demonstrates how the expanded surface area of a tearsheet allows users to easily navigate a robust layout without feeling overwhelmed. +Choose a tearsheet over a modal when users need to process detailed and complex workflows. This example demonstrates how the expanded surface area of a tearsheet allows users to easily navigate a robust layout without feeling overwhelmed. ```ts file="./TearsheetComparison.tsx" ``` From cad6f9fb602f2720929934f4954de395b9a3a318 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Tue, 1 Sep 2026 12:21:31 -0400 Subject: [PATCH 34/37] chore: Remove empty instances of useStyles (PR feedback) --- packages/module/src/TearsheetBody/TearsheetBody.tsx | 12 +----------- .../module/src/TearsheetFooter/TearsheetFooter.tsx | 12 +----------- .../module/src/TearsheetGroup/TearsheetGroup.tsx | 10 +--------- .../module/src/TearsheetHeader/TearsheetHeader.tsx | 12 +----------- 4 files changed, 4 insertions(+), 42 deletions(-) diff --git a/packages/module/src/TearsheetBody/TearsheetBody.tsx b/packages/module/src/TearsheetBody/TearsheetBody.tsx index 3309c644..3874f518 100644 --- a/packages/module/src/TearsheetBody/TearsheetBody.tsx +++ b/packages/module/src/TearsheetBody/TearsheetBody.tsx @@ -1,13 +1,6 @@ import type { FunctionComponent, ReactNode } from 'react'; -import { css } from '@patternfly/react-styles'; -import { createUseStyles } from 'react-jss'; import { ModalBody, type ModalBodyProps } from '@patternfly/react-core'; -const useStyles = createUseStyles({ - tearsheetBody: { - }, -}); - export interface TearsheetBodyProps extends ModalBodyProps { /** Content rendered inside the tearsheet body. */ children?: ReactNode; @@ -15,10 +8,7 @@ export interface TearsheetBodyProps extends ModalBodyProps { className?: string; } -const TearsheetBody: FunctionComponent = ({ className, ...props }: TearsheetBodyProps) => { - const classes = useStyles(); - return ; -}; +const TearsheetBody: FunctionComponent = ({ className, ...props }: TearsheetBodyProps) => ; TearsheetBody.displayName = 'TearsheetBody'; export default TearsheetBody; \ No newline at end of file diff --git a/packages/module/src/TearsheetFooter/TearsheetFooter.tsx b/packages/module/src/TearsheetFooter/TearsheetFooter.tsx index a251551f..f0ecf1d5 100644 --- a/packages/module/src/TearsheetFooter/TearsheetFooter.tsx +++ b/packages/module/src/TearsheetFooter/TearsheetFooter.tsx @@ -1,13 +1,6 @@ import type { FunctionComponent, ReactNode } from 'react'; -import { css } from '@patternfly/react-styles'; -import { createUseStyles } from 'react-jss'; import { ModalFooter, type ModalFooterProps } from '@patternfly/react-core'; -const useStyles = createUseStyles({ - tearsheetFooter: { - }, -}); - export interface TearsheetFooterProps extends ModalFooterProps { /** Content rendered inside the tearsheet footer. */ children?: ReactNode; @@ -18,10 +11,7 @@ export interface TearsheetFooterProps extends ModalFooterProps { export const TearsheetFooter: FunctionComponent = ({ className, ...props -}: TearsheetFooterProps) => { - const classes = useStyles(); - return ; -}; +}: TearsheetFooterProps) => ; TearsheetFooter.displayName = 'TearsheetFooter'; export default TearsheetFooter; diff --git a/packages/module/src/TearsheetGroup/TearsheetGroup.tsx b/packages/module/src/TearsheetGroup/TearsheetGroup.tsx index 9cf20521..4a5dcc51 100644 --- a/packages/module/src/TearsheetGroup/TearsheetGroup.tsx +++ b/packages/module/src/TearsheetGroup/TearsheetGroup.tsx @@ -1,13 +1,6 @@ import { Children, cloneElement, isValidElement, useId, useRef, type FunctionComponent, type ReactElement } from 'react'; -import { css } from '@patternfly/react-styles'; -import { createUseStyles } from 'react-jss'; import Tearsheet, { type TearsheetProps } from '../Tearsheet'; -const useStyles = createUseStyles({ - tearsheetGroup: { - }, -}); - const MAX_VISIBLE_LEVELS = 3; export interface TearsheetGroupProps { @@ -27,7 +20,6 @@ const TearsheetGroup: FunctionComponent = ({ id, ...props }: TearsheetGroupProps) => { - const classes = useStyles(); const generatedId = useId(); const groupId = id ?? generatedId; // Track each child's last assigned stack level so closing tearsheets keep @@ -79,7 +71,7 @@ const TearsheetGroup: FunctionComponent = ({ }); return ( -
+
{enhancedChildren}
); diff --git a/packages/module/src/TearsheetHeader/TearsheetHeader.tsx b/packages/module/src/TearsheetHeader/TearsheetHeader.tsx index 3631754d..932e6e6a 100644 --- a/packages/module/src/TearsheetHeader/TearsheetHeader.tsx +++ b/packages/module/src/TearsheetHeader/TearsheetHeader.tsx @@ -1,13 +1,6 @@ import type { FunctionComponent, ReactNode } from 'react'; -import { css } from '@patternfly/react-styles'; -import { createUseStyles } from 'react-jss'; import { ModalHeader, type ModalHeaderProps } from '@patternfly/react-core'; -const useStyles = createUseStyles({ - tearsheetHeader: { - }, -}); - export interface TearsheetHeaderProps extends ModalHeaderProps { /** Content rendered inside the tearsheet header. */ children?: ReactNode; @@ -18,10 +11,7 @@ export interface TearsheetHeaderProps extends ModalHeaderProps { const TearsheetHeader: FunctionComponent = ({ className, ...props -}: TearsheetHeaderProps) => { - const classes = useStyles(); - return ; -}; +}: TearsheetHeaderProps) => ; TearsheetHeader.displayName = 'TearsheetHeader'; export default TearsheetHeader; From 6e1a4c6945a275b81ebcad8b497d792c9c5d9db6 Mon Sep 17 00:00:00 2001 From: Gustavo Andres Murcia Date: Tue, 1 Sep 2026 13:13:21 -0400 Subject: [PATCH 35/37] chore: Update Tearsheet styles (PR feedback) Apply batched suggestions from code review From: @mcoker Co-authored-by: Michael Coker <35148959+mcoker@users.noreply.github.com> --- packages/module/src/Tearsheet/Tearsheet.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/module/src/Tearsheet/Tearsheet.tsx b/packages/module/src/Tearsheet/Tearsheet.tsx index 230e658f..0971e7cd 100644 --- a/packages/module/src/Tearsheet/Tearsheet.tsx +++ b/packages/module/src/Tearsheet/Tearsheet.tsx @@ -26,21 +26,18 @@ const useStyles = createUseStyles({ maxWidth: 'calc(100% - 2rem) !important', height: 'calc(100% - 6rem) !important', maxHeight: 'calc(100% - 6rem) !important', - insetBlockStart: '3rem !important', }, '&.pf-m-stack-level-2': { width: 'calc(100% - 0rem) !important', maxWidth: 'calc(100% - 0rem) !important', height: 'calc(100% - 8rem) !important', maxHeight: 'calc(100% - 8rem) !important', - insetBlockStart: '4rem !important', }, '&.pf-m-stack-hidden': { width: 'calc(100% - 4rem) !important', maxWidth: 'calc(100% - 4rem) !important', height: 'calc(100% - 4rem) !important', maxHeight: 'calc(100% - 4rem) !important', - insetBlockStart: '3rem !important', opacity: '0 !important', pointerEvents: 'none !important', }, From 4c9cf03e48861ea0107bfd220f2720297bb93a53 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Tue, 1 Sep 2026 13:18:39 -0400 Subject: [PATCH 36/37] chore: Update jest snapshots ``` SH npx jest packages -u ``` --- .../__snapshots__/BulkSelect.test.tsx.snap | 8 +- .../ExternalLinkButton.test.tsx.snap | 80 ++- .../__snapshots__/LogSnippet.test.tsx.snap | 8 +- .../MultiContentCard.test.tsx.snap | 584 +++++++++++++----- .../ResponsiveActions.test.tsx.snap | 20 +- .../__snapshots__/ServiceCard.test.tsx.snap | 4 +- .../__snapshots__/Severity.test.tsx.snap | 140 ++++- .../SkeletonTableBody.test.tsx.snap | 4 +- .../SkeletonTableHead.test.tsx.snap | 50 +- .../Status/__snapshots__/Status.test.tsx.snap | 200 ++++-- .../__snapshots__/TagCount.test.tsx.snap | 80 ++- .../UnauthorizedAccess.test.tsx.snap | 140 ++++- .../UnavailableContent.test.tsx.snap | 80 ++- .../__snapshots__/WarningModal.test.tsx.snap | 8 +- 14 files changed, 1063 insertions(+), 343 deletions(-) diff --git a/packages/module/src/BulkSelect/__snapshots__/BulkSelect.test.tsx.snap b/packages/module/src/BulkSelect/__snapshots__/BulkSelect.test.tsx.snap index dd4832a2..f79b636b 100644 --- a/packages/module/src/BulkSelect/__snapshots__/BulkSelect.test.tsx.snap +++ b/packages/module/src/BulkSelect/__snapshots__/BulkSelect.test.tsx.snap @@ -54,11 +54,11 @@ exports[`BulkSelect component should render 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 320 512" + viewBox="0 0 20 20" width="1em" > @@ -117,11 +117,11 @@ exports[`BulkSelect component should render 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 320 512" + viewBox="0 0 20 20" width="1em" > diff --git a/packages/module/src/ExternalLinkButton/__snapshots__/ExternalLinkButton.test.tsx.snap b/packages/module/src/ExternalLinkButton/__snapshots__/ExternalLinkButton.test.tsx.snap index 44ecc7b4..e174bf4e 100644 --- a/packages/module/src/ExternalLinkButton/__snapshots__/ExternalLinkButton.test.tsx.snap +++ b/packages/module/src/ExternalLinkButton/__snapshots__/ExternalLinkButton.test.tsx.snap @@ -22,7 +22,6 @@ exports[`ExternalLinkButton component should accept IconProps 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 512 512" width="1em" > (Opens in new tab) - + + + + + + @@ -56,7 +68,6 @@ exports[`ExternalLinkButton component should accept IconProps 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 512 512" width="1em" > (Opens in new tab) - + + + + + + @@ -147,12 +171,24 @@ exports[`ExternalLinkButton component should render 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 512 512" width="1em" > - + + + + + + @@ -176,12 +212,24 @@ exports[`ExternalLinkButton component should render 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 512 512" width="1em" > - + + + + + + diff --git a/packages/module/src/LogSnippet/__snapshots__/LogSnippet.test.tsx.snap b/packages/module/src/LogSnippet/__snapshots__/LogSnippet.test.tsx.snap index b377ef71..c7410c80 100644 --- a/packages/module/src/LogSnippet/__snapshots__/LogSnippet.test.tsx.snap +++ b/packages/module/src/LogSnippet/__snapshots__/LogSnippet.test.tsx.snap @@ -27,11 +27,11 @@ exports[`LogSnippet component should render LogSnippet component 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 512 512" + viewBox="0 0 32 32" width="1em" >
@@ -96,11 +96,11 @@ exports[`LogSnippet component should render LogSnippet component 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 512 512" + viewBox="0 0 32 32" width="1em" >
diff --git a/packages/module/src/MultiContentCard/__snapshots__/MultiContentCard.test.tsx.snap b/packages/module/src/MultiContentCard/__snapshots__/MultiContentCard.test.tsx.snap index 39596a22..de8aed77 100644 --- a/packages/module/src/MultiContentCard/__snapshots__/MultiContentCard.test.tsx.snap +++ b/packages/module/src/MultiContentCard/__snapshots__/MultiContentCard.test.tsx.snap @@ -17,7 +17,7 @@ exports[`MultiContentCard component should render basic multi-content card 1`] = >

@@ -1007,7 +1139,7 @@ exports[`MultiContentCard component should render multi-content card with a sing >

diff --git a/packages/module/src/ServiceCard/__snapshots__/ServiceCard.test.tsx.snap b/packages/module/src/ServiceCard/__snapshots__/ServiceCard.test.tsx.snap index 17f54bd7..b6f867cf 100644 --- a/packages/module/src/ServiceCard/__snapshots__/ServiceCard.test.tsx.snap +++ b/packages/module/src/ServiceCard/__snapshots__/ServiceCard.test.tsx.snap @@ -31,7 +31,7 @@ exports[`ServiceCard component should render ServiceCard component 1`] = ` >
@@ -58,12 +70,24 @@ exports[`Severity component should render correctly CriticalSeverity 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 1024 1024" width="1em" > - + + + + + +
@@ -97,12 +121,24 @@ exports[`Severity component should render correctly HighSeverity 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 1024 1024" width="1em" > - + + + + + +
@@ -136,12 +172,24 @@ exports[`Severity component should render correctly LowSeverity 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 1024 1024" width="1em" > - + + + + + +

@@ -175,12 +223,24 @@ exports[`Severity component should render correctly LowSeverity 2`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 1024 1024" width="1em" > - + + + + + +
@@ -214,12 +274,24 @@ exports[`Severity component should render correctly MediumSeverity 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 1024 1024" width="1em" > - + + + + + +

@@ -253,12 +325,24 @@ exports[`Severity component should render correctly UndefinedSeverity, default 1 fill="currentColor" height="1em" role="img" - viewBox="0 0 1024 1024" width="1em" > - + + + + + +
diff --git a/packages/module/src/SkeletonTableBody/__snapshots__/SkeletonTableBody.test.tsx.snap b/packages/module/src/SkeletonTableBody/__snapshots__/SkeletonTableBody.test.tsx.snap index 6e683202..ed0b70f6 100644 --- a/packages/module/src/SkeletonTableBody/__snapshots__/SkeletonTableBody.test.tsx.snap +++ b/packages/module/src/SkeletonTableBody/__snapshots__/SkeletonTableBody.test.tsx.snap @@ -7,7 +7,7 @@ exports[`SkeletonTableBody component should render correctly 1`] = `
- + + + + + + @@ -82,12 +94,24 @@ exports[`SkeletonTableHead component should render correctly with Th element col fill="currentColor" height="1em" role="img" - viewBox="0 0 256 512" width="1em" > - + + + + + + @@ -106,7 +130,7 @@ exports[`SkeletonTableHead component should render correctly with count 1`] = `
- + + + + + + @@ -75,12 +87,24 @@ exports[`Status component should render correctly 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 576 512" width="1em" > - + + + + + + @@ -192,12 +216,24 @@ exports[`Status component should render correctly link 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 512 512" width="1em" > - + + + + + + @@ -254,12 +290,24 @@ exports[`Status component should render correctly link 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 512 512" width="1em" > - + + + + + + @@ -376,12 +424,24 @@ exports[`Status component should render correctly popover 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 512 512" width="1em" > - + + + + + + @@ -442,12 +502,24 @@ exports[`Status component should render correctly popover 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 512 512" width="1em" > - + + + + + + @@ -551,12 +623,24 @@ exports[`Status component should render correctly with description 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 576 512" width="1em" > - + + + + + + @@ -609,12 +693,24 @@ exports[`Status component should render correctly with description 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 576 512" width="1em" > - + + + + + + @@ -724,12 +820,24 @@ exports[`Status component should render iconOnly correctly 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 576 512" width="1em" > - + + + + + + @@ -759,12 +867,24 @@ exports[`Status component should render iconOnly correctly 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 576 512" width="1em" > - + + + + + + diff --git a/packages/module/src/TagCount/__snapshots__/TagCount.test.tsx.snap b/packages/module/src/TagCount/__snapshots__/TagCount.test.tsx.snap index cc5f5167..207393cf 100644 --- a/packages/module/src/TagCount/__snapshots__/TagCount.test.tsx.snap +++ b/packages/module/src/TagCount/__snapshots__/TagCount.test.tsx.snap @@ -30,12 +30,24 @@ exports[`TagCount component should render a disabled tag count with no value 1`] fill="currentColor" height="1em" role="img" - viewBox="0 0 512 512" width="1em" > - + + + + + + @@ -73,12 +85,24 @@ exports[`TagCount component should render a disabled tag count with no value 1`] fill="currentColor" height="1em" role="img" - viewBox="0 0 512 512" width="1em" > - + + + + + + @@ -172,12 +196,24 @@ exports[`TagCount component should render a tag count of 11 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 512 512" width="1em" > - + + + + + + @@ -216,12 +252,24 @@ exports[`TagCount component should render a tag count of 11 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 512 512" width="1em" > - + + + + + + diff --git a/packages/module/src/UnauthorizedAccess/__snapshots__/UnauthorizedAccess.test.tsx.snap b/packages/module/src/UnauthorizedAccess/__snapshots__/UnauthorizedAccess.test.tsx.snap index f246db42..42f56d44 100644 --- a/packages/module/src/UnauthorizedAccess/__snapshots__/UnauthorizedAccess.test.tsx.snap +++ b/packages/module/src/UnauthorizedAccess/__snapshots__/UnauthorizedAccess.test.tsx.snap @@ -20,12 +20,24 @@ exports[`UnauthorizedAccess component should apply custom styles 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 448 512" width="1em" > - + + + + + +
- + + + + + +
- + + + + + +
- + + + + + +
- + + + + + +
- + + + + + +
- + + + + + +
- + + + + + +
- + + + + + +
- + + + + + +
- + + + + + +
@@ -73,11 +73,11 @@ exports[`WarningModal component should render 1`] = ` fill="currentColor" height="1em" role="img" - viewBox="0 0 576 512" + viewBox="0 0 32 32" width="1em" > From fc3e5e7d8bdf04d7e4648ce74c7ef2d715d31d38 Mon Sep 17 00:00:00 2001 From: Gustavo Murcia Date: Tue, 1 Sep 2026 14:52:16 -0400 Subject: [PATCH 37/37] fix: Lint --- .../component-groups/examples/Tearsheet/TearsheetComparison.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetComparison.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetComparison.tsx index b756aa4c..6da9e350 100644 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetComparison.tsx +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Tearsheet/TearsheetComparison.tsx @@ -24,7 +24,6 @@ import { ModalFooter, ModalHeader, ModalVariant, - PageSection, SearchInput, Sidebar, SidebarContent,