-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
518 additions
and
119 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@alice-ui/react": patch | ||
"@alice-ui/theme": patch | ||
--- | ||
|
||
Add Drawer component |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
export const slideHorizontal = { | ||
enter: { | ||
x: 'var(--slide-enter)', | ||
opacity: 1, | ||
transition: { | ||
opacity: { | ||
duration: 0.4, | ||
ease: [0.36, 0.66, 0.4, 1], | ||
}, | ||
x: { | ||
type: 'spring', | ||
bounce: 0, | ||
duration: 0.6, | ||
}, | ||
}, | ||
}, | ||
exit: { | ||
x: 'var(--slide-exit)', | ||
opacity: 0, | ||
transition: { | ||
duration: 0.4, | ||
ease: [0.36, 0.66, 0.4, 1], | ||
}, | ||
}, | ||
}; | ||
|
||
export const slideVertical = { | ||
enter: { | ||
y: 'var(--slide-enter)', | ||
transition: { | ||
y: { | ||
type: 'spring', | ||
bounce: 0, | ||
duration: 0.6, | ||
}, | ||
}, | ||
}, | ||
exit: { | ||
y: 'var(--slide-exit)', | ||
transition: { | ||
duration: 0.4, | ||
ease: [0.36, 0.66, 0.4, 1], | ||
}, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
'use client'; | ||
|
||
import { clsx } from '@alice-ui/shared-utils'; | ||
import type { DrawerSlots, DrawerVariantProps, SlotsToClasses } from '@alice-ui/theme'; | ||
import { drawer } from '@alice-ui/theme'; | ||
import type { HTMLMotionProps } from 'framer-motion'; | ||
import { AnimatePresence, motion } from 'framer-motion'; | ||
import { useMemo } from 'react'; | ||
import type { ModalOverlayProps } from 'react-aria-components'; | ||
import { Modal as AriaModal, ModalOverlay } from 'react-aria-components'; | ||
import { InternalModalContext } from '../modal/modal'; | ||
import { slideHorizontal, slideVertical } from './drawer-transition'; | ||
|
||
export interface DrawerProps extends ModalOverlayProps, DrawerVariantProps { | ||
/** | ||
* The props to modify the framer motion animation. Use the `variants` API to create your own animation. | ||
*/ | ||
motionProps?: HTMLMotionProps<'section'>; | ||
/** | ||
* Classes object to style the modal and its children. | ||
*/ | ||
classNames?: SlotsToClasses<DrawerSlots>; | ||
} | ||
|
||
function Drawer(props: DrawerProps) { | ||
const { | ||
children, | ||
classNames, | ||
className, | ||
placement, | ||
backdrop = 'opaque', | ||
motionProps, | ||
...otherProps | ||
} = props; | ||
|
||
const slots = useMemo(() => drawer({ placement, backdrop }), [backdrop, placement]); | ||
|
||
const baseStyles = clsx(classNames?.base, className); | ||
|
||
return ( | ||
<ModalOverlay {...otherProps} className={slots.backdrop({ class: classNames?.backdrop })}> | ||
{({ state }) => ( | ||
<InternalModalContext.Provider value={{ slots, classNames, state }}> | ||
<AnimatePresence> | ||
{state.isOpen && ( | ||
<motion.div | ||
className={slots.base({ class: baseStyles })} | ||
data-placement={placement} | ||
animate="enter" | ||
exit="exit" | ||
initial="exit" | ||
variants={ | ||
placement === 'top' || placement === 'bottom' ? slideVertical : slideHorizontal | ||
} | ||
{...motionProps} | ||
> | ||
<AriaModal style={{ height: '100%' }}>{children}</AriaModal> | ||
</motion.div> | ||
)} | ||
</AnimatePresence> | ||
</InternalModalContext.Provider> | ||
)} | ||
</ModalOverlay> | ||
); | ||
} | ||
|
||
export { Drawer }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
'use client'; | ||
|
||
import { ModalBody } from '../modal/modal-body'; | ||
import { ModalCloseButton } from '../modal/modal-close-button'; | ||
import { ModalContent } from '../modal/modal-content'; | ||
import { ModalFooter } from '../modal/modal-footer'; | ||
import { ModalHeader } from '../modal/modal-header'; | ||
import { Drawer } from './drawer'; | ||
|
||
// export types | ||
export type { DrawerProps } from './drawer'; | ||
|
||
// export component | ||
|
||
export { | ||
Drawer, | ||
ModalBody as DrawerBody, | ||
ModalCloseButton as DrawerCloseButton, | ||
ModalContent as DrawerContent, | ||
ModalFooter as DrawerFooter, | ||
ModalHeader as DrawerHeader, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
import { drawer } from '@alice-ui/theme'; | ||
import { Meta, StoryObj } from '@storybook/react'; | ||
import React from 'react'; | ||
import { Button } from '../src/button'; | ||
import { | ||
Drawer, | ||
DrawerBody, | ||
DrawerCloseButton, | ||
DrawerContent, | ||
DrawerFooter, | ||
DrawerHeader, | ||
DrawerProps, | ||
} from '../src/drawer'; | ||
|
||
const TemplateContent = () => ( | ||
<> | ||
<p> | ||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus | ||
hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. | ||
</p> | ||
</> | ||
); | ||
|
||
const meta: Meta<typeof Drawer> = { | ||
title: 'Components/Drawer', | ||
component: Drawer, | ||
argTypes: { | ||
placement: { | ||
control: { | ||
type: 'select', | ||
}, | ||
options: ['top', 'right', 'bottom', 'left'], | ||
}, | ||
backdrop: { | ||
control: { | ||
type: 'select', | ||
}, | ||
options: ['transparent', 'blur', 'opaque'], | ||
}, | ||
isDismissable: { | ||
control: { | ||
type: 'boolean', | ||
}, | ||
}, | ||
isKeyboardDismissDisabled: { | ||
control: { | ||
type: 'boolean', | ||
}, | ||
}, | ||
children: { | ||
control: { | ||
disable: true, | ||
}, | ||
}, | ||
}, | ||
decorators: [ | ||
(Story) => ( | ||
<div className="flex h-screen w-screen items-center justify-center"> | ||
<Story /> | ||
</div> | ||
), | ||
], | ||
}; | ||
|
||
export default meta; | ||
type Story = StoryObj<typeof Drawer>; | ||
|
||
const defaultProps: DrawerProps = { | ||
...drawer.defaultVariants, | ||
}; | ||
|
||
const Template = (args: DrawerProps) => { | ||
const [isOpen, setOpen] = React.useState(false); | ||
|
||
return ( | ||
<> | ||
<Button onPress={() => setOpen(true)}>Open drawer</Button> | ||
<Drawer {...args} isDismissable isOpen={isOpen} onOpenChange={setOpen}> | ||
<DrawerContent> | ||
{({ close }) => ( | ||
<> | ||
<DrawerCloseButton /> | ||
<DrawerHeader>Drawer Title</DrawerHeader> | ||
<DrawerBody> | ||
<TemplateContent /> | ||
</DrawerBody> | ||
<DrawerFooter> | ||
<Button color="danger" variant="light" onPress={close}> | ||
Close | ||
</Button> | ||
<Button color="primary" onPress={close}> | ||
Action | ||
</Button> | ||
</DrawerFooter> | ||
</> | ||
)} | ||
</DrawerContent> | ||
</Drawer> | ||
</> | ||
); | ||
}; | ||
|
||
export const Left: Story = { | ||
render: Template, | ||
|
||
args: { | ||
...defaultProps, | ||
backdrop: 'blur', | ||
placement: 'left', | ||
className: 'w-[360px]', | ||
}, | ||
}; | ||
|
||
export const Right: Story = { | ||
render: Template, | ||
|
||
args: { | ||
...defaultProps, | ||
backdrop: 'opaque', | ||
placement: 'right', | ||
className: 'w-[360px]', | ||
}, | ||
}; | ||
|
||
export const Top: Story = { | ||
render: Template, | ||
|
||
args: { | ||
...defaultProps, | ||
backdrop: 'blur', | ||
placement: 'top', | ||
className: 'h-[300px]', | ||
}, | ||
}; | ||
|
||
export const Bottom: Story = { | ||
render: Template, | ||
|
||
args: { | ||
...defaultProps, | ||
backdrop: 'blur', | ||
placement: 'bottom', | ||
className: 'h-[300px]', | ||
}, | ||
}; |
Oops, something went wrong.