From e4a379f3dbd4307bfe17d5275429e0cf7a2397db Mon Sep 17 00:00:00 2001 From: Tyler Jones Date: Thu, 6 Aug 2026 10:59:14 -0400 Subject: [PATCH 1/3] Allow `Banner.Title` to be set as `

` --- .changeset/tidy-banners-title-element.md | 5 +++++ packages/react/src/Banner/Banner.docs.json | 3 ++- packages/react/src/Banner/Banner.test.tsx | 26 ++++++++++++++++------ packages/react/src/Banner/Banner.tsx | 14 ++++++------ 4 files changed, 33 insertions(+), 15 deletions(-) create mode 100644 .changeset/tidy-banners-title-element.md diff --git a/.changeset/tidy-banners-title-element.md b/.changeset/tidy-banners-title-element.md new file mode 100644 index 00000000000..5c035fd64fa --- /dev/null +++ b/.changeset/tidy-banners-title-element.md @@ -0,0 +1,5 @@ +--- +'@primer/react': major +--- + +Banner: Allow `Banner.Title` to render as a paragraph or any heading level, and change its default element to `h1`. \ No newline at end of file diff --git a/packages/react/src/Banner/Banner.docs.json b/packages/react/src/Banner/Banner.docs.json index be04df252ca..f0673b95592 100644 --- a/packages/react/src/Banner/Banner.docs.json +++ b/packages/react/src/Banner/Banner.docs.json @@ -131,7 +131,8 @@ "props": [ { "name": "as", - "type": "'h2' | 'h3' | 'h4' | 'h5' | 'h6'" + "type": "'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p'", + "defaultValue": "'h1'" } ] }, diff --git a/packages/react/src/Banner/Banner.test.tsx b/packages/react/src/Banner/Banner.test.tsx index 73d771ad36a..6ea2d70ef7d 100644 --- a/packages/react/src/Banner/Banner.test.tsx +++ b/packages/react/src/Banner/Banner.test.tsx @@ -129,10 +129,10 @@ describe('Banner', () => { expect(screen.getByRole('heading')).toHaveAttribute('id', 'custom-title-id') }) - it('should default the title to a h2', () => { + it('should default the title to a h1', () => { render() - expect(screen.getByRole('heading', {level: 2})).toBeInTheDocument() - expect(screen.getByRole('heading', {level: 2})).toEqual(screen.getByText('test')) + expect(screen.getByRole('heading', {level: 1})).toBeInTheDocument() + expect(screen.getByRole('heading', {level: 1})).toEqual(screen.getByText('test')) }) it('should throw an error if no title is provided', () => { @@ -310,20 +310,23 @@ describe('Banner', () => { }) describe('Banner.Title', () => { - it('should render as a h2 element by default', () => { + it('should render as a h1 element by default', () => { render( test , ) - expect(screen.getByRole('heading', {level: 2, name: 'test'})).toBeInTheDocument() + expect(screen.getByRole('heading', {level: 1, name: 'test'})).toBeInTheDocument() }) - it('should support rendering as any heading element above level 2', () => { - const levels = [2, 3, 4, 5, 6] as const + it('should support rendering as any heading element', () => { + const levels = [1, 2, 3, 4, 5, 6] as const render( <> + + test level 1 + test level 2 @@ -347,6 +350,15 @@ describe('Banner', () => { } }) + it('should support rendering as a paragraph element', () => { + render( + + test paragraph + , + ) + expect(screen.getByText('test paragraph')).toHaveRole('paragraph') + }) + it('should support a custom `className` on the container element', () => { render( diff --git a/packages/react/src/Banner/Banner.tsx b/packages/react/src/Banner/Banner.tsx index 0fb19589f75..62a67191099 100644 --- a/packages/react/src/Banner/Banner.tsx +++ b/packages/react/src/Banner/Banner.tsx @@ -202,20 +202,20 @@ export const Banner = React.forwardRef(function Banner ) }) -type HeadingElement = 'h2' | 'h3' | 'h4' | 'h5' | 'h6' +type TitleElement = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' -export type BannerTitleProps = { +export type BannerTitleProps = { as?: As className?: string -} & React.ComponentPropsWithoutRef +} & React.ComponentPropsWithoutRef -export function BannerTitle(props: BannerTitleProps) { - const {as: Heading = 'h2', className, children, id, ...rest} = props +export function BannerTitle(props: BannerTitleProps) { + const {as: Element = 'h1', className, children, id, ...rest} = props const context = React.useContext(BannerContext) const titleId = id ?? context?.titleId return ( - (props: BannerTitleProps {children} - + ) } From 3b1c47fcbd77446e801689f52c5e90d9f71efc56 Mon Sep 17 00:00:00 2001 From: Tyler Jones Date: Thu, 6 Aug 2026 11:07:26 -0400 Subject: [PATCH 2/3] Keep the same default --- .changeset/tidy-banners-title-element.md | 4 ++-- packages/react/src/Banner/Banner.docs.json | 2 +- packages/react/src/Banner/Banner.test.tsx | 10 +++++----- packages/react/src/Banner/Banner.tsx | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.changeset/tidy-banners-title-element.md b/.changeset/tidy-banners-title-element.md index 5c035fd64fa..3aaf9df0a93 100644 --- a/.changeset/tidy-banners-title-element.md +++ b/.changeset/tidy-banners-title-element.md @@ -1,5 +1,5 @@ --- -'@primer/react': major +'@primer/react': minor --- -Banner: Allow `Banner.Title` to render as a paragraph or any heading level, and change its default element to `h1`. \ No newline at end of file +Banner: Add support for rendering `Banner.Title` as a paragraph or `h1` heading. diff --git a/packages/react/src/Banner/Banner.docs.json b/packages/react/src/Banner/Banner.docs.json index f0673b95592..f80af61ff5d 100644 --- a/packages/react/src/Banner/Banner.docs.json +++ b/packages/react/src/Banner/Banner.docs.json @@ -132,7 +132,7 @@ { "name": "as", "type": "'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p'", - "defaultValue": "'h1'" + "defaultValue": "'h2'" } ] }, diff --git a/packages/react/src/Banner/Banner.test.tsx b/packages/react/src/Banner/Banner.test.tsx index 6ea2d70ef7d..91e408b406e 100644 --- a/packages/react/src/Banner/Banner.test.tsx +++ b/packages/react/src/Banner/Banner.test.tsx @@ -129,10 +129,10 @@ describe('Banner', () => { expect(screen.getByRole('heading')).toHaveAttribute('id', 'custom-title-id') }) - it('should default the title to a h1', () => { + it('should default the title to a h2', () => { render() - expect(screen.getByRole('heading', {level: 1})).toBeInTheDocument() - expect(screen.getByRole('heading', {level: 1})).toEqual(screen.getByText('test')) + expect(screen.getByRole('heading', {level: 2})).toBeInTheDocument() + expect(screen.getByRole('heading', {level: 2})).toEqual(screen.getByText('test')) }) it('should throw an error if no title is provided', () => { @@ -310,13 +310,13 @@ describe('Banner', () => { }) describe('Banner.Title', () => { - it('should render as a h1 element by default', () => { + it('should render as a h2 element by default', () => { render( test , ) - expect(screen.getByRole('heading', {level: 1, name: 'test'})).toBeInTheDocument() + expect(screen.getByRole('heading', {level: 2, name: 'test'})).toBeInTheDocument() }) it('should support rendering as any heading element', () => { diff --git a/packages/react/src/Banner/Banner.tsx b/packages/react/src/Banner/Banner.tsx index 62a67191099..507f8b5bec5 100644 --- a/packages/react/src/Banner/Banner.tsx +++ b/packages/react/src/Banner/Banner.tsx @@ -204,13 +204,13 @@ export const Banner = React.forwardRef(function Banner type TitleElement = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' -export type BannerTitleProps = { +export type BannerTitleProps = { as?: As className?: string } & React.ComponentPropsWithoutRef -export function BannerTitle(props: BannerTitleProps) { - const {as: Element = 'h1', className, children, id, ...rest} = props +export function BannerTitle(props: BannerTitleProps) { + const {as: Element = 'h2', className, children, id, ...rest} = props const context = React.useContext(BannerContext) const titleId = id ?? context?.titleId From 1a54814e7028314b775ce5b1f68e83724b303553 Mon Sep 17 00:00:00 2001 From: Tyler Jones Date: Thu, 6 Aug 2026 11:09:57 -0400 Subject: [PATCH 3/3] Remove `h1` --- .changeset/tidy-banners-title-element.md | 2 +- packages/react/src/Banner/Banner.docs.json | 2 +- packages/react/src/Banner/Banner.test.tsx | 7 ++----- packages/react/src/Banner/Banner.tsx | 2 +- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.changeset/tidy-banners-title-element.md b/.changeset/tidy-banners-title-element.md index 3aaf9df0a93..428a0e3cbc1 100644 --- a/.changeset/tidy-banners-title-element.md +++ b/.changeset/tidy-banners-title-element.md @@ -2,4 +2,4 @@ '@primer/react': minor --- -Banner: Add support for rendering `Banner.Title` as a paragraph or `h1` heading. +Banner: Add support for rendering `Banner.Title` as a paragraph. diff --git a/packages/react/src/Banner/Banner.docs.json b/packages/react/src/Banner/Banner.docs.json index f80af61ff5d..f1189de6042 100644 --- a/packages/react/src/Banner/Banner.docs.json +++ b/packages/react/src/Banner/Banner.docs.json @@ -131,7 +131,7 @@ "props": [ { "name": "as", - "type": "'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p'", + "type": "'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p'", "defaultValue": "'h2'" } ] diff --git a/packages/react/src/Banner/Banner.test.tsx b/packages/react/src/Banner/Banner.test.tsx index 91e408b406e..b939b6c9893 100644 --- a/packages/react/src/Banner/Banner.test.tsx +++ b/packages/react/src/Banner/Banner.test.tsx @@ -319,14 +319,11 @@ describe('Banner', () => { expect(screen.getByRole('heading', {level: 2, name: 'test'})).toBeInTheDocument() }) - it('should support rendering as any heading element', () => { - const levels = [1, 2, 3, 4, 5, 6] as const + it('should support rendering as any supported heading element', () => { + const levels = [2, 3, 4, 5, 6] as const render( <> - - test level 1 - test level 2 diff --git a/packages/react/src/Banner/Banner.tsx b/packages/react/src/Banner/Banner.tsx index 507f8b5bec5..7bfd5e3e6cc 100644 --- a/packages/react/src/Banner/Banner.tsx +++ b/packages/react/src/Banner/Banner.tsx @@ -202,7 +202,7 @@ export const Banner = React.forwardRef(function Banner ) }) -type TitleElement = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' +type TitleElement = 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' export type BannerTitleProps = { as?: As