Skip to content

Commit

Permalink
feat(title): allow title prop to be passed as a node
Browse files Browse the repository at this point in the history
  • Loading branch information
tomdavies73 committed Oct 17, 2024
1 parent 421c4a6 commit d918014
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 11 deletions.
2 changes: 1 addition & 1 deletion playwright/components/note/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const noteComponent = (page: Page) => {
return page.locator(NOTE_COMPONENT);
};
const noteHeader = (page: Page) => {
return page.locator(NOTE_COMPONENT).locator("header");
return page.locator(NOTE_COMPONENT).locator("h2");
};
const noteContent = (page: Page) => {
return page.locator(DATA_CONTENTS);
Expand Down
57 changes: 56 additions & 1 deletion src/components/note/note-test.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { EditorState, ContentState, convertFromHTML } from "draft-js";
import Note, { NoteProps } from "./note.component";

import { ActionPopover, ActionPopoverMenuButton } from "../action-popover";
import Box from "../box";
import Typography from "../typography";

export default {
title: "Note/Test",
includeStories: ["DefaultStory", "InlineControlMenuButton"],
includeStories: ["DefaultStory", "InlineControlMenuButton", "TitleNodes"],
parameters: {
info: { disable: true },
chromatic: {
Expand Down Expand Up @@ -100,3 +102,56 @@ InlineControlMenuButton.story = {
InlineControlMenuButton.parameters = {
themeProvider: { chromatic: { disableSnapshot: false, theme: "sage" } },
};

export const TitleNodes = () => {
const noteContent = EditorState.createWithContent(
ContentState.createFromText("Here is some plain text content")
);

const titleElements = (
<Box display="flex" flexWrap="wrap" gap="16px">
<Box flex="1 1 50%" display="flex" flexDirection="row" gap="8px">
<Typography variant="h1-large">Title</Typography>
<Typography variant="h1">Title</Typography>
<Typography variant="h2">Title</Typography>
<Typography variant="h3">Title</Typography>
<Typography variant="h4">Title</Typography>
<Typography variant="h5">Title</Typography>
<Typography variant="segment-header">Title</Typography>
<Typography variant="segment-header-small">Title</Typography>
<Typography variant="segment-subheader">Title</Typography>
<Typography variant="segment-subheader-alt">Title</Typography>
</Box>
<Box flex="1 1 50%" display="flex" flexDirection="row" gap="8px">
<Typography variant="p">Title</Typography>
<Typography variant="span">Title</Typography>
<Typography variant="small">Title</Typography>
<Typography variant="big">Title</Typography>
<Typography variant="sup">Title</Typography>
<Typography variant="sub">Title</Typography>
<Typography variant="strong">Title</Typography>
<Typography variant="b">Title</Typography>
<Typography variant="em">Title</Typography>
<Typography variant="ul">Title</Typography>
<Typography variant="ol">Title</Typography>
</Box>
</Box>
);

return (
<Note
name="Lauren Smith"
noteContent={noteContent}
createdDate="23 May 2020, 12:08 PM"
title={titleElements}
/>
);
};

TitleNodes.story = {
name: "Title Nodes",
};

TitleNodes.parameters = {
themeProvider: { chromatic: { disableSnapshot: false, theme: "sage" } },
};
21 changes: 18 additions & 3 deletions src/components/note/note.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
StyledNoteContent,
StyledNoteMain,
StyledInlineControl,
StyledTitle,
StyledTitleWrapper,
StyledFooter,
StyledFooterContent,
} from "./note.style";
Expand All @@ -16,6 +16,7 @@ import { ActionPopover } from "../action-popover";
import { getDecoratedValue } from "../text-editor/__internal__/utils";
import EditorContext from "../text-editor/__internal__/editor.context";
import LinkPreview, { LinkPreviewProps } from "../link-preview";
import Typography from "../typography";

export interface NoteProps extends MarginProps {
/** Adds a created on date to the Note footer */
Expand All @@ -36,7 +37,7 @@ export interface NoteProps extends MarginProps {
timeStamp: string;
};
/** Adds a Title to the Note */
title?: string;
title?: React.ReactNode;
/** Set a percentage-based width for the whole Note component, relative to its parent. */
width?: number;
}
Expand Down Expand Up @@ -87,7 +88,21 @@ export const Note = ({
<StyledNote width={width} {...rest} data-component="note">
<StyledNoteMain>
<StyledNoteContent>
{title && <StyledTitle>{title}</StyledTitle>}
{title &&
(typeof title === "string" ? (
<Typography
data-role="note-title"
fontWeight="700"
fontSize="16px"
lineHeight="21px"
paddingBottom="16px"
variant="h2"
>
{title}
</Typography>
) : (
<StyledTitleWrapper>{title}</StyledTitleWrapper>
))}
<Editor
readOnly
editorState={getDecoratedValue(noteContent)}
Expand Down
3 changes: 2 additions & 1 deletion src/components/note/note.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ static method.

### With title

An optional title can be provided using the `title` prop.
An optional title can be provided using the `title` prop, the `title` prop can be any valid React node.
However we recommend consumers use a `Typography` component to ensure consistency.

<Canvas of={NoteStories.WithTitle} />

Expand Down
5 changes: 4 additions & 1 deletion src/components/note/note.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import LinkPreview from "../link-preview";
import Box from "../box";
import Note from "./note.component";
import Typography from "../typography";

const styledSystemProps = generateStyledSystemProps({
margin: true,
Expand Down Expand Up @@ -86,10 +87,12 @@ export const WithTitle: Story = () => {
blocksFromHTML.entityMap
);
const noteContent = EditorState.createWithContent(content);
const titleNode = <Typography variant="h3">Here is a Title Node</Typography>;

return (
<Box height={300} width="50%">
<Note
title="Here is a Title"
title={titleNode}
noteContent={noteContent}
name="Lauren Smith"
createdDate="23 May 2020, 12:08 PM"
Expand Down
11 changes: 9 additions & 2 deletions src/components/note/note.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import styled, { css } from "styled-components";
import { margin } from "styled-system";
import baseTheme from "../../style/themes/base";
import { StyledLinkPreview } from "../link-preview/link-preview.style";
import { VARIANT_TYPES } from "../typography/typography.component";

const StyledNoteContent = styled.div<{
hasPreview?: boolean;
Expand Down Expand Up @@ -45,11 +46,17 @@ const StyledInlineControl = styled.div`
min-width: fit-content;
`;

const StyledTitle = styled.header`
const StyledTitleWrapper = styled.div`
${VARIANT_TYPES.map(
(variant) => `
${variant}{
font-weight: 700;
font-size: 16px;
line-height: 21px;
padding-bottom: 16px;
}
`
)}
`;

const StyledFooterContent = styled.div<{ hasName: boolean }>`
Expand Down Expand Up @@ -141,7 +148,7 @@ export {
StyledNoteContent,
StyledNoteMain,
StyledInlineControl,
StyledTitle,
StyledTitleWrapper,
StyledFooter,
StyledFooterContent,
};
27 changes: 25 additions & 2 deletions src/components/note/note.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Note from ".";
import LinkPreview from "../link-preview";
import { ActionPopover, ActionPopoverItem } from "../action-popover";
import { testStyledSystemMarginRTL } from "../../__spec_helper__/__internal__/test-utils";
import Typography from "../typography";

test("should render with required props", () => {
render(
Expand All @@ -18,7 +19,7 @@ test("should render with required props", () => {
expect(screen.getByText("23 May 2020, 12:08 PM")).toBeVisible();
});

test("should render with provided `title` prop", () => {
test("renders a Typography component with h2 `variant` and `title` as its child when `title` prop is a string", () => {
render(
<Note
createdDate="23 May 2020, 12:08 PM"
Expand All @@ -27,7 +28,29 @@ test("should render with provided `title` prop", () => {
/>
);

expect(screen.getByRole("banner")).toHaveTextContent("Title");
const titleElement = screen.getByRole("heading", { level: 2 });

expect(titleElement).toHaveTextContent("Title");
expect(titleElement).toHaveAttribute("data-role", "note-title");
});

test("renders the `title` node when `title` prop is a React node", () => {
render(
<Note
createdDate="23 May 2020, 12:08 PM"
noteContent={EditorState.createEmpty()}
title={
<Typography data-role="note-node" variant="h4">
Title
</Typography>
}
/>
);

const titleNode = screen.getByRole("heading", { level: 4 });

expect(titleNode).toHaveTextContent("Title");
expect(titleNode).toHaveAttribute("data-role", "note-node");
});

test("should render with provided `name` prop", () => {
Expand Down

0 comments on commit d918014

Please sign in to comment.