import { splitProps, mergeProps, JSX, Show } from 'solid-js'; import clsx from 'clsx'; export type ButtonVariant = 'primary' | 'secondary' | 'ghost'; export type ButtonSize = 'sm' | 'md' | 'lg'; export type SemanticColor = 'success' | 'error' | 'warning' | 'info'; export interface ButtonProps extends JSX.ButtonHTMLAttributes { variant?: ButtonVariant; size?: ButtonSize; color?: SemanticColor; accent?: string; loading?: boolean; } /** * Button — angular outlined button with primary (magenta), secondary (cyan), and ghost variants. * * Consumes hh-btn CSS class from App.css and interaction state classes from components.css. * Primary = magenta (default hh-btn color), Secondary = cyan (hh-btn--secondary), Ghost = text-only. */ export function Button(rawProps: ButtonProps) { const merged = mergeProps({ variant: 'secondary' as ButtonVariant, size: 'md' as ButtonSize }, rawProps); const [local, rest] = splitProps(merged, [ 'variant', 'size', 'color', 'accent', 'loading', 'class', 'children', 'disabled', 'style', ]); const isDisabled = () => local.disabled || local.loading; const classes = () => clsx( local.variant !== 'ghost' && 'hh-btn', local.variant !== 'ghost' && 'hh-hover-gradient', local.variant === 'primary' && '', // default hh-btn color is magenta = primary local.variant === 'secondary' && 'hh-btn--secondary', local.variant === 'ghost' && 'hh-btn--ghost', 'hh-focus-pulse', local.variant !== 'ghost' && 'hh-active-flood', 'hh-disabled', `hh-size-${local.size}`, local.color && `hh-color-${local.color}`, local.loading && 'hh-btn--loading', local.class, ); const accentStyle = (): JSX.CSSProperties | undefined => { const base = local.accent ? { '--hh-comp-accent': local.accent } : {}; // Merge with any user-provided style if (typeof local.style === 'object' && local.style) { return { ...base, ...local.style } as JSX.CSSProperties; } if (Object.keys(base).length > 0) { return base as JSX.CSSProperties; } return local.style as JSX.CSSProperties | undefined; }; return ( ); }