Skip to content

Commit

Permalink
feat(settings-row,heading): surface headingType prop on components
Browse files Browse the repository at this point in the history
surfaces the `headingType` prop on the `SettingsRow` and `Heading` components to provide consumers
with the ability to specify which level of section headings they wish to apply from h1 to h6.

BREAKING CHANGE: default heading level on `SettingsRow` is changed from `h1` to `h4`

fix #5723
  • Loading branch information
tomdavies73 committed Feb 9, 2023
1 parent 39e3b34 commit 054c11a
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 4 deletions.
6 changes: 5 additions & 1 deletion src/components/heading/heading.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
} from "./heading.style";
import useLocale from "../../hooks/__internal__/useLocale";

export type HeadingType = "h1" | "h2" | "h3" | "h4" | "h5";
export interface HeadingProps extends MarginProps, TagProps {
/** Child elements */
children?: React.ReactNode;
Expand All @@ -31,6 +32,8 @@ export interface HeadingProps extends MarginProps, TagProps {
subheader?: React.ReactNode;
/** Defines the subtitle id for the heading. */
subtitleId?: string;
/** Defines the HTML heading element of the title. */
headingType?: HeadingType;
/** Defines the help text for the heading. */
help?: string;
/** Defines the help link for the heading. */
Expand Down Expand Up @@ -66,6 +69,7 @@ export const Heading = ({
separator = false,
subheader,
subtitleId,
headingType = "h1",
title,
titleId,
...rest
Expand Down Expand Up @@ -141,7 +145,7 @@ export const Heading = ({
<StyledHeaderContent>
<StyledHeadingTitle
withMargin={!!pills || !!help}
variant="h1"
variant={headingType}
data-element="title"
id={titleId}
>
Expand Down
15 changes: 14 additions & 1 deletion src/components/heading/heading.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import { shallow, mount, ReactWrapper } from "enzyme";
import Heading from ".";
import Heading, { HeadingType } from ".";
import {
StyledHeader,
StyledSubHeader,
Expand Down Expand Up @@ -41,6 +41,19 @@ describe("Heading", () => {
});
});

describe("when headingType prop is provided", () => {
it.each<HeadingType>(["h1", "h2", "h3", "h4", "h5"])(
"HTML heading element is correct when headingType is %s",
(headingType) => {
const wrapper = mount(
<Heading headingType={headingType} title="foo" />
);

expect(wrapper.find(headingType).text()).toBe("foo");
}
);
});

describe("when the help prop is provided", () => {
it("renders a help component", () => {
const wrapper = mount(
Expand Down
11 changes: 11 additions & 0 deletions src/components/heading/heading.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ import Heading from "carbon-react/lib/components/heading";
</Story>
</Canvas>

### Heading with headingType

The `headingType` prop sets the HTML heading element which is rendered on the page. It can take values `"h1"` up to `"h5"`.

<Canvas>
<Story name="with headingType">
<Heading headingType="h4" title="This is a h4 Title" />
</Story>
</Canvas>


### Heading without Divider

<Canvas>
Expand Down
13 changes: 13 additions & 0 deletions src/components/heading/heading.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,19 @@ context("Testing Heading component", () => {
}
);

describe("when headingType prop is provided", () => {
it.each(["h1", "h2", "h3", "h4", "h5"])(
"should check HTML heading element is correct when headingType is %s",
(headingType) => {
CypressMountWithProviders(
<HeadingComponent headingType={headingType} title="foo" />
);

cy.get(headingType).contains("foo");
}
);
});

describe("should render Heading component and check accessibility issues", () => {
it("should check heading accessibility", () => {
CypressMountWithProviders(<HeadingComponent />);
Expand Down
2 changes: 1 addition & 1 deletion src/components/heading/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { default } from "./heading.component";
export type { HeadingProps } from "./heading.component";
export type { HeadingProps, HeadingType } from "./heading.component";
4 changes: 4 additions & 0 deletions src/components/settings-row/settings-row.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const marginPropTypes = filterStyledSystemMarginProps(

const SettingsRow = ({
title,
headingType = "h4",
description,
children,
className,
Expand All @@ -28,6 +29,7 @@ const SettingsRow = ({

return (
<Heading
headingType={headingType}
title={title}
subheader={description}
separator={description !== undefined}
Expand Down Expand Up @@ -58,6 +60,8 @@ SettingsRow.propTypes = {
className: PropTypes.string,
/** A title for this group of settings. */
title: PropTypes.string,
/** Defines the HTML heading element of the `title` within the component. */
headingType: PropTypes.oneOf(["h1", "h2", "h3", "h4", "h5"]),
/** A string or JSX object that provides a short description about the group of settings. */
description: PropTypes.node,
/** Shows a divider below the component. */
Expand Down
3 changes: 3 additions & 0 deletions src/components/settings-row/settings-row.d.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import * as React from "react";
import { HeadingType } from "../heading";

export interface SettingsRowProps {
/** The CSS classes to apply to the component. */
className?: string;
/** A title for this group of settings. */
title?: string;
/** Defines the HTML heading element of the `title` within the component. */
headingType: HeadingType;
/** A string or JSX object that provides a short description about the group of settings. */
description?: React.ReactNode;
/** Shows a divider below the component. */
Expand Down
21 changes: 20 additions & 1 deletion src/components/settings-row/settings-row.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ describe("SettingsRow", () => {
describe("render", () => {
const name = "foobar-row";
const title = "Some Title";
const description = <span>Some descriptive text</span>;
const childId = "my_child";
const children = <span id={childId} />;
let wrapper = shallow(
Expand Down Expand Up @@ -58,7 +59,6 @@ describe("SettingsRow", () => {
});

describe("when description is provided", () => {
const description = <span>Some descriptive text</span>;
let head;

beforeEach(() => {
Expand All @@ -77,6 +77,25 @@ describe("SettingsRow", () => {
});
});

describe("when headingType prop is provided", () => {
it.each(["h1", "h2", "h3", "h4", "h5"])(
"HTML heading element is correct when headingType is %s",
(headingType) => {
wrapper = mount(
<SettingsRow
headingType={headingType}
title={title}
description={description}
>
Content for settings
</SettingsRow>
);

expect(wrapper.find(headingType).text()).toBe(title);
}
);
});

describe("when title is not provided", () => {
it("does not render a header", () => {
wrapper = shallow(
Expand Down
11 changes: 11 additions & 0 deletions src/components/settings-row/settings-row.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ All `children` are rendered in the input column to the right of the header colum
</Story>
</Canvas>

### with HeadingType

The `headingType` prop sets the HTML heading element of the `title` within the component which is rendered on the page. It can take values `"h1"` up to `"h5"`.
<Canvas>
<Story name="headingType">
<SettingsRow headingType="h3" description="Description" title="This is a h3 Title">
Content for settings
</SettingsRow>
</Story>
</Canvas>

## Props

### Settings Row
Expand Down
15 changes: 15 additions & 0 deletions src/components/settings-row/settings-row.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,21 @@ context("Tests for SettingsRow component", () => {
}
);

it.each(["h1", "h2", "h3", "h4", "h5"])(
"should check HTML heading element is correct when headingType is %s",
(headingType) => {
CypressMountWithProviders(
<SettingsRowComponent
headingType={headingType}
title="foo"
description="bar"
/>
);

cy.get(headingType).contains("foo");
}
);

it.each(testData)(
"should check %s as description for SettingsRow component",
(description) => {
Expand Down

0 comments on commit 054c11a

Please sign in to comment.