Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions components/ContentModal/ContentModal.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
title: "ContentModal"
description: "A lightweight modal component for embedding custom content."
author: "@andrewerdman"
version: "1.0.0"
---

import { useEffect, useState } from 'react';

export const ContentModal = ({
label,
title,
content,
size = 'md',
buttonColor = '#0B1440'
}) => {
const [open, setOpen] = useState(false);

const sizeClasses = {
sm: 'max-w-[480px]',
md: 'max-w-[720px]',
lg: 'max-w-[960px]',
xl: 'max-w-[1200px]'
};

// ESC to close
useEffect(() => {
if (!open) return;
const onKey = (e) => {
if (e.key === 'Escape') setOpen(false);
};
window.addEventListener('keydown', onKey);
return () => window.removeEventListener('keydown', onKey);
}, [open]);

return (
<>
<button
type="button"
className={`inline-flex items-center justify-center gap-2 py-3 px-5 text-white bg-[${buttonColor}] border-none rounded-sm cursor-pointer hover:opacity-85`}
onClick={() => setOpen(true)}
>
{label} <i className="fa-solid fa-up-right-from-square" aria-hidden="true" />
</button>

{/* Backdrop */}
<div
className="fixed inset-0 z-40 before:content-[''] before:absolute before:inset-0 before:bg-black/50 before:backdrop-blur"
style={{ display: open ? 'block' : 'none' }}
/>

{/* Dialog Wrapper */}
<div
className="fixed inset-0 flex items-center justify-center p-6 z-50"
style={{ display: open ? 'flex' : 'none' }}
onClick={() => setOpen(false)}
>
<div
className={`${sizeClasses[size]} w-full max-h-[86vh] bg-white dark:bg-gray-800 rounded-xl shadow-2xl flex flex-col`}
role="dialog"
aria-modal="true"
aria-label={title}
onClick={(e) => e.stopPropagation()}
>
{/* Header */}
<div className="flex items-center justify-between gap-4 px-6 py-4 border-b border-gray-200 dark:border-gray-700 shrink-0">
<h2 className="m-0 text-lg! font-semibold text-gray-900 dark:text-white!">
{title}
</h2>
<button
className="flex-shrink-0 border-none bg-transparent text-md leading-none cursor-pointer text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-300 transition-colors p-0"
type="button"
aria-label="Close"
onClick={() => setOpen(false)}
>
<i className="fa-solid fa-xmark" aria-hidden="true" />
</button>
</div>

{/* Body */}
<div className="overflow-y-auto px-6 py-5 text-gray-900 dark:text-white">
{content}
</div>
</div>
</div>
</>
);
};

<ContentModal
label="Open Content Modal"
title="Content Modal"
size="md"
buttonColor="#0B1440"
content="
The ContentModal component can be used to display information in a focused, overlay-style container that sits on top of your guides page.
Modals are typically used to draw attention to important actions, confirmations, or details without navigating away from the current view.
Users can close it by clicking outside, pressing ESC, or selecting the close button.
"
/>
Binary file added components/ContentModal/content-modal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions components/ContentModal/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# `<ContentModal/>`

## Overview

Display custom content in an overlay-style container that sits on top of your guides page.

<img src="content-modal.png" width="800" />

## Usage

```mdx
<ContentModal
label="Open Content Modal"
title="Content Modal"
size="md"
buttonColor="#0B1440"
content="
The ContentModal component can be used to display information in a focused, overlay-style container that sits on top of your guides page.
Modals are typically used to draw attention to important actions, confirmations, or details without navigating away from the current view.
Users can close it by clicking outside, pressing ESC, or selecting the close button.
"
/>
```

## Props

| Prop | Type | Description |
| ------------- | ------ | ------------------------------------------------------------------------------------------------- |
| `label` | string | The text displayed on the trigger button. |
| `title` | string | The title displayed at the top of the modal. |
| `content` | string | The content to display inside the modal body. |
| `size` | string | Modal width: `'sm'` (480px), `'md'` (720px), `'lg'` (960px), `'xl'` (1200px). Defaults to `'md'`. |
| `buttonColor` | string | Hex color code for the button background. Defaults to `'#0B1440'`. |
Loading