aural-ui 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +456 -0
- package/dist/components/aspect-ratio/AspectRatio.stories.tsx +1327 -0
- package/dist/components/aspect-ratio/index.tsx +10 -0
- package/dist/components/aspect-ratio/meta.ts +8 -0
- package/dist/components/avatar/Avatar.stories.tsx +645 -0
- package/dist/components/avatar/index.tsx +50 -0
- package/dist/components/avatar/meta.ts +8 -0
- package/dist/components/badge/Badge.stories.tsx +169 -0
- package/dist/components/badge/index.tsx +28 -0
- package/dist/components/badge/meta.ts +6 -0
- package/dist/components/banner/Banner.stories.tsx +475 -0
- package/dist/components/banner/index.tsx +256 -0
- package/dist/components/banner/meta.ts +36 -0
- package/dist/components/button/Button.stories.tsx +74 -0
- package/dist/components/button/index.tsx +158 -0
- package/dist/components/button/meta.ts +33 -0
- package/dist/components/card/Card.stories.tsx +377 -0
- package/dist/components/card/index.tsx +85 -0
- package/dist/components/card/meta.ts +14 -0
- package/dist/components/char-count/CharCount.stories.tsx +334 -0
- package/dist/components/char-count/index.tsx +51 -0
- package/dist/components/char-count/meta.ts +13 -0
- package/dist/components/checkbox/Checkbox.stories.tsx +209 -0
- package/dist/components/checkbox/index.tsx +34 -0
- package/dist/components/checkbox/meta.ts +19 -0
- package/dist/components/chip/Chip.stories.tsx +207 -0
- package/dist/components/chip/index.tsx +92 -0
- package/dist/components/chip/meta.ts +17 -0
- package/dist/components/circular-loader/CircularLoader.stories.tsx +741 -0
- package/dist/components/circular-loader/index.tsx +138 -0
- package/dist/components/circular-loader/meta.ts +11 -0
- package/dist/components/collapsible/Collapsible.stories.tsx +319 -0
- package/dist/components/collapsible/index.tsx +158 -0
- package/dist/components/collapsible/meta.ts +22 -0
- package/dist/components/command/Command.stories.tsx +996 -0
- package/dist/components/command/index.tsx +324 -0
- package/dist/components/command/meta.ts +18 -0
- package/dist/components/dialog/Dialog.stories.tsx +963 -0
- package/dist/components/dialog/index.tsx +250 -0
- package/dist/components/dialog/meta.ts +28 -0
- package/dist/components/divider/Divider.stories.tsx +633 -0
- package/dist/components/divider/index.tsx +181 -0
- package/dist/components/divider/meta.ts +12 -0
- package/dist/components/dot-loader/DotLoader.stories.tsx +352 -0
- package/dist/components/dot-loader/index.tsx +78 -0
- package/dist/components/dot-loader/meta.ts +14 -0
- package/dist/components/dropdown/Dropdown.stories.tsx +1210 -0
- package/dist/components/dropdown/index.tsx +479 -0
- package/dist/components/dropdown/meta.ts +21 -0
- package/dist/components/form/Form.stories.tsx +320 -0
- package/dist/components/form/index.tsx +183 -0
- package/dist/components/form/meta.ts +11 -0
- package/dist/components/helper-text/HelperText.stories.tsx +254 -0
- package/dist/components/helper-text/index.tsx +102 -0
- package/dist/components/helper-text/meta.ts +18 -0
- package/dist/components/hover-card/HoverCard.stories.tsx +1328 -0
- package/dist/components/hover-card/index.tsx +42 -0
- package/dist/components/hover-card/meta.ts +12 -0
- package/dist/components/icon-button/IconButton.stories.tsx +252 -0
- package/dist/components/icon-button/index.tsx +130 -0
- package/dist/components/icon-button/meta.ts +20 -0
- package/dist/components/if-else/if-else.stories.tsx +100 -0
- package/dist/components/if-else/index.tsx +56 -0
- package/dist/components/if-else/meta.ts +6 -0
- package/dist/components/index.ts +70 -0
- package/dist/components/input/Input.stories.tsx +431 -0
- package/dist/components/input/index.tsx +487 -0
- package/dist/components/input/meta.ts +28 -0
- package/dist/components/label/Label.stories.tsx +200 -0
- package/dist/components/label/index.tsx +43 -0
- package/dist/components/label/meta.ts +14 -0
- package/dist/components/list/List.stories.tsx +963 -0
- package/dist/components/list/index.tsx +567 -0
- package/dist/components/list/meta.ts +24 -0
- package/dist/components/marquee/Marquee.stories.tsx +819 -0
- package/dist/components/marquee/index.tsx +107 -0
- package/dist/components/marquee/meta.ts +6 -0
- package/dist/components/overlay/Overlay.stories.tsx +954 -0
- package/dist/components/overlay/index.tsx +58 -0
- package/dist/components/overlay/meta.ts +10 -0
- package/dist/components/pagination/Pagination.stories.tsx +354 -0
- package/dist/components/pagination/index.tsx +455 -0
- package/dist/components/pagination/meta.ts +29 -0
- package/dist/components/popover/Popover.stories.tsx +1037 -0
- package/dist/components/popover/index.tsx +67 -0
- package/dist/components/popover/meta.ts +12 -0
- package/dist/components/radio/Radio.stories.tsx +146 -0
- package/dist/components/radio/index.tsx +41 -0
- package/dist/components/radio/meta.ts +19 -0
- package/dist/components/resizable/Resizable.stories.tsx +866 -0
- package/dist/components/resizable/index.tsx +55 -0
- package/dist/components/resizable/meta.ts +12 -0
- package/dist/components/scroll-area/ScrollArea.stories.tsx +1104 -0
- package/dist/components/scroll-area/index.tsx +55 -0
- package/dist/components/scroll-area/meta.ts +8 -0
- package/dist/components/search/Search.stories.tsx +678 -0
- package/dist/components/search/index.tsx +141 -0
- package/dist/components/search/meta.ts +6 -0
- package/dist/components/select/Select.stories.tsx +962 -0
- package/dist/components/select/index.tsx +512 -0
- package/dist/components/select/meta.ts +40 -0
- package/dist/components/sheet/Sheet.stories.tsx +1060 -0
- package/dist/components/sheet/index.tsx +440 -0
- package/dist/components/sheet/meta.ts +38 -0
- package/dist/components/skelton/Skelton.stories.tsx +859 -0
- package/dist/components/skelton/index.tsx +17 -0
- package/dist/components/skelton/meta.ts +6 -0
- package/dist/components/slider/Slider.stories.tsx +876 -0
- package/dist/components/slider/index.tsx +156 -0
- package/dist/components/slider/meta.ts +29 -0
- package/dist/components/stepper/Stepper.stories.tsx +639 -0
- package/dist/components/stepper/index.tsx +650 -0
- package/dist/components/stepper/meta.ts +19 -0
- package/dist/components/switch/Switch.stories.tsx +85 -0
- package/dist/components/switch/index.tsx +37 -0
- package/dist/components/switch/meta.ts +24 -0
- package/dist/components/switch-case/SwitchCase.stories.tsx +209 -0
- package/dist/components/switch-case/index.tsx +89 -0
- package/dist/components/switch-case/meta.ts +6 -0
- package/dist/components/table/Table.stories.tsx +1095 -0
- package/dist/components/table/index.tsx +113 -0
- package/dist/components/table/meta.ts +20 -0
- package/dist/components/tabs/Tabs.stories.tsx +1379 -0
- package/dist/components/tabs/index.tsx +186 -0
- package/dist/components/tabs/meta.ts +25 -0
- package/dist/components/tag/Tag.stories.tsx +625 -0
- package/dist/components/tag/index.tsx +320 -0
- package/dist/components/tag/meta.ts +52 -0
- package/dist/components/textarea/TextArea.stories.tsx +723 -0
- package/dist/components/textarea/index.tsx +480 -0
- package/dist/components/textarea/meta.ts +23 -0
- package/dist/components/toast/Toast.stories.tsx +1427 -0
- package/dist/components/toast/index.tsx +26 -0
- package/dist/components/toast/meta.ts +19 -0
- package/dist/components/toggle/Toggle.stories.tsx +1093 -0
- package/dist/components/toggle/index.tsx +44 -0
- package/dist/components/toggle/meta.ts +19 -0
- package/dist/components/tooltip/Tooltip.stories.tsx +1548 -0
- package/dist/components/tooltip/index.tsx +304 -0
- package/dist/components/tooltip/meta.ts +21 -0
- package/dist/components/typography/Typography.stories.tsx +197 -0
- package/dist/components/typography/index.tsx +184 -0
- package/dist/components/typography/meta.ts +38 -0
- package/dist/fonts/LabGrotesque-Regular.ttf +0 -0
- package/dist/fonts/LabGrotesqueTRIAL-Bold.otf +0 -0
- package/dist/fonts/LabGrotesqueTRIAL-Light.otf +0 -0
- package/dist/fonts/LabGrotesqueTRIAL-Medium.otf +0 -0
- package/dist/fonts/LabGrotesqueTRIAL-Regular.otf +0 -0
- package/dist/fonts/PPSupplySans-Regular (1).otf +0 -0
- package/dist/fonts/PPSupplySans-Regular.otf +0 -0
- package/dist/fonts/PPSupplySans-Ultralight.otf +0 -0
- package/dist/hooks/index.ts +3 -0
- package/dist/hooks/use-previous/UsePrevious.stories.tsx +997 -0
- package/dist/hooks/use-previous/index.ts +15 -0
- package/dist/hooks/use-previous/meta.ts +6 -0
- package/dist/hooks/use-standalone-pagination/UseStandalonePagination.stories.tsx +983 -0
- package/dist/hooks/use-standalone-pagination/index.ts +146 -0
- package/dist/hooks/use-standalone-pagination/meta.ts +6 -0
- package/dist/icons/Icons.stories.tsx +29 -0
- package/dist/icons/alert-icon/AlertIcon.stories.tsx +991 -0
- package/dist/icons/alert-icon/index.tsx +48 -0
- package/dist/icons/alert-icon/meta.ts +8 -0
- package/dist/icons/all-icons.tsx +738 -0
- package/dist/icons/angle-down-icon/AngleDownIcon.stories.tsx +1031 -0
- package/dist/icons/angle-down-icon/index.tsx +25 -0
- package/dist/icons/angle-down-icon/meta.ts +8 -0
- package/dist/icons/arrow-box-left-icon/ArrowBoxLeftIcon.stories.tsx +1080 -0
- package/dist/icons/arrow-box-left-icon/index.tsx +24 -0
- package/dist/icons/arrow-box-left-icon/meta.ts +8 -0
- package/dist/icons/arrow-right-icon/ArrowRightIcon.stories.tsx +1151 -0
- package/dist/icons/arrow-right-icon/index.tsx +26 -0
- package/dist/icons/arrow-right-icon/meta.ts +8 -0
- package/dist/icons/arrow-right-up-icon/ArrowRightUpIcon.stories.tsx +1273 -0
- package/dist/icons/arrow-right-up-icon/index.tsx +24 -0
- package/dist/icons/arrow-right-up-icon/meta.ts +8 -0
- package/dist/icons/art-board-icon/ArtBoardIcon.stories.tsx +670 -0
- package/dist/icons/art-board-icon/index.tsx +24 -0
- package/dist/icons/art-board-icon/meta.ts +7 -0
- package/dist/icons/audio-bar-icon/AudioBarIcon.stories.tsx +1244 -0
- package/dist/icons/audio-bar-icon/index.tsx +19 -0
- package/dist/icons/audio-bar-icon/meta.ts +8 -0
- package/dist/icons/bubble-check-icon/BubbleCheckIcon.stories.tsx +1239 -0
- package/dist/icons/bubble-check-icon/index.tsx +24 -0
- package/dist/icons/bubble-check-icon/meta.ts +8 -0
- package/dist/icons/bubble-crossed-icon/BubbleCrossedIcon.stories.tsx +1228 -0
- package/dist/icons/bubble-crossed-icon/index.tsx +24 -0
- package/dist/icons/bubble-crossed-icon/meta.ts +8 -0
- package/dist/icons/bubble-sparkle-icon/BubbleSparkleIcon.stories.tsx +912 -0
- package/dist/icons/bubble-sparkle-icon/index.tsx +26 -0
- package/dist/icons/bubble-sparkle-icon/meta.ts +8 -0
- package/dist/icons/chevron-double-left-icon/ChevronDoubleLeftIcon.stories.tsx +1021 -0
- package/dist/icons/chevron-double-left-icon/index.tsx +34 -0
- package/dist/icons/chevron-double-left-icon/meta.ts +8 -0
- package/dist/icons/chevron-double-right-icon/ChevronDoubleRightIcon.stories.tsx +1021 -0
- package/dist/icons/chevron-double-right-icon/index.tsx +34 -0
- package/dist/icons/chevron-double-right-icon/meta.ts +8 -0
- package/dist/icons/chevron-down-icon/ChevronDownIcon.stories.tsx +1001 -0
- package/dist/icons/chevron-down-icon/index.tsx +27 -0
- package/dist/icons/chevron-down-icon/meta.ts +8 -0
- package/dist/icons/chevron-left-icon/ChevronLeftIcon.stories.tsx +1029 -0
- package/dist/icons/chevron-left-icon/index.tsx +27 -0
- package/dist/icons/chevron-left-icon/meta.ts +8 -0
- package/dist/icons/chevron-right-icon/ChevronRightIcon.stories.tsx +1021 -0
- package/dist/icons/chevron-right-icon/index.tsx +27 -0
- package/dist/icons/chevron-right-icon/meta.ts +8 -0
- package/dist/icons/chevron-up-icon/ChevronUpIcon.stories.tsx +1036 -0
- package/dist/icons/chevron-up-icon/index.tsx +27 -0
- package/dist/icons/chevron-up-icon/meta.ts +8 -0
- package/dist/icons/command-icon/CommandIcon.stories.tsx +1098 -0
- package/dist/icons/command-icon/index.tsx +24 -0
- package/dist/icons/command-icon/meta.ts +8 -0
- package/dist/icons/cross-circle-icon/CrossCircleIcon.stories.tsx +1061 -0
- package/dist/icons/cross-circle-icon/index.tsx +23 -0
- package/dist/icons/cross-circle-icon/meta.ts +8 -0
- package/dist/icons/cross-icon/CrossIcon.stories.tsx +1027 -0
- package/dist/icons/cross-icon/index.tsx +24 -0
- package/dist/icons/cross-icon/meta.ts +8 -0
- package/dist/icons/edit-big-icon/EditBigIcon.stories.tsx +1092 -0
- package/dist/icons/edit-big-icon/index.tsx +22 -0
- package/dist/icons/edit-big-icon/meta.ts +8 -0
- package/dist/icons/eye-close-icon/EyeCloseIcon.stories.tsx +1090 -0
- package/dist/icons/eye-close-icon/index.tsx +26 -0
- package/dist/icons/eye-close-icon/meta.ts +8 -0
- package/dist/icons/eye-open-icon/EyeOpenIcon.stories.tsx +1098 -0
- package/dist/icons/eye-open-icon/index.tsx +24 -0
- package/dist/icons/eye-open-icon/meta.ts +8 -0
- package/dist/icons/feature-shine-icon/FeatureShineIcon.stories.tsx +1071 -0
- package/dist/icons/feature-shine-icon/index.tsx +29 -0
- package/dist/icons/feature-shine-icon/meta.ts +8 -0
- package/dist/icons/file-chart-icon/FileChartIcon.stories.tsx +1115 -0
- package/dist/icons/file-chart-icon/index.tsx +24 -0
- package/dist/icons/file-chart-icon/meta.ts +8 -0
- package/dist/icons/file-text-icon/FileTextIcon.stories.tsx +668 -0
- package/dist/icons/file-text-icon/index.tsx +24 -0
- package/dist/icons/file-text-icon/meta.ts +8 -0
- package/dist/icons/grip-vertical-icon/GripVerticalIcon.stories.tsx +1239 -0
- package/dist/icons/grip-vertical-icon/index.tsx +28 -0
- package/dist/icons/grip-vertical-icon/meta.ts +8 -0
- package/dist/icons/image-icon/ImageIcon.stories.tsx +1181 -0
- package/dist/icons/image-icon/index.tsx +24 -0
- package/dist/icons/image-icon/meta.ts +8 -0
- package/dist/icons/import-folder-icon/ImportFolderIcon.stories.tsx +1248 -0
- package/dist/icons/import-folder-icon/index.tsx +22 -0
- package/dist/icons/import-folder-icon/meta.ts +8 -0
- package/dist/icons/index.ts +46 -0
- package/dist/icons/light-bulb-simple-icon/LightBulbSimpleIcon.stories.tsx +1272 -0
- package/dist/icons/light-bulb-simple-icon/index.tsx +24 -0
- package/dist/icons/light-bulb-simple-icon/meta.ts +8 -0
- package/dist/icons/magic-book-icon/MagicBookIcon.stories.tsx +1245 -0
- package/dist/icons/magic-book-icon/index.tsx +32 -0
- package/dist/icons/magic-book-icon/meta.ts +8 -0
- package/dist/icons/maintenance-icon/MaintenanceIcon.stories.tsx +1251 -0
- package/dist/icons/maintenance-icon/index.tsx +23 -0
- package/dist/icons/maintenance-icon/meta.ts +8 -0
- package/dist/icons/message-icon/MessageIcon.stories.tsx +595 -0
- package/dist/icons/message-icon/index.tsx +30 -0
- package/dist/icons/message-icon/meta.ts +8 -0
- package/dist/icons/move-horizontal-icon/MoveHorizontalIcon.stories.tsx +1245 -0
- package/dist/icons/move-horizontal-icon/index.tsx +23 -0
- package/dist/icons/move-horizontal-icon/meta.ts +8 -0
- package/dist/icons/move-vertical-icon/MoveVerticalIcon.stories.tsx +1196 -0
- package/dist/icons/move-vertical-icon/index.tsx +23 -0
- package/dist/icons/move-vertical-icon/meta.ts +8 -0
- package/dist/icons/page-search-icon/PageSearchIcon.stories.tsx +1167 -0
- package/dist/icons/page-search-icon/index.tsx +21 -0
- package/dist/icons/page-search-icon/meta.ts +8 -0
- package/dist/icons/pencil-icon/PencilIcon.stories.tsx +1131 -0
- package/dist/icons/pencil-icon/index.tsx +21 -0
- package/dist/icons/pencil-icon/meta.ts +8 -0
- package/dist/icons/plus-icon/PlusIcon.stories.tsx +1151 -0
- package/dist/icons/plus-icon/index.tsx +24 -0
- package/dist/icons/plus-icon/meta.ts +8 -0
- package/dist/icons/search-icon/SearchIcon.stories.tsx +1181 -0
- package/dist/icons/search-icon/index.tsx +24 -0
- package/dist/icons/search-icon/meta.ts +8 -0
- package/dist/icons/site-logo-icon/SiteLogoIcon.stories.tsx +1167 -0
- package/dist/icons/site-logo-icon/index.tsx +79 -0
- package/dist/icons/site-logo-icon/meta.ts +8 -0
- package/dist/icons/spinner-gradient-icon/SpinnerGradientIcon.stories.tsx +637 -0
- package/dist/icons/spinner-gradient-icon/index.tsx +53 -0
- package/dist/icons/spinner-gradient-icon/meta.ts +8 -0
- package/dist/icons/spinner-solid-icon/SpinnerSolidIcon.stories.tsx +644 -0
- package/dist/icons/spinner-solid-icon/index.tsx +59 -0
- package/dist/icons/spinner-solid-icon/meta.ts +8 -0
- package/dist/icons/spinner-solid-neutral-icon/SpinnerSolidINeutralcon.stories.tsx +736 -0
- package/dist/icons/spinner-solid-neutral-icon/index.tsx +53 -0
- package/dist/icons/spinner-solid-neutral-icon/meta.ts +8 -0
- package/dist/icons/tick-circle-icon/TickCircleIcon.stories.tsx +1204 -0
- package/dist/icons/tick-circle-icon/index.tsx +23 -0
- package/dist/icons/tick-circle-icon/meta.ts +8 -0
- package/dist/icons/tick-icon/TickIcon.stories.tsx +1340 -0
- package/dist/icons/tick-icon/index.tsx +24 -0
- package/dist/icons/tick-icon/meta.ts +8 -0
- package/dist/icons/trash-icon/TrashIcon.stories.tsx +996 -0
- package/dist/icons/trash-icon/index.tsx +24 -0
- package/dist/icons/trash-icon/meta.ts +8 -0
- package/dist/icons/upload-icon/UploadIcon.stories.tsx +947 -0
- package/dist/icons/upload-icon/index.tsx +24 -0
- package/dist/icons/upload-icon/meta.ts +8 -0
- package/dist/icons/vertical-menu-icon/VerticalMenuIcon.stories.tsx +1045 -0
- package/dist/icons/vertical-menu-icon/index.tsx +27 -0
- package/dist/icons/vertical-menu-icon/meta.ts +8 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +206 -0
- package/dist/lib/utils.ts +6 -0
- package/dist/styles/aural-theme.css +1008 -0
- package/package.json +142 -0
|
@@ -0,0 +1,963 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import React, { useState } from "react"
|
|
3
|
+
import { Button } from "@components/button"
|
|
4
|
+
import { Checkbox } from "@components/checkbox"
|
|
5
|
+
import Input from "@components/input"
|
|
6
|
+
import { Label } from "@components/label"
|
|
7
|
+
import Textarea from "@components/textarea"
|
|
8
|
+
import { AlertIcon } from "@icons/alert-icon"
|
|
9
|
+
import { EditBigIcon } from "@icons/edit-big-icon"
|
|
10
|
+
import { LightBulbSimpleIcon } from "@icons/light-bulb-simple-icon"
|
|
11
|
+
import { TickIcon } from "@icons/tick-icon"
|
|
12
|
+
import { TrashIcon } from "@icons/trash-icon"
|
|
13
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
Dialog,
|
|
17
|
+
DialogClose,
|
|
18
|
+
DialogContent,
|
|
19
|
+
DialogDescription,
|
|
20
|
+
DialogFooter,
|
|
21
|
+
DialogHeader,
|
|
22
|
+
DialogTitle,
|
|
23
|
+
DialogTrigger,
|
|
24
|
+
useDialogCleanup,
|
|
25
|
+
} from "."
|
|
26
|
+
|
|
27
|
+
const meta: Meta<typeof DialogContent> = {
|
|
28
|
+
title: "Components/UI/Dialog",
|
|
29
|
+
component: Dialog,
|
|
30
|
+
parameters: {
|
|
31
|
+
layout: "centered",
|
|
32
|
+
backgrounds: {
|
|
33
|
+
default: "dark",
|
|
34
|
+
values: [
|
|
35
|
+
{ name: "dark", value: "#0a0a0a" },
|
|
36
|
+
{ name: "light", value: "#ffffff" },
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
docs: {
|
|
40
|
+
description: {
|
|
41
|
+
component: `
|
|
42
|
+
# Dialog Component
|
|
43
|
+
|
|
44
|
+
A modal dialog component built on Radix UI primitives with customizable overlays, animations, and variant styling. Includes React 18 compatibility fixes for pointer-events issues.
|
|
45
|
+
|
|
46
|
+
## Features
|
|
47
|
+
|
|
48
|
+
- **Multiple Variants**: Neutral, positive, negative, warning, and info styles
|
|
49
|
+
- **Custom Overlays**: Configurable opacity, glass effect, and noise texture
|
|
50
|
+
- **Smooth Animations**: Zoom in/out animations with duration control
|
|
51
|
+
- **Accessible**: Full keyboard navigation and screen reader support
|
|
52
|
+
- **Flexible Content**: Header, footer, and body sections with custom styling
|
|
53
|
+
- **Close Button**: Positioned close button with icon
|
|
54
|
+
- **Portal Rendering**: Renders outside normal DOM hierarchy
|
|
55
|
+
- **Focus Management**: Automatic focus trapping and restoration
|
|
56
|
+
- **React 18 Fix**: Includes \`useDialogCleanup\` hook for pointer-events issues
|
|
57
|
+
|
|
58
|
+
## Component Structure
|
|
59
|
+
|
|
60
|
+
- **Dialog**: Root component that manages dialog state
|
|
61
|
+
- **DialogTrigger**: Button or element that opens the dialog
|
|
62
|
+
- **DialogContent**: Main dialog container with overlay and content
|
|
63
|
+
- **DialogHeader**: Header section for title and description
|
|
64
|
+
- **DialogFooter**: Footer section for action buttons
|
|
65
|
+
- **DialogTitle**: Accessible title element
|
|
66
|
+
- **DialogDescription**: Optional description text
|
|
67
|
+
- **DialogClose**: Close button component
|
|
68
|
+
- **useDialogCleanup**: Hook to fix React 18 pointer-events issues
|
|
69
|
+
|
|
70
|
+
## Usage Examples
|
|
71
|
+
|
|
72
|
+
### Basic Dialog
|
|
73
|
+
\`\`\`tsx
|
|
74
|
+
import { Dialog, DialogContent, DialogTrigger, useDialogCleanup } from '@/components/dialog'
|
|
75
|
+
|
|
76
|
+
function MyComponent() {
|
|
77
|
+
const { handleDialogClose } = useDialogCleanup({ threshold: 100 })
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<Dialog>
|
|
81
|
+
<DialogTrigger asChild>
|
|
82
|
+
<Button>Open Dialog</Button>
|
|
83
|
+
</DialogTrigger>
|
|
84
|
+
<DialogContent onEscapeKeyDown={handleDialogClose}>
|
|
85
|
+
<DialogHeader>
|
|
86
|
+
<DialogTitle>Dialog Title</DialogTitle>
|
|
87
|
+
<DialogDescription>Dialog description text.</DialogDescription>
|
|
88
|
+
</DialogHeader>
|
|
89
|
+
<div>Dialog content goes here.</div>
|
|
90
|
+
<DialogFooter>
|
|
91
|
+
<DialogClose asChild>
|
|
92
|
+
<Button variant="outline" onClick={handleDialogClose}>Cancel</Button>
|
|
93
|
+
</DialogClose>
|
|
94
|
+
<Button>Confirm</Button>
|
|
95
|
+
</DialogFooter>
|
|
96
|
+
</DialogContent>
|
|
97
|
+
</Dialog>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
\`\`\`
|
|
101
|
+
|
|
102
|
+
### Variant Styling
|
|
103
|
+
\`\`\`tsx
|
|
104
|
+
<DialogContent variant="negative">
|
|
105
|
+
{/* Negative variant with red shadow */}
|
|
106
|
+
</DialogContent>
|
|
107
|
+
\`\`\`
|
|
108
|
+
|
|
109
|
+
### Custom Overlay
|
|
110
|
+
\`\`\`tsx
|
|
111
|
+
<DialogContent opacity="high" glass="high" noise="low">
|
|
112
|
+
{/* High opacity overlay with glass effect and subtle noise */}
|
|
113
|
+
</DialogContent>
|
|
114
|
+
\`\`\`
|
|
115
|
+
|
|
116
|
+
### React 18 Compatibility
|
|
117
|
+
\`\`\`tsx
|
|
118
|
+
function DialogWithCleanup() {
|
|
119
|
+
const { handleDialogClose } = useDialogCleanup({ threshold: 150 })
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<DialogContent
|
|
123
|
+
onInteractOutside={handleDialogClose}
|
|
124
|
+
onPointerDownOutside={handleDialogClose}
|
|
125
|
+
>
|
|
126
|
+
{/* Dialog content */}
|
|
127
|
+
</DialogContent>
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
\`\`\`
|
|
131
|
+
`,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
argTypes: {
|
|
136
|
+
variant: {
|
|
137
|
+
control: { type: "select" },
|
|
138
|
+
options: ["neutral", "positive", "negative", "warning", "info"],
|
|
139
|
+
description: "Dialog variant for different use cases",
|
|
140
|
+
},
|
|
141
|
+
opacity: {
|
|
142
|
+
control: { type: "select" },
|
|
143
|
+
options: ["high", "medium", "low", "none"],
|
|
144
|
+
description: "Overlay opacity level",
|
|
145
|
+
},
|
|
146
|
+
glass: {
|
|
147
|
+
control: { type: "select" },
|
|
148
|
+
options: ["high", "medium", "low", "none"],
|
|
149
|
+
description: "Glass blur effect intensity",
|
|
150
|
+
},
|
|
151
|
+
noise: {
|
|
152
|
+
control: { type: "select" },
|
|
153
|
+
options: ["high", "medium", "low", "none"],
|
|
154
|
+
description: "Noise texture intensity",
|
|
155
|
+
},
|
|
156
|
+
showCloseButton: {
|
|
157
|
+
control: "boolean",
|
|
158
|
+
description: "Show/hide the close button",
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
tags: ["autodocs"],
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export default meta
|
|
165
|
+
type Story = StoryObj<typeof Dialog>
|
|
166
|
+
|
|
167
|
+
// 1. Dialog Cleanup Example - React 18 Compatibility
|
|
168
|
+
export const DialogCleanupExample: Story = {
|
|
169
|
+
render: () => {
|
|
170
|
+
const DialogWithCleanup = () => {
|
|
171
|
+
const { handleDialogClose } = useDialogCleanup({ threshold: 100 })
|
|
172
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
173
|
+
|
|
174
|
+
const handleClose = () => {
|
|
175
|
+
handleDialogClose()
|
|
176
|
+
setIsOpen(false)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return (
|
|
180
|
+
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
|
181
|
+
<DialogTrigger asChild>
|
|
182
|
+
<Button>Open Dialog with Cleanup</Button>
|
|
183
|
+
</DialogTrigger>
|
|
184
|
+
<DialogContent
|
|
185
|
+
//@ts-expect-error onEscapeKeyDown available in Radix v2.0.0
|
|
186
|
+
onEscapeKeyDown={handleClose}
|
|
187
|
+
onPointerDownOutside={handleClose}
|
|
188
|
+
>
|
|
189
|
+
<DialogHeader>
|
|
190
|
+
<DialogTitle>Dialog with React 18 Fix</DialogTitle>
|
|
191
|
+
<DialogDescription>
|
|
192
|
+
This dialog uses useDialogCleanup to prevent pointer-events
|
|
193
|
+
issues in React 18.
|
|
194
|
+
</DialogDescription>
|
|
195
|
+
</DialogHeader>
|
|
196
|
+
<div className="py-4">
|
|
197
|
+
<div className="rounded-lg border border-blue-500/20 bg-blue-500/10 p-3">
|
|
198
|
+
<p className="text-sm text-blue-200">
|
|
199
|
+
The useDialogCleanup hook ensures that pointer-events: none
|
|
200
|
+
doesn't get stuck on the body element when the dialog closes,
|
|
201
|
+
which was a common issue in React 18.
|
|
202
|
+
</p>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
<DialogFooter>
|
|
206
|
+
<DialogClose asChild>
|
|
207
|
+
<Button variant="outline" onClick={handleClose}>
|
|
208
|
+
Cancel
|
|
209
|
+
</Button>
|
|
210
|
+
</DialogClose>
|
|
211
|
+
<Button onClick={handleClose}>Confirm</Button>
|
|
212
|
+
</DialogFooter>
|
|
213
|
+
</DialogContent>
|
|
214
|
+
</Dialog>
|
|
215
|
+
)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return (
|
|
219
|
+
<div className="space-y-8">
|
|
220
|
+
<div className="text-center">
|
|
221
|
+
<h3 className="mb-2 font-medium text-white">Dialog Cleanup Hook</h3>
|
|
222
|
+
<p className="text-sm text-white/60">
|
|
223
|
+
Demonstrates useDialogCleanup hook for React 18 compatibility
|
|
224
|
+
</p>
|
|
225
|
+
</div>
|
|
226
|
+
<div className="flex justify-center">
|
|
227
|
+
<DialogWithCleanup />
|
|
228
|
+
</div>
|
|
229
|
+
<div className="text-center">
|
|
230
|
+
<div className="inline-block max-w-lg rounded-lg border border-white/10 bg-white/5 p-4">
|
|
231
|
+
<h4 className="mb-2 text-sm font-medium text-white">
|
|
232
|
+
React 18 Compatibility
|
|
233
|
+
</h4>
|
|
234
|
+
<p className="text-xs leading-relaxed text-white/60">
|
|
235
|
+
The useDialogCleanup hook prevents the pointer-events: none style
|
|
236
|
+
from persisting on the body element after dialog close, which
|
|
237
|
+
could make the page uninteractive in React 18.
|
|
238
|
+
</p>
|
|
239
|
+
</div>
|
|
240
|
+
</div>
|
|
241
|
+
</div>
|
|
242
|
+
)
|
|
243
|
+
},
|
|
244
|
+
parameters: {
|
|
245
|
+
docs: {
|
|
246
|
+
description: {
|
|
247
|
+
story:
|
|
248
|
+
"Example showing how to use useDialogCleanup hook to fix React 18 pointer-events issues.",
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// 2. Basic Dialog Variants with Cleanup
|
|
255
|
+
export const BasicVariants: Story = {
|
|
256
|
+
render: () => {
|
|
257
|
+
const DialogWithCleanupVariant = ({
|
|
258
|
+
variant,
|
|
259
|
+
title,
|
|
260
|
+
description,
|
|
261
|
+
children,
|
|
262
|
+
}: any) => {
|
|
263
|
+
const { handleDialogClose } = useDialogCleanup({ threshold: 100 })
|
|
264
|
+
|
|
265
|
+
return (
|
|
266
|
+
<Dialog>
|
|
267
|
+
<DialogTrigger asChild>
|
|
268
|
+
<Button variant="outline">{title}</Button>
|
|
269
|
+
</DialogTrigger>
|
|
270
|
+
<DialogContent
|
|
271
|
+
variant={variant}
|
|
272
|
+
//@ts-expect-error onEscapeKeyDown available in Radix v2.0.0
|
|
273
|
+
onEscapeKeyDown={handleDialogClose}
|
|
274
|
+
onPointerDownOutside={handleDialogClose}
|
|
275
|
+
>
|
|
276
|
+
<DialogHeader>
|
|
277
|
+
<DialogTitle>{title}</DialogTitle>
|
|
278
|
+
<DialogDescription>{description}</DialogDescription>
|
|
279
|
+
</DialogHeader>
|
|
280
|
+
<div className="py-4">{children}</div>
|
|
281
|
+
<DialogFooter>
|
|
282
|
+
<DialogClose asChild>
|
|
283
|
+
<Button variant="outline" onClick={handleDialogClose}>
|
|
284
|
+
Cancel
|
|
285
|
+
</Button>
|
|
286
|
+
</DialogClose>
|
|
287
|
+
<Button onClick={handleDialogClose}>Continue</Button>
|
|
288
|
+
</DialogFooter>
|
|
289
|
+
</DialogContent>
|
|
290
|
+
</Dialog>
|
|
291
|
+
)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return (
|
|
295
|
+
<div className="space-y-8">
|
|
296
|
+
<div className="text-center">
|
|
297
|
+
<h3 className="mb-2 font-medium text-white">
|
|
298
|
+
Dialog Variants with Cleanup
|
|
299
|
+
</h3>
|
|
300
|
+
<p className="text-sm text-white/60">
|
|
301
|
+
Different dialog variants with React 18 compatibility fixes
|
|
302
|
+
</p>
|
|
303
|
+
</div>
|
|
304
|
+
|
|
305
|
+
<div className="flex flex-wrap justify-center gap-4">
|
|
306
|
+
<DialogWithCleanupVariant
|
|
307
|
+
variant="neutral"
|
|
308
|
+
title="Neutral Dialog"
|
|
309
|
+
description="This is a neutral dialog with standard styling."
|
|
310
|
+
>
|
|
311
|
+
<p className="text-sm text-white/80">
|
|
312
|
+
Neutral dialogs are perfect for general information, settings, or
|
|
313
|
+
any content that doesn't require specific emotional context.
|
|
314
|
+
</p>
|
|
315
|
+
</DialogWithCleanupVariant>
|
|
316
|
+
|
|
317
|
+
<DialogWithCleanupVariant
|
|
318
|
+
variant="positive"
|
|
319
|
+
title="Success Dialog"
|
|
320
|
+
description="Operation completed successfully!"
|
|
321
|
+
>
|
|
322
|
+
<div className="mb-2 flex items-center gap-2">
|
|
323
|
+
<TickIcon className="h-5 w-5 text-green-400" />
|
|
324
|
+
<span className="font-medium text-green-400">Success!</span>
|
|
325
|
+
</div>
|
|
326
|
+
<p className="text-sm text-white/80">
|
|
327
|
+
Your changes have been saved and are now live. Users will see the
|
|
328
|
+
updates immediately.
|
|
329
|
+
</p>
|
|
330
|
+
</DialogWithCleanupVariant>
|
|
331
|
+
|
|
332
|
+
<DialogWithCleanupVariant
|
|
333
|
+
variant="warning"
|
|
334
|
+
title="Warning Dialog"
|
|
335
|
+
description="Please review the following before proceeding."
|
|
336
|
+
>
|
|
337
|
+
<div className="rounded-lg border border-yellow-500/20 bg-yellow-500/10 p-3">
|
|
338
|
+
<div className="mb-2 flex items-center gap-2">
|
|
339
|
+
<AlertIcon className="h-4 w-4 text-yellow-400" />
|
|
340
|
+
<span className="font-medium text-yellow-400">Warning</span>
|
|
341
|
+
</div>
|
|
342
|
+
<p className="text-sm text-yellow-200">
|
|
343
|
+
This action will modify existing data. Make sure you have a
|
|
344
|
+
backup before continuing.
|
|
345
|
+
</p>
|
|
346
|
+
</div>
|
|
347
|
+
</DialogWithCleanupVariant>
|
|
348
|
+
|
|
349
|
+
<DialogWithCleanupVariant
|
|
350
|
+
variant="negative"
|
|
351
|
+
title="Error Dialog"
|
|
352
|
+
description="An error occurred that requires your attention."
|
|
353
|
+
>
|
|
354
|
+
<div className="rounded-lg border border-red-500/20 bg-red-500/10 p-3">
|
|
355
|
+
<div className="mb-2 flex items-center gap-2">
|
|
356
|
+
<AlertIcon className="h-4 w-4 text-red-400" />
|
|
357
|
+
<span className="font-medium text-red-400">Error</span>
|
|
358
|
+
</div>
|
|
359
|
+
<p className="text-sm text-red-200">
|
|
360
|
+
Failed to save changes. Please check your connection and try
|
|
361
|
+
again.
|
|
362
|
+
</p>
|
|
363
|
+
</div>
|
|
364
|
+
</DialogWithCleanupVariant>
|
|
365
|
+
|
|
366
|
+
<DialogWithCleanupVariant
|
|
367
|
+
variant="info"
|
|
368
|
+
title="Information Dialog"
|
|
369
|
+
description="Here's some important information for you."
|
|
370
|
+
>
|
|
371
|
+
<div className="rounded-lg border border-blue-500/20 bg-blue-500/10 p-3">
|
|
372
|
+
<div className="mb-2 flex items-center gap-2">
|
|
373
|
+
<LightBulbSimpleIcon className="h-4 w-4 text-blue-400" />
|
|
374
|
+
<span className="font-medium text-blue-400">Information</span>
|
|
375
|
+
</div>
|
|
376
|
+
<p className="text-sm text-blue-200">
|
|
377
|
+
The new features will be available starting next week. Check
|
|
378
|
+
your email for detailed release notes.
|
|
379
|
+
</p>
|
|
380
|
+
</div>
|
|
381
|
+
</DialogWithCleanupVariant>
|
|
382
|
+
</div>
|
|
383
|
+
</div>
|
|
384
|
+
)
|
|
385
|
+
},
|
|
386
|
+
parameters: {
|
|
387
|
+
docs: {
|
|
388
|
+
description: {
|
|
389
|
+
story:
|
|
390
|
+
"Different dialog variants with useDialogCleanup hook for React 18 compatibility.",
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// 3. Nested Modal with Cleanup
|
|
397
|
+
export const NestedModalWithCleanup: Story = {
|
|
398
|
+
render: () => {
|
|
399
|
+
const NestedDialogComponent = () => {
|
|
400
|
+
const { handleDialogClose } = useDialogCleanup({ threshold: 150 })
|
|
401
|
+
const [isEditOpen, setIsEditOpen] = useState(false)
|
|
402
|
+
const [isDeleteOpen, setIsDeleteOpen] = useState(false)
|
|
403
|
+
|
|
404
|
+
const handleEditClose = () => {
|
|
405
|
+
handleDialogClose()
|
|
406
|
+
setIsEditOpen(false)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const handleDeleteClose = () => {
|
|
410
|
+
handleDialogClose()
|
|
411
|
+
setIsDeleteOpen(false)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const handleDelete = () => {
|
|
415
|
+
console.log("User deleted")
|
|
416
|
+
handleDeleteClose()
|
|
417
|
+
handleEditClose()
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return (
|
|
421
|
+
<>
|
|
422
|
+
<Dialog open={isEditOpen} onOpenChange={setIsEditOpen}>
|
|
423
|
+
<DialogTrigger asChild>
|
|
424
|
+
<Button className="gap-2">
|
|
425
|
+
<EditBigIcon className="h-4 w-4" />
|
|
426
|
+
Edit with Cleanup
|
|
427
|
+
</Button>
|
|
428
|
+
</DialogTrigger>
|
|
429
|
+
<DialogContent
|
|
430
|
+
className="max-w-md"
|
|
431
|
+
//@ts-expect-error onEscapeKeyDown available in Radix v2.0.0
|
|
432
|
+
onEscapeKeyDown={handleEditClose}
|
|
433
|
+
onPointerDownOutside={handleEditClose}
|
|
434
|
+
>
|
|
435
|
+
<DialogHeader>
|
|
436
|
+
<DialogTitle>Edit User Profile</DialogTitle>
|
|
437
|
+
<DialogDescription>
|
|
438
|
+
Update user information or delete the account.
|
|
439
|
+
</DialogDescription>
|
|
440
|
+
</DialogHeader>
|
|
441
|
+
|
|
442
|
+
<div className="space-y-4">
|
|
443
|
+
<Input placeholder="User name" />
|
|
444
|
+
<Input placeholder="Email address" type="email" />
|
|
445
|
+
<Textarea placeholder="Bio" rows={3} />
|
|
446
|
+
</div>
|
|
447
|
+
|
|
448
|
+
<DialogFooter className="flex-col space-y-2 sm:flex-col sm:space-y-2 sm:space-x-0">
|
|
449
|
+
<div className="flex gap-2 sm:order-2">
|
|
450
|
+
<Button
|
|
451
|
+
variant="outline"
|
|
452
|
+
onClick={handleEditClose}
|
|
453
|
+
className="flex-1"
|
|
454
|
+
>
|
|
455
|
+
Cancel
|
|
456
|
+
</Button>
|
|
457
|
+
<Button className="flex-1">Save Changes</Button>
|
|
458
|
+
</div>
|
|
459
|
+
<div className="sm:order-1">
|
|
460
|
+
<Button
|
|
461
|
+
size="sm"
|
|
462
|
+
className="mb-4 w-full gap-2"
|
|
463
|
+
onClick={() => setIsDeleteOpen(true)}
|
|
464
|
+
>
|
|
465
|
+
<TrashIcon className="h-4 w-4" />
|
|
466
|
+
Delete Account
|
|
467
|
+
</Button>
|
|
468
|
+
</div>
|
|
469
|
+
</DialogFooter>
|
|
470
|
+
</DialogContent>
|
|
471
|
+
</Dialog>
|
|
472
|
+
|
|
473
|
+
<Dialog open={isDeleteOpen} onOpenChange={setIsDeleteOpen}>
|
|
474
|
+
<DialogContent
|
|
475
|
+
variant="negative"
|
|
476
|
+
classes={{
|
|
477
|
+
root: "max-w-sm",
|
|
478
|
+
overlay: "z-60",
|
|
479
|
+
content: "z-70",
|
|
480
|
+
}}
|
|
481
|
+
//@ts-expect-error onEscapeKeyDown available in Radix v2.0.0
|
|
482
|
+
onEscapeKeyDown={handleDeleteClose}
|
|
483
|
+
onPointerDownOutside={handleDeleteClose}
|
|
484
|
+
>
|
|
485
|
+
<DialogHeader>
|
|
486
|
+
<DialogTitle className="flex items-center gap-2">
|
|
487
|
+
<AlertIcon className="h-5 w-5 text-red-400" />
|
|
488
|
+
Delete Account
|
|
489
|
+
</DialogTitle>
|
|
490
|
+
<DialogDescription>
|
|
491
|
+
This action cannot be undone.
|
|
492
|
+
</DialogDescription>
|
|
493
|
+
</DialogHeader>
|
|
494
|
+
|
|
495
|
+
<div className="py-4">
|
|
496
|
+
<div className="rounded-lg border border-red-500/20 bg-red-500/10 p-3">
|
|
497
|
+
<p className="text-sm text-red-200">
|
|
498
|
+
Are you absolutely sure you want to delete this account?
|
|
499
|
+
This will permanently remove all associated data.
|
|
500
|
+
</p>
|
|
501
|
+
</div>
|
|
502
|
+
</div>
|
|
503
|
+
|
|
504
|
+
<DialogFooter>
|
|
505
|
+
<Button variant="outline" onClick={handleDeleteClose}>
|
|
506
|
+
Cancel
|
|
507
|
+
</Button>
|
|
508
|
+
<Button onClick={handleDelete} className="gap-2">
|
|
509
|
+
<TrashIcon className="h-4 w-4" />
|
|
510
|
+
Delete Forever
|
|
511
|
+
</Button>
|
|
512
|
+
</DialogFooter>
|
|
513
|
+
</DialogContent>
|
|
514
|
+
</Dialog>
|
|
515
|
+
</>
|
|
516
|
+
)
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
return (
|
|
520
|
+
<div className="space-y-8">
|
|
521
|
+
<div className="text-center">
|
|
522
|
+
<h3 className="mb-2 font-medium text-white">
|
|
523
|
+
Nested Modal with Cleanup
|
|
524
|
+
</h3>
|
|
525
|
+
<p className="text-sm text-white/60">
|
|
526
|
+
Modal-on-modal with proper cleanup handling
|
|
527
|
+
</p>
|
|
528
|
+
</div>
|
|
529
|
+
<div className="flex justify-center">
|
|
530
|
+
<NestedDialogComponent />
|
|
531
|
+
</div>
|
|
532
|
+
<div className="text-center">
|
|
533
|
+
<div className="inline-block max-w-lg rounded-lg border border-white/10 bg-white/5 p-4">
|
|
534
|
+
<h4 className="mb-2 text-sm font-medium text-white">
|
|
535
|
+
Modal Stacking
|
|
536
|
+
</h4>
|
|
537
|
+
<p className="text-xs leading-relaxed text-white/60">
|
|
538
|
+
This example demonstrates proper modal stacking where a delete
|
|
539
|
+
confirmation dialog opens on top of an edit form dialog with
|
|
540
|
+
proper cleanup handling for React 18.
|
|
541
|
+
</p>
|
|
542
|
+
</div>
|
|
543
|
+
</div>
|
|
544
|
+
</div>
|
|
545
|
+
)
|
|
546
|
+
},
|
|
547
|
+
parameters: {
|
|
548
|
+
docs: {
|
|
549
|
+
description: {
|
|
550
|
+
story:
|
|
551
|
+
"Nested modal example with useDialogCleanup hook to handle multiple modal layers properly.",
|
|
552
|
+
},
|
|
553
|
+
},
|
|
554
|
+
},
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// 4. Form Dialog with Cleanup
|
|
558
|
+
export const FormDialog: Story = {
|
|
559
|
+
render: () => {
|
|
560
|
+
const FormDialogComponent = () => {
|
|
561
|
+
const { handleDialogClose } = useDialogCleanup({ threshold: 100 })
|
|
562
|
+
const [formData, setFormData] = useState({
|
|
563
|
+
name: "",
|
|
564
|
+
email: "",
|
|
565
|
+
message: "",
|
|
566
|
+
newsletter: false,
|
|
567
|
+
})
|
|
568
|
+
|
|
569
|
+
const handleClose = () => {
|
|
570
|
+
handleDialogClose()
|
|
571
|
+
// Reset form data on close
|
|
572
|
+
setFormData({
|
|
573
|
+
name: "",
|
|
574
|
+
email: "",
|
|
575
|
+
message: "",
|
|
576
|
+
newsletter: false,
|
|
577
|
+
})
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return (
|
|
581
|
+
<Dialog>
|
|
582
|
+
<DialogTrigger asChild>
|
|
583
|
+
<Button className="gap-2">
|
|
584
|
+
<EditBigIcon className="h-4 w-4" />
|
|
585
|
+
Contact Form
|
|
586
|
+
</Button>
|
|
587
|
+
</DialogTrigger>
|
|
588
|
+
<DialogContent
|
|
589
|
+
className="max-w-md"
|
|
590
|
+
//@ts-expect-error onEscapeKeyDown available in Radix v2.0.0
|
|
591
|
+
onEscapeKeyDown={handleClose}
|
|
592
|
+
onPointerDownOutside={handleClose}
|
|
593
|
+
>
|
|
594
|
+
<DialogHeader>
|
|
595
|
+
<DialogTitle>Contact Us</DialogTitle>
|
|
596
|
+
<DialogDescription>
|
|
597
|
+
Send us a message and we'll get back to you soon.
|
|
598
|
+
</DialogDescription>
|
|
599
|
+
</DialogHeader>
|
|
600
|
+
|
|
601
|
+
<div className="space-y-4">
|
|
602
|
+
<div className="space-y-2">
|
|
603
|
+
<Label htmlFor="name">Name</Label>
|
|
604
|
+
<Input
|
|
605
|
+
id="name"
|
|
606
|
+
placeholder="Your name"
|
|
607
|
+
value={formData.name}
|
|
608
|
+
onChange={(e) =>
|
|
609
|
+
setFormData((prev) => ({ ...prev, name: e.target.value }))
|
|
610
|
+
}
|
|
611
|
+
/>
|
|
612
|
+
</div>
|
|
613
|
+
|
|
614
|
+
<div className="space-y-2">
|
|
615
|
+
<Label htmlFor="email">Email</Label>
|
|
616
|
+
<Input
|
|
617
|
+
id="email"
|
|
618
|
+
type="email"
|
|
619
|
+
placeholder="your.email@example.com"
|
|
620
|
+
value={formData.email}
|
|
621
|
+
onChange={(e) =>
|
|
622
|
+
setFormData((prev) => ({
|
|
623
|
+
...prev,
|
|
624
|
+
email: e.target.value,
|
|
625
|
+
}))
|
|
626
|
+
}
|
|
627
|
+
/>
|
|
628
|
+
</div>
|
|
629
|
+
|
|
630
|
+
<div className="space-y-2">
|
|
631
|
+
<Label htmlFor="message">Message</Label>
|
|
632
|
+
<Textarea
|
|
633
|
+
id="message"
|
|
634
|
+
placeholder="Your message..."
|
|
635
|
+
rows={4}
|
|
636
|
+
value={formData.message}
|
|
637
|
+
onChange={(e) =>
|
|
638
|
+
setFormData((prev) => ({
|
|
639
|
+
...prev,
|
|
640
|
+
message: e.target.value,
|
|
641
|
+
}))
|
|
642
|
+
}
|
|
643
|
+
/>
|
|
644
|
+
</div>
|
|
645
|
+
|
|
646
|
+
<div className="flex items-center space-x-2">
|
|
647
|
+
<Checkbox
|
|
648
|
+
id="newsletter"
|
|
649
|
+
checked={formData.newsletter}
|
|
650
|
+
onCheckedChange={(checked) =>
|
|
651
|
+
setFormData((prev) => ({
|
|
652
|
+
...prev,
|
|
653
|
+
newsletter: !!checked,
|
|
654
|
+
}))
|
|
655
|
+
}
|
|
656
|
+
/>
|
|
657
|
+
<Label htmlFor="newsletter" className="text-sm">
|
|
658
|
+
Subscribe to newsletter
|
|
659
|
+
</Label>
|
|
660
|
+
</div>
|
|
661
|
+
</div>
|
|
662
|
+
|
|
663
|
+
<DialogFooter>
|
|
664
|
+
<DialogClose asChild>
|
|
665
|
+
<Button variant="outline" onClick={handleClose}>
|
|
666
|
+
Cancel
|
|
667
|
+
</Button>
|
|
668
|
+
</DialogClose>
|
|
669
|
+
<Button
|
|
670
|
+
disabled={
|
|
671
|
+
!formData.name || !formData.email || !formData.message
|
|
672
|
+
}
|
|
673
|
+
onClick={() => {
|
|
674
|
+
console.log("Form submitted:", formData)
|
|
675
|
+
handleClose()
|
|
676
|
+
}}
|
|
677
|
+
>
|
|
678
|
+
Send Message
|
|
679
|
+
</Button>
|
|
680
|
+
</DialogFooter>
|
|
681
|
+
</DialogContent>
|
|
682
|
+
</Dialog>
|
|
683
|
+
)
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
return (
|
|
687
|
+
<div className="space-y-8">
|
|
688
|
+
<div className="text-center">
|
|
689
|
+
<h3 className="mb-2 font-medium text-white">Form Dialog</h3>
|
|
690
|
+
<p className="text-sm text-white/60">
|
|
691
|
+
Dialog containing form elements with cleanup handling
|
|
692
|
+
</p>
|
|
693
|
+
</div>
|
|
694
|
+
<div className="flex justify-center">
|
|
695
|
+
<FormDialogComponent />
|
|
696
|
+
</div>
|
|
697
|
+
</div>
|
|
698
|
+
)
|
|
699
|
+
},
|
|
700
|
+
parameters: {
|
|
701
|
+
docs: {
|
|
702
|
+
description: {
|
|
703
|
+
story:
|
|
704
|
+
"Form dialog with validation and cleanup handling for React 18 compatibility.",
|
|
705
|
+
},
|
|
706
|
+
},
|
|
707
|
+
},
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// 5. Overlay Variations
|
|
711
|
+
export const OverlayVariations: Story = {
|
|
712
|
+
render: () => {
|
|
713
|
+
const OverlayDialog = ({
|
|
714
|
+
opacity,
|
|
715
|
+
glass,
|
|
716
|
+
noise,
|
|
717
|
+
title,
|
|
718
|
+
description,
|
|
719
|
+
}: any) => {
|
|
720
|
+
const { handleDialogClose } = useDialogCleanup({ threshold: 100 })
|
|
721
|
+
|
|
722
|
+
return (
|
|
723
|
+
<Dialog>
|
|
724
|
+
<DialogTrigger asChild>
|
|
725
|
+
<Button variant="outline">{title}</Button>
|
|
726
|
+
</DialogTrigger>
|
|
727
|
+
<DialogContent opacity={opacity} glass={glass} noise={noise}>
|
|
728
|
+
<DialogHeader>
|
|
729
|
+
<DialogTitle>{title}</DialogTitle>
|
|
730
|
+
<DialogDescription>{description}</DialogDescription>
|
|
731
|
+
</DialogHeader>
|
|
732
|
+
<div className="py-4">
|
|
733
|
+
<div className="grid grid-cols-2 gap-2 text-xs text-white/60">
|
|
734
|
+
<div>
|
|
735
|
+
Opacity:{" "}
|
|
736
|
+
<span className="text-white">{opacity || "default"}</span>
|
|
737
|
+
</div>
|
|
738
|
+
<div>
|
|
739
|
+
Glass:{" "}
|
|
740
|
+
<span className="text-white">{glass || "default"}</span>
|
|
741
|
+
</div>
|
|
742
|
+
<div>
|
|
743
|
+
Noise: <span className="text-white">{noise || "none"}</span>
|
|
744
|
+
</div>
|
|
745
|
+
</div>
|
|
746
|
+
</div>
|
|
747
|
+
<DialogFooter>
|
|
748
|
+
<DialogClose asChild>
|
|
749
|
+
<Button onClick={handleDialogClose}>Close</Button>
|
|
750
|
+
</DialogClose>
|
|
751
|
+
</DialogFooter>
|
|
752
|
+
</DialogContent>
|
|
753
|
+
</Dialog>
|
|
754
|
+
)
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
return (
|
|
758
|
+
<div className="space-y-8">
|
|
759
|
+
<div className="text-center">
|
|
760
|
+
<h3 className="mb-2 font-medium text-white">Overlay Variations</h3>
|
|
761
|
+
<p className="text-sm text-white/60">
|
|
762
|
+
Different overlay effects with cleanup handling
|
|
763
|
+
</p>
|
|
764
|
+
</div>
|
|
765
|
+
|
|
766
|
+
<div className="grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4">
|
|
767
|
+
<OverlayDialog
|
|
768
|
+
opacity="low"
|
|
769
|
+
title="Low Opacity"
|
|
770
|
+
description="Subtle background dimming (40%)"
|
|
771
|
+
/>
|
|
772
|
+
<OverlayDialog
|
|
773
|
+
opacity="medium"
|
|
774
|
+
title="Medium Opacity"
|
|
775
|
+
description="Balanced background dimming (60%)"
|
|
776
|
+
/>
|
|
777
|
+
<OverlayDialog
|
|
778
|
+
opacity="high"
|
|
779
|
+
title="High Opacity"
|
|
780
|
+
description="Strong background dimming (80%)"
|
|
781
|
+
/>
|
|
782
|
+
<OverlayDialog
|
|
783
|
+
opacity="none"
|
|
784
|
+
title="Full Opacity"
|
|
785
|
+
description="Complete background coverage (100%)"
|
|
786
|
+
/>
|
|
787
|
+
<OverlayDialog
|
|
788
|
+
glass="low"
|
|
789
|
+
title="Low Glass"
|
|
790
|
+
description="Subtle backdrop blur effect"
|
|
791
|
+
/>
|
|
792
|
+
<OverlayDialog
|
|
793
|
+
glass="medium"
|
|
794
|
+
title="Medium Glass"
|
|
795
|
+
description="Balanced backdrop blur effect"
|
|
796
|
+
/>
|
|
797
|
+
<OverlayDialog
|
|
798
|
+
glass="high"
|
|
799
|
+
title="High Glass"
|
|
800
|
+
description="Strong backdrop blur effect"
|
|
801
|
+
/>
|
|
802
|
+
<OverlayDialog
|
|
803
|
+
noise="low"
|
|
804
|
+
title="Low Noise"
|
|
805
|
+
description="Subtle texture pattern"
|
|
806
|
+
/>
|
|
807
|
+
<OverlayDialog
|
|
808
|
+
noise="medium"
|
|
809
|
+
title="Medium Noise"
|
|
810
|
+
description="Balanced texture pattern"
|
|
811
|
+
/>
|
|
812
|
+
<OverlayDialog
|
|
813
|
+
noise="high"
|
|
814
|
+
title="High Noise"
|
|
815
|
+
description="Strong texture pattern"
|
|
816
|
+
/>
|
|
817
|
+
<OverlayDialog
|
|
818
|
+
opacity="high"
|
|
819
|
+
glass="high"
|
|
820
|
+
title="High + Glass"
|
|
821
|
+
description="Maximum focus with glass effect"
|
|
822
|
+
/>
|
|
823
|
+
<OverlayDialog
|
|
824
|
+
opacity="medium"
|
|
825
|
+
glass="medium"
|
|
826
|
+
noise="low"
|
|
827
|
+
title="Balanced Mix"
|
|
828
|
+
description="Balanced combination of effects"
|
|
829
|
+
/>
|
|
830
|
+
</div>
|
|
831
|
+
</div>
|
|
832
|
+
)
|
|
833
|
+
},
|
|
834
|
+
parameters: {
|
|
835
|
+
docs: {
|
|
836
|
+
description: {
|
|
837
|
+
story:
|
|
838
|
+
"Showcase of different overlay configurations including opacity, glass, and noise effects.",
|
|
839
|
+
},
|
|
840
|
+
},
|
|
841
|
+
},
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// 6. Accessibility Example
|
|
845
|
+
export const AccessibilityExample: Story = {
|
|
846
|
+
render: () => {
|
|
847
|
+
const AccessibleDialog = () => {
|
|
848
|
+
const { handleDialogClose } = useDialogCleanup({ threshold: 100 })
|
|
849
|
+
|
|
850
|
+
return (
|
|
851
|
+
<Dialog>
|
|
852
|
+
<DialogTrigger asChild>
|
|
853
|
+
<Button>Accessible Dialog Demo</Button>
|
|
854
|
+
</DialogTrigger>
|
|
855
|
+
<DialogContent
|
|
856
|
+
//@ts-expect-error onEscapeKeyDown available in Radix v2.0.0
|
|
857
|
+
onEscapeKeyDown={handleDialogClose}
|
|
858
|
+
onPointerDownOutside={handleDialogClose}
|
|
859
|
+
>
|
|
860
|
+
<DialogHeader>
|
|
861
|
+
<DialogTitle>Accessibility Features</DialogTitle>
|
|
862
|
+
<DialogDescription>
|
|
863
|
+
This dialog demonstrates proper accessibility implementation.
|
|
864
|
+
</DialogDescription>
|
|
865
|
+
</DialogHeader>
|
|
866
|
+
|
|
867
|
+
<div className="space-y-4">
|
|
868
|
+
<div className="rounded-lg border border-white/10 bg-white/5 p-4">
|
|
869
|
+
<h4 className="mb-2 font-medium text-white">
|
|
870
|
+
Keyboard Navigation
|
|
871
|
+
</h4>
|
|
872
|
+
<ul className="space-y-1 text-sm text-white/80">
|
|
873
|
+
<li>
|
|
874
|
+
• <kbd className="rounded bg-white/10 px-1">Tab</kbd> -
|
|
875
|
+
Navigate between elements
|
|
876
|
+
</li>
|
|
877
|
+
<li>
|
|
878
|
+
• <kbd className="rounded bg-white/10 px-1">Escape</kbd> -
|
|
879
|
+
Close dialog
|
|
880
|
+
</li>
|
|
881
|
+
<li>
|
|
882
|
+
• <kbd className="rounded bg-white/10 px-1">Enter</kbd> -
|
|
883
|
+
Activate buttons
|
|
884
|
+
</li>
|
|
885
|
+
<li>
|
|
886
|
+
• <kbd className="rounded bg-white/10 px-1">Space</kbd> -
|
|
887
|
+
Activate buttons
|
|
888
|
+
</li>
|
|
889
|
+
</ul>
|
|
890
|
+
</div>
|
|
891
|
+
|
|
892
|
+
<div className="rounded-lg border border-white/10 bg-white/5 p-4">
|
|
893
|
+
<h4 className="mb-2 font-medium text-white">
|
|
894
|
+
Screen Reader Support
|
|
895
|
+
</h4>
|
|
896
|
+
<ul className="space-y-1 text-sm text-white/80">
|
|
897
|
+
<li>• Proper ARIA labels and roles</li>
|
|
898
|
+
<li>• Focus management and trapping</li>
|
|
899
|
+
<li>• Descriptive close button</li>
|
|
900
|
+
<li>• Semantic heading structure</li>
|
|
901
|
+
</ul>
|
|
902
|
+
</div>
|
|
903
|
+
|
|
904
|
+
<div className="rounded-lg border border-white/10 bg-white/5 p-4">
|
|
905
|
+
<h4 className="mb-2 font-medium text-white">
|
|
906
|
+
React 18 Compatibility
|
|
907
|
+
</h4>
|
|
908
|
+
<ul className="space-y-1 text-sm text-white/80">
|
|
909
|
+
<li>• Cleanup hook prevents pointer-events issues</li>
|
|
910
|
+
<li>• Proper modal stacking support</li>
|
|
911
|
+
<li>• Body scroll restoration</li>
|
|
912
|
+
<li>• Focus restoration on close</li>
|
|
913
|
+
</ul>
|
|
914
|
+
</div>
|
|
915
|
+
</div>
|
|
916
|
+
|
|
917
|
+
<DialogFooter>
|
|
918
|
+
<DialogClose asChild>
|
|
919
|
+
<Button onClick={handleDialogClose}>Close Dialog</Button>
|
|
920
|
+
</DialogClose>
|
|
921
|
+
</DialogFooter>
|
|
922
|
+
</DialogContent>
|
|
923
|
+
</Dialog>
|
|
924
|
+
)
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
return (
|
|
928
|
+
<div className="space-y-8">
|
|
929
|
+
<div className="text-center">
|
|
930
|
+
<h3 className="mb-2 font-medium text-white">
|
|
931
|
+
Accessibility Features
|
|
932
|
+
</h3>
|
|
933
|
+
<p className="text-sm text-white/60">
|
|
934
|
+
Dialog with comprehensive accessibility and React 18 compatibility
|
|
935
|
+
</p>
|
|
936
|
+
</div>
|
|
937
|
+
<div className="flex justify-center">
|
|
938
|
+
<AccessibleDialog />
|
|
939
|
+
</div>
|
|
940
|
+
<div className="text-center">
|
|
941
|
+
<div className="inline-block max-w-lg rounded-lg border border-white/10 bg-white/5 p-4">
|
|
942
|
+
<h4 className="mb-2 text-sm font-medium text-white">
|
|
943
|
+
Accessibility Best Practices
|
|
944
|
+
</h4>
|
|
945
|
+
<p className="text-xs leading-relaxed text-white/60">
|
|
946
|
+
The Dialog component follows WCAG guidelines with proper focus
|
|
947
|
+
management, keyboard navigation, screen reader support, semantic
|
|
948
|
+
HTML structure, and React 18 compatibility fixes.
|
|
949
|
+
</p>
|
|
950
|
+
</div>
|
|
951
|
+
</div>
|
|
952
|
+
</div>
|
|
953
|
+
)
|
|
954
|
+
},
|
|
955
|
+
parameters: {
|
|
956
|
+
docs: {
|
|
957
|
+
description: {
|
|
958
|
+
story:
|
|
959
|
+
"Comprehensive accessibility example with React 18 compatibility features.",
|
|
960
|
+
},
|
|
961
|
+
},
|
|
962
|
+
},
|
|
963
|
+
}
|