Files
UI/packages/skin/ui/src/layout.ts
T
2026-10-26 22:48:04 +08:00

33 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { h, signal } from '@ui-arch/frame';
import type { LayoutProps } from './types.js';
// 侧栏展开态缺省宽度(px):够放下四个汉字的菜单项,再窄就要靠折叠态图标栏
const SIDER_DEFAULT = 220;
/*** 布局骨架:页头 / 侧栏 / 内容 / 页脚四区一次成型,侧栏可折叠(受控或自管);只管骨架与间距,导航内容交给 menu / anchor ***/
export function layout(props: LayoutProps, ...children: unknown[]): HTMLElement {
const collapsed = props.collapsed ?? signal(false); // 折叠态:外部给了信号就双向绑定,没给就内部自管
const width = props.siderWidth ?? SIDER_DEFAULT; // 侧栏宽度:折叠时由样式表收到 0,这里只给展开值
const toggle = (): void => { collapsed(!collapsed()); }; // 折叠开关:只翻信号,视觉由类名响应
const rootCls = ['ua-layout', props.sticky ? 'is-sticky' : ''].filter(Boolean).join(' '); // 根类名:吸顶页头是同一个容器上的修饰类
const header = props.header === undefined
? null // 没有页头就不渲染容器,避免多一层空盒子影响 :first-child 选择器
: h(
'header',
{ class: 'ua-layout-header' },
props.collapsible ? h('button', { class: 'ua-layout-toggle', type: 'button', 'aria-expanded': () => String(!collapsed()), 'aria-label': '折叠或展开侧栏', onClick: toggle }, '⟨⟩') : null,
props.header,
);
const sider = props.sider === undefined
? null // 没有侧栏时内容区独占整行,省掉一条 220px 的空白
: h('aside', {
class: () => `ua-layout-sider${collapsed() ? ' is-collapsed' : ''}`,
style: `width:${width}px`, // 展开宽度内联,折叠后的收拢宽度交给类名(0 + overflow hidden)
'aria-hidden': () => (collapsed() ? 'true' : null), // 折叠后视觉消失,读屏也不再报里面的菜单
}, props.sider);
const content = h('main', { class: 'ua-layout-content' }, ...children);
const body = sider ? h('div', { class: 'ua-layout-body' }, sider, content) : content; // 无侧栏时不套 body 层
const footer = props.footer === undefined ? null : h('footer', { class: 'ua-layout-footer' }, props.footer);
return h('div', { class: rootCls }, header, body, footer) as HTMLElement;
}