writekit/frontends/ui/src/Button.tsx
Josh bef5dd4437 refactor: move studio to frontends workspace
- Move studio from root to frontends/studio/
- Add owner-tools frontend for live blog admin UI
- Add shared ui component library
- Set up npm workspaces for frontends
- Add enhanced code block extension for editor

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 02:06:19 +02:00

64 lines
1.6 KiB
TypeScript

import type { ButtonHTMLAttributes, AnchorHTMLAttributes, ReactNode } from 'react'
import { Icons, type IconComponent } from './Icons'
type ButtonVariant = 'primary' | 'secondary' | 'danger' | 'ghost' | 'accent'
type ButtonBaseProps = {
variant?: ButtonVariant
loading?: boolean
Icon?: IconComponent
children: ReactNode
}
type ButtonAsButton = ButtonBaseProps & ButtonHTMLAttributes<HTMLButtonElement> & { href?: never }
type ButtonAsLink = ButtonBaseProps & AnchorHTMLAttributes<HTMLAnchorElement> & { href: string }
type ButtonProps = ButtonAsButton | ButtonAsLink
const variantClasses: Record<ButtonVariant, string> = {
primary: 'btn-primary',
secondary: 'btn-secondary',
danger: 'btn-danger',
ghost: 'btn-ghost',
accent: 'btn-accent',
}
export function Button({
variant = 'secondary',
loading = false,
Icon,
children,
className = '',
...props
}: ButtonProps) {
const content = (
<>
{loading ? (
<Icons.Loader className="animate-spin text-xs" />
) : Icon ? (
<Icon className="text-xs opacity-70" />
) : null}
<span>{children}</span>
</>
)
if ('href' in props && props.href) {
const { href, ...linkProps } = props
return (
<a href={href} className={`${variantClasses[variant]} ${className}`} {...linkProps}>
{content}
</a>
)
}
const { disabled, ...buttonProps } = props as ButtonAsButton
return (
<button
className={`${variantClasses[variant]} ${className}`}
disabled={disabled || loading}
{...buttonProps}
>
{content}
</button>
)
}