Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(modal): enhance modal component with multiple animation variants #81

Merged
merged 6 commits into from
Oct 20, 2024
Merged
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
33 changes: 32 additions & 1 deletion apps/www/app/playground/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import {
SelectSeparator,
selectAnimationVariants,
} from "ruru-ui/components/select";
import Modal, { ModalProvider } from "ruru-ui/components/modal";
import Modal, { ModalProvider, modalVariants } from "ruru-ui/components/modal";
import { Dropzone } from "ruru-ui/components/dropzone";
import AdvanceDropzone from "@/components/preview/dropzone/advanceDropzone";
import StackPlayground from "@/components/stackPlayground";
Expand Down Expand Up @@ -610,6 +610,37 @@ const Playground = () => {
</ModalProvider>
</Card>

{(Object.keys(modalVariants) as Array<keyof typeof modalVariants>).map(
(variantKey) => (
<Card key={variantKey}>
<ModalProvider>
<Modal.Trigger>Open {variantKey} Modal</Modal.Trigger>
<Modal animationVariant={variantKey}>
<Modal.Body>
<Modal.Header>
<Modal.Title>Create Username</Modal.Title>
<Modal.Subtitle>
Enter a unique name for your token to differentiate it
from other tokens and then select the scope.
</Modal.Subtitle>
</Modal.Header>
<Modal.Content>
<Input
label="username"
placeholder="enter your username."
/>
</Modal.Content>
</Modal.Body>
<Modal.Actions>
<Modal.Close variant="secondary">Cancel</Modal.Close>
<Modal.Action onClick={handleSubmit}>Submit</Modal.Action>
</Modal.Actions>
</Modal>
</ModalProvider>
</Card>
),
)}

<Card className="p-10">
<Dropzone onDrop={(acceptedFiles) => console.log(acceptedFiles)} />
</Card>
Expand Down
94 changes: 94 additions & 0 deletions apps/www/components/preview/Modal/modalAnimation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
"use client";

import React, { useState } from "react";
import { Stack } from "ruru-ui/components/stack";
import {
Select,
SelectGroup,
SelectValue,
SelectTrigger,
SelectContent,
SelectLabel,
SelectItem,
SelectSeparator,
} from "ruru-ui/components/select";
import Modal, { ModalProvider, modalVariants } from "ruru-ui/components/modal";
import { Input } from "ruru-ui/components/input";
import { Spinner } from "ruru-ui/components/spinner";

const ModalAnimation = (): JSX.Element => {
const [selectedVariant, setSelectedVariant] = useState<string>("default");
ruru-m07 marked this conversation as resolved.
Show resolved Hide resolved
const [submissionStatus, setSubmissionStatus] = useState<
"idle" | "loading" | "success" | "error"
>("idle");

const handleSubmit = async () => {
setSubmissionStatus("loading");
try {
// Your submit logic here
console.log(`Submitting with variant: ${selectedVariant}`);
// Simulate an API call or any async operation
await new Promise((resolve) => setTimeout(resolve, 1000));
setSubmissionStatus("success");
} catch (error) {
console.error("Submission failed:", error);
setSubmissionStatus("error");
}
};

return (
<Stack direction={"column"} justify={"center"} align={"center"} gap={20}>
<Select
onValueChange={(e) => setSelectedVariant(e)}
defaultValue="default"
>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select a animation variants" />
ruru-m07 marked this conversation as resolved.
Show resolved Hide resolved
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>variants</SelectLabel>
<SelectSeparator />
{(
Object.keys(modalVariants) as Array<keyof typeof modalVariants>
).map((variantKey) => (
<SelectItem key={variantKey} value={variantKey}>
{variantKey}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
<ModalProvider>
<Modal.Trigger>Open {selectedVariant} Modal</Modal.Trigger>
<Modal animationVariant={selectedVariant as keyof typeof modalVariants}>
ruru-m07 marked this conversation as resolved.
Show resolved Hide resolved
<Modal.Body>
<Modal.Header>
<Modal.Title>Create Username</Modal.Title>
<Modal.Subtitle>
Enter a unique name for your token to differentiate it from
other tokens and then select the scope.
</Modal.Subtitle>
ruru-m07 marked this conversation as resolved.
Show resolved Hide resolved
</Modal.Header>
<Modal.Content>
<Input label="username" placeholder="enter your username." />
</Modal.Content>
</Modal.Body>
<Modal.Actions>
<Modal.Close variant="secondary">Cancel</Modal.Close>
<Modal.Action
disabled={submissionStatus === "loading"}
variant={submissionStatus === "loading" ? "secondary" : "default"}
onClick={handleSubmit}
>
{submissionStatus === "loading" && <Spinner className="mr-2" />}{" "}
Submit
</Modal.Action>
</Modal.Actions>
</Modal>
</ModalProvider>
</Stack>
);
};

export default ModalAnimation;
103 changes: 94 additions & 9 deletions apps/www/content/docs/components/modal.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ description: The Modal component is used to display content in a modal dialog.
preview: modal
---


import Modal, { ModalProvider } from "ruru-ui/components/modal";
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
import { Tabs as Rutabs, Tab as Rutab } from "ruru-ui/components/tabs";
Expand All @@ -15,6 +14,7 @@ import Disabled from "../../../components/preview/Modal/disabled.tsx";
import CustomWidth from "../../../components/preview/Modal/customWidth.tsx";
import CustomWidth2 from "../../../components/preview/Modal/customWidth2.tsx";
import Preview from "../../../components/preview/Modal/preview.tsx";
import ModalAnimation from "../../../components/preview/Modal/modalAnimation";

## Installation

Expand Down Expand Up @@ -125,7 +125,6 @@ export default Usage;
</Tab>
</Tabs>


## Example

### Modal with Trigger
Expand Down Expand Up @@ -185,7 +184,6 @@ export default TriggerDemo;
</Tab>
</Tabs>


### Single button

The `Modal` component can be used with a single button.
Expand Down Expand Up @@ -527,18 +525,105 @@ export default Preview;
</Tab>
</Tabs>

## Props
## Animation Variants

Here's how the props table would look for the `Modal` component, formatted in the same style:
The `Modal` component supports multiple animation variants for opening and closing. You can set the animation variant by passing the `animationVariant` prop to the `Modal` component.

<Tabs items={["Preview", "Code"]}>
<Tab className={"flex justify-center"} value="Preview">
<ModalAnimation />
</Tab>
<Tab className={"-mt-8"} value="Code">
```tsx
"use client";

import React, { useState } from "react";
import { Stack } from "ruru-ui/components/stack";
import {
Select,
SelectGroup,
SelectValue,
SelectTrigger,
SelectContent,
SelectLabel,
SelectItem,
SelectSeparator,
} from "ruru-ui/components/select";
import Modal, { ModalProvider, modalVariants } from "ruru-ui/components/modal";
import { Input } from "ruru-ui/components/input";

const ModalAnimation = (): React.ReactNode => {
const [selectedVariant, setSelectedVariant] = useState<string>("default");

const handleSubmit = async () => {
// Your submit logic here
console.log("Submitted");
// Simulate an API call or any async operation
await new Promise((resolve) => setTimeout(resolve, 1000));
};

return (
<Stack direction={"column"} justify={"center"} align={"center"} gap={20}>
<Select
onValueChange={(e) => setSelectedVariant(e)}
defaultValue="default"
>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select a animation variants" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>variants</SelectLabel>
<SelectSeparator />
{(
Object.keys(modalVariants) as Array<keyof typeof modalVariants>
).map((variantKey, index) => (
<SelectItem value={variantKey}>{variantKey}</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
<ModalProvider>
<Modal.Trigger>Open {selectedVariant} Modal</Modal.Trigger>
<Modal animationVariant={selectedVariant as keyof typeof modalVariants}>
<Modal.Body>
<Modal.Header>
<Modal.Title>Create Username</Modal.Title>
<Modal.Subtitle>
Enter a unique name for your token to differentiate it from
other tokens and then select the scope.
</Modal.Subtitle>
</Modal.Header>
<Modal.Content>
<Input label="username" placeholder="enter your username." />
</Modal.Content>
</Modal.Body>
<Modal.Actions>
<Modal.Close variant="secondary">Cancel</Modal.Close>
<Modal.Action onClick={handleSubmit}>Submit</Modal.Action>
</Modal.Actions>
</Modal>
</ModalProvider>
</Stack>
);
};

export default ModalAnimation;
```
</Tab>
</Tabs>

## Props

Here's how the props table would look for the `Modal` component, formatted in the same style:

### Modal

| Name | Type | Default | Description |
| ----------------- | --------------------------------- | ----------- | -------------------------------------------------------------------------------------- |
| **children** | **ReactNode** | `undefined` | The children of the Modal component. |
| **onClickOutside**| **() => void** | `undefined` | The function to call when the user clicks outside the modal. |
| Name | Type | Default | Description |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------- |
| **children** | **ReactNode** | `undefined` | The children of the Modal component. |
| **onClickOutside** | **() => void** | `undefined` | The function to call when the user clicks outside the modal. |
| **animationVariant** | **"default" \| "fade" \| "zoom" \| "scaleBounce" \| "slideUp" \| "slideDown" \| "slideRight" \| "slideLeft" \| "flip" \| "rotate"** | `"default"` | Specifies the animation style for opening and closing the modal. Each variant provides a different visual effect. |

### ModalAction

Expand Down
Loading