schema: ai-cjm-component-contract/v1 id: tabs version: 1.0.0 status: stable owner: AI CJM Design purpose: Переключает один из взаимно исключающих content panels. use_when: - Контент имеет несколько равноправных представлений. evidence: - id: production-style url: https://aicjm.ru/edu/cases/catalog.css?v=20260811-catalog-all locator: .catalog-tabs, .catalog-tabs button, .catalog-tabs button:hover, .catalog-tabs button.is-active, .catalog-controls button:focus-visible supports: - anatomy - variant:inline - size:default - state:default - state:hover - state:focus-visible - state:selected - id: production-dom url: https://aicjm.ru/edu/cases/ locator: .catalog-controls .catalog-tabs[role=tablist] and its panel/result region supports: - approved-example - content anatomy: - id: tablist required: true role: Контейнер вкладок. - id: tab required: true role: Управляющий элемент. - id: panel required: true role: Связанная область контента. - id: indicator required: false role: Видимый selected cue. variants: - id: inline status: stable description: Горизонтальный tablist. evidence_refs: - production-style - id: stacked status: candidate description: Нормативный compact reflow. 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: stable basis: observed description: focus-visible is observed at the exact production locator in evidence_refs. evidence_refs: - production-style active: status: not-applicable basis: not-applicable description: Persistent choice is owned by selected; transient press uses native button behavior. selected: status: stable basis: observed description: selected is observed at the exact production locator in evidence_refs. evidence_refs: - production-style open: status: not-applicable basis: not-applicable description: open is not owned by tabs. disabled: status: candidate basis: normative-gap description: Proposed disabled contract for tabs; 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: - surface.card - surface.deep - text.secondary 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 tabs manual state check. loading: status: not-applicable basis: not-applicable description: loading is not owned by tabs. success: status: not-applicable basis: not-applicable description: success is not owned by tabs. error: status: not-applicable basis: not-applicable description: error is not owned by tabs. empty: status: not-applicable basis: not-applicable description: empty is not owned by tabs. responsive: mode: inline-scrollable-tablist reading_order: DOM order remains authoritative in every mode. rules: - Keep tablist before all panels in DOM order. - When tabs do not fit, retain one horizontal scroll row; do not silently switch to an unapproved stacked variant. - Scroll the newly focused tab into view without moving page focus. accessibility: pattern: aria-tabs-manual-activation semantics: - Use tablist, tab, tabpanel, aria-selected and matching aria-controls/id pairs. keyboard: - ArrowLeft/ArrowRight move roving focus; Home/End jump; Enter/Space activates the focused tab. focus: - Exactly one tab has tabindex=0; activation moves focus nowhere and reveals its panel. motion: - Panel switching uses no required animation; scrolling a focused tab is instant under reduced motion. tokens: - surface.card - surface.deep - text.secondary - text.on-deep - state.active-indicator-on-deep - border.default - focus.ring - control.minimum-height content: required: - Короткие взаимоисключающие labels. constraints: - Один tab selected. - Panel имеет собственный heading при необходимости. do: - Следовать ARIA Tabs pattern. dont: - Не использовать tabs как набор независимых ссылок без panels. examples: approved: status: stable description: Компонент tabs в указанном scoped production locator. evidence: https://aicjm.ru/edu/teachers/ prohibited: description: Не использовать tabs как набор независимых ссылок без panels. acceptance: - id: tabs-1 criterion: Arrow keys меняют активный tab. method: manual - id: tabs-2 criterion: aria-controls и aria-selected согласованы. method: manual