mirror of
https://github.com/hanzoai/o11y-components.git
synced 2026-10-30 14:54:15 +00:00
A version written into a manifest is written into every manifest that wants it, which is how eslint came to exist in a hundred and four forms across this estate and how a package came to resolve twice at run time. The catalog moves the number out of the manifest: a manifest names the package, the workspace names the version. Four are held below their latest because the newer release cannot be used, and the reason is recorded rather than the version alone: @noble/hashes 2 renamed every subpath the web3 stack imports, @splinetool/runtime 2 depends on a package that was never published, @dynamic-labs 5.4.1 the same, and react-resizable-panels 3 points its types condition at the bundle.
275 lines
6.9 KiB
Plaintext
275 lines
6.9 KiB
Plaintext
import { Meta, Controls, Primary, Story } from '@storybook/addon-docs/blocks';
|
||
import * as DialogStories from './dialog.stories';
|
||
import * as DialogWrapperStories from './dialog-wrapper.stories';
|
||
import * as ConfirmDialogStories from './confirm-dialog.stories';
|
||
import * as ConfirmDialogUrlStories from './confirm-dialog-url.stories';
|
||
import * as AlertDialogStories from './alert-dialog.stories';
|
||
import * as DialogPrimitiveStories from './dialog-primitive.stories';
|
||
import * as DialogTriggerStories from './dialog-trigger.stories';
|
||
import * as DialogContentStories from './dialog-content.stories';
|
||
import * as DialogHeaderStories from './dialog-header.stories';
|
||
import * as DialogTitleStories from './dialog-title.stories';
|
||
import * as DialogDescriptionStories from './dialog-description.stories';
|
||
import * as DialogFooterStories from './dialog-footer.stories';
|
||
import * as DialogCloseStories from './dialog-close.stories';
|
||
import * as DialogOverlayStories from './dialog-overlay.stories';
|
||
import * as DialogPortalStories from './dialog-portal.stories';
|
||
|
||
<Meta of={DialogStories} />
|
||
|
||
# Dialog
|
||
|
||
A modal dialog component for displaying content that requires user attention or interaction.
|
||
|
||
## How to use
|
||
|
||
### DialogWrapper (preset)
|
||
|
||
Use `DialogWrapper` for a simple dialog with title, optional trigger, and content. Pass `open` and `onOpenChange` for controlled mode with exit animations:
|
||
|
||
```tsx
|
||
import { DialogWrapper, Button } from '@signozhq/ui';
|
||
|
||
export default function MyComponent() {
|
||
const [open, setOpen] = React.useState(false);
|
||
|
||
return (
|
||
<DialogWrapper
|
||
open={open}
|
||
onOpenChange={setOpen}
|
||
title="Edit Details"
|
||
trigger={<Button variant="solid">Open Dialog</Button>}
|
||
>
|
||
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
|
||
<p>Dialog content goes here</p>
|
||
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||
<Button variant="solid" color="primary" onClick={() => setOpen(false)}>
|
||
Save Changes
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
</DialogWrapper>
|
||
);
|
||
}
|
||
```
|
||
|
||
<Primary />
|
||
|
||
## DialogWrapper Props
|
||
|
||
<Controls of={DialogWrapperStories.Default} />
|
||
|
||
## ConfirmDialog
|
||
|
||
For confirm/cancel flows with a title, description, and footer actions:
|
||
|
||
```tsx
|
||
import { ConfirmDialog, Button } from '@signozhq/ui';
|
||
|
||
export default function MyComponent() {
|
||
const [open, setOpen] = useState(false);
|
||
|
||
return (
|
||
<>
|
||
<Button onClick={() => setOpen(true)}>Delete</Button>
|
||
<ConfirmDialog
|
||
open={open}
|
||
onOpenChange={setOpen}
|
||
title="Confirm action"
|
||
confirmText="Delete"
|
||
cancelText="Cancel"
|
||
confirmColor="destructive"
|
||
onConfirm={() => setOpen(false)}
|
||
onCancel={() => setOpen(false)}
|
||
width="narrow"
|
||
>
|
||
Are you sure? This action cannot be undone.
|
||
</ConfirmDialog>
|
||
</>
|
||
);
|
||
}
|
||
```
|
||
|
||
## ConfirmDialog Props
|
||
|
||
<Controls of={ConfirmDialogStories.Default} />
|
||
|
||
## AlertDialog
|
||
|
||
For destructive or high-impact actions, with optional checkbox (e.g. “Don’t ask again”) and custom footer:
|
||
|
||
```tsx
|
||
import { AlertDialog, Button } from '@signozhq/ui';
|
||
|
||
export default function MyComponent() {
|
||
const [open, setOpen] = useState(false);
|
||
const [dontAskAgain, setDontAskAgain] = useState(false);
|
||
|
||
return (
|
||
<AlertDialog
|
||
open={open}
|
||
onOpenChange={setOpen}
|
||
title="Delete this step"
|
||
checkboxLabel="Do not ask me this again"
|
||
checkboxChecked={dontAskAgain}
|
||
onCheckboxChange={setDontAskAgain}
|
||
trigger={<Button>Delete</Button>}
|
||
footer={
|
||
<>
|
||
<Button variant="ghost" onClick={() => setOpen(false)}>Cancel</Button>
|
||
<Button color="destructive" onClick={() => setOpen(false)}>Delete</Button>
|
||
</>
|
||
}
|
||
>
|
||
Deleting this step would stop further analytics using this step.
|
||
</AlertDialog>
|
||
);
|
||
}
|
||
```
|
||
|
||
## AlertDialog Props
|
||
|
||
<Controls of={AlertDialogStories.Default} />
|
||
|
||
## ConfirmDialogUrl
|
||
|
||
For confirm dialogs controlled via a URL query parameter:
|
||
|
||
> This component requires the setup with [nuqs](https://nuqs.dev/).
|
||
|
||
```tsx
|
||
import { ConfirmDialogUrl, Button } from '@signozhq/ui';
|
||
import { useQueryState, parseAsBoolean } from 'nuqs';
|
||
|
||
export default function MyComponent() {
|
||
const [, setOpen] = useQueryState('dialog-delete-step', parseAsBoolean.withDefault(false));
|
||
|
||
return (
|
||
<>
|
||
<Button
|
||
variant="solid"
|
||
color="primary"
|
||
onClick={() => setOpen(true)}
|
||
>
|
||
Open confirm dialog (URL)
|
||
</Button>
|
||
<ConfirmDialogUrl
|
||
urlKey="dialog-delete-step"
|
||
title="Delete from URL param"
|
||
confirmText="Delete"
|
||
cancelText="Cancel"
|
||
confirmColor="destructive"
|
||
onConfirm={async () => {
|
||
// Simulate async work, this will change the button to loading state
|
||
await new Promise((resolve) => setTimeout(resolve, 300));
|
||
return true;
|
||
}}
|
||
width="narrow"
|
||
>
|
||
This confirm dialog is controlled via a URL query parameter using nuqs.
|
||
</ConfirmDialogUrl>
|
||
</>
|
||
);
|
||
}
|
||
```
|
||
|
||
## ConfirmDialogUrl Props
|
||
|
||
<Controls of={ConfirmDialogUrlStories.Default} />
|
||
|
||
## Primitive composition
|
||
|
||
For full control, use the low-level building blocks: `Dialog`, `DialogTrigger`, `DialogContent`, `DialogHeader`, `DialogTitle`, `DialogDescription`, `DialogFooter`, and `DialogClose`.
|
||
|
||
### Exit animations
|
||
|
||
To animate the dialog on close, wrap `DialogContent` in `AnimatePresence` and pass `forceMount` plus a stable `key`:
|
||
|
||
```tsx
|
||
import {
|
||
Dialog,
|
||
DialogTrigger,
|
||
DialogContent,
|
||
DialogHeader,
|
||
DialogTitle,
|
||
DialogDescription,
|
||
DialogFooter,
|
||
DialogClose,
|
||
Button,
|
||
} from '@signozhq/ui';
|
||
import { AnimatePresence } from 'motion/react';
|
||
|
||
export default function MyComponent() {
|
||
const [open, setOpen] = useState(false);
|
||
|
||
return (
|
||
<Dialog open={open} onOpenChange={setOpen}>
|
||
<DialogTrigger asChild>
|
||
<Button>Open</Button>
|
||
</DialogTrigger>
|
||
<AnimatePresence>
|
||
{open && (
|
||
<DialogContent key="dialog" width="base" forceMount>
|
||
<DialogHeader>
|
||
<DialogTitle>Title</DialogTitle>
|
||
</DialogHeader>
|
||
<DialogDescription>
|
||
Description and body content.
|
||
</DialogDescription>
|
||
<DialogFooter>
|
||
<Button variant="ghost" onClick={() => setOpen(false)}>Cancel</Button>
|
||
<DialogClose asChild>
|
||
<Button>Confirm</Button>
|
||
</DialogClose>
|
||
</DialogFooter>
|
||
</DialogContent>
|
||
)}
|
||
</AnimatePresence>
|
||
</Dialog>
|
||
);
|
||
}
|
||
```
|
||
|
||
Without `AnimatePresence`, `forceMount`, and `key`, the dialog closes instantly. `DialogWrapper` uses this pattern internally when `open` and `onOpenChange` are provided.
|
||
|
||
## Dialog Props
|
||
|
||
<Controls of={DialogPrimitiveStories.Default} />
|
||
|
||
## DialogTrigger Props
|
||
|
||
<Controls of={DialogTriggerStories.Default} />
|
||
|
||
## DialogContent Props
|
||
|
||
<Controls of={DialogContentStories.Default} />
|
||
|
||
## DialogHeader Props
|
||
|
||
<Controls of={DialogHeaderStories.Default} />
|
||
|
||
## DialogTitle Props
|
||
|
||
<Controls of={DialogTitleStories.Default} />
|
||
|
||
## DialogDescription Props
|
||
|
||
<Controls of={DialogDescriptionStories.Default} />
|
||
|
||
## DialogFooter Props
|
||
|
||
<Controls of={DialogFooterStories.Default} />
|
||
|
||
## DialogClose Props
|
||
|
||
<Controls of={DialogCloseStories.Default} />
|
||
|
||
## DialogOverlay Props
|
||
|
||
<Controls of={DialogOverlayStories.Default} />
|
||
|
||
## DialogPortal Props
|
||
|
||
<Controls of={DialogPortalStories.Default} />
|
||
|