From 60e173c1599546c894de237c057371840dc5f4cc Mon Sep 17 00:00:00 2001 From: llastflowers Date: Thu, 2 Jul 2026 12:18:54 -0700 Subject: [PATCH 01/14] update SplitPageLayout.tsx --- .../src/SplitPageLayout/SplitPageLayout.tsx | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/react/src/SplitPageLayout/SplitPageLayout.tsx b/packages/react/src/SplitPageLayout/SplitPageLayout.tsx index 8eeb4a9203d..2a196c11dac 100644 --- a/packages/react/src/SplitPageLayout/SplitPageLayout.tsx +++ b/packages/react/src/SplitPageLayout/SplitPageLayout.tsx @@ -16,6 +16,7 @@ export type SplitPageLayoutProps = {className?: string} export const Root: React.FC> = props => { return ( { // eslint-disable-next-line primer-react/direct-slot-children - return + return } Header.displayName = 'SplitPageLayout.Header' @@ -58,7 +59,7 @@ export const Content: React.FC { - return + return } Content.displayName = 'SplitPageLayout.Content' @@ -77,6 +78,7 @@ export const Pane: React.FC> = }) => { return ( { - return + return ( + + ) } Sidebar.displayName = 'SplitPageLayout.Sidebar' @@ -114,7 +124,7 @@ export const Footer: React.FC { // eslint-disable-next-line primer-react/direct-slot-children - return + return } Footer.displayName = 'SplitPageLayout.Footer' From 8d8e160d68ac1c83ddad9d14f880e650d78e989d Mon Sep 17 00:00:00 2001 From: llastflowers Date: Thu, 2 Jul 2026 12:22:05 -0700 Subject: [PATCH 02/14] add test --- .../SplitPageLayout/SplitPageLayout.test.tsx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/react/src/SplitPageLayout/SplitPageLayout.test.tsx b/packages/react/src/SplitPageLayout/SplitPageLayout.test.tsx index 0cc036ad5f5..5b73425d244 100644 --- a/packages/react/src/SplitPageLayout/SplitPageLayout.test.tsx +++ b/packages/react/src/SplitPageLayout/SplitPageLayout.test.tsx @@ -7,6 +7,25 @@ import {implementsClassName} from '../utils/testing' describe('SplitPageLayout', () => { implementsClassName(SplitPageLayout) + it('renders data-component attributes for all components', () => { + const {container} = render( + + Header + Content + Pane + Sidebar + Footer + , + ) + + expect(container.firstChild).toHaveAttribute('data-component', 'SplitPageLayout') + expect(container.querySelector('[data-component="SplitPageLayout.Header"]')).toBeInTheDocument() + expect(container.querySelector('[data-component="SplitPageLayout.Content"]')).toBeInTheDocument() + expect(container.querySelector('[data-component="SplitPageLayout.Pane"]')).toBeInTheDocument() + expect(container.querySelector('[data-component="SplitPageLayout.Sidebar"]')).toBeInTheDocument() + expect(container.querySelector('[data-component="SplitPageLayout.Footer"]')).toBeInTheDocument() + }) + it('renders Pane with a custom ID', () => { const {getByText} = render( From b91501d7cc5bba3257419d0ac94143c5b2efa7d2 Mon Sep 17 00:00:00 2001 From: llastflowers Date: Thu, 2 Jul 2026 13:56:02 -0700 Subject: [PATCH 03/14] update Stack.tsx and tests --- packages/react/src/Stack/Stack.tsx | 2 ++ packages/react/src/Stack/__tests__/Stack.test.tsx | 5 +++++ packages/react/src/Stack/__tests__/StackItem.test.tsx | 9 +++++++++ 3 files changed, 16 insertions(+) diff --git a/packages/react/src/Stack/Stack.tsx b/packages/react/src/Stack/Stack.tsx index 9a96c6e71f6..3d305129df3 100644 --- a/packages/react/src/Stack/Stack.tsx +++ b/packages/react/src/Stack/Stack.tsx @@ -102,6 +102,7 @@ const Stack = forwardRef( { implementsClassName(Stack, classes.Stack) + it('renders data-component attribute', () => { + render() + expect(screen.getByTestId('stack')).toHaveAttribute('data-component', 'Stack') + }) + it('should support rendering content through `children`', () => { render( diff --git a/packages/react/src/Stack/__tests__/StackItem.test.tsx b/packages/react/src/Stack/__tests__/StackItem.test.tsx index 91566b91e1c..371c786d5e0 100644 --- a/packages/react/src/Stack/__tests__/StackItem.test.tsx +++ b/packages/react/src/Stack/__tests__/StackItem.test.tsx @@ -8,6 +8,15 @@ import classes from '../Stack.module.css' describe('StackItem', () => { implementsClassName(StackItem, classes.StackItem) + it('renders data-component attribute', () => { + render( + + Content + , + ) + expect(screen.getByTestId('stack-item')).toHaveAttribute('data-component', 'StackItem') + }) + it('should render its children', () => { render( From 677d6863f20432159fc265f01df278dcc64a8979 Mon Sep 17 00:00:00 2001 From: llastflowers Date: Thu, 2 Jul 2026 14:16:03 -0700 Subject: [PATCH 04/14] Allow SplitPageLayout to override PageLayout data-component when appropriate --- packages/react/src/PageLayout/PageLayout.tsx | 38 ++++++++++++++----- .../src/SplitPageLayout/SplitPageLayout.tsx | 6 +++ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/packages/react/src/PageLayout/PageLayout.tsx b/packages/react/src/PageLayout/PageLayout.tsx index 1fcbbc78f97..483cf27cb0b 100644 --- a/packages/react/src/PageLayout/PageLayout.tsx +++ b/packages/react/src/PageLayout/PageLayout.tsx @@ -67,6 +67,7 @@ export type PageLayoutProps = { _slotsConfig?: Record<'header' | 'footer' | 'sidebar', React.ElementType> className?: string style?: React.CSSProperties + 'data-component'?: string } // TODO: refs @@ -79,6 +80,7 @@ const Root: React.FC> = ({ className, style, _slotsConfig: slotsConfig, + 'data-component': dataComponent = 'PageLayout', }) => { const paneRef = useRef(null) const contentWrapperRef = useRef(null) @@ -101,7 +103,13 @@ const Root: React.FC> = ({ return ( - + {slots.sidebar}
{slots.header} @@ -120,7 +128,10 @@ const RootWrapper = memo( children, className, hasSidebar, - }: React.PropsWithChildren & {hasSidebar?: boolean}>) => { + dataComponent, + }: React.PropsWithChildren< + Pick & {hasSidebar?: boolean; dataComponent: string} + >) => { return (
{children} @@ -549,6 +560,7 @@ export type PageLayoutHeaderProps = { hidden?: boolean | ResponsiveValue className?: string style?: React.CSSProperties + 'data-component'?: string } const Header: FCWithSlotMarker> = ({ @@ -561,6 +573,7 @@ const Header: FCWithSlotMarker> = children, style, className, + 'data-component': dataComponent = 'PageLayout.Header', }) => { // Combine divider and dividerWhenNarrow for backwards compatibility const dividerProp = @@ -574,7 +587,7 @@ const Header: FCWithSlotMarker> =
className?: string style?: React.CSSProperties + 'data-component'?: string } // TODO: Account for pane width when centering content @@ -645,6 +659,7 @@ const Content: FCWithSlotMarker> children, className, style, + 'data-component': dataComponent = 'PageLayout.Content', }) => { const Component = as const {contentWrapperRef} = React.useContext(PageLayoutContext) @@ -654,7 +669,7 @@ const Content: FCWithSlotMarker> ref={contentWrapperRef} aria-label={label} aria-labelledby={labelledBy} - data-component="PageLayout.Content" + data-component={dataComponent} style={style} className={clsx(classes.ContentWrapper, className)} {...getResponsiveAttributes('is-hidden', hidden)} @@ -750,6 +765,7 @@ export type PageLayoutPaneBaseProps = { id?: string className?: string style?: React.CSSProperties + 'data-component'?: string } export type PageLayoutPaneProps = PageLayoutPaneBaseProps & @@ -799,6 +815,7 @@ const Pane = React.forwardRef { @@ -902,7 +919,7 @@ const Pane = React.forwardRef { @@ -1237,7 +1256,7 @@ const Sidebar = React.forwardRef className?: string style?: React.CSSProperties + 'data-component'?: string } const Footer: FCWithSlotMarker> = ({ @@ -1325,8 +1345,8 @@ const Footer: FCWithSlotMarker> = children, className, style, + 'data-component': dataComponent = 'PageLayout.Footer', }) => { - // Combine divider and dividerWhenNarrow for backwards compatibility const dividerProp = !isResponsiveValue(divider) && dividerWhenNarrow !== 'inherit' ? {regular: divider, narrow: dividerWhenNarrow} @@ -1338,7 +1358,7 @@ const Footer: FCWithSlotMarker> =