Andrey Epifancev d2b4ff2018 feat: skill aura-design — дизайн-система AURA для личных проектов (#17)
Скилл переносится из ~/.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>
2026-10-22 12:10:34 +04:00

20 lines
1.4 KiB
TypeScript

import { useEffect, useRef, type DialogHTMLAttributes, type ReactNode, type SyntheticEvent } from "react";
// окно: родной <dialog> держит фокус и закрывает фон; Esc — onClose, закрытие по фону — на стороне использующего.
// Остальные атрибуты <dialog> (onCancel, onClick, aria-labelledby …) проходят насквозь и могут переопределить поведение по
// умолчанию; нативное событие close — onNativeClose (имя onClose занято запросом закрытия).
type Rest = Omit<DialogHTMLAttributes<HTMLDialogElement>, "className" | "children" | "onClose" | "aria-label">;
export function Dialog({ label, onClose, onNativeClose, size = "md", className, children, ...rest }: {
label: string; onClose(): void; onNativeClose?(e: SyntheticEvent<HTMLDialogElement>): void;
size?: "sm" | "md" | "lg"; className?: string; children: ReactNode;
} & Rest) {
const ref = useRef<HTMLDialogElement>(null);
useEffect(() => { const d = ref.current; if (d && !d.open) d.showModal(); }, []);
return (
<dialog ref={ref} className={["ui-dialog", `ui-dialog--${size}`, className].filter(Boolean).join(" ")} aria-label={label}
onCancel={(e) => { e.preventDefault(); onClose(); }} {...rest} onClose={onNativeClose}>
{children}
</dialog>
);
}