diff --git a/.ua/index.json b/.ua/index.json index ad907b5..15c7ae1 100644 --- a/.ua/index.json +++ b/.ua/index.json @@ -1,6 +1,6 @@ { "$schema": "ui-arch-registry-index/0.1", - "generatedAt": "2026-10-26T02:24:35.622Z", + "generatedAt": "2026-10-26T02:50:02.720Z", "repoRoot": ".", "packages": [ { @@ -149,8 +149,9 @@ "slider(props):滑块,value 信号双向绑定,min/max/step 可配,原生 range 承载键盘交互,右侧可显示当前值", "checkbox(props):复选框,checked 信号双向绑定,disabled 支持布尔或信号禁用", "switchButton(props):开关,checked 信号双向绑定,disabled 支持布尔或信号禁用", - "select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画,disabled 支持布尔或信号禁用", - "menu(props):下拉菜单,触发器 + 自绘弹层,条目支持禁用 / 危险 / 分隔线,↑↓ 环形导航,点外部 / Esc 关闭", + "select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画,disabled 支持布尔或信号禁用,空间不足自动翻转", + "menu(props):下拉菜单,触发器 + 自绘弹层,条目支持禁用 / 危险 / 分隔线,↑↓ 环形导航,点外部 / Esc 关闭,空间不足自动翻转", + "flip(trigger, panel, preferred):浮层上下翻转判定,按触发器与面板的视口几何决定 preferred 方位放不下时是否翻转,返回实际生效方位 'top' | 'bottom'", "radioGroup(props):单选组,options + value 信号双向绑定,disabled 整组禁用", "accordion(props):折叠面板,标题按钮 + grid 行高过渡,单开(手风琴)或多开,支持禁用面板与 active 信号受控", "breadcrumb(props):面包屑,nav + ol 语义结构,末项为当前页(aria-current),有 href 走原生链接、无 href 交给 onNavigate", @@ -160,8 +161,8 @@ "avatar(props):头像,有 src 渲染图片(alt 用名称)、无 src 用首字占位,size 可调 + 四档语义底色", "alert(props):提示条,variant 四档语义色 + 可选 title 与 closable 关闭按钮,role=alert 读屏可播报", "toast.info/success/warning/error(message, duration?):消息提示工厂,右上角堆叠,默认 3s 自动消失,出入场微动画;showToast(props) 为完整入参版本(closable 显示关闭按钮,同屏最多 4 条)", - "tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起", - "popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素", + "tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起;视口一侧空间不足时自动翻转", + "popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素;视口一侧空间不足时自动翻转", "skeleton(props):骨架屏占位,variant = text | rect | circle,text 支持 rows 多行,扫光微动画", "pagination(props):独立分页器,page 信号双向绑定,页码过多折叠省略号,首末页禁用翻页,键盘可达", "spinner(props):加载指示器,size 控制直径", diff --git a/apps/demo/main.ts b/apps/demo/main.ts index f40dd08..441e513 100644 --- a/apps/demo/main.ts +++ b/apps/demo/main.ts @@ -214,7 +214,7 @@ const content = h( section( 'sec-form', '表单控件', - 'checkbox / switch / select / radioGroup / textarea:状态一律由调用方信号持有。', + 'checkbox / switch / select / radioGroup / textarea:状态一律由调用方信号持有;select 弹层在视口下方空间不足时自动翻到上方。', h('div', { class: 'row' }, checkbox({ label: '同意条款', checked: agreed }), h('span', { class: 'out' }, () => (agreed() ? '已同意' : '未同意'))), h('div', { class: 'row' }, switchButton({ label: '夜间模式', checked: nightMode }), h('span', { class: 'out' }, () => (nightMode() ? '开' : '关'))), h('div', { class: 'row' }, select({ options: cities.map((c) => ({ value: c, label: c })), value: city, placeholder: '选择城市…' }), h('span', { class: 'out' }, () => (city() ? `城市:${city()}` : '未选择'))), @@ -332,7 +332,7 @@ const content = h( section( 'sec-tooltip', '悬浮提示', - 'tooltip 包裹触发器:hover / 聚焦延迟 150ms 出场,移出、失焦或 Esc 收起,气泡不抢指针。', + 'tooltip 包裹触发器:hover / 聚焦延迟 150ms 出场,移出、失焦或 Esc 收起,气泡不抢指针;视口一侧空间不足时气泡自动翻到另一侧。', h( 'div', { class: 'row' }, @@ -568,7 +568,7 @@ const content = h( section( 'sec-menu', '下拉菜单', - 'menu 触发器 + 自绘弹层:条目支持禁用 / 危险 / 分隔线,↑↓ 环形导航,点外部或 Esc 收起。', + 'menu 触发器 + 自绘弹层:条目支持禁用 / 危险 / 分隔线,↑↓ 环形导航,点外部或 Esc 收起;视口下方空间不足时弹层自动翻到上方。', h( 'div', { class: 'row' }, @@ -599,7 +599,7 @@ const content = h( section( 'sec-popover', '气泡卡片', - 'popover:可交互弹层(tooltip 只展示,popover 里能点),点外部 / Esc 收起。', + 'popover:可交互弹层(tooltip 只展示,popover 里能点),点外部 / Esc 收起;视口下方空间不足时弹层自动翻到上方。', h( 'div', { class: 'row' }, diff --git a/llms-full.txt b/llms-full.txt index dfa3328..1b86303 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -1,6 +1,6 @@ # @ui-arch 组件库 Agent 文档(无图形版) -> 自动生成于 2026-10-26T02:24:35.622Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 +> 自动生成于 2026-10-26T02:50:02.720Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 ## 快速上手 @@ -1014,8 +1014,9 @@ API 速览: - slider(props):滑块,value 信号双向绑定,min/max/step 可配,原生 range 承载键盘交互,右侧可显示当前值 - checkbox(props):复选框,checked 信号双向绑定,disabled 支持布尔或信号禁用 - switchButton(props):开关,checked 信号双向绑定,disabled 支持布尔或信号禁用 -- select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画,disabled 支持布尔或信号禁用 -- menu(props):下拉菜单,触发器 + 自绘弹层,条目支持禁用 / 危险 / 分隔线,↑↓ 环形导航,点外部 / Esc 关闭 +- select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画,disabled 支持布尔或信号禁用,空间不足自动翻转 +- menu(props):下拉菜单,触发器 + 自绘弹层,条目支持禁用 / 危险 / 分隔线,↑↓ 环形导航,点外部 / Esc 关闭,空间不足自动翻转 +- flip(trigger, panel, preferred):浮层上下翻转判定,按触发器与面板的视口几何决定 preferred 方位放不下时是否翻转,返回实际生效方位 'top' | 'bottom' - radioGroup(props):单选组,options + value 信号双向绑定,disabled 整组禁用 - accordion(props):折叠面板,标题按钮 + grid 行高过渡,单开(手风琴)或多开,支持禁用面板与 active 信号受控 - breadcrumb(props):面包屑,nav + ol 语义结构,末项为当前页(aria-current),有 href 走原生链接、无 href 交给 onNavigate @@ -1025,8 +1026,8 @@ API 速览: - avatar(props):头像,有 src 渲染图片(alt 用名称)、无 src 用首字占位,size 可调 + 四档语义底色 - alert(props):提示条,variant 四档语义色 + 可选 title 与 closable 关闭按钮,role=alert 读屏可播报 - toast.info/success/warning/error(message, duration?):消息提示工厂,右上角堆叠,默认 3s 自动消失,出入场微动画;showToast(props) 为完整入参版本(closable 显示关闭按钮,同屏最多 4 条) -- tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起 -- popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素 +- tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起;视口一侧空间不足时自动翻转 +- popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素;视口一侧空间不足时自动翻转 - skeleton(props):骨架屏占位,variant = text | rect | circle,text 支持 rows 多行,扫光微动画 - pagination(props):独立分页器,page 信号双向绑定,页码过多折叠省略号,首末页禁用翻页,键盘可达 - spinner(props):加载指示器,size 控制直径 diff --git a/llms.txt b/llms.txt index 2748cd5..54a08a8 100644 --- a/llms.txt +++ b/llms.txt @@ -54,8 +54,9 @@ - slider(props):滑块,value 信号双向绑定,min/max/step 可配,原生 range 承载键盘交互,右侧可显示当前值 - checkbox(props):复选框,checked 信号双向绑定,disabled 支持布尔或信号禁用 - switchButton(props):开关,checked 信号双向绑定,disabled 支持布尔或信号禁用 - - select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画,disabled 支持布尔或信号禁用 - - menu(props):下拉菜单,触发器 + 自绘弹层,条目支持禁用 / 危险 / 分隔线,↑↓ 环形导航,点外部 / Esc 关闭 + - select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画,disabled 支持布尔或信号禁用,空间不足自动翻转 + - menu(props):下拉菜单,触发器 + 自绘弹层,条目支持禁用 / 危险 / 分隔线,↑↓ 环形导航,点外部 / Esc 关闭,空间不足自动翻转 + - flip(trigger, panel, preferred):浮层上下翻转判定,按触发器与面板的视口几何决定 preferred 方位放不下时是否翻转,返回实际生效方位 'top' | 'bottom' - radioGroup(props):单选组,options + value 信号双向绑定,disabled 整组禁用 - accordion(props):折叠面板,标题按钮 + grid 行高过渡,单开(手风琴)或多开,支持禁用面板与 active 信号受控 - breadcrumb(props):面包屑,nav + ol 语义结构,末项为当前页(aria-current),有 href 走原生链接、无 href 交给 onNavigate @@ -65,8 +66,8 @@ - avatar(props):头像,有 src 渲染图片(alt 用名称)、无 src 用首字占位,size 可调 + 四档语义底色 - alert(props):提示条,variant 四档语义色 + 可选 title 与 closable 关闭按钮,role=alert 读屏可播报 - toast.info/success/warning/error(message, duration?):消息提示工厂,右上角堆叠,默认 3s 自动消失,出入场微动画;showToast(props) 为完整入参版本(closable 显示关闭按钮,同屏最多 4 条) - - tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起 - - popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素 + - tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起;视口一侧空间不足时自动翻转 + - popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素;视口一侧空间不足时自动翻转 - skeleton(props):骨架屏占位,variant = text | rect | circle,text 支持 rows 多行,扫光微动画 - pagination(props):独立分页器,page 信号双向绑定,页码过多折叠省略号,首末页禁用翻页,键盘可达 - spinner(props):加载指示器,size 控制直径 diff --git a/packages/skin/ui/src/index.ts b/packages/skin/ui/src/index.ts index b97c867..59ddb77 100644 --- a/packages/skin/ui/src/index.ts +++ b/packages/skin/ui/src/index.ts @@ -20,6 +20,7 @@ export { alert } from './alert.js'; export { toast, showToast } from './toast.js'; export { tooltip } from './tooltip.js'; export { popover } from './popover.js'; +export { flip } from './position.js'; export { skeleton } from './skeleton.js'; export { pagination } from './pagination.js'; export { spinner } from './spinner.js'; diff --git a/packages/skin/ui/src/menu.ts b/packages/skin/ui/src/menu.ts index 0e7a650..59c2972 100644 --- a/packages/skin/ui/src/menu.ts +++ b/packages/skin/ui/src/menu.ts @@ -1,10 +1,12 @@ import { effect, h, signal } from '@ui-arch/frame'; import type { MenuItem, MenuProps } from './types.js'; +import { flip } from './position.js'; /*** 下拉菜单:触发器 + 自绘弹层,项支持禁用 / 危险 / 分隔线;点项 / 点外部 / Esc 关闭,↑↓ 环形导航 + Home/End 跳转 ***/ export function menu(props: MenuProps): HTMLElement { // —— 状态集中声明 —— const open = signal(false); // 弹层开合 + const place = signal<'top' | 'bottom'>('bottom'); // 实际生效方位:打开时按视口空间自动翻转 const focusables: HTMLButtonElement[] = []; // 可聚焦项(跳过分隔线与禁用项),供键盘导航 const pick = (item: MenuItem): void => { @@ -47,7 +49,7 @@ export function menu(props: MenuProps): HTMLElement { const pop = h( 'div', { - class: () => `ua-menu-pop${open() ? ' ua-open' : ''}${props.align === 'end' ? ' is-end' : ''}`, + class: () => `ua-menu-pop${open() ? ' ua-open' : ''}${place() === 'top' ? ' is-flip' : ''}${props.align === 'end' ? ' is-end' : ''}`, role: 'menu', }, ...rows, @@ -81,5 +83,6 @@ export function menu(props: MenuProps): HTMLElement { }); effect(() => open()); // 建立依赖,保证开合信号生效 + effect(() => { if (open()) place(flip(trigger, pop, 'bottom')); }); // 每次打开重算方位:空间不足自动翻转 return root; } diff --git a/packages/skin/ui/src/popover.ts b/packages/skin/ui/src/popover.ts index 15035d1..e53c14c 100644 --- a/packages/skin/ui/src/popover.ts +++ b/packages/skin/ui/src/popover.ts @@ -1,5 +1,6 @@ import { effect, h, signal } from '@ui-arch/frame'; import type { PopoverProps } from './types.js'; +import { flip } from './position.js'; let seq = 0; // 全局自增序号:保证每个弹层 id 唯一,供 aria-controls 关联 @@ -7,6 +8,7 @@ let seq = 0; // 全局自增序号:保证每个弹层 id 唯一,供 aria-con export function popover(props: PopoverProps, trigger: HTMLElement): HTMLElement { // —— 状态集中声明 —— const open = signal(false); // 弹层显隐 + const place = signal(props.placement ?? 'bottom'); // 实际生效方位:打开时按视口空间自动翻转 const id = `ua-pop-${++seq}`; // 弹层唯一 id let timer: number | null = null; // hover 模式下的出入场计时器 @@ -24,7 +26,7 @@ export function popover(props: PopoverProps, trigger: HTMLElement): HTMLElement 'div', { id, - class: () => `ua-pop ua-pop-${props.placement ?? 'bottom'}${open() ? ' ua-open' : ''}`, + class: () => `ua-pop ua-pop-${place()}${open() ? ' ua-open' : ''}`, role: 'dialog', 'aria-hidden': () => String(!open()), onClick: (e: Event) => e.stopPropagation(), // 弹层内点击不触发外部关闭 @@ -55,6 +57,7 @@ export function popover(props: PopoverProps, trigger: HTMLElement): HTMLElement trigger.focus(); // 收起后焦点回触发器 }); document.addEventListener('click', () => setOpen(false)); // 点外部收起(弹层内已阻止冒泡) + effect(() => { if (open()) place(flip(trigger, panel, props.placement ?? 'bottom')); }); // 每次打开重算方位:空间不足自动翻转 return root; } diff --git a/packages/skin/ui/src/position.ts b/packages/skin/ui/src/position.ts new file mode 100644 index 0000000..22e08ac --- /dev/null +++ b/packages/skin/ui/src/position.ts @@ -0,0 +1,11 @@ +/*** 浮层上下翻转判定:按触发器与面板的视口几何判断首选方位是否放得下,放不下且另一侧更宽敞则翻转;返回实际生效方位 'top' | 'bottom' ***/ +export function flip(trigger: HTMLElement, panel: HTMLElement, preferred: 'top' | 'bottom'): 'top' | 'bottom' { + const GAP = 8; // 与 CSS 预留的浮层间距一致(popover 为 8px) + const MIN = 24; // 兜底:面板尚未量出高度时按最小可读高度估算 + const t = trigger.getBoundingClientRect(); // 触发器视口矩形 + const h = panel.offsetHeight || MIN; // 面板高度(visibility:hidden 仍占布局,可直接量) + const up = t.top; // 触发器上方可用空间 + const down = window.innerHeight - t.bottom; // 触发器下方可用空间 + if (preferred === 'top') return up >= h + GAP || up >= down ? 'top' : 'bottom'; // 首选上方:放得下、或不比下方更局促就保持 + return down >= h + GAP || down >= up ? 'bottom' : 'top'; // 首选下方:对称判定 +} diff --git a/packages/skin/ui/src/select.ts b/packages/skin/ui/src/select.ts index 917ae31..c924733 100644 --- a/packages/skin/ui/src/select.ts +++ b/packages/skin/ui/src/select.ts @@ -1,10 +1,12 @@ import { effect, h, signal } from '@ui-arch/frame'; import type { SelectProps } from './types.js'; +import { flip } from './position.js'; /*** 下拉选择:自绘弹层替代原生 select,value 信号双向绑定;支持 ↑↓/Home/End 键盘导航,点选项 / 点外部 / Esc 关闭 ***/ export function select(props: SelectProps): HTMLElement { // —— 状态集中声明 —— const open = signal(false); // 弹层开合 + const place = signal<'top' | 'bottom'>('bottom'); // 实际生效方位:打开时按视口空间自动翻转 const value = props.value ?? signal(''); // 选中值;未传信号则内部持有 const labelOf = (v: string) => props.options.find((o) => o.value === v)?.label ?? ''; @@ -45,7 +47,7 @@ export function select(props: SelectProps): HTMLElement { opt.label, ), ); - const pop = h('div', { class: () => `ua-select-pop${open() ? ' ua-open' : ''}`, role: 'listbox' }, ...options); + const pop = h('div', { class: () => `ua-select-pop${open() ? ' ua-open' : ''}${place() === 'top' ? ' is-flip' : ''}`, role: 'listbox' }, ...options); const root = h('div', { class: () => `ua-select${open() ? ' ua-open' : ''}` }, trigger, pop); // 根带开合类,供箭头旋转 @@ -68,5 +70,6 @@ export function select(props: SelectProps): HTMLElement { open(false); // 点外部关闭 }); effect(() => open()); // 建立依赖,保证开合信号生效 + effect(() => { if (open()) place(flip(trigger, pop, 'bottom')); }); // 每次打开重算方位:空间不足自动翻转 return root; } diff --git a/packages/skin/ui/src/tooltip.ts b/packages/skin/ui/src/tooltip.ts index f85cc92..0919c28 100644 --- a/packages/skin/ui/src/tooltip.ts +++ b/packages/skin/ui/src/tooltip.ts @@ -1,5 +1,6 @@ -import { h, signal } from '@ui-arch/frame'; +import { effect, h, signal } from '@ui-arch/frame'; import type { TooltipProps } from './types.js'; +import { flip } from './position.js'; let seq = 0; // 全局自增序号:保证每个气泡 id 唯一,供 aria-describedby 关联 @@ -7,6 +8,7 @@ let seq = 0; // 全局自增序号:保证每个气泡 id 唯一,供 aria-des export function tooltip(props: TooltipProps, trigger: HTMLElement): HTMLElement { // —— 状态集中声明 —— const open = signal(false); // 气泡显隐 + const place = signal(props.placement ?? 'top'); // 实际生效方位:出场时按视口空间自动翻转 const id = `ua-tip-${++seq}`; // 气泡唯一 id const delay = props.delay ?? 150; // 出场延迟毫秒;<=0 视为立即显示 let timer: number | null = null; // 出场延迟计时器句柄 @@ -33,7 +35,7 @@ export function tooltip(props: TooltipProps, trigger: HTMLElement): HTMLElement 'span', { id, - class: () => `ua-tip ua-tip-${props.placement ?? 'top'}${open() ? ' ua-open' : ''}`, + class: () => `ua-tip ua-tip-${place()}${open() ? ' ua-open' : ''}`, role: 'tooltip', 'aria-hidden': () => String(!open()), }, @@ -45,6 +47,7 @@ export function tooltip(props: TooltipProps, trigger: HTMLElement): HTMLElement root.addEventListener('pointerleave', hide); // 鼠标离开 root.addEventListener('focusin', show); // 键盘聚焦(focusin 会冒泡) root.addEventListener('focusout', hide); // 失焦 + effect(() => { if (open()) place(flip(trigger, bubble, props.placement ?? 'top')); }); // 每次出场重算方位:空间不足自动翻转 root.addEventListener('keydown', (e: KeyboardEvent) => { if (e.key === 'Escape') hide(); // Esc 立即收起,不必等延迟 }); diff --git a/packages/skin/ui/ua.manifest.json b/packages/skin/ui/ua.manifest.json index 4b06162..9ea20f9 100644 --- a/packages/skin/ui/ua.manifest.json +++ b/packages/skin/ui/ua.manifest.json @@ -20,8 +20,9 @@ "slider(props):滑块,value 信号双向绑定,min/max/step 可配,原生 range 承载键盘交互,右侧可显示当前值", "checkbox(props):复选框,checked 信号双向绑定,disabled 支持布尔或信号禁用", "switchButton(props):开关,checked 信号双向绑定,disabled 支持布尔或信号禁用", - "select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画,disabled 支持布尔或信号禁用", - "menu(props):下拉菜单,触发器 + 自绘弹层,条目支持禁用 / 危险 / 分隔线,↑↓ 环形导航,点外部 / Esc 关闭", + "select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画,disabled 支持布尔或信号禁用,空间不足自动翻转", + "menu(props):下拉菜单,触发器 + 自绘弹层,条目支持禁用 / 危险 / 分隔线,↑↓ 环形导航,点外部 / Esc 关闭,空间不足自动翻转", + "flip(trigger, panel, preferred):浮层上下翻转判定,按触发器与面板的视口几何决定 preferred 方位放不下时是否翻转,返回实际生效方位 'top' | 'bottom'", "radioGroup(props):单选组,options + value 信号双向绑定,disabled 整组禁用", "accordion(props):折叠面板,标题按钮 + grid 行高过渡,单开(手风琴)或多开,支持禁用面板与 active 信号受控", "breadcrumb(props):面包屑,nav + ol 语义结构,末项为当前页(aria-current),有 href 走原生链接、无 href 交给 onNavigate", @@ -31,8 +32,8 @@ "avatar(props):头像,有 src 渲染图片(alt 用名称)、无 src 用首字占位,size 可调 + 四档语义底色", "alert(props):提示条,variant 四档语义色 + 可选 title 与 closable 关闭按钮,role=alert 读屏可播报", "toast.info/success/warning/error(message, duration?):消息提示工厂,右上角堆叠,默认 3s 自动消失,出入场微动画;showToast(props) 为完整入参版本(closable 显示关闭按钮,同屏最多 4 条)", - "tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起", - "popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素", + "tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起;视口一侧空间不足时自动翻转", + "popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素;视口一侧空间不足时自动翻转", "skeleton(props):骨架屏占位,variant = text | rect | circle,text 支持 rows 多行,扫光微动画", "pagination(props):独立分页器,page 信号双向绑定,页码过多折叠省略号,首末页禁用翻页,键盘可达", "spinner(props):加载指示器,size 控制直径", diff --git a/packages/skin/ui/ui.css b/packages/skin/ui/ui.css index ba19c67..69ed123 100644 --- a/packages/skin/ui/ui.css +++ b/packages/skin/ui/ui.css @@ -284,6 +284,11 @@ visibility: hidden; transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s; } +.ua-select-pop.is-flip { + top: auto; /* 空间不足翻到触发器上方 */ + bottom: calc(100% + 4px); + transform: translateY(4px); /* 入场方向随翻转镜像:从下方 4px 滑入 */ +} .ua-select-pop.ua-open { opacity: 1; transform: none; @@ -354,6 +359,11 @@ left: auto; right: 0; } +.ua-menu-pop.is-flip { + top: auto; /* 空间不足翻到触发器上方 */ + bottom: calc(100% + 4px); + transform: translateY(4px); /* 入场方向随翻转镜像:从下方 4px 滑入 */ +} .ua-menu-pop.ua-open { opacity: 1; transform: none;