Скилл переносится из ~/.claude/skills/aura-design в репозиторий обвязки: SKILL.md, справочники reference/ и набор kit/ (токены, base.css, компоненты React, оболочка AppShell, тест токенов, test-setup, примеры входа). install.sh ставит его в ~/.claude/skills/aura-design, --check его видит. tests/test-aura-design.sh проверяет структуру и инварианты набора. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
27 lines
1.1 KiB
TypeScript
27 lines
1.1 KiB
TypeScript
import type { ButtonHTMLAttributes, ReactNode } from "react";
|
|
|
|
export type ButtonProps = {
|
|
variant?: "primary" | "secondary" | "danger" | "ghost";
|
|
size?: "md" | "lg";
|
|
icon?: ReactNode;
|
|
loading?: boolean;
|
|
} & ButtonHTMLAttributes<HTMLButtonElement>;
|
|
|
|
export function Button({ variant = "secondary", size = "md", icon, loading, className, children, disabled, type = "button", ...rest }: ButtonProps) {
|
|
const cls = ["ui-btn", `ui-btn--${variant}`, `ui-btn--${size}`, className].filter(Boolean).join(" ");
|
|
return (
|
|
<button {...rest} type={type} className={cls} disabled={disabled || loading} aria-busy={loading ? "true" : undefined}>
|
|
{loading ? <span className="ui-spinner" aria-hidden="true" /> : icon}
|
|
{children}
|
|
</button>
|
|
);
|
|
}
|
|
|
|
export function IconButton({ label, icon, className, title, type = "button", ...rest }: { label: string; icon: ReactNode } & ButtonHTMLAttributes<HTMLButtonElement>) {
|
|
return (
|
|
<button {...rest} type={type} className={["ui-icon-btn", className].filter(Boolean).join(" ")} aria-label={label} title={title ?? label}>
|
|
{icon}
|
|
</button>
|
|
);
|
|
}
|