diff --git a/package.json b/package.json index 91a1bbf7..05ebe459 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ }, "dependencies": { "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-slot": "^1.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fa8d45b6..e0b9d6b1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ dependencies: '@radix-ui/react-avatar': specifier: ^1.0.4 version: 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-dialog': + specifier: ^1.0.5 + version: 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-dropdown-menu': specifier: ^2.0.6 version: 2.0.6(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) @@ -2240,6 +2243,40 @@ packages: '@types/react': 18.2.48 react: 18.2.0 + /@radix-ui/react-dialog@1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@types/react': 18.2.48 + '@types/react-dom': 18.2.18 + aria-hidden: 1.2.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.2.48)(react@18.2.0) + dev: false + /@radix-ui/react-direction@1.0.1(@types/react@18.2.48)(react@18.2.0): resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==} peerDependencies: diff --git a/src/presentation/components/ui/sheet/content/index.tsx b/src/presentation/components/ui/sheet/content/index.tsx new file mode 100644 index 00000000..8bad5c25 --- /dev/null +++ b/src/presentation/components/ui/sheet/content/index.tsx @@ -0,0 +1,37 @@ +import { ElementRef, forwardRef } from 'react' + +import { + Content as ContentPrimitive, + Close as ClosePrimitive, + Portal as PortalPrimitive +} from '@radix-ui/react-dialog' +import { X } from 'lucide-react' + +import { cn } from '@/main/utils' + +import { Overlay } from '../overlay' + +import { sheetVariants } from './styles' +import { ContentProps } from './types' + +export const Content = forwardRef< + ElementRef, + ContentProps +>(({ side = 'right', className, children, ...props }, ref) => ( + + + + {children} + + + Fechar + + + +)) + +Content.displayName = ContentPrimitive.displayName diff --git a/src/presentation/components/ui/sheet/content/styles.ts b/src/presentation/components/ui/sheet/content/styles.ts new file mode 100644 index 00000000..e135cb2b --- /dev/null +++ b/src/presentation/components/ui/sheet/content/styles.ts @@ -0,0 +1,18 @@ +import { cva } from 'class-variance-authority' +import clsx from 'clsx' + +const baseStyles = clsx`flex flex-col fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500` + +export const sheetVariants = cva(baseStyles, { + variants: { + side: { + top: clsx`inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top`, + bottom: clsx`inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom`, + left: clsx`inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm`, + right: clsx`inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm` + } + }, + defaultVariants: { + side: 'right' + } +}) diff --git a/src/presentation/components/ui/sheet/content/types.ts b/src/presentation/components/ui/sheet/content/types.ts new file mode 100644 index 00000000..7d79b938 --- /dev/null +++ b/src/presentation/components/ui/sheet/content/types.ts @@ -0,0 +1,7 @@ +import { Content } from '@radix-ui/react-dialog' +import { VariantProps } from 'class-variance-authority' + +import { sheetVariants } from './styles' + +export type ContentProps = React.ComponentPropsWithoutRef & + VariantProps diff --git a/src/presentation/components/ui/sheet/description.tsx b/src/presentation/components/ui/sheet/description.tsx new file mode 100644 index 00000000..1358d060 --- /dev/null +++ b/src/presentation/components/ui/sheet/description.tsx @@ -0,0 +1,18 @@ +import { forwardRef, ElementRef, ComponentPropsWithoutRef } from 'react' + +import { Description as DescriptionPrimitive } from '@radix-ui/react-dialog' + +import { cn } from '@/main/utils' + +export const Description = forwardRef< + ElementRef, + ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +Description.displayName = DescriptionPrimitive.displayName diff --git a/src/presentation/components/ui/sheet/footer.tsx b/src/presentation/components/ui/sheet/footer.tsx new file mode 100644 index 00000000..370c1cdc --- /dev/null +++ b/src/presentation/components/ui/sheet/footer.tsx @@ -0,0 +1,16 @@ +import { cn } from '@/main/utils' + +export const Footer = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) + +Footer.displayName = 'SheetFooter' diff --git a/src/presentation/components/ui/sheet/header.tsx b/src/presentation/components/ui/sheet/header.tsx new file mode 100644 index 00000000..80b68a3e --- /dev/null +++ b/src/presentation/components/ui/sheet/header.tsx @@ -0,0 +1,16 @@ +import { cn } from '@/main/utils' + +export const Header = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) + +Header.displayName = 'SheetHeader' diff --git a/src/presentation/components/ui/sheet/index.stories.tsx b/src/presentation/components/ui/sheet/index.stories.tsx new file mode 100644 index 00000000..86d2965d --- /dev/null +++ b/src/presentation/components/ui/sheet/index.stories.tsx @@ -0,0 +1,76 @@ +import { Meta, StoryFn } from '@storybook/react/' + +import { Button } from '../button' +import { Input } from '../input' +import { Label } from '../label' + +import { ContentProps } from './content/types' + +import { Sheet } from '.' + +export default { + title: 'Components/UI/Sheet' +} as Meta + +const Template: StoryFn = ({ side, ...args }) => ( + + + + + + + Edit profile + + Make changes to your profile here. Click save when you are done. + + +
+
+ + +
+
+ + +
+
+ + + + + + + + + +
+
+) + +export const Top = Template.bind({}) +Top.args = { + side: 'top' +} + +export const Right = Template.bind({}) +Right.args = { + side: 'right' +} + +export const Bottom = Template.bind({}) +Bottom.args = { + side: 'bottom' +} + +export const Left = Template.bind({}) +Left.args = { + side: 'left' +} diff --git a/src/presentation/components/ui/sheet/index.ts b/src/presentation/components/ui/sheet/index.ts new file mode 100644 index 00000000..f3083fc6 --- /dev/null +++ b/src/presentation/components/ui/sheet/index.ts @@ -0,0 +1,21 @@ +import { Root, Portal, Trigger, Close } from '@radix-ui/react-dialog' + +import { Content } from './content' +import { Description } from './description' +import { Footer } from './footer' +import { Header } from './header' +import { Overlay } from './overlay' +import { Title } from './title' + +export const Sheet = { + Root, + Portal, + Overlay, + Trigger, + Close, + Content, + Header, + Footer, + Title, + Description +} diff --git a/src/presentation/components/ui/sheet/overlay.tsx b/src/presentation/components/ui/sheet/overlay.tsx new file mode 100644 index 00000000..410227c8 --- /dev/null +++ b/src/presentation/components/ui/sheet/overlay.tsx @@ -0,0 +1,21 @@ +import { forwardRef, ElementRef, ComponentPropsWithoutRef } from 'react' + +import { Overlay as OverlayPrimitive } from '@radix-ui/react-dialog' + +import { cn } from '@/main/utils' + +export const Overlay = forwardRef< + ElementRef, + ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +Overlay.displayName = OverlayPrimitive.displayName diff --git a/src/presentation/components/ui/sheet/title.tsx b/src/presentation/components/ui/sheet/title.tsx new file mode 100644 index 00000000..27afb15d --- /dev/null +++ b/src/presentation/components/ui/sheet/title.tsx @@ -0,0 +1,18 @@ +import { forwardRef, ElementRef, ComponentPropsWithoutRef } from 'react' + +import { Title as TitlePrimitive } from '@radix-ui/react-dialog' + +import { cn } from '@/main/utils' + +export const Title = forwardRef< + ElementRef, + ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +Title.displayName = TitlePrimitive.displayName