feat: dashboard v2, esm, upgrades (#211)
* 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
This commit is contained in:
committed by
GitHub
parent
436e81ecc9
commit
81a7e5d62e
219
apps/start/src/components/ui/button.tsx
Normal file
219
apps/start/src/components/ui/button.tsx
Normal file
@@ -0,0 +1,219 @@
|
||||
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 };
|
||||
Reference in New Issue
Block a user