Skip to content

Commit

Permalink
feat(modal): enhance modal component with multiple animation variants
Browse files Browse the repository at this point in the history
Fixes #65

Add support for multiple animation variants in the Modal component.

* Extend the `modalVariants` object in `packages/ui/src/components/modal.tsx` to include multiple animation options such as `fade`, `zoom`, `scaleBounce`, `slideUp`, `slideDown`, `slideRight`, `slideLeft`, `flip`, and `rotate`.
* Allow dynamic selection of animation variants based on the `animationVariant` prop in the `Modal` component.
* Update the documentation in `apps/www/content/docs/components/modal.mdx` to explain how to select and use the new animation variants.
* Add test cases in `apps/www/app/playground/page.tsx` to cover all supported animation options for the `Modal` component.
* Add a new file `apps/www/components/preview/Modal/modalAnimation.tsx` to demonstrate the use of different animation variants in the Modal component.
* Update the version in `packages/ui/package.json` from `2.2.3` to `2.2.4`.

---

For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/ruru-m07/ruru-ui/issues/65?shareId=XXXX-XXXX-XXXX-XXXX).
  • Loading branch information
ruru-m07 committed Oct 20, 2024
1 parent 894b8b4 commit 2acf2ae
Show file tree
Hide file tree
Showing 6 changed files with 383 additions and 30 deletions.
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, index) => (
<Card key={index}>
<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
74 changes: 74 additions & 0 deletions apps/www/components/preview/Modal/modalAnimation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"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;
95 changes: 90 additions & 5 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. |
| **animationVariant** | **"default" \| "fade" \| "slide"** | `"default"` | The animation variant to use for the modal. |

### ModalAction

Expand Down
Loading

0 comments on commit 2acf2ae

Please sign in to comment.