Skip to content

Commit

Permalink
feat: add onClose feature to CommonMessage (#81)
Browse files Browse the repository at this point in the history
  • Loading branch information
jaredcwhite authored Apr 23, 2024
1 parent 36b3091 commit 6c4b9d9
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 33 deletions.
2 changes: 1 addition & 1 deletion src/blocks/__stories__/Alert.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const withLink = () => (

export const wideContainerLayout = () => (
<>
<Alert id="in-container" variant="alert" fullwidth>
<Alert id="in-container" variant="alert" fullwidth onClose={() => alert("Closing!")}>
An alert that scales to full container width
</Alert>

Expand Down
35 changes: 32 additions & 3 deletions src/blocks/__tests__/CommonMessage.test.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { render, cleanup } from "@testing-library/react"
import { render, cleanup, fireEvent } from "@testing-library/react"
import CommonMessage from "../shared/CommonMessage"

afterEach(cleanup)

describe("<CommonMessage>", () => {
it("displays the message", () => {
const content = "Common message here"
const { getByText, container } = render(<CommonMessage role="alert" id="test-id" className="test-class">{content}</CommonMessage>)
const { getByText, container } = render(
<CommonMessage role="alert" id="test-id" className="test-class">
{content}
</CommonMessage>
)
expect(getByText(content)).toBeInTheDocument()
expect(container.querySelector("#test-id")).not.toBeNull()
expect(container.querySelector("#test-id.test-class")).not.toBeNull()
Expand All @@ -15,11 +19,36 @@ describe("<CommonMessage>", () => {

it("supports variants", () => {
const content = "Common message here"
const { getByText, container } = render(<CommonMessage variant="warn" id="test-id" className="test-class" closeable>{content}</CommonMessage>)
const { getByText, container } = render(
<CommonMessage variant="warn" id="test-id" className="test-class" closeable>
{content}
</CommonMessage>
)
expect(getByText(content)).toBeInTheDocument()
expect(container.querySelector("#test-id.test-class")).not.toBeNull()
expect(container.querySelector("#test-id[data-variant=warn]")).not.toBeNull()
expect(container.querySelector("button[aria-label=Close]")).not.toBeNull()
expect(container.querySelector("svg.fa-clock")).not.toBeNull()
})

it("supports a custom onClose callback", () => {
let wasClosed = false
const content = "Click me"
const { getByLabelText } = render(
<CommonMessage
variant="warn"
id="test-id"
className="test-class"
closeable
onClose={() => {
wasClosed = true
}}
>
{content}
</CommonMessage>
)

fireEvent.click(getByLabelText("Close"))
expect(wasClosed).toBeTruthy()
})
})
72 changes: 43 additions & 29 deletions src/blocks/shared/CommonMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export interface CommonMessageProps {
customIcon?: React.ReactNode
/** If the component can hide via a close icon */
closeable?: boolean
/** A callback function when the component has closed */
onClose?: () => void
/** Scale to fit component to its container */
fullwidth?: boolean
/** Element ID */
Expand All @@ -59,36 +61,48 @@ export interface CommonMessageProps {
tabIndex?: number
}

const CommonMessage = forwardRef((props: CommonMessageProps, ref: React.ForwardedRef<HTMLDivElement>) => {
const [visible, toggler] = useToggle(true)
const classNames = ["seeds-common-message"]
if (props.fullwidth) classNames.push("is-fullwidth")
if (props.className) classNames.push(props.className)
const CommonMessage = forwardRef(
(props: CommonMessageProps, ref: React.ForwardedRef<HTMLDivElement>) => {
const [visible, toggler] = useToggle(true)
const classNames = ["seeds-common-message"]
if (props.fullwidth) classNames.push("is-fullwidth")
if (props.className) classNames.push(props.className)

const variant = props.variant || "primary"
const variant = props.variant || "primary"

return props.children ? (
<div
ref={ref}
id={props.id}
className={classNames.join(" ")}
data-variant={variant}
hidden={visible === false}
role={props.role}
tabIndex={props.tabIndex}
data-testid={props.testId}
>
{props.customIcon
? props.customIcon
: CommonMessageIconMap[variant] && <Icon icon={CommonMessageIconMap[variant]} size="md" />}
<span data-part="content">{props.children}</span>
{props.closeable && (
<button aria-label="Close" onClick={toggler}>
<Icon icon={faClose} size="md" />
</button>
)}
</div>
) : null
})
return props.children ? (
<div
ref={ref}
id={props.id}
className={classNames.join(" ")}
data-variant={variant}
hidden={visible === false}
role={props.role}
tabIndex={props.tabIndex}
data-testid={props.testId}
>
{props.customIcon
? props.customIcon
: CommonMessageIconMap[variant] && (
<Icon icon={CommonMessageIconMap[variant]} size="md" />
)}
<span data-part="content">{props.children}</span>
{props.closeable && (
<button
aria-label="Close"
onClick={() => {
toggler()
if (props.onClose) {
props.onClose()
}
}}
>
<Icon icon={faClose} size="md" />
</button>
)}
</div>
) : null
}
)

export default CommonMessage

0 comments on commit 6c4b9d9

Please sign in to comment.