mirror of
https://github.com/Infisical/infisical.git
synced 2025-03-25 14:05:03 +00:00
feat(ui): added card component
This commit is contained in:
40
frontend/src/components/v2/Card/Card.stories.tsx
Normal file
40
frontend/src/components/v2/Card/Card.stories.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { Card, CardBody, CardFooter, CardProps, CardTitle } from './Card';
|
||||
|
||||
const meta: Meta<typeof Card> = {
|
||||
title: 'Components/Card',
|
||||
component: Card,
|
||||
tags: ['v2'],
|
||||
argTypes: {
|
||||
isRounded: {
|
||||
type: 'boolean',
|
||||
defaultValue: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Card>;
|
||||
|
||||
// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
|
||||
const Template = (args: CardProps) => (
|
||||
<div className="w-96">
|
||||
<Card {...args}>
|
||||
<CardTitle subTitle="Please add your subtitle here">Title</CardTitle>
|
||||
<CardBody>Content</CardBody>
|
||||
<CardFooter>Footer</CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const Basic: Story = {
|
||||
render: (args) => <Template {...args} />
|
||||
};
|
||||
|
||||
export const Hoverable: Story = {
|
||||
render: (args) => <Template {...args} />,
|
||||
args: {
|
||||
isHoverable: true
|
||||
}
|
||||
};
|
62
frontend/src/components/v2/Card/Card.tsx
Normal file
62
frontend/src/components/v2/Card/Card.tsx
Normal file
@ -0,0 +1,62 @@
|
||||
import { forwardRef, ReactNode } from 'react';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export type CardTitleProps = {
|
||||
children: ReactNode;
|
||||
subTitle?: string;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export const CardTitle = ({ children, className, subTitle }: CardTitleProps) => (
|
||||
<div className={twMerge('p-6 pb-4 font-sans text-xl font-medium', className)}>
|
||||
{children}
|
||||
{subTitle && <p className="py-1 text-sm font-normal text-gray-400">{subTitle}</p>}
|
||||
</div>
|
||||
);
|
||||
|
||||
export type CardFooterProps = {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export const CardFooter = ({ children, className }: CardFooterProps) => (
|
||||
<div className={twMerge('p-6 pt-0', className)}>{children}</div>
|
||||
);
|
||||
|
||||
export type CardBodyProps = {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export const CardBody = ({ children, className }: CardBodyProps) => (
|
||||
<div className={twMerge('p-6 pt-0', className)}>{children}</div>
|
||||
);
|
||||
|
||||
export type CardProps = {
|
||||
children: ReactNode;
|
||||
isFullHeight?: boolean;
|
||||
isRounded?: boolean;
|
||||
isPlain?: boolean;
|
||||
isHoverable?: boolean;
|
||||
};
|
||||
|
||||
export const Card = forwardRef<HTMLDivElement, CardProps>(
|
||||
({ children, isFullHeight, isRounded, isHoverable, isPlain }, ref): JSX.Element => {
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={twMerge(
|
||||
'flex flex-col w-full text-gray-200 bg-mineshaft shadow-md',
|
||||
isFullHeight && 'h-full',
|
||||
isRounded && 'rounded-md',
|
||||
isPlain && 'shadow-none',
|
||||
isHoverable && 'hover:shadow-xl'
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Card.displayName = 'Card';
|
2
frontend/src/components/v2/Card/index.tsx
Normal file
2
frontend/src/components/v2/Card/index.tsx
Normal file
@ -0,0 +1,2 @@
|
||||
export type { CardBodyProps, CardFooterProps, CardProps, CardTitleProps } from './Card';
|
||||
export { Card, CardBody, CardFooter, CardTitle } from './Card';
|
@ -1,4 +1,5 @@
|
||||
export * from './Button';
|
||||
export * from './Card';
|
||||
export * from './FormControl';
|
||||
export * from './IconButton';
|
||||
export * from './Input';
|
||||
|
Reference in New Issue
Block a user