* esm * wip * wip * wip * wip * wip * wip * subscription notice * wip * wip * wip * fix envs * fix: update docker build * fix * esm/types * delete dashboard :D * add patches to dockerfiles * update packages + catalogs + ts * wip * remove native libs * ts * improvements * fix redirects and fetching session * try fix favicon * fixes * fix * order and resize reportds within a dashboard * improvements * wip * added userjot to dashboard * fix * add op * wip * different cache key * improve date picker * fix table * event details loading * redo onboarding completely * fix login * fix * fix * extend session, billing and improve bars * fix * reduce price on 10M
220 lines
6.0 KiB
TypeScript
220 lines
6.0 KiB
TypeScript
import { cn } from '@/utils/cn';
|
|
import { Slot } from '@radix-ui/react-slot';
|
|
import { Link, type LinkComponentProps } from '@tanstack/react-router';
|
|
import type { VariantProps } from 'class-variance-authority';
|
|
import { cva } from 'class-variance-authority';
|
|
import type { LucideIcon } from 'lucide-react';
|
|
import * as React from 'react';
|
|
import { Spinner, type SpinnerProps } from './spinner';
|
|
|
|
const buttonVariants = cva(
|
|
'inline-flex flex-shrink-0 select-none items-center justify-center whitespace-nowrap rounded-md font-medium ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 hover:translate-y-[-0.5px] transition-all',
|
|
{
|
|
variants: {
|
|
variant: {
|
|
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
|
cta: 'bg-highlight text-white hover:bg-highlight/80',
|
|
destructive:
|
|
'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
|
outline:
|
|
'border border-input bg-card hover:bg-accent hover:text-accent-foreground',
|
|
secondary: 'bg-def-100 text-secondary-foreground hover:bg-def-100/80',
|
|
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
|
link: 'text-primary underline-offset-4 hover:underline',
|
|
},
|
|
size: {
|
|
default: 'h-10 px-4 py-2',
|
|
sm: 'h-8 rounded-md px-2',
|
|
lg: 'h-11 rounded-md px-8',
|
|
icon: 'h-8 w-8',
|
|
},
|
|
},
|
|
defaultVariants: {
|
|
variant: 'default',
|
|
size: 'sm',
|
|
},
|
|
},
|
|
);
|
|
|
|
export interface ButtonProps
|
|
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
VariantProps<typeof buttonVariants> {
|
|
asChild?: boolean;
|
|
loading?: boolean;
|
|
loadingType?: SpinnerProps['type'];
|
|
loadingSpeed?: SpinnerProps['speed'];
|
|
icon?: LucideIcon;
|
|
responsive?: boolean;
|
|
autoHeight?: boolean;
|
|
loadingAbsolute?: boolean;
|
|
}
|
|
|
|
function fixHeight({
|
|
autoHeight,
|
|
size,
|
|
}: { autoHeight?: boolean; size: ButtonProps['size'] }) {
|
|
if (autoHeight) {
|
|
switch (size) {
|
|
case 'lg':
|
|
return 'h-auto min-h-11 py-2';
|
|
case 'icon':
|
|
return 'h-auto min-h-8 py-1';
|
|
case 'default':
|
|
return 'h-auto min-h-10 py-2';
|
|
default:
|
|
return 'h-auto min-h-8 py-1';
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
|
|
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
(
|
|
{
|
|
className,
|
|
variant,
|
|
size,
|
|
asChild = false,
|
|
children,
|
|
loading,
|
|
loadingType = 'circle',
|
|
loadingSpeed = 'normal',
|
|
disabled,
|
|
icon,
|
|
responsive,
|
|
autoHeight,
|
|
loadingAbsolute,
|
|
...props
|
|
},
|
|
ref,
|
|
) => {
|
|
const Comp = asChild ? Slot : 'button';
|
|
const Icon = loading ? null : (icon ?? null);
|
|
|
|
// Determine spinner size based on button size
|
|
const spinnerSize = size === 'lg' ? 'md' : size === 'icon' ? 'sm' : 'sm';
|
|
|
|
return (
|
|
<Comp
|
|
className={cn(
|
|
buttonVariants({ variant, size, className }),
|
|
fixHeight({ autoHeight, size }),
|
|
loadingAbsolute && 'relative',
|
|
)}
|
|
ref={ref}
|
|
disabled={loading || disabled}
|
|
{...props}
|
|
>
|
|
{loading && (
|
|
<div
|
|
className={cn(
|
|
loadingAbsolute &&
|
|
'absolute top-0 left-0 right-0 bottom-0 center-center backdrop-blur bg-background/10',
|
|
)}
|
|
>
|
|
<Spinner
|
|
type={loadingType}
|
|
size={spinnerSize}
|
|
speed={loadingSpeed}
|
|
variant={
|
|
variant === 'default' || variant === 'cta' ? 'white' : 'default'
|
|
}
|
|
className={cn(
|
|
'flex-shrink-0',
|
|
size !== 'icon' && responsive && 'mr-0 sm:mr-2',
|
|
size !== 'icon' && !responsive && 'mr-2',
|
|
)}
|
|
/>
|
|
</div>
|
|
)}
|
|
{Icon && (
|
|
<Icon
|
|
className={cn(
|
|
'h-4 w-4 flex-shrink-0',
|
|
size !== 'icon' && responsive && 'mr-0 sm:mr-2',
|
|
size !== 'icon' && !responsive && 'mr-2',
|
|
)}
|
|
/>
|
|
)}
|
|
{responsive ? (
|
|
<span className="hidden sm:block">{children}</span>
|
|
) : (
|
|
children
|
|
)}
|
|
</Comp>
|
|
);
|
|
},
|
|
);
|
|
Button.displayName = 'Button';
|
|
|
|
const LinkButton = ({
|
|
className,
|
|
variant,
|
|
size,
|
|
children,
|
|
loading,
|
|
loadingType = 'circle',
|
|
loadingSpeed = 'normal',
|
|
icon,
|
|
responsive,
|
|
...props
|
|
}: LinkComponentProps &
|
|
VariantProps<typeof buttonVariants> & {
|
|
loading?: boolean;
|
|
loadingType?: SpinnerProps['type'];
|
|
loadingSpeed?: SpinnerProps['speed'];
|
|
icon?: LucideIcon;
|
|
responsive?: boolean;
|
|
}) => {
|
|
const Icon = loading ? null : (icon ?? null);
|
|
|
|
// Determine spinner size based on button size
|
|
const spinnerSize = size === 'lg' ? 'md' : size === 'icon' ? 'sm' : 'sm';
|
|
|
|
return (
|
|
<Link
|
|
className={cn(buttonVariants({ variant, size, className }))}
|
|
{...props}
|
|
>
|
|
{(linkProps) => (
|
|
<>
|
|
{loading && (
|
|
<Spinner
|
|
type={loadingType}
|
|
size={spinnerSize}
|
|
speed={loadingSpeed}
|
|
variant={
|
|
variant === 'default' || variant === 'cta' ? 'white' : 'default'
|
|
}
|
|
className={cn(
|
|
'flex-shrink-0',
|
|
responsive && 'mr-0 sm:mr-2',
|
|
!responsive && 'mr-2',
|
|
)}
|
|
/>
|
|
)}
|
|
{Icon && (
|
|
<Icon
|
|
className={cn(
|
|
'mr-2 h-4 w-4 flex-shrink-0',
|
|
responsive && 'mr-0 sm:mr-2',
|
|
)}
|
|
/>
|
|
)}
|
|
{responsive ? (
|
|
<span className="hidden sm:block">
|
|
{typeof children === 'function' ? children(linkProps) : children}
|
|
</span>
|
|
) : typeof children === 'function' ? (
|
|
children(linkProps)
|
|
) : (
|
|
children
|
|
)}
|
|
</>
|
|
)}
|
|
</Link>
|
|
);
|
|
};
|
|
|
|
export { Button, LinkButton, buttonVariants };
|