iter: d03 新增折叠面板 accordion 组件
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import { h, signal } from '@ui-arch/frame';
|
||||
import type { AccordionItem, AccordionProps } from './types.js';
|
||||
|
||||
/*** 折叠面板:标题按钮 + grid 行高过渡;单开(手风琴)或多开,展开态由 active 信号驱动或内部持有 ***/
|
||||
export function accordion(props: AccordionProps): HTMLElement {
|
||||
// —— 状态集中声明 ——
|
||||
const internal = signal<string[]>([]); // 内部展开集合(未传 active 时使用)
|
||||
const opened = (v: string): boolean => (props.active ? props.active() === v : internal().includes(v));
|
||||
|
||||
const toggle = (item: AccordionItem): void => {
|
||||
if (props.active) {
|
||||
const next = props.active() === item.value ? '' : item.value; // 单开:再点收起
|
||||
props.active(next);
|
||||
props.onChange?.(next);
|
||||
return;
|
||||
}
|
||||
const cur = internal();
|
||||
const next = cur.includes(item.value)
|
||||
? cur.filter((v) => v !== item.value)
|
||||
: props.multiple
|
||||
? [...cur, item.value]
|
||||
: [item.value];
|
||||
internal(next);
|
||||
props.onChange?.(next[0] ?? '');
|
||||
};
|
||||
|
||||
// —— 面板:标题为原生 button(键盘可达),内容包一层 overflow 容器供过渡裁剪 ——
|
||||
const rows = props.items.map((item, i) =>
|
||||
h(
|
||||
'div',
|
||||
{ class: () => `ua-acc-item${opened(item.value) ? ' ua-open' : ''}` },
|
||||
h(
|
||||
'button',
|
||||
{
|
||||
type: 'button',
|
||||
class: 'ua-acc-head',
|
||||
id: `ua-acc-h-${i}`,
|
||||
'aria-expanded': () => String(opened(item.value)),
|
||||
'aria-controls': `ua-acc-b-${i}`,
|
||||
disabled: item.disabled ?? false, // 布尔透传即得禁用态
|
||||
onClick: () => toggle(item),
|
||||
},
|
||||
h('span', { class: 'ua-acc-title' }, item.title),
|
||||
h('span', { class: 'ua-acc-caret' }, '▸'),
|
||||
),
|
||||
h(
|
||||
'div',
|
||||
{ class: 'ua-acc-body', id: `ua-acc-b-${i}`, role: 'region', 'aria-labelledby': `ua-acc-h-${i}` },
|
||||
h('div', { class: 'ua-acc-inner' }, item.content),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return h('div', { class: 'ua-accordion' }, ...rows);
|
||||
}
|
||||
Reference in New Issue
Block a user