diff --git a/src/components/Modal/README.md b/src/components/Modal/README.md
index 0558370..769c640 100644
--- a/src/components/Modal/README.md
+++ b/src/components/Modal/README.md
@@ -39,6 +39,7 @@ import { BBBModal } from 'bbb-ui-components-react';
| `shouldCloseOnEsc` | `boolean` | `false` | Allows closing with ESC key. |
| `allowScroll` | `boolean` | `true` | Enables scroll in the modal body. |
| `noFooter` | `boolean` | `false` | Hides the modal footer. |
+| `hideCloseButton` | `boolean` | `false` | Hides the header close button. |
| `footerContent` | `React.ReactNode` | `null` | Custom content for the footer. |
| `stickyFooter` | `boolean` | `true` | Makes the footer sticky. |
| `testId` | `string` | — | Test identifier applied to the modal element (native `ReactModal` prop). |
diff --git a/src/components/Modal/component.stories.tsx b/src/components/Modal/component.stories.tsx
index 9367b1e..731eb33 100644
--- a/src/components/Modal/component.stories.tsx
+++ b/src/components/Modal/component.stories.tsx
@@ -59,6 +59,10 @@ const meta = {
control: 'boolean',
description: 'Hide the footer section.',
},
+ hideCloseButton: {
+ control: 'boolean',
+ description: 'Hide the header close button.',
+ },
footerContent: {
control: false,
description: 'Custom React node to render inside the footer.',
@@ -190,3 +194,12 @@ export const Default: Story = {
},
render: (args) => ,
};
+
+/** Modal without a header close button, for mandatory-action or externally-controlled flows. */
+export const HideCloseButton: Story = {
+ args: {
+ ...Default.args,
+ hideCloseButton: true,
+ },
+ render: (args) => ,
+};
diff --git a/src/components/Modal/component.tsx b/src/components/Modal/component.tsx
index b1d9d8b..6376cf1 100644
--- a/src/components/Modal/component.tsx
+++ b/src/components/Modal/component.tsx
@@ -25,6 +25,7 @@ const Modal: React.FC = ({
shouldCloseOnEsc = false,
allowScroll = true,
noFooter = false,
+ hideCloseButton = false,
footerContent = null,
stickyFooter = true,
testId,
@@ -65,14 +66,16 @@ const Modal: React.FC = ({
>
{title}
- }
- onClick={onRequestClose}
- variant="subtle"
- ariaLabel="close"
- {...(_closeButtonDataTest ? { dataTest: _closeButtonDataTest } : {})}
- />
+ {!hideCloseButton && (
+ }
+ onClick={onRequestClose}
+ variant="subtle"
+ ariaLabel="close"
+ {...(_closeButtonDataTest ? { dataTest: _closeButtonDataTest } : {})}
+ />
+ )}
{showDividers && }
diff --git a/src/components/Modal/styles.ts b/src/components/Modal/styles.ts
index 708c871..1002ac9 100644
--- a/src/components/Modal/styles.ts
+++ b/src/components/Modal/styles.ts
@@ -45,15 +45,6 @@ export const ModalHeader = styled.div`
align-items: center;
`;
-export const CloseButton = styled.button`
- background: none;
- border: none;
- font-size: 1.5rem;
- cursor: pointer;
- padding: 0;
- line-height: 1;
-`;
-
export const ModalScrollArea = styled.div`
flex-grow: 1;
overflow-y: ${({ $allowScroll }) => $allowScroll ? 'auto' : 'hidden'};
diff --git a/src/components/Modal/types.ts b/src/components/Modal/types.ts
index d82a8f3..5cc7b41 100644
--- a/src/components/Modal/types.ts
+++ b/src/components/Modal/types.ts
@@ -28,6 +28,9 @@ export interface ModalProps extends Omit {
/** Hide the footer section. @default false */
noFooter?: boolean;
+ /** Hide the header close button. @default false */
+ hideCloseButton?: boolean;
+
/** When true, the footer is sticky to the bottom instead of scrolling with the body. @default true */
stickyFooter?: boolean;