import type { Morfo } from '../types'; import { v } from '../types'; export const tabsMorfo = { name: 'Tabs', kebab: 'tabs', scope: ['soma', 'sema', 'eidos'], apg: 'https://www.w3.org/WAI/ARIA/apg/patterns/tabs/', events: [ { name: 'select', semantic: { family: 'commit', verb: 'select', target: v.partRef('trigger'), intent: 'neutral', sequence: 'pre' } } ], parts: [ { name: 'Provider', kebab: 'provider', archetype: 'provider', kind: 'public', defaultElement: 'div', optional: false, data: [ { attr: 'data-orientation', values: ['horizontal', 'vertical'] }, { attr: 'data-disabled', severity: 'optional' } ], aria: [] }, { name: 'List', kebab: 'list', archetype: 'group', kind: 'public', defaultElement: 'div', role: 'tablist', optional: false, data: [{ attr: 'data-orientation', values: ['horizontal', 'vertical'] }], aria: [{ attr: 'aria-orientation', value: v.propRef('orientation') }] }, { name: 'Trigger', kebab: 'trigger', archetype: 'trigger', kind: 'public', defaultElement: 'button', role: 'tab', optional: false, states: ['active', 'inactive'], data: [ { attr: 'data-state', values: ['active', 'inactive'] }, { attr: 'data-disabled', severity: 'optional' }, { attr: 'data-orientation', values: ['horizontal', 'vertical'] } ], aria: [ { attr: 'type', value: v.literal('button') }, { attr: 'aria-selected', value: v.stateRef('active') }, { attr: 'aria-controls', value: v.partRef('content'), condition: { when: 'part-present', part: 'content' }, severity: 'recommended' } ], keyboard: [ { key: 'ArrowRight', action: 'next-item' }, { key: 'ArrowLeft', action: 'prev-item' }, { key: 'ArrowDown', action: 'next-item' }, { key: 'ArrowUp', action: 'prev-item' }, { key: 'Home', action: 'first-item' }, { key: 'End', action: 'last-item' }, { key: 'Enter', action: 'activate' }, { key: ' ', action: 'activate' } ] }, { name: 'Content', kebab: 'content', archetype: 'content', kind: 'public', defaultElement: 'div', role: 'tabpanel', optional: false, states: ['active', 'inactive'], data: [ { attr: 'data-state', values: ['active', 'inactive'] }, { attr: 'data-orientation', values: ['horizontal', 'vertical'] } ], aria: [ { attr: 'aria-labelledby', value: v.partRef('trigger'), condition: { when: 'part-present', part: 'trigger' }, severity: 'recommended' }, { // Emitted when `data-state === 'inactive'` so inactive panels // are also hidden from AT. Optional because the active panel // omits it entirely. attr: 'aria-hidden', value: v.literal('true'), severity: 'optional' } ] }, { // Animated indicator that slides between active triggers. Optional; // renders as an absolutely-positioned element parented to the List. // Soma exposes the active trigger's bounding rect on the provider so // the indicator can compute its transform / size. name: 'Indicator', kebab: 'indicator', archetype: 'indicator', kind: 'public', defaultElement: 'div', optional: true, data: [{ attr: 'data-orientation', values: ['horizontal', 'vertical'] }], aria: [{ attr: 'aria-hidden', value: v.literal('true') }] } ] } as const satisfies Morfo;