diff --git a/.changeset/three-jokes-bow.md b/.changeset/three-jokes-bow.md new file mode 100644 index 00000000000..20a3dbe9e18 --- /dev/null +++ b/.changeset/three-jokes-bow.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +Make sure all components accept `className` as a prop on outermost component element. diff --git a/packages/react/src/Banner/Banner.test.tsx b/packages/react/src/Banner/Banner.test.tsx index 7771c22cf3c..13fecdc6fb8 100644 --- a/packages/react/src/Banner/Banner.test.tsx +++ b/packages/react/src/Banner/Banner.test.tsx @@ -2,6 +2,7 @@ import {render, screen} from '@testing-library/react' import userEvent from '@testing-library/user-event' import React from 'react' import {Banner} from '../Banner' +import {FeatureFlags} from '../FeatureFlags' describe('Banner', () => { let spy: jest.SpyInstance @@ -30,8 +31,22 @@ describe('Banner', () => { }) it('should support a custom `className` on the outermost element', () => { - const {container} = render() - expect(container.firstChild).toHaveClass('test') + const Element = () => + const FeatureFlagElement = () => { + return ( + + + + ) + } + expect(render().container.firstChild).toHaveClass('test-class-name') + expect(render().container.firstChild).toHaveClass('test-class-name') }) it('should label the landmark element with the corresponding variant label text', () => { diff --git a/packages/react/src/Breadcrumbs/__tests__/Breadcrumbs.test.tsx b/packages/react/src/Breadcrumbs/__tests__/Breadcrumbs.test.tsx index 2c92fd0badf..e3fd9c693f7 100644 --- a/packages/react/src/Breadcrumbs/__tests__/Breadcrumbs.test.tsx +++ b/packages/react/src/Breadcrumbs/__tests__/Breadcrumbs.test.tsx @@ -3,6 +3,7 @@ import Breadcrumbs, {Breadcrumb} from '..' import {render, behavesAsComponent, checkExports} from '../../utils/testing' import {render as HTMLRender} from '@testing-library/react' import axe from 'axe-core' +import {FeatureFlags} from '../../FeatureFlags' describe('Breadcrumbs', () => { behavesAsComponent({Component: Breadcrumbs, options: {skipAs: true}}) @@ -12,6 +13,25 @@ describe('Breadcrumbs', () => { Breadcrumb, }) + it('should support `className` on the outermost element', () => { + const Element = () => + const FeatureFlagElement = () => { + return ( + + + + ) + } + expect(HTMLRender().container.firstChild).toHaveClass('test-class-name') + expect(HTMLRender().container.firstChild).toHaveClass('test-class-name') + }) + it('should have no axe violations', async () => { const {container} = HTMLRender() const results = await axe.run(container) diff --git a/packages/react/src/Button/__tests__/Button.test.tsx b/packages/react/src/Button/__tests__/Button.test.tsx index 4705433bde0..d1a0fe74ee0 100644 --- a/packages/react/src/Button/__tests__/Button.test.tsx +++ b/packages/react/src/Button/__tests__/Button.test.tsx @@ -31,6 +31,25 @@ describe('Button', () => { options: {skipSx: true, skipAs: true}, }) + it('should support `className` on the outermost element', () => { + const Element = () => ) const button = container.getByRole('button') diff --git a/packages/react/src/Checkbox/Checkbox.test.tsx b/packages/react/src/Checkbox/Checkbox.test.tsx index 085fae85432..bf115bfd6ec 100644 --- a/packages/react/src/Checkbox/Checkbox.test.tsx +++ b/packages/react/src/Checkbox/Checkbox.test.tsx @@ -3,6 +3,7 @@ import userEvent from '@testing-library/user-event' import React from 'react' import Checkbox from '../Checkbox' import {behavesAsComponent, checkExports} from '../utils/testing' +import {FeatureFlags} from '../FeatureFlags' describe('Checkbox', () => { beforeEach(() => { @@ -14,6 +15,25 @@ describe('Checkbox', () => { default: Checkbox, }) + it('should support `className` on the outermost element', () => { + const Element = () => + const FeatureFlagElement = () => { + return ( + + + + ) + } + expect(render().container.firstChild).toHaveClass('test-class-name') + expect(render().container.firstChild).toHaveClass('test-class-name') + }) + it('renders a valid checkbox input', () => { const {getByRole} = render() diff --git a/packages/react/src/CounterLabel/CounterLabel.test.tsx b/packages/react/src/CounterLabel/CounterLabel.test.tsx index 78ae5497bbe..17ba502ed01 100644 --- a/packages/react/src/CounterLabel/CounterLabel.test.tsx +++ b/packages/react/src/CounterLabel/CounterLabel.test.tsx @@ -3,6 +3,7 @@ import {CounterLabel} from '..' import {behavesAsComponent, checkExports} from '../utils/testing' import {render as HTMLRender} from '@testing-library/react' import axe from 'axe-core' +import {FeatureFlags} from '../FeatureFlags' describe('CounterLabel', () => { behavesAsComponent({Component: CounterLabel, options: {skipAs: true, skipSx: true}}) @@ -11,6 +12,25 @@ describe('CounterLabel', () => { default: CounterLabel, }) + it('should support `className` on the outermost element', () => { + const Element = () => + const FeatureFlagElement = () => { + return ( + + + + ) + } + expect(HTMLRender().container.firstChild).toHaveClass('test-class-name') + expect(HTMLRender().container.firstChild).toHaveClass('test-class-name') + }) + it('renders a ', () => { const {container} = HTMLRender(1234) expect(container.firstChild?.nodeName).toEqual('SPAN') diff --git a/packages/react/src/Heading/__tests__/Heading.test.tsx b/packages/react/src/Heading/__tests__/Heading.test.tsx index 63a2484d050..732e235cb73 100644 --- a/packages/react/src/Heading/__tests__/Heading.test.tsx +++ b/packages/react/src/Heading/__tests__/Heading.test.tsx @@ -4,6 +4,7 @@ import {render, behavesAsComponent, checkExports} from '../../utils/testing' import {render as HTMLRender, screen} from '@testing-library/react' import axe from 'axe-core' import ThemeProvider from '../../ThemeProvider' +import {FeatureFlags} from '../../FeatureFlags' const theme = { breakpoints: ['400px', '640px', '960px', '1280px'], @@ -35,6 +36,25 @@ describe('Heading', () => { default: Heading, }) + it('should support `className` on the outermost element', () => { + const Element = () => + const FeatureFlagElement = () => { + return ( + + + + ) + } + expect(HTMLRender().container.firstChild).toHaveClass('test-class-name') + expect(HTMLRender().container.firstChild).toHaveClass('test-class-name') + }) + it('renders

by default', () => { expect(render().type).toEqual('h2') }) @@ -149,11 +169,6 @@ describe('Heading', () => { expect(screen.getByText('test')).not.toHaveClass(/^Heading__StyledHeading/) }) - it('should support `className` on the outermost element', () => { - const {container} = HTMLRender(test) - expect(container.firstChild).toHaveClass('test') - }) - it('should support overrides with sx if provided', () => { HTMLRender( { behavesAsComponent({Component: Link}) @@ -11,6 +12,25 @@ describe('Link', () => { default: Link, }) + it('should support `className` on the outermost element', () => { + const Element = () => + const FeatureFlagElement = () => { + return ( + + + + ) + } + expect(HTMLRender().container.firstChild).toHaveClass('test-class-name') + expect(HTMLRender().container.firstChild).toHaveClass('test-class-name') + }) + it('should have no axe violations', async () => { const {container} = HTMLRender(GitHub) const results = await axe.run(container) diff --git a/packages/react/src/Spinner/Spinner.tsx b/packages/react/src/Spinner/Spinner.tsx index 46e55968e50..63cd0d33304 100644 --- a/packages/react/src/Spinner/Spinner.tsx +++ b/packages/react/src/Spinner/Spinner.tsx @@ -19,10 +19,17 @@ export type SpinnerProps = { srText?: string | null /** @deprecated Use `srText` instead. */ 'aria-label'?: string + className?: string } & HTMLDataAttributes & SxProp -function Spinner({size: sizeKey = 'medium', srText = 'Loading', 'aria-label': ariaLabel, ...props}: SpinnerProps) { +function Spinner({ + size: sizeKey = 'medium', + srText = 'Loading', + 'aria-label': ariaLabel, + className, + ...props +}: SpinnerProps) { const size = sizeMap[sizeKey] const hasHiddenLabel = srText !== null && ariaLabel === undefined const labelId = useId() @@ -38,6 +45,7 @@ function Spinner({size: sizeKey = 'medium', srText = 'Loading', 'aria-label': ar aria-hidden aria-label={ariaLabel ?? undefined} aria-labelledby={hasHiddenLabel ? labelId : undefined} + className={className} {...props} > { behavesAsComponent({Component: Avatar}) @@ -12,6 +13,25 @@ describe('Avatar', () => { default: Avatar, }) + it('should support `className` on the outermost element', () => { + const Element = () => + const FeatureFlagElement = () => { + return ( + + + + ) + } + expect(HTMLRender().container.firstChild).toHaveClass('test-class-name') + expect(HTMLRender().container.firstChild).toHaveClass('test-class-name') + }) + it('should have no axe violations', async () => { const {container} = HTMLRender() const results = await axe.run(container) diff --git a/packages/react/src/__tests__/AvatarStack.test.tsx b/packages/react/src/__tests__/AvatarStack.test.tsx index c04aa672470..2807a9b76aa 100644 --- a/packages/react/src/__tests__/AvatarStack.test.tsx +++ b/packages/react/src/__tests__/AvatarStack.test.tsx @@ -3,6 +3,7 @@ import {AvatarStack} from '..' import {render, behavesAsComponent, checkExports} from '../utils/testing' import {render as HTMLRender} from '@testing-library/react' import axe from 'axe-core' +import {FeatureFlags} from '../FeatureFlags' const avatarComp = ( @@ -33,6 +34,32 @@ describe('Avatar', () => { default: AvatarStack, }) + it('should support `className` on the outermost element', () => { + const Element = () => ( + + + + + + + ) + const FeatureFlagElement = () => { + return ( + + + + ) + } + expect(HTMLRender().container.firstChild).toHaveClass('test-class-name') + expect(HTMLRender().container.firstChild).toHaveClass('test-class-name') + }) + it('should have no axe violations', async () => { const {container} = HTMLRender(avatarComp) const results = await axe.run(container) diff --git a/packages/react/src/__tests__/Box.test.tsx b/packages/react/src/__tests__/Box.test.tsx index edaf2fda5ab..ef739d508f8 100644 --- a/packages/react/src/__tests__/Box.test.tsx +++ b/packages/react/src/__tests__/Box.test.tsx @@ -4,6 +4,7 @@ import React from 'react' import {Box} from '..' import theme from '../theme' import {behavesAsComponent, checkExports, render} from '../utils/testing' +import {FeatureFlags} from '../FeatureFlags' describe('Box', () => { behavesAsComponent({Component: Box}) @@ -12,6 +13,25 @@ describe('Box', () => { default: Box, }) + it('should support `className` on the outermost element', () => { + const Element = () => + const FeatureFlagElement = () => { + return ( + + + + ) + } + expect(HTMLRender().container.firstChild).toHaveClass('test-class-name') + expect(HTMLRender().container.firstChild).toHaveClass('test-class-name') + }) + it('should have no axe violations', async () => { const {container} = HTMLRender() const results = await axe.run(container) diff --git a/packages/react/src/__tests__/Label.test.tsx b/packages/react/src/__tests__/Label.test.tsx index ec4550880e7..61467d8a924 100644 --- a/packages/react/src/__tests__/Label.test.tsx +++ b/packages/react/src/__tests__/Label.test.tsx @@ -4,8 +4,27 @@ import axe from 'axe-core' import type {LabelColorOptions} from '../Label' import Label, {variants} from '../Label' import {renderStyles} from '../utils/testing' +import {FeatureFlags} from '../FeatureFlags' describe('Label', () => { + it('should support `className` on the outermost element', () => { + const Element = () =>