@sproutsocial/seeds-react-modal 1.1.0 → 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.
Files changed (45) hide show
  1. package/.turbo/turbo-build.log +23 -23
  2. package/CHANGELOG.md +182 -0
  3. package/dist/ModalAction-BB7qJtQj.d.mts +445 -0
  4. package/dist/ModalAction-BB7qJtQj.d.ts +445 -0
  5. package/dist/esm/chunk-ETVICNHP.js +1353 -0
  6. package/dist/esm/chunk-ETVICNHP.js.map +1 -0
  7. package/dist/esm/index.js +11 -11
  8. package/dist/esm/index.js.map +1 -1
  9. package/dist/esm/v2/index.js +12 -20
  10. package/dist/index.d.mts +2 -1
  11. package/dist/index.d.ts +2 -1
  12. package/dist/index.js +1154 -546
  13. package/dist/index.js.map +1 -1
  14. package/dist/v2/index.d.mts +4 -11
  15. package/dist/v2/index.d.ts +4 -11
  16. package/dist/v2/index.js +1152 -545
  17. package/dist/v2/index.js.map +1 -1
  18. package/package.json +8 -7
  19. package/src/index.ts +11 -12
  20. package/src/shared/constants.ts +11 -7
  21. package/src/v2/Modal.tsx +169 -0
  22. package/src/v2/ModalTypes.ts +343 -0
  23. package/src/v2/ModalV2.stories.tsx +413 -128
  24. package/src/v2/MotionConfig.ts +185 -0
  25. package/src/v2/components/ModalAction.tsx +94 -0
  26. package/src/v2/components/ModalBody.tsx +54 -0
  27. package/src/v2/components/ModalCloseWrapper.tsx +35 -0
  28. package/src/v2/components/ModalContent.tsx +288 -11
  29. package/src/v2/components/ModalDescription.tsx +14 -2
  30. package/src/v2/components/ModalFooter.tsx +94 -13
  31. package/src/v2/components/ModalHeader.tsx +77 -34
  32. package/src/v2/components/ModalOverlay.tsx +52 -0
  33. package/src/v2/components/ModalRail.tsx +35 -99
  34. package/src/v2/components/index.ts +11 -7
  35. package/src/v2/index.ts +13 -16
  36. package/dist/ModalRail-5PeilhW7.d.mts +0 -186
  37. package/dist/ModalRail-5PeilhW7.d.ts +0 -186
  38. package/dist/esm/chunk-4ITF4DBY.js +0 -717
  39. package/dist/esm/chunk-4ITF4DBY.js.map +0 -1
  40. package/src/v2/ModalV2.tsx +0 -388
  41. package/src/v2/ModalV2Styles.tsx +0 -180
  42. package/src/v2/ModalV2Types.ts +0 -154
  43. package/src/v2/components/ModalClose.tsx +0 -29
  44. package/src/v2/components/ModalCloseButton.tsx +0 -100
  45. package/src/v2/components/ModalTrigger.tsx +0 -39
@@ -1,154 +0,0 @@
1
- import * as React from "react";
2
- import * as Dialog from "@radix-ui/react-dialog";
3
- import type {
4
- TypeBoxProps,
5
- TypeContainerProps,
6
- } from "@sproutsocial/seeds-react-box";
7
- import type { TypeButtonProps } from "@sproutsocial/seeds-react-button";
8
- import type { TypeIconName } from "@sproutsocial/seeds-react-icon";
9
-
10
- export interface TypeModalV2TriggerProps extends TypeButtonProps {
11
- /** The content to display inside the trigger button */
12
- children: React.ReactNode;
13
- /** Custom click handler - will be called before the modal opens */
14
- onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
15
- /** Use asChild to render a custom trigger element */
16
- asChild?: boolean;
17
- }
18
-
19
- export interface TypeModalV2CloseButtonProps
20
- extends Omit<TypeButtonProps, "children" | "size"> {
21
- children?: React.ReactNode;
22
- /** Custom click handler - will be called before the modal closes */
23
- onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
24
- /** Use asChild to render a custom close element */
25
- asChild?: boolean;
26
- /** aria-label for modal close button */
27
- closeButtonLabel?: string;
28
- /** Size of the close button in pixels */
29
- size?: number;
30
- /** Position type - absolute (outside modal) or relative (inside modal) */
31
- position?: "absolute" | "relative";
32
- /** Which side to position the button on (for absolute positioning) */
33
- side?: "right" | "left";
34
- /** Offset from the modal edge in pixels (for absolute positioning) */
35
- offset?: number;
36
- }
37
-
38
- export interface TypeModalV2HeaderProps extends TypeBoxProps {
39
- title?: string;
40
- subtitle?: string;
41
-
42
- /** Passing children will override the default modal header */
43
- children?: React.ReactNode;
44
-
45
- /** Additional props for the Dialog.Title when title is provided */
46
- titleProps?: Omit<
47
- React.ComponentPropsWithoutRef<typeof Dialog.Title>,
48
- "asChild" | "children"
49
- >;
50
-
51
- /** Additional props for the Dialog.Description when subtitle is provided */
52
- subtitleProps?: Omit<
53
- React.ComponentPropsWithoutRef<typeof Dialog.Description>,
54
- "asChild" | "children"
55
- >;
56
-
57
- /** Opt-in inline close inside header; default is floating rail */
58
- showInlineClose?: boolean;
59
- }
60
-
61
- export interface TypeModalV2FooterProps extends TypeBoxProps {
62
- bg?: string;
63
- children: React.ReactNode;
64
- }
65
-
66
- export interface TypeModalV2ContentProps extends TypeBoxProps {
67
- children?: React.ReactNode;
68
- }
69
-
70
- export interface TypeModalV2DescriptionProps extends TypeBoxProps {
71
- children: React.ReactNode;
72
- /** Additional props for the Dialog.Description */
73
- descriptionProps?: Omit<
74
- React.ComponentPropsWithoutRef<typeof Dialog.Description>,
75
- "asChild" | "children"
76
- >;
77
- }
78
-
79
- export interface TypeModalV2Props
80
- extends TypeContainerProps,
81
- Omit<React.ComponentPropsWithoutRef<"div">, keyof TypeContainerProps> {
82
- /** Controls whether the modal is open (controlled mode) */
83
- open?: boolean;
84
-
85
- /** Default open state for uncontrolled mode */
86
- defaultOpen?: boolean;
87
-
88
- /** body content of the modal */
89
- children: React.ReactNode;
90
-
91
- /** Callback when open state changes */
92
- onOpenChange?: (open: boolean) => void;
93
-
94
- /** The element that will trigger the modal when clicked.
95
- * Can be any React element like a button, link, or custom component. */
96
- modalTrigger?: React.ReactElement<any>;
97
-
98
- /** Enable draggable functionality using react-dnd */
99
- draggable?: boolean;
100
-
101
- /** Simplified API: Modal title (creates ModalHeader automatically) */
102
- title?: string;
103
-
104
- /** Simplified API: Modal subtitle (creates ModalHeader automatically) */
105
- subtitle?: string;
106
-
107
- /** Simplified API: Modal description (automatically wrapped in Dialog.Description) */
108
- description?: string;
109
-
110
- /** Modal size preset or custom width */
111
- size?: "small" | "medium" | "large" | "full" | string | number;
112
-
113
- /** Priority level that maps to z-index presets */
114
- priority?: "low" | "medium" | "high";
115
-
116
- /**
117
- * Custom attributes to be added to the modals container
118
- * Each key will be prepended with "data-" when rendered in the DOM
119
- */
120
- data?: Record<string, string | boolean | number>;
121
-
122
- /** Whether to show the background overlay (defaults to true) */
123
- showOverlay?: boolean;
124
-
125
- /** Optional quick actions to render on a modal side rail */
126
- actions?: TypeModalActionProps[];
127
-
128
- /** Optional props to customize the side rail position/size */
129
- railProps?: Partial<TypeModalRailProps>;
130
- }
131
-
132
- export type TypeModalRailProps = {
133
- side?: "right" | "left"; // default: "right"
134
- offset?: number; // px from card edge; default: 12
135
- gap?: number; // space between buttons; default: 12
136
- size?: number; // button square size; default: 44
137
- children?: React.ReactNode;
138
- };
139
-
140
- type ModalActionBase = Omit<
141
- React.ButtonHTMLAttributes<HTMLButtonElement>,
142
- "onClick"
143
- > & {
144
- /** Icon name from the Seeds icon set */
145
- iconName?: TypeIconName;
146
- /** Optional click handler; ignored for type "close" */
147
- onClick?: () => void;
148
- /** Accessible name for the action button */
149
- "aria-label": string;
150
- };
151
-
152
- export type TypeModalActionProps =
153
- | (ModalActionBase & { actionType: "close" }) // uses Dialog.Close
154
- | (ModalActionBase & { actionType?: "button" }); // regular button action
@@ -1,29 +0,0 @@
1
- import * as React from "react";
2
- import * as Dialog from "@radix-ui/react-dialog";
3
-
4
- export interface ModalCloseProps {
5
- children: React.ReactNode;
6
- onClick?: (e: React.MouseEvent) => void;
7
- asChild?: boolean;
8
- }
9
-
10
- /**
11
- * A component that closes the modal when clicked.
12
- * Uses asChild pattern like Radix primitives.
13
- */
14
- export const ModalClose = (props: ModalCloseProps) => {
15
- const { children, onClick, asChild = false, ...rest } = props;
16
-
17
- const handleClick = (e: React.MouseEvent) => {
18
- onClick?.(e);
19
- // Dialog.Close automatically handles closing
20
- };
21
-
22
- return (
23
- <Dialog.Close asChild={asChild} onClick={handleClick} {...rest}>
24
- {children}
25
- </Dialog.Close>
26
- );
27
- };
28
-
29
- ModalClose.displayName = "ModalClose";
@@ -1,100 +0,0 @@
1
- import * as React from "react";
2
- import * as Dialog from "@radix-ui/react-dialog";
3
- import styled from "styled-components";
4
- import Icon from "@sproutsocial/seeds-react-icon";
5
- import type { TypeModalV2CloseButtonProps } from "../ModalV2Types";
6
-
7
- const CloseButtonWrapper = styled.button<{
8
- size?: number;
9
- position?: "absolute" | "relative";
10
- side?: "right" | "left";
11
- offset?: number;
12
- }>`
13
- width: ${(p) => p.size || 44}px;
14
- height: ${(p) => p.size || 44}px;
15
- display: inline-grid;
16
- place-items: center;
17
- border-radius: 8px;
18
- border: none;
19
- background: rgba(22, 32, 32, 0.56);
20
- color: #ffffff;
21
- cursor: pointer;
22
- outline: none;
23
- transition: all 0.2s ease;
24
-
25
- ${(p) =>
26
- p.position === "absolute" &&
27
- `
28
- position: absolute;
29
- top: 0px;
30
- ${p.side || "right"}: ${p.offset || -48}px;
31
- z-index: 1;
32
- `}
33
-
34
- &:hover {
35
- background: rgba(22, 32, 32, 0.7);
36
- transform: translateY(-1px);
37
- }
38
-
39
- &:active {
40
- transform: translateY(0);
41
- }
42
-
43
- &:focus-visible {
44
- box-shadow: 0 0 0 2px #ffffff, 0 0 0 4px #205bc3;
45
- }
46
-
47
- &:disabled {
48
- opacity: 0.5;
49
- cursor: not-allowed;
50
- }
51
- `;
52
-
53
- export const ModalCloseButton = (props: TypeModalV2CloseButtonProps) => {
54
- const {
55
- children,
56
- onClick,
57
- asChild,
58
- closeButtonLabel = "Close modal",
59
- size = 44,
60
- position = "absolute",
61
- side = "right",
62
- offset = -48,
63
- ...rest
64
- } = props;
65
-
66
- const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
67
- onClick?.(e);
68
- // Dialog.Close automatically handles closing
69
- };
70
-
71
- if (asChild) {
72
- return (
73
- <Dialog.Close asChild>
74
- {React.cloneElement(children as React.ReactElement, {
75
- onClick: handleClick,
76
- ...rest,
77
- })}
78
- </Dialog.Close>
79
- );
80
- }
81
-
82
- return (
83
- <Dialog.Close asChild>
84
- <CloseButtonWrapper
85
- onClick={handleClick}
86
- size={size}
87
- position={position}
88
- side={side}
89
- offset={offset}
90
- aria-label={closeButtonLabel}
91
- title={closeButtonLabel}
92
- {...rest}
93
- >
94
- {children || <Icon name="x-outline" size="small" />}
95
- </CloseButtonWrapper>
96
- </Dialog.Close>
97
- );
98
- };
99
-
100
- ModalCloseButton.displayName = "ModalCloseButton";
@@ -1,39 +0,0 @@
1
- import * as React from "react";
2
- import * as Dialog from "@radix-ui/react-dialog";
3
- import Button from "@sproutsocial/seeds-react-button";
4
- import type { TypeModalV2TriggerProps } from "../ModalV2Types";
5
-
6
- /**
7
- * A trigger button that opens the modal when clicked.
8
- * Must be used inside a Modal component's Dialog.Root context.
9
- * Uses Seeds Button by default but supports asChild for custom elements.
10
- */
11
- export const ModalTrigger = (props: TypeModalV2TriggerProps) => {
12
- const { children, onClick, asChild, ...rest } = props;
13
-
14
- const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
15
- onClick?.(e);
16
- // Dialog.Trigger automatically handles modal opening
17
- };
18
-
19
- if (asChild) {
20
- return (
21
- <Dialog.Trigger asChild>
22
- {React.cloneElement(children as React.ReactElement, {
23
- onClick: handleClick,
24
- ...rest,
25
- })}
26
- </Dialog.Trigger>
27
- );
28
- }
29
-
30
- return (
31
- <Dialog.Trigger asChild>
32
- <Button onClick={handleClick} {...rest}>
33
- {children}
34
- </Button>
35
- </Dialog.Trigger>
36
- );
37
- };
38
-
39
- ModalTrigger.displayName = "ModalTrigger";