Skip to content

Commit

Permalink
feat(pod): allow title and subtitle to be passed as a node
Browse files Browse the repository at this point in the history
the `title` and `subtitle` props can now be passed as a node, providing consumers with the ability
to pass components such as `Typography` to control what element is rendered and its appearance.
Also, conditional rendering has been used to ensure when `title` is passed as a node is not wrapped
in any other section headings

fix #4607
  • Loading branch information
tomdavies73 committed Aug 10, 2023
1 parent 349e8ee commit 8c48636
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 6 deletions.
33 changes: 33 additions & 0 deletions cypress/components/pod/pod.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import {
assertCssValueIsApproximately,
} from "../../support/component-helper/common-steps";
import { SIZE, CHARACTERS } from "../../support/component-helper/constants";
import Typography, {
VariantTypes,
} from "../../../src/components/typography/typography.component";

const specialCharacters = [CHARACTERS.DIACRITICS, CHARACTERS.SPECIALCHARACTERS];

Expand Down Expand Up @@ -104,6 +107,20 @@ context("Testing Pod component", () => {
}
);

it.each<VariantTypes>(["h1", "h2", "h3", "h4", "h5"])(
"renders title node when node is passed with %s variant",
(variantType) => {
const title = "title";
CypressMountWithProviders(
<PodExample
title={<Typography variant={variantType}>{title}</Typography>}
/>
);

cy.get(variantType).contains(title);
}
);

it.each(specialCharacters)(
"should check subtitle as %s for Pod component",
(subtitle) => {
Expand All @@ -112,6 +129,22 @@ context("Testing Pod component", () => {
}
);

it.each<VariantTypes>(["h2", "h3", "p", "em", "b"])(
"renders subtitle node when node is passed with %s variant",
(variantType) => {
const title = "title";
const subtitle = "subtitle";
CypressMountWithProviders(
<PodExample
title
subtitle={<Typography variant={variantType}>{subtitle}</Typography>}
/>
);

cy.get(variantType).contains(title);
}
);

it.each(["left", "center", "right"] as PodProps["alignTitle"][])(
"should check title alignment for Pod component when text is aligned to the %s",
(alignTitle) => {
Expand Down
15 changes: 11 additions & 4 deletions src/components/pod/pod.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ export interface PodProps extends MarginProps {
/** Prop to apply a theme to the Pod */
variant?: PodVariant;
/** Title for the pod h4 element always shown */
title?: string | React.ReactNode;
title?: React.ReactNode;
/** Optional subtitle for the pod */
subtitle?: string;
subtitle?: React.ReactNode;
/** A component to render as a Pod footer */
footer?: string | React.ReactNode;
/** Supplies an edit action to the pod */
Expand Down Expand Up @@ -199,11 +199,18 @@ const Pod = React.forwardRef<HTMLDivElement, PodProps>(
internalEditButton={internalEditButton}
size={size}
>
<StyledTitle data-element="title">{title}</StyledTitle>
{subtitle && (
{typeof title === "string" ? (
<StyledTitle data-element="title">{title}</StyledTitle>
) : (
title
)}

{typeof subtitle === "string" ? (
<StyledSubtitle data-element="subtitle">
{subtitle}
</StyledSubtitle>
) : (
subtitle
)}
</StyledHeader>
)}
Expand Down
26 changes: 25 additions & 1 deletion src/components/pod/pod.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
testStyledSystemMargin,
} from "../../__spec_helper__/test-utils";
import Logger from "../../__internal__/utils/logger";
import Typography, { VariantTypes } from "../typography/typography.component";

const variantColors = {
primary: {
Expand Down Expand Up @@ -137,6 +138,7 @@ describe("Pod", () => {

describe("when title prop is set", () => {
const title = "title";
const subtitle = "subtitle";

it("renders header with correct styles", () => {
const wrapper = render({ title });
Expand All @@ -148,12 +150,34 @@ describe("Pod", () => {
expect(wrapper.find(StyledTitle).text()).toBe(title);
});

it.each<VariantTypes>(["h1", "h2", "h3", "h4", "h5"])(
"renders title node when node is passed as %s variant",
(variantType) => {
const wrapper = render({
title: <Typography variant={variantType}>{title}</Typography>,
});

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

it("renders subtitle when subtitle prop is also passed", () => {
const subtitle = "subtitle";
const wrapper = render({ title, subtitle });
expect(wrapper.find(StyledSubtitle).text()).toBe(subtitle);
});

it.each<VariantTypes>(["h2", "h3", "p", "em", "b"])(
"renders subtitle node when node is passed as %s variant",
(variantType) => {
const wrapper = render({
title,
subtitle: <Typography variant={variantType}>{subtitle}</Typography>,
});

expect(wrapper.find(variantType).text()).toBe(subtitle);
}
);

it("renders header with correct right margin, when internalEditButton prop is passed and alignTitle is `right`", () => {
const wrapper = render({
title,
Expand Down
8 changes: 8 additions & 0 deletions src/components/pod/pod.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ import Pod from "carbon-react/lib/components/pod";
<Story name="default" story={stories.Default} />
</Canvas>

### with title and subtitle passed as nodes

A node can be passed as both the `title` and `subtitle` props, we recommend using `<Typography>`

<Canvas>
<Story name="with title and subtitle passed as nodes" story={stories.WithTitleAndSubtitleNode} />
</Canvas>

### Custom height

<Canvas>
Expand Down
9 changes: 9 additions & 0 deletions src/components/pod/pod.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ export const Default: ComponentStory<typeof Pod> = () => (
<Pod title="Title">Content</Pod>
);

export const WithTitleAndSubtitleNode: ComponentStory<typeof Pod> = () => (
<Pod
title={<Typography variant="h1">Title</Typography>}
subtitle={<Typography variant="h2">Subtitle</Typography>}
>
Content
</Pod>
);

export const WithCustomHeight: ComponentStory<typeof Pod> = () => (
<Pod title="Title" subtitle="Subtitle" footer="Footer" height={350}>
Content
Expand Down
2 changes: 1 addition & 1 deletion src/components/typography/typography.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const VARIANT_TYPES = [
"ul",
"ol",
] as const;
type VariantTypes = typeof VARIANT_TYPES[number];
export type VariantTypes = typeof VARIANT_TYPES[number];
export interface TypographyProps extends SpaceProps, ColorProps {
/** Override the variant component */
as?: React.ElementType;
Expand Down

0 comments on commit 8c48636

Please sign in to comment.