schema: ai-cjm-component-contract/v1 id: button version: 1.0.0 status: stable owner: AI CJM Design purpose: Запускает действие или ведёт к одному ясному следующему шагу. use_when: - Пользователь может выполнить действие или перейти к целевому сценарию. evidence: - id: production-style url: https://aicjm.ru/edu/styles.css?v=20260812-horizontal-team-cards locator: .button, .button:hover, .button--light, .button--light:hover, .hero__actions .button, .lead-form .button supports: - anatomy - variant:primary - variant:secondary - size:default - state:default - state:hover - id: production-dom url: https://aicjm.ru/edu/ locator: .hero__actions .button and .lead-form button.button supports: - approved-example - content anatomy: - id: label required: true role: Глагольная подпись действия. - id: icon required: false role: Дополняющая смысл иконка. - id: progress required: false role: Индикатор нормативного loading-state. variants: - id: primary status: stable description: Главное действие на поверхности. evidence_refs: - production-style - id: secondary status: stable description: Вторичное действие. evidence_refs: - production-style sizes: - id: default status: stable description: Размер определяется содержимым и перечисленными semantic/component tokens; raw dimensions запрещены. evidence_refs: - production-style states: default: status: stable basis: observed description: default is observed at the exact production locator in evidence_refs. evidence_refs: - production-style hover: status: stable basis: observed description: hover is observed at the exact production locator in evidence_refs. evidence_refs: - production-style focus-visible: status: candidate basis: normative-gap description: Proposed focus-visible contract for button; approval is required before production use. behavior: Render focus.ring without changing layout or relying on hover. semantics: Keep the native element in DOM order and expose keyboard focus visibly. token_refs: - component.button.primary.background - component.button.primary.background-hover - component.button.primary.text transition: Enter for keyboard-origin focus and return to default on blur. acceptance: - focus-visible behavior, semantics, token refs and transition pass the button manual state check. active: status: candidate basis: normative-gap description: Proposed active contract for button; approval is required before production use. behavior: Render transient press feedback while preserving native activation. semantics: No persistent ARIA state; use native button/link activation semantics. token_refs: - component.button.primary.background - component.button.primary.background-hover - component.button.primary.text transition: Enter during pointer/key press and resolve to hover, focus-visible or default on release. acceptance: - active behavior, semantics, token refs and transition pass the button manual state check. selected: status: not-applicable basis: not-applicable description: selected is not owned by button. open: status: not-applicable basis: not-applicable description: open is not owned by button. disabled: status: candidate basis: normative-gap description: Proposed disabled contract for button; approval is required before production use. behavior: Prevent activation or editing while preserving label, context and layout. semantics: Use native disabled where available; otherwise aria-disabled=true and suppress activation. token_refs: - component.button.primary.background - component.button.primary.background-hover - component.button.primary.text transition: Enter only when the action is unavailable and return to default when it becomes available. acceptance: - disabled behavior, semantics, token refs and transition pass the button manual state check. loading: status: candidate basis: normative-gap description: Proposed loading contract for button; approval is required before production use. behavior: Prevent duplicate work, preserve the initiating label and expose progress text. semantics: Set aria-busy=true on the owning region and announce progress through role=status. token_refs: - component.button.primary.background - component.button.primary.background-hover - component.button.primary.text transition: Enter after activation and resolve exactly once to success, error or default. acceptance: - loading behavior, semantics, token refs and transition pass the button manual state check. success: status: not-applicable basis: not-applicable description: Outcome message is owned by validation-status, not button. error: status: not-applicable basis: not-applicable description: Error message is owned by validation-status, not button. empty: status: not-applicable basis: not-applicable description: empty is not owned by button. responsive: mode: content-sized-to-full-row-action reading_order: DOM order remains authoritative in every mode. rules: - Keep content-sized action in wide decision areas. - In narrow hero/form contexts expand the button to the available inline size. - Label and optional icon never reverse order or truncate the action verb. - Primary web action uses 52 px minimum height, 15 px text, weight 650, line-height 1 and 14 px gap. accessibility: pattern: native-button-or-link-action semantics: - Use button for actions and a for navigation; disabled actions use native disabled where possible. keyboard: - Enter and Space activate button; Enter follows a navigation link. focus: - Show focus.ring for keyboard focus and preserve source-order focus. motion: - Press/hover feedback uses motion.duration.state and is removed for reduced motion. tokens: - component.button.primary.background - component.button.primary.background-hover - component.button.primary.text - component.button.primary.border - component.button.primary.border-width - component.button.primary.minimum-height - component.button.primary.web-minimum-height - component.button.primary.padding-inline - component.button.primary.gap - component.button.primary.web-gap - component.button.primary.web-font-size - component.button.primary.web-font-weight - component.button.primary.web-line-height - component.button.primary.radius - component.button.secondary.background - component.button.secondary.text - component.button.secondary.border - component.button.secondary.border-width - component.button.secondary.minimum-height - focus.ring content: required: - Понятный следующий шаг. constraints: - Подпись начинается с действия. - Один primary button на локальную decision area. do: - Использовать button для действия и a для перехода. dont: - Не писать абстрактное «Подробнее» без контекста. examples: approved: status: stable description: Компонент button в указанном scoped production locator. evidence: https://aicjm.ru/edu/ prohibited: description: Не писать абстрактное «Подробнее» без контекста. acceptance: - id: button-1 criterion: Hit area не меньше component.button.*.minimum-height. method: manual - id: button-2 criterion: Focus-visible различим и не зависит от hover. method: manual - id: button-3 criterion: Primary web action matches the production 52/15/650/1/14 signature. method: automated