mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 11:27:32 +00:00
feat(ui): fine tuning components library with exiting app design
This commit is contained in:
@@ -18,7 +18,8 @@ const buttonVariants = cva(
|
|||||||
'font-inter font-medium',
|
'font-inter font-medium',
|
||||||
'cursor-pointer',
|
'cursor-pointer',
|
||||||
'inline-flex items-center justify-center',
|
'inline-flex items-center justify-center',
|
||||||
'relative'
|
'relative',
|
||||||
|
'whitespace-nowrap'
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
@@ -33,7 +34,7 @@ const buttonVariants = cva(
|
|||||||
plain: ''
|
plain: ''
|
||||||
},
|
},
|
||||||
isDisabled: {
|
isDisabled: {
|
||||||
true: 'bg-opacity-70 cursor-not-allowed',
|
true: 'bg-opacity-40 cursor-not-allowed',
|
||||||
false: ''
|
false: ''
|
||||||
},
|
},
|
||||||
isFullWidth: {
|
isFullWidth: {
|
||||||
@@ -45,9 +46,9 @@ const buttonVariants = cva(
|
|||||||
false: ''
|
false: ''
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
xs: ['text-xs', 'py-1', 'px-2'],
|
xs: ['text-xs', 'py-1', 'px-1'],
|
||||||
sm: ['text-sm', 'py-2', 'px-4'],
|
sm: ['text-sm', 'py-2', 'px-2'],
|
||||||
md: ['text-md', 'py-2', 'px-6'],
|
md: ['text-md', 'py-2', 'px-4'],
|
||||||
lg: ['text-lg', 'py-2', 'px-8']
|
lg: ['text-lg', 'py-2', 'px-8']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -75,7 +76,7 @@ const buttonVariants = cva(
|
|||||||
{
|
{
|
||||||
colorSchema: 'secondary',
|
colorSchema: 'secondary',
|
||||||
variant: 'plain',
|
variant: 'plain',
|
||||||
className: 'text-mineshaft'
|
className: 'text-mineshaft-300'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
colorSchema: 'danger',
|
colorSchema: 'danger',
|
||||||
@@ -101,7 +102,7 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|||||||
children,
|
children,
|
||||||
isDisabled = false,
|
isDisabled = false,
|
||||||
className = '',
|
className = '',
|
||||||
size = 'md',
|
size = 'sm',
|
||||||
variant = 'solid',
|
variant = 'solid',
|
||||||
isFullWidth,
|
isFullWidth,
|
||||||
isRounded = true,
|
isRounded = true,
|
||||||
@@ -144,7 +145,7 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|||||||
)}
|
)}
|
||||||
<span
|
<span
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
'transition-all shrink-0 cursor-pointer',
|
'shrink-0 cursor-pointer transition-all',
|
||||||
loadingToggleClass,
|
loadingToggleClass,
|
||||||
size === 'xs' ? 'mr-1' : 'mr-2'
|
size === 'xs' ? 'mr-1' : 'mr-2'
|
||||||
)}
|
)}
|
||||||
@@ -154,7 +155,7 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|||||||
<span className={twMerge('transition-all', loadingToggleClass)}>{children}</span>
|
<span className={twMerge('transition-all', loadingToggleClass)}>{children}</span>
|
||||||
<span
|
<span
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
'transition-all shrink-0 cursor-pointer',
|
'shrink-0 cursor-pointer transition-all',
|
||||||
loadingToggleClass,
|
loadingToggleClass,
|
||||||
size === 'xs' ? 'ml-1' : 'ml-2'
|
size === 'xs' ? 'ml-1' : 'ml-2'
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export type CardBodyProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const CardBody = ({ children, className }: CardBodyProps) => (
|
export const CardBody = ({ children, className }: CardBodyProps) => (
|
||||||
<div className={twMerge('p-6 pt-0', className)}>{children}</div>
|
<div className={twMerge('p-6 pb-4 pt-0', className)}>{children}</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export type CardProps = {
|
export type CardProps = {
|
||||||
@@ -47,7 +47,7 @@ export const Card = forwardRef<HTMLDivElement, CardProps>(
|
|||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
'flex flex-col w-full font-inter text-gray-200 bg-mineshaft-700 shadow-md',
|
'flex w-full flex-col bg-mineshaft-800 font-inter text-gray-200 shadow-md',
|
||||||
isFullHeight && 'h-full',
|
isFullHeight && 'h-full',
|
||||||
isRounded && 'rounded-md',
|
isRounded && 'rounded-md',
|
||||||
isPlain && 'shadow-none',
|
isPlain && 'shadow-none',
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
import { useToggle } from '@app/hooks';
|
||||||
|
|
||||||
|
import { Button } from '../Button';
|
||||||
|
import { FormControl } from '../FormControl';
|
||||||
|
import { Input } from '../Input';
|
||||||
|
import { Modal, ModalContent } from '../Modal';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isOpen?: boolean;
|
||||||
|
onClose?: () => void;
|
||||||
|
onChange?: (isOpen: boolean) => void;
|
||||||
|
deleteKey: string;
|
||||||
|
title: string;
|
||||||
|
onDeleteApproved: () => Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DeleteActionModal = ({
|
||||||
|
isOpen,
|
||||||
|
onClose,
|
||||||
|
onChange,
|
||||||
|
deleteKey,
|
||||||
|
onDeleteApproved,
|
||||||
|
title
|
||||||
|
}: Props): JSX.Element => {
|
||||||
|
const [inputData, setInputData] = useState('');
|
||||||
|
const [isLoading, setIsLoading] = useToggle();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setInputData('');
|
||||||
|
}, [isOpen]);
|
||||||
|
|
||||||
|
const onDelete = async () => {
|
||||||
|
setIsLoading.on();
|
||||||
|
try {
|
||||||
|
await onDeleteApproved();
|
||||||
|
} catch {
|
||||||
|
setIsLoading.off();
|
||||||
|
} finally {
|
||||||
|
setIsLoading.off();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
isOpen={isOpen}
|
||||||
|
onOpenChange={(isOpenState) => {
|
||||||
|
setInputData('');
|
||||||
|
if (onChange) onChange(isOpenState);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ModalContent
|
||||||
|
title={title}
|
||||||
|
subTitle="This action is irreversible!!!"
|
||||||
|
footerContent={
|
||||||
|
<div className="flex items-center">
|
||||||
|
<Button
|
||||||
|
className="mr-4"
|
||||||
|
colorSchema="danger"
|
||||||
|
isDisabled={!(deleteKey === inputData) || isLoading}
|
||||||
|
onClick={onDelete}
|
||||||
|
isLoading={isLoading}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
<Button variant="plain" colorSchema="secondary" onClick={onClose}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
onClose={onClose}
|
||||||
|
>
|
||||||
|
<form>
|
||||||
|
<FormControl
|
||||||
|
label={
|
||||||
|
<div className="pb-2 text-sm">
|
||||||
|
Type <span className="font-bold">{deleteKey}</span> to delete the resource
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
className="mb-4"
|
||||||
|
>
|
||||||
|
<Input value={inputData} onChange={(e) => setInputData(e.target.value)} />
|
||||||
|
</FormControl>
|
||||||
|
</form>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { DeleteActionModal } from './DeleteActionModal';
|
||||||
@@ -11,7 +11,7 @@ export type FormLabelProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const FormLabel = ({ id, label, isRequired }: FormLabelProps) => (
|
export const FormLabel = ({ id, label, isRequired }: FormLabelProps) => (
|
||||||
<Label.Root className="text-mineshaft-300 text-sm font-medium block mb-1 ml-0.5" htmlFor={id}>
|
<Label.Root className="mb-1 ml-0.5 block text-sm font-medium text-mineshaft-300" htmlFor={id}>
|
||||||
{label}
|
{label}
|
||||||
{isRequired && <span className="ml-1 text-red">*</span>}
|
{isRequired && <span className="ml-1 text-red">*</span>}
|
||||||
</Label.Root>
|
</Label.Root>
|
||||||
@@ -25,7 +25,7 @@ export type FormHelperTextProps = {
|
|||||||
export const FormHelperText = ({ isError, text }: FormHelperTextProps) => (
|
export const FormHelperText = ({ isError, text }: FormHelperTextProps) => (
|
||||||
<div
|
<div
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
'text-xs font-inter flex items-center opacity-90 text-mineshaft-300 mt-2',
|
'mt-2 flex items-center font-inter text-xs text-mineshaft-300 opacity-90',
|
||||||
isError && 'text-red-600'
|
isError && 'text-red-600'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -46,6 +46,7 @@ export type FormControlProps = {
|
|||||||
helperText?: ReactNode;
|
helperText?: ReactNode;
|
||||||
errorText?: ReactNode;
|
errorText?: ReactNode;
|
||||||
children: JSX.Element;
|
children: JSX.Element;
|
||||||
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FormControl = ({
|
export const FormControl = ({
|
||||||
@@ -55,10 +56,11 @@ export const FormControl = ({
|
|||||||
helperText,
|
helperText,
|
||||||
errorText,
|
errorText,
|
||||||
id,
|
id,
|
||||||
isError
|
isError,
|
||||||
|
className
|
||||||
}: FormControlProps): JSX.Element => {
|
}: FormControlProps): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className={twMerge('mb-4', className)}>
|
||||||
{typeof label === 'string' ? (
|
{typeof label === 'string' ? (
|
||||||
<FormLabel label={label} isRequired={isRequired} id={id} />
|
<FormLabel label={label} isRequired={isRequired} id={id} />
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const iconButtonVariants = cva(
|
|||||||
[
|
[
|
||||||
'button',
|
'button',
|
||||||
'transition-all',
|
'transition-all',
|
||||||
'font-inter font-medium',
|
'font-inter font-medium user-select-none',
|
||||||
'cursor-pointer',
|
'cursor-pointer',
|
||||||
'inline-flex items-center justify-center',
|
'inline-flex items-center justify-center',
|
||||||
'relative'
|
'relative'
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ type Props = {
|
|||||||
isRequired?: boolean;
|
isRequired?: boolean;
|
||||||
leftIcon?: ReactNode;
|
leftIcon?: ReactNode;
|
||||||
rightIcon?: ReactNode;
|
rightIcon?: ReactNode;
|
||||||
|
isDisabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const inputVariants = cva(
|
const inputVariants = cva(
|
||||||
@@ -46,7 +47,7 @@ const inputParentContainerVariants = cva('inline-flex font-inter items-center bo
|
|||||||
},
|
},
|
||||||
isError: {
|
isError: {
|
||||||
true: 'border-red',
|
true: 'border-red',
|
||||||
false: 'border-mineshaft-400'
|
false: 'border-mineshaft-500'
|
||||||
},
|
},
|
||||||
isFullWidth: {
|
isFullWidth: {
|
||||||
true: 'w-full',
|
true: 'w-full',
|
||||||
@@ -70,6 +71,7 @@ export const Input = forwardRef<HTMLInputElement, InputProps>(
|
|||||||
className,
|
className,
|
||||||
isRounded = true,
|
isRounded = true,
|
||||||
isFullWidth = true,
|
isFullWidth = true,
|
||||||
|
isDisabled,
|
||||||
isError = false,
|
isError = false,
|
||||||
isRequired,
|
isRequired,
|
||||||
leftIcon,
|
leftIcon,
|
||||||
@@ -87,6 +89,7 @@ export const Input = forwardRef<HTMLInputElement, InputProps>(
|
|||||||
{...props}
|
{...props}
|
||||||
required={isRequired}
|
required={isRequired}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
disabled={isDisabled}
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
leftIcon ? 'pl-9' : 'pl-4',
|
leftIcon ? 'pl-9' : 'pl-4',
|
||||||
rightIcon ? 'pr-9' : 'pr-4',
|
rightIcon ? 'pr-9' : 'pr-4',
|
||||||
|
|||||||
@@ -11,31 +11,32 @@ export type ModalContentProps = DialogPrimitive.DialogContentProps & {
|
|||||||
title?: ReactNode;
|
title?: ReactNode;
|
||||||
subTitle?: string;
|
subTitle?: string;
|
||||||
footerContent?: ReactNode;
|
footerContent?: ReactNode;
|
||||||
|
onClose?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ModalContent = forwardRef<HTMLDivElement, ModalContentProps>(
|
export const ModalContent = forwardRef<HTMLDivElement, ModalContentProps>(
|
||||||
({ children, title, subTitle, className, footerContent, ...props }, forwardedRef) => (
|
({ children, title, subTitle, className, footerContent, onClose, ...props }, forwardedRef) => (
|
||||||
<DialogPrimitive.Portal>
|
<DialogPrimitive.Portal>
|
||||||
<DialogPrimitive.Overlay
|
<DialogPrimitive.Overlay
|
||||||
className="fixed inset-0 w-full h-full animate-fadeIn"
|
className="fixed inset-0 h-full w-full animate-fadeIn"
|
||||||
style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }}
|
style={{ backgroundColor: 'rgba(0, 0, 0, 0.7)' }}
|
||||||
/>
|
/>
|
||||||
<DialogPrimitive.Content {...props} ref={forwardedRef}>
|
<DialogPrimitive.Content {...props} ref={forwardedRef}>
|
||||||
<Card
|
<Card
|
||||||
isRounded
|
isRounded
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
'fixed max-w-md animate-popIn top-1/2 left-1/2 -translate-y-2/4 -translate-x-2/4',
|
'fixed top-1/2 left-1/2 max-w-lg -translate-y-2/4 -translate-x-2/4 animate-popIn drop-shadow-md',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{title && <CardTitle subTitle={subTitle}>{title}</CardTitle>}
|
{title && <CardTitle subTitle={subTitle}>{title}</CardTitle>}
|
||||||
<CardBody>{children}</CardBody>
|
<CardBody>{children}</CardBody>
|
||||||
{footerContent && <CardFooter>{footerContent}</CardFooter>}
|
{footerContent && <CardFooter>{footerContent}</CardFooter>}
|
||||||
<DialogPrimitive.Close aria-label="Close" asChild>
|
<DialogPrimitive.Close aria-label="Close" asChild onClick={onClose}>
|
||||||
<IconButton
|
<IconButton
|
||||||
variant="plain"
|
variant="plain"
|
||||||
ariaLabel="close"
|
ariaLabel="close"
|
||||||
className="absolute top-2.5 right-2.5 text-white hover:bg-gray-600 rounded"
|
className="absolute top-2.5 right-2.5 rounded text-white hover:bg-gray-600"
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faTimes} size="sm" className="cursor-pointer" />
|
<FontAwesomeIcon icon={faTimes} size="sm" className="cursor-pointer" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
@@ -55,3 +56,6 @@ export const Modal = ({ isOpen, ...props }: ModalProps) => (
|
|||||||
|
|
||||||
export const ModalTrigger = DialogPrimitive.Trigger;
|
export const ModalTrigger = DialogPrimitive.Trigger;
|
||||||
export type ModalTriggerProps = DialogPrimitive.DialogTriggerProps;
|
export type ModalTriggerProps = DialogPrimitive.DialogTriggerProps;
|
||||||
|
|
||||||
|
export const ModalClose = DialogPrimitive.Close;
|
||||||
|
export type ModalCloseProps = DialogPrimitive.DialogCloseProps;
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
export type { ModalContentProps, ModalProps, ModalTriggerProps } from './Modal';
|
export type { ModalCloseProps, ModalContentProps, ModalProps, ModalTriggerProps } from './Modal';
|
||||||
export { Modal, ModalContent, ModalTrigger } from './Modal';
|
export { Modal, ModalClose, ModalContent, ModalTrigger } from './Modal';
|
||||||
|
|||||||
@@ -22,21 +22,23 @@ export const Select = forwardRef<HTMLButtonElement, SelectProps>(
|
|||||||
<SelectPrimitive.Trigger
|
<SelectPrimitive.Trigger
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
`inline-flex items-center justify-between data-[placeholder]:text-gray-500
|
`inline-flex items-center justify-between rounded-md
|
||||||
px-3 py-2 font-inter text-sm text-bunker-200 font-normal rounded-md bg-mineshaft-800 outline-none`,
|
bg-mineshaft-800 px-3 py-2 font-inter text-sm font-normal text-bunker-200 outline-none data-[placeholder]:text-gray-500`,
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<SelectPrimitive.Value placeholder={placeholder} />
|
<SelectPrimitive.Value placeholder={placeholder} />
|
||||||
{!props.disabled && <SelectPrimitive.Icon className="ml-3">
|
{!props.disabled && (
|
||||||
<FontAwesomeIcon icon={faChevronDown} size="sm" />
|
<SelectPrimitive.Icon className="ml-3">
|
||||||
</SelectPrimitive.Icon>}
|
<FontAwesomeIcon icon={faChevronDown} size="sm" />
|
||||||
|
</SelectPrimitive.Icon>
|
||||||
|
)}
|
||||||
</SelectPrimitive.Trigger>
|
</SelectPrimitive.Trigger>
|
||||||
<SelectPrimitive.Portal>
|
<SelectPrimitive.Portal>
|
||||||
<SelectPrimitive.Content
|
<SelectPrimitive.Content
|
||||||
// position="popper"
|
// position="popper"
|
||||||
sideOffset={4}
|
sideOffset={4}
|
||||||
className="overflow-hidden text-bunker-100 rounded-md shadow-md font-inter bg-mineshaft-800"
|
className="overflow-hidden rounded-md bg-mineshaft-800 font-inter text-bunker-100 shadow-md"
|
||||||
style={{ width: 'var(--radix-select-trigger-width) + 6' }}
|
style={{ width: 'var(--radix-select-trigger-width) + 6' }}
|
||||||
>
|
>
|
||||||
<SelectPrimitive.ScrollUpButton>
|
<SelectPrimitive.ScrollUpButton>
|
||||||
@@ -75,11 +77,11 @@ export const SelectItem = forwardRef<HTMLDivElement, SelectItemProps>(
|
|||||||
<SelectPrimitive.Item
|
<SelectPrimitive.Item
|
||||||
{...props}
|
{...props}
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
`text-sm rounded-sm transition-all hover:bg-mineshaft-500
|
`relative flex cursor-pointer
|
||||||
flex items-center pl-10 pr-4 py-2 cursor-pointer rounded-md
|
select-none items-center rounded-md py-2 pl-10 pr-4 text-sm
|
||||||
select-none outline-none relative`,
|
outline-none transition-all hover:bg-mineshaft-500`,
|
||||||
isSelected && 'bg-primary',
|
isSelected && 'bg-primary',
|
||||||
isDisabled && 'text-gray-600 hover:bg-transparent cursor-not-allowed hover:text-gray-600',
|
isDisabled && 'cursor-not-allowed text-gray-600 hover:bg-transparent hover:text-gray-600',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
ref={forwardedRef}
|
ref={forwardedRef}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ReactNode } from 'react';
|
import { HTMLAttributes, ReactNode, TdHTMLAttributes } from 'react';
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
export type TableContainerProps = {
|
export type TableContainerProps = {
|
||||||
@@ -14,7 +14,7 @@ export const TableContainer = ({
|
|||||||
}: TableContainerProps): JSX.Element => (
|
}: TableContainerProps): JSX.Element => (
|
||||||
<div
|
<div
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
'overflow-x-auto font-inter shadow-md relative border border-solid border-mineshaft-700',
|
'relative w-full overflow-x-auto border border-solid border-mineshaft-700 font-inter shadow-md',
|
||||||
isRounded && 'rounded-md',
|
isRounded && 'rounded-md',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
@@ -32,7 +32,7 @@ export type TableProps = {
|
|||||||
export const Table = ({ children, className }: TableProps): JSX.Element => (
|
export const Table = ({ children, className }: TableProps): JSX.Element => (
|
||||||
<table
|
<table
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
'bg-bunker-800 p-2 roun text-gray-300 w-full text-sm text-left rounded-md',
|
'w-full rounded rounded-md bg-bunker-800 p-2 text-left text-sm text-gray-300',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -47,7 +47,7 @@ export type THeadProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const THead = ({ children, className }: THeadProps): JSX.Element => (
|
export const THead = ({ children, className }: THeadProps): JSX.Element => (
|
||||||
<thead className={twMerge('text-xs bg-bunker text-bunker-300 uppercase', className)}>
|
<thead className={twMerge('bg-bunker text-xs uppercase text-bunker-300', className)}>
|
||||||
{children}
|
{children}
|
||||||
</thead>
|
</thead>
|
||||||
);
|
);
|
||||||
@@ -56,15 +56,17 @@ export const THead = ({ children, className }: THeadProps): JSX.Element => (
|
|||||||
export type TrProps = {
|
export type TrProps = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
} & HTMLAttributes<HTMLTableRowElement>;
|
||||||
|
|
||||||
export const Tr = ({ children, className }: TrProps): JSX.Element => (
|
export const Tr = ({ children, className, ...props }: TrProps): JSX.Element => (
|
||||||
<tr className={twMerge('border border-solid border-mineshaft-700', className)}>{children}</tr>
|
<tr className={twMerge('border border-solid border-mineshaft-700', className)} {...props}>
|
||||||
|
{children}
|
||||||
|
</tr>
|
||||||
);
|
);
|
||||||
|
|
||||||
// table head columns
|
// table head columns
|
||||||
export type ThProps = {
|
export type ThProps = {
|
||||||
children: ReactNode;
|
children?: ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -84,10 +86,12 @@ export const TBody = ({ children, className }: TBodyProps): JSX.Element => (
|
|||||||
|
|
||||||
// table body columns
|
// table body columns
|
||||||
export type TdProps = {
|
export type TdProps = {
|
||||||
children: ReactNode;
|
children?: ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
} & TdHTMLAttributes<HTMLTableCellElement>;
|
||||||
|
|
||||||
export const Td = ({ children, className }: TdProps): JSX.Element => (
|
export const Td = ({ children, className, ...props }: TdProps): JSX.Element => (
|
||||||
<td className={twMerge('text-left px-6 py-3', className)}>{children}</td>
|
<td className={twMerge('px-6 py-3 text-left', className)} {...props}>
|
||||||
|
{children}
|
||||||
|
</td>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
import { Button } from '../Button';
|
||||||
|
import { Modal, ModalClose, ModalContent } from '../Modal';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isOpen?: boolean;
|
||||||
|
onOpenChange?: (isOpen: boolean) => void;
|
||||||
|
text: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const UpgradePlanModal = ({ text, isOpen, onOpenChange }: Props): JSX.Element => (
|
||||||
|
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
||||||
|
<ModalContent
|
||||||
|
title="Unleash Infisical's Full Power"
|
||||||
|
footerContent={[
|
||||||
|
<Link
|
||||||
|
href={`/settings/billing/${localStorage.getItem('projectData.id') as string}`}
|
||||||
|
key="upgrade-plan"
|
||||||
|
>
|
||||||
|
<Button className="mr-4">Upgrade Plan</Button>
|
||||||
|
</Link>,
|
||||||
|
<ModalClose asChild key="upgrade-plan-cancel">
|
||||||
|
<Button colorSchema="secondary" variant="plain">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</ModalClose>
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<p className="mb-4 text-bunker-300">{text}</p>
|
||||||
|
<p className="font-medium text-bunker-300">
|
||||||
|
Upgrade and get access to this, as well as to other powerful enhancements.
|
||||||
|
</p>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { UpgradePlanModal } from './UpgradePlanModal';
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
export * from './Button';
|
export * from './Button';
|
||||||
export * from './Card';
|
export * from './Card';
|
||||||
export * from './Checkbox';
|
export * from './Checkbox';
|
||||||
|
export * from './DeleteActionModal';
|
||||||
export * from './Dropdown';
|
export * from './Dropdown';
|
||||||
export * from './FormControl';
|
export * from './FormControl';
|
||||||
export * from './IconButton';
|
export * from './IconButton';
|
||||||
@@ -12,3 +13,4 @@ export * from './Spinner';
|
|||||||
export * from './Switch';
|
export * from './Switch';
|
||||||
export * from './Table';
|
export * from './Table';
|
||||||
export * from './TextArea';
|
export * from './TextArea';
|
||||||
|
export * from './UpgradePlanModal';
|
||||||
|
|||||||
Reference in New Issue
Block a user