2023-07-13 07:22:08 -04:00
|
|
|
import { ActionIcon, ActionIconProps } from './ActionIcon'
|
2023-07-27 18:59:40 -04:00
|
|
|
import React from 'react'
|
2023-08-10 13:30:32 -04:00
|
|
|
import { paths } from '../Router'
|
2023-08-15 21:56:24 -04:00
|
|
|
import { Link } from 'react-router-dom'
|
|
|
|
import type { LinkProps } from 'react-router-dom'
|
2023-07-13 07:22:08 -04:00
|
|
|
|
2023-08-15 21:56:24 -04:00
|
|
|
interface BaseActionButtonProps {
|
2023-07-13 07:22:08 -04:00
|
|
|
icon?: ActionIconProps
|
|
|
|
className?: string
|
|
|
|
}
|
|
|
|
|
2023-08-15 21:56:24 -04:00
|
|
|
type ActionButtonAsButton = BaseActionButtonProps &
|
|
|
|
Omit<
|
|
|
|
React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
|
|
keyof BaseActionButtonProps
|
|
|
|
> & {
|
|
|
|
Element: 'button'
|
|
|
|
}
|
|
|
|
|
|
|
|
type ActionButtonAsLink = BaseActionButtonProps &
|
|
|
|
Omit<LinkProps, keyof BaseActionButtonProps> & {
|
|
|
|
Element: 'link'
|
|
|
|
}
|
|
|
|
|
|
|
|
type ActionButtonAsExternal = BaseActionButtonProps &
|
2023-10-02 13:26:23 -04:00
|
|
|
Omit<LinkProps, keyof BaseActionButtonProps> & {
|
2023-08-15 21:56:24 -04:00
|
|
|
Element: 'externalLink'
|
|
|
|
}
|
|
|
|
|
|
|
|
type ActionButtonAsElement = BaseActionButtonProps &
|
|
|
|
Omit<React.HTMLAttributes<HTMLElement>, keyof BaseActionButtonProps> & {
|
|
|
|
Element: React.ComponentType<React.HTMLAttributes<HTMLButtonElement>>
|
|
|
|
}
|
|
|
|
|
|
|
|
type ActionButtonProps =
|
|
|
|
| ActionButtonAsButton
|
|
|
|
| ActionButtonAsLink
|
|
|
|
| ActionButtonAsExternal
|
|
|
|
| ActionButtonAsElement
|
|
|
|
|
|
|
|
export const ActionButton = (props: ActionButtonProps) => {
|
2023-08-09 15:41:41 -04:00
|
|
|
const classNames = `group mono text-base flex items-center gap-2 rounded-sm border border-chalkboard-40 dark:border-chalkboard-60 hover:border-liquid-40 dark:hover:bg-chalkboard-90 p-[3px] text-chalkboard-110 dark:text-chalkboard-10 hover:text-chalkboard-110 hover:dark:text-chalkboard-10 ${
|
2023-08-15 21:56:24 -04:00
|
|
|
props.icon ? 'pr-2' : 'px-2'
|
|
|
|
} ${props.className || ''}`
|
|
|
|
|
|
|
|
switch (props.Element) {
|
|
|
|
case 'button': {
|
|
|
|
// Note we have to destructure 'className' and 'Element' out of props
|
|
|
|
// because we don't want to pass them to the button element;
|
|
|
|
// the same is true for the other cases below.
|
|
|
|
const { Element, icon, children, className, ...rest } = props
|
|
|
|
return (
|
|
|
|
<button className={classNames} {...rest}>
|
|
|
|
{props.icon && <ActionIcon {...icon} />}
|
|
|
|
{children}
|
|
|
|
</button>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
case 'link': {
|
|
|
|
const { Element, to, icon, children, className, ...rest } = props
|
|
|
|
return (
|
|
|
|
<Link to={to || paths.INDEX} className={classNames} {...rest}>
|
|
|
|
{icon && <ActionIcon {...icon} />}
|
|
|
|
{children}
|
|
|
|
</Link>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
case 'externalLink': {
|
2023-10-02 13:26:23 -04:00
|
|
|
const { Element, to, icon, children, className, ...rest } = props
|
2023-08-15 21:56:24 -04:00
|
|
|
return (
|
2023-10-02 13:26:23 -04:00
|
|
|
<Link
|
|
|
|
to={to || paths.INDEX}
|
|
|
|
className={classNames}
|
|
|
|
{...rest}
|
|
|
|
target="_blank"
|
|
|
|
>
|
2023-08-15 21:56:24 -04:00
|
|
|
{icon && <ActionIcon {...icon} />}
|
|
|
|
{children}
|
2023-10-02 13:26:23 -04:00
|
|
|
</Link>
|
2023-08-15 21:56:24 -04:00
|
|
|
)
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
const { Element, icon, children, className, ...rest } = props
|
|
|
|
if (!Element) throw new Error('Element is required')
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Element className={classNames} {...rest}>
|
|
|
|
{props.icon && <ActionIcon {...props.icon} />}
|
|
|
|
{children}
|
|
|
|
</Element>
|
|
|
|
)
|
|
|
|
}
|
2023-07-27 18:59:40 -04:00
|
|
|
}
|
2023-07-13 07:22:08 -04:00
|
|
|
}
|