1
1
mirror of https://github.com/theoludwig/theoludwig.git synced 2025-05-29 22:37:44 +02:00

perf!: monorepo setup + fully static + webp images

BREAKING CHANGE: minimum supported Node.js >= 22.0.0 and pnpm >= 9.5.0
This commit is contained in:
2024-07-30 23:59:06 +02:00
parent 0f44e64c0c
commit 7bde328b96
336 changed files with 22933 additions and 26923 deletions

View File

@ -0,0 +1,111 @@
import { classNames } from "@repo/config-tailwind/classNames"
import { Link as NextLink } from "@repo/i18n/navigation"
import type { VariantProps } from "cva"
import { cva } from "cva"
import { Spinner } from "../Spinner/Spinner"
import { Ripple } from "./Ripple"
const buttonVariants = cva({
base: "relative inline-flex items-center justify-center overflow-hidden rounded-md text-base font-semibold transition duration-150 ease-in-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
variants: {
variant: {
solid: "bg-primary hover:bg-primary/80 text-white",
outline:
"dark:border-primary-dark/60 dark:text-primary-dark dark:hover:border-primary-dark border-primary/60 text-primary hover:border-primary hover:bg-gray border bg-transparent dark:hover:bg-transparent",
},
size: {
small: "h-9 rounded-md px-3",
medium: "h-10 px-4 py-2",
large: "h-11 rounded-md px-8",
},
},
defaultVariants: {
variant: "solid",
size: "medium",
},
})
interface ButtonBaseProps extends VariantProps<typeof buttonVariants> {
leftIcon?: React.ReactNode
rightIcon?: React.ReactNode
disabled?: boolean
isLoading?: boolean
}
interface ButtonElementProps extends React.ComponentPropsWithoutRef<"button"> {}
interface LinkElementProps
extends React.ComponentPropsWithoutRef<typeof NextLink> {}
export type ButtonLinkProps = ButtonBaseProps &
LinkElementProps & { href: string }
export type ButtonButtonProps = ButtonBaseProps &
ButtonElementProps & { href?: never }
export type ButtonProps = ButtonButtonProps | ButtonLinkProps
/**
* Buttons allow users to take actions, and make choices, with a single click.
* @param props
* @returns
*/
export const Button: React.FC<ButtonProps> = (props) => {
const rippleColor =
props.variant === "outline" ? "rgb(30, 64, 175)" : "rgb(229, 231, 235)"
if (typeof props.href === "string") {
const { variant, size, leftIcon, rightIcon, className, children, ...rest } =
props
return (
<NextLink
className={classNames(buttonVariants({ variant, size }), className)}
{...rest}
>
{leftIcon != null ? <span className="mr-2">{leftIcon}</span> : null}
<span>{children}</span>
{rightIcon != null ? <span className="ml-2">{rightIcon}</span> : null}
<Ripple color={rippleColor} />
</NextLink>
)
}
const {
variant,
size,
leftIcon,
rightIcon,
className,
isLoading = false,
disabled = false,
children,
...rest
} = props
const isDisabled = disabled || isLoading
const leftIconElement = isLoading ? (
<Spinner size={18} className="text-inherit dark:text-inherit" />
) : (
leftIcon
)
return (
<button
className={classNames(buttonVariants({ variant, size }), className)}
disabled={isDisabled}
{...rest}
>
{leftIconElement != null ? (
<span className="mr-2">{leftIconElement}</span>
) : null}
<span>{children}</span>
{rightIcon != null && !isLoading ? (
<span className="ml-2">{rightIcon}</span>
) : null}
<Ripple color={rippleColor} />
</button>
)
}