-
Notifications
You must be signed in to change notification settings - Fork 322
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ModalTopActions): top actions component for internal use (#2415)
- Loading branch information
1 parent
66d900c
commit 3e6faca
Showing
4 changed files
with
132 additions
and
0 deletions.
There are no files selected for viewing
5 changes: 5 additions & 0 deletions
5
packages/core/src/components/ModalNew/ModalTopActions/ModalTopActions.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.actions { | ||
position: absolute; | ||
right: var(--spacing-large); | ||
top: var(--spacing-large); | ||
} |
32 changes: 32 additions & 0 deletions
32
packages/core/src/components/ModalNew/ModalTopActions/ModalTopActions.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import React from "react"; | ||
import styles from "./ModalTopActions.module.scss"; | ||
import { ModalTopActionsButtonColor, ModalTopActionsColor, ModalTopActionsProps } from "./ModalTopActions.types"; | ||
import Flex from "../../Flex/Flex"; | ||
import IconButton from "../../IconButton/IconButton"; | ||
import { CloseSmall } from "../../Icon/Icons"; | ||
import { ButtonColor } from "../../Button/ButtonConstants"; | ||
|
||
const colorToButtonColor: Record<ModalTopActionsColor, ModalTopActionsButtonColor> = { | ||
dark: ButtonColor.ON_INVERTED_BACKGROUND, | ||
light: ButtonColor.ON_PRIMARY_COLOR | ||
}; | ||
|
||
const ModalTopActions = ({ renderAction, color, closeButtonAriaLabel, onClose }: ModalTopActionsProps) => { | ||
const buttonColor = colorToButtonColor[color] || ButtonColor.PRIMARY; | ||
|
||
return ( | ||
<Flex className={styles.actions}> | ||
{typeof renderAction === "function" ? renderAction(buttonColor) : renderAction} | ||
<IconButton | ||
icon={CloseSmall} | ||
onClick={onClose} | ||
size={IconButton.sizes.SMALL} | ||
kind={IconButton.kinds.TERTIARY} | ||
color={buttonColor} | ||
ariaLabel={closeButtonAriaLabel} | ||
/> | ||
</Flex> | ||
); | ||
}; | ||
|
||
export default ModalTopActions; |
23 changes: 23 additions & 0 deletions
23
packages/core/src/components/ModalNew/ModalTopActions/ModalTopActions.types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import React from "react"; | ||
import MenuButton from "../../MenuButton/MenuButton"; | ||
import IconButton from "../../IconButton/IconButton"; | ||
import { ButtonColor } from "../../Button/ButtonConstants"; | ||
|
||
export type ModalTopActionsColor = "light" | "dark"; | ||
export type ModalTopActionsButtonColor = | ||
| ButtonColor.PRIMARY | ||
| ButtonColor.ON_PRIMARY_COLOR | ||
| ButtonColor.ON_INVERTED_BACKGROUND; | ||
|
||
export interface ModalTopActionsProps { | ||
/** | ||
* action can be passed either as a function or direct | ||
* it allows passing back to consumer the color he chose, so he won't have to define it twice | ||
*/ | ||
renderAction?: | ||
| React.ReactElement<typeof MenuButton | typeof IconButton> | ||
| ((color?: ModalTopActionsButtonColor) => React.ReactElement<typeof MenuButton | typeof IconButton>); | ||
color?: ModalTopActionsColor; | ||
closeButtonAriaLabel?: string; | ||
onClose?: React.MouseEventHandler<HTMLDivElement>; | ||
} |
72 changes: 72 additions & 0 deletions
72
packages/core/src/components/ModalNew/ModalTopActions/__tests__/ModalTopActions.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import React from "react"; | ||
import { render, fireEvent, within } from "@testing-library/react"; | ||
import ModalTopActions from "../ModalTopActions"; | ||
import IconButton from "../../../IconButton/IconButton"; | ||
import { Feedback as FeedbackIcon } from "../../../Icon/Icons"; | ||
import { ButtonColor } from "../../../Button/ButtonConstants"; | ||
import { camelCase } from "lodash-es"; | ||
|
||
describe("ModalTopActions", () => { | ||
const closeButtonAriaLabel = "Close modal"; | ||
|
||
it("renders the close button with the correct aria-label", () => { | ||
const { getByLabelText } = render(<ModalTopActions closeButtonAriaLabel={closeButtonAriaLabel} />); | ||
|
||
expect(getByLabelText(closeButtonAriaLabel)).toBeInTheDocument(); | ||
}); | ||
|
||
it("calls onClose when the close button is clicked", () => { | ||
const mockOnClose = jest.fn(); | ||
|
||
const { getByLabelText } = render( | ||
<ModalTopActions onClose={mockOnClose} closeButtonAriaLabel={closeButtonAriaLabel} /> | ||
); | ||
|
||
fireEvent.click(getByLabelText(closeButtonAriaLabel)); | ||
expect(mockOnClose).toHaveBeenCalled(); | ||
}); | ||
|
||
it("does not fail when onClose is not provided", () => { | ||
const { getByLabelText } = render(<ModalTopActions closeButtonAriaLabel={closeButtonAriaLabel} />); | ||
fireEvent.click(getByLabelText(closeButtonAriaLabel)); | ||
expect(() => getByLabelText(closeButtonAriaLabel)).not.toThrow(); | ||
}); | ||
|
||
it("renders the action button using the renderAction prop as a function", () => { | ||
const renderAction = jest.fn(color => <IconButton data-testid="extra-action" icon={FeedbackIcon} color={color} />); | ||
const { getByTestId } = render(<ModalTopActions renderAction={renderAction} />); | ||
|
||
expect(within(getByTestId("extra-action")).getByTestId("icon")).toBeInTheDocument(); | ||
}); | ||
|
||
it("calls renderAction with correct color argument", () => { | ||
const renderAction = jest.fn(color => <IconButton data-testid="extra-action" icon={FeedbackIcon} color={color} />); | ||
render(<ModalTopActions color="dark" renderAction={renderAction} />); | ||
|
||
expect(renderAction).toHaveBeenCalledWith(ButtonColor.ON_INVERTED_BACKGROUND); | ||
}); | ||
|
||
it("renders the action button using the renderAction prop directly", () => { | ||
const renderAction = ( | ||
<IconButton data-testid="extra-action" icon={FeedbackIcon} color={IconButton.colors.ON_PRIMARY_COLOR} /> | ||
); | ||
const { getByTestId } = render(<ModalTopActions renderAction={renderAction} />); | ||
|
||
expect(within(getByTestId("extra-action")).getByTestId("icon")).toBeInTheDocument(); | ||
}); | ||
|
||
it("applies the correct color when 'dark' is passed", () => { | ||
const { getByLabelText } = render(<ModalTopActions color="dark" closeButtonAriaLabel={closeButtonAriaLabel} />); | ||
expect(getByLabelText(closeButtonAriaLabel)).toHaveClass(camelCase("color-" + ButtonColor.ON_INVERTED_BACKGROUND)); | ||
}); | ||
|
||
it("applies the correct color when 'light' is passed", () => { | ||
const { getByLabelText } = render(<ModalTopActions color="light" closeButtonAriaLabel={closeButtonAriaLabel} />); | ||
expect(getByLabelText(closeButtonAriaLabel)).toHaveClass(camelCase("color-" + ButtonColor.ON_PRIMARY_COLOR)); | ||
}); | ||
|
||
it("applies the default color when no color is passed", () => { | ||
const { getByLabelText } = render(<ModalTopActions closeButtonAriaLabel={closeButtonAriaLabel} />); | ||
expect(getByLabelText(closeButtonAriaLabel)).toHaveClass(camelCase("color-" + ButtonColor.PRIMARY)); | ||
}); | ||
}); |