etaf-ui/README.zh-CN.md
2026-08-22 06:19:05 +08:00

4.1 KiB
Raw Blame History

etaf-ui

etaf-ui 是 ETAF 的官方 Component 目录,是建立在 etaf 之上的可选独立包。它不增加第二套 Control 或 Widget 模型Button、Checkbox、Label、Panel、DataGrid 都是使用同一套 View、属性、slot、事件和 Data 契约的普通 Component。

(require 'etaf-ui)

(let ((done (etaf-ref nil)))
  (etaf-view
   (panel :title "Account"
    (slot :name 'header
          (button :label "Save" :ref 'save-button
                  :on-press (lambda () (message "saved"))))
    (label :text "Preferences")
    (checkbox :checked (etaf-value done) :label "Done"
              :ref 'done-checkbox
              :on-change (lambda (next)
                           (setf (etaf-value done) next))))))

.etaf 文件的结构使用已注册的短标签(panellabelbuttoncheckboxdata-grid)。配套 .el 文件负责响应式值、Action、Behavior 和回调;其中 etaf-view 也使用同一组短标签。Elisp 定义和 API 文档仍使用 规范的 etaf-* 名称。

Button 和 Checkbox 都是受控组件。etaf-button 支持 :label:on-press:disabled:ref,以及最小 presentation 属性 :class:color:bgcolor:border:padding:face:tab-index:aria-label 和公共 Behavior 列表 :use。启用按钮默认使用 button role 和 tab-index 0;禁用按钮仍显示标签和禁用样式,但没有 press 回调、Behavior也不进入 tab 顺序。etaf-checkbox 支持 :checked:label:on-change:disabled:ref 及相同的 presentation 属性。启用时它提供 checkbox role、稳定的 :reftab-index 0:on-change 接收下一个 布尔值。禁用 checkbox 没有回调或 tab stop。

Component 的 :styles 声明负责默认外观。调用者提供的非 nil presentation 属性会覆盖默认值;省略或传 nil 时,继承的 Theme/默认样式仍可生效。Button 只提供刻意收敛的 primarysecondaryghost 三种视觉 variant这是 视觉状态集合,不是第二套 widget 分类体系。

启用的 button 和 checkbox 共享同一套交互反馈:小手指针、mouse-face 悬停 反馈、可读的 help-echo、数字 tab stop 和语义 role。Button 按下时短暂进入 pressed 外观。禁用控件保留文字和禁用样式,但没有回调、指针激活或 tab stop。 显式 :on-* 回调和 Behavior 回调的组合由 Runtime 负责UI 包只声明控件和 视觉状态。

间距由父布局负责,而不是由 Button 偷塞。相邻控件应放在带明确横向 :gaprow/flex 中,这样每个控件的 mouse-face 和命中范围才保持语义独立。

etaf-label 支持 :text:face:class:color:bgcolor:width:border:padding:refetaf-panel 支持 :title、相同的 surface presentation 属性,并投影命名的 header slot 和默认 slot。

DataGrid 支持列描述、函数型 :row-key,以及可选的 :loading-label:error-label:empty-label:selected-key 或函数型 :row-selected-p。提供 :on-row-press 后,每一行都是可交互 button必须 提供 :row-ref,它对每一行返回非 nil 的稳定 Host ref行会获得 button role 和 tab-index 0,且回调接收该行。没有 :on-row-press 时, 行没有回调或 tab stop。:row-key 仍然是 retained row 必须具备的非 nil 稳定标量 identity。

etaf-pagination 是受控 Data Component。它接收 Data controller 以及稳定的 :previous-ref:next-ref,显示易读的 / 控件和 Page N / M 摘要; 加载中或已经位于首/末页时会禁用对应动作。它不拥有页码状态,并复用 Button 的交互契约。

键盘焦点使用 ETAF 的公共 Runtime 端口:用 (etaf-focus-next runtime) 在带数值且非负 :tab-index 的可见 Host 之间 移动;需要代码触发动作时使用 (etaf-dispatch-event runtime ref 'press)。禁用控件和不可交互的 DataGrid 行不会进入 tab 顺序。

在该目录运行 make check EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs