mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-09 13:28:27 +00:00
feat: added card and modal component
This commit is contained in:
@@ -34,6 +34,7 @@ export const CardBody = ({ children, className }: CardBodyProps) => (
|
||||
|
||||
export type CardProps = {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
isFullHeight?: boolean;
|
||||
isRounded?: boolean;
|
||||
isPlain?: boolean;
|
||||
@@ -41,16 +42,17 @@ export type CardProps = {
|
||||
};
|
||||
|
||||
export const Card = forwardRef<HTMLDivElement, CardProps>(
|
||||
({ children, isFullHeight, isRounded, isHoverable, isPlain }, ref): JSX.Element => {
|
||||
({ children, isFullHeight, isRounded, isHoverable, isPlain, className }, ref): JSX.Element => {
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={twMerge(
|
||||
'flex flex-col w-full text-gray-200 bg-mineshaft shadow-md',
|
||||
'flex flex-col w-full text-gray-200 bg-mineshaft-700 shadow-md',
|
||||
isFullHeight && 'h-full',
|
||||
isRounded && 'rounded-md',
|
||||
isPlain && 'shadow-none',
|
||||
isHoverable && 'hover:shadow-xl'
|
||||
isHoverable && 'hover:shadow-xl',
|
||||
className
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { Button } from '../Button';
|
||||
import { Modal, ModalContent, ModalContentProps, ModalTrigger } from './Modal';
|
||||
|
||||
const meta: Meta<typeof Modal> = {
|
||||
title: 'Components/Modal',
|
||||
component: Modal,
|
||||
tags: ['v2'],
|
||||
argTypes: {}
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof ModalContent>;
|
||||
|
||||
const Template = (args: ModalContentProps) => (
|
||||
<Modal>
|
||||
<ModalTrigger asChild>
|
||||
<Button>Open</Button>
|
||||
</ModalTrigger>
|
||||
<ModalContent {...args}>Hello world</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
export const Basic: Story = {
|
||||
render: (args) => <Template {...args} />,
|
||||
args: {
|
||||
title: 'Title',
|
||||
subTitle: 'Something as subtitle',
|
||||
footerContent: 'footer content'
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
import { forwardRef, ReactNode } from 'react';
|
||||
import { faTimes } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
import { Card, CardBody, CardFooter, CardTitle } from '../Card';
|
||||
import { IconButton } from '../IconButton';
|
||||
|
||||
export type ModalContentProps = Omit<DialogPrimitive.DialogContentProps, 'open'> & {
|
||||
title?: ReactNode;
|
||||
subTitle?: string;
|
||||
footerContent?: ReactNode;
|
||||
};
|
||||
|
||||
export const ModalContent = forwardRef<HTMLDivElement, ModalContentProps>(
|
||||
({ children, title, subTitle, className, footerContent, ...props }, forwardedRef) => (
|
||||
<DialogPrimitive.Portal>
|
||||
<DialogPrimitive.Overlay
|
||||
className="fixed inset-0 w-full h-full animate-fadeIn"
|
||||
style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }}
|
||||
/>
|
||||
<DialogPrimitive.Content {...props} ref={forwardedRef}>
|
||||
<Card
|
||||
isRounded
|
||||
className={twMerge(
|
||||
'fixed max-w-md animate-popIn top-1/2 left-1/2 -translate-y-2/4 -translate-x-2/4',
|
||||
className
|
||||
)}
|
||||
>
|
||||
{title && <CardTitle subTitle={subTitle}>{title}</CardTitle>}
|
||||
<CardBody>{children}</CardBody>
|
||||
{footerContent && <CardFooter>{footerContent}</CardFooter>}
|
||||
<DialogPrimitive.Close aria-label="Close" asChild>
|
||||
<IconButton
|
||||
variant="plain"
|
||||
ariaLabel="close"
|
||||
className="absolute top-2.5 right-2.5 text-white hover:bg-gray-600 rounded"
|
||||
>
|
||||
<FontAwesomeIcon icon={faTimes} size="sm" className="cursor-pointer" />
|
||||
</IconButton>
|
||||
</DialogPrimitive.Close>
|
||||
</Card>
|
||||
</DialogPrimitive.Content>
|
||||
</DialogPrimitive.Portal>
|
||||
)
|
||||
);
|
||||
|
||||
ModalContent.displayName = 'ModalContent';
|
||||
|
||||
export const Modal = DialogPrimitive.Root;
|
||||
export type ModalProps = DialogPrimitive.DialogProps;
|
||||
|
||||
export const ModalTrigger = DialogPrimitive.Trigger;
|
||||
export type ModalTriggerProps = DialogPrimitive.DialogTriggerProps;
|
||||
@@ -0,0 +1,2 @@
|
||||
export type { ModalContentProps, ModalProps, ModalTriggerProps } from './Modal';
|
||||
export { Modal, ModalContent, ModalTrigger } from './Modal';
|
||||
@@ -3,4 +3,5 @@ export * from './Card';
|
||||
export * from './FormControl';
|
||||
export * from './IconButton';
|
||||
export * from './Input';
|
||||
export * from './Modal';
|
||||
export * from './Select';
|
||||
|
||||
Reference in New Issue
Block a user