From 7f465fc6d7e871ec57f85a57f3fd7a7aa681e591 Mon Sep 17 00:00:00 2001 From: Kinneyzhang Date: Fri, 28 Aug 2026 22:06:57 +0800 Subject: [PATCH] refactor: migrate UI styles to canonical properties --- README.md | 7 ++++--- README.zh-CN.md | 7 ++++--- etaf-ui.el | 14 ++++++++------ tests/etaf-ui-tests.el | 6 ++++-- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 0291b91..10b8c8f 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ definition and API names. Button and Checkbox are controlled Components. `etaf-button` accepts `:label`, `:on-press`, `:disabled`, `:ref`, and the small presentation set -`:class`, `:color`, `:bgcolor`, `:border`, `:padding`, `:face`, `:tab-index`, +`:class`, `:color`, `:bgcolor`, `:border`, `:padding`, `:font-weight`, `:tab-index`, and `:aria-label`, plus `:use` for a public Behavior list. An enabled button defaults to role `button` and tab index `0`; a disabled button keeps its label and disabled styling but has no press handler, Behavior, or tab stop. @@ -70,8 +70,9 @@ Spacing is owned by the parent layout, not by Button. Put adjacent controls in a `row`/`flex` with an explicit horizontal `:gap`; this keeps each control's mouse-face and hit range semantically separate. -`etaf-label` accepts `:text`, `:face`, `:class`, `:color`, `:bgcolor`, `:width`, -`:border`, `:padding`, and `:ref`. `etaf-panel` accepts `:title`, the same +`etaf-label` accepts `:text`, `:class`, `:color`, `:bgcolor`, `:font-weight`, +`:width`, `:border`, `:padding`, and `:ref`. +`etaf-panel` accepts `:title`, the same surface presentation props, and projects the named `header` slot plus the default slot. diff --git a/README.zh-CN.md b/README.zh-CN.md index b1fe370..5bd9988 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -25,7 +25,7 @@ Button 和 Checkbox 都是受控组件。`etaf-button` 支持 `:label`、 `:on-press`、`:disabled`、`:ref`,以及最小 presentation 属性 -`:class`、`:color`、`:bgcolor`、`:border`、`:padding`、`:face`、 +`:class`、`:color`、`:bgcolor`、`:border`、`:padding`、`:font-weight`、 `:tab-index`、`:aria-label` 和公共 Behavior 列表 `:use`。启用按钮默认使用 `button` role 和 `tab-index 0`;禁用按钮仍显示标签和禁用样式,但没有 press 回调、Behavior,也不进入 tab 顺序。`etaf-checkbox` 支持 `:checked`、`:label`、`:on-change`、 @@ -61,8 +61,9 @@ Component 的 `:styles` 声明负责默认外观。调用者提供的非 nil pre 间距由父布局负责,而不是由 Button 偷塞。相邻控件应放在带明确横向 `:gap` 的 `row`/`flex` 中,这样每个控件的 mouse-face 和命中范围才保持语义独立。 -`etaf-label` 支持 `:text`、`:face`、`:class`、`:color`、`:bgcolor`、`:width`、 -`:border`、`:padding` 和 `:ref`。`etaf-panel` 支持 `:title`、相同的 +`etaf-label` 支持 `:text`、`:class`、`:color`、`:bgcolor`、`:font-weight`、 +`:width`、`:border`、`:padding` 和 `:ref`。 +`etaf-panel` 支持 `:title`、相同的 surface presentation 属性,并投影命名的 `header` slot 和默认 slot。 DataGrid 支持列描述、函数型 `:row-key`,以及可选的 diff --git a/etaf-ui.el b/etaf-ui.el index 4484225..1843f7b 100644 --- a/etaf-ui.el +++ b/etaf-ui.el @@ -145,15 +145,15 @@ Component render depend on the Theme source." "Return Ebox border VALUE, preserving complete caller-owned specs. Semantic Theme border tokens conventionally contain a color string. The -catalog turns a hex color into its one-cell border shape; an existing border -plist or a legacy caller-owned string remains untouched for compatibility." +catalog turns a hex color into a one-pixel solid border; an existing canonical +border value remains unchanged." (cond ((etaf-theme-token-p value) (etaf-theme-token (nth 1 value) (nth 2 value) #'etaf-ui--theme-border)) ((and (stringp value) (string-match-p "\\`#[[:xdigit:]]+\\'" value)) - (list (list 1) 'solid value)) + (list 1 'solid value)) (t value))) (defun etaf-ui--class-value (base state custom) @@ -200,7 +200,8 @@ plist or a legacy caller-owned string remains untouched for compatibility." "Return a Button Host showing LABEL. ON-PRESS and USE provide callbacks and Behaviors. DISABLED controls whether -the Host is interactive. REF, CLASS, COLOR, BGCOLOR, BORDER, PADDING, FACE, +the Host is interactive. REF, CLASS, COLOR, BGCOLOR, BORDER, PADDING, +FONT-WEIGHT, TAB-INDEX, and ARIA-LABEL provide Host identity and presentation." (let ((class-value (etaf-ui--class-value "etaf-button" @@ -384,7 +385,8 @@ ROW-ACTIONS owns stable keyed callbacks across body reevaluation." :ref host-ref :role (when interactive-p 'button) :tab-index (when interactive-p 0) - :border-bottom-p t + :border-bottom-width 1 + :border-bottom-style 'solid :border-bottom-color (plist-get theme :ui-grid-border) :on-press (when interactive-p (etaf-ui--grid-row-action @@ -897,7 +899,7 @@ readable in both GUI and text review." (plist-get theme :ui-fg))) (parent-bgcolor (or (etaf-current-prop :bgcolor) (plist-get theme :ui-bg))) - (arrow-border '((0) solid "transparent"))) + (arrow-border '(0 solid "transparent"))) (setq current-controller controller-value current-parent-color parent-color current-parent-bgcolor parent-bgcolor) diff --git a/tests/etaf-ui-tests.el b/tests/etaf-ui-tests.el index e1d5db8..caaa76a 100644 --- a/tests/etaf-ui-tests.el +++ b/tests/etaf-ui-tests.el @@ -665,8 +665,10 @@ (should (equal "light-grid-border" (etaf-ui-test--paint-color border-slot :border-bottom-color))) - (should (plist-get (etaf-ui-test--props-with-key buffer-name 1) - :border-bottom-p)) + (let ((row-props + (etaf-ui-test--props-with-key buffer-name 1))) + (should (= (plist-get row-props :border-bottom-width) 1)) + (should (eq (plist-get row-props :border-bottom-style) 'solid))) (setf (etaf-value theme) '(:color "dark-ink" :ui-grid-border "dark-grid-border" :ui-grid-selected-fg "dark-selected"