Merge branch 'main' into worktree-agent-ad7403b5194d75449

This commit is contained in:
ZacharyZhang-NY committed 2026-10-05 12:22:05 -04:00
commit 2c0134975b
227 files changed
+13252 -30

No files matched your search

+53
View File
@@ -0,0 +1,53 @@
# 001 AppShell 应用外壳
## 用途
搭建桌面窗口的整体骨架:顶部标题栏、左侧侧栏、主内容区和底部状态栏四个插槽。侧栏可折叠为只含切换按钮的窄条;侧栏与主内容各自独立滚动。
## 最小示例
```go
var collapsed bool
mujica.AppShell(c, &collapsed, mujica.AppShellOptions{
TitleBar: func() { mujica.TitleBar(c, "Court Records", mujica.TitleBarOptions{}) },
Sidebar: func() { ui.Text(c, "Chronicles") },
Content: func() { ui.Text(c, "The Grand Hall") },
})
```
签名:`func AppShell(c *ui.Context, collapsed *bool, opts AppShellOptions) AppShellResult`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `collapsed` | `*bool` | 必填 | 侧栏是否折叠,由应用持有;为 nil 时 panic。 |
| `TitleBar` | `func()` | nil | 顶部插槽,通常放 `TitleBar`。 |
| `Sidebar` | `func()` | nil | 侧栏内容,自带独立滚动;为 nil 时没有侧栏与折叠快捷键。 |
| `Content` | `func()` | 必填 | 主内容,自带独立滚动;为 nil 时 panic。 |
| `StatusBar` | `func()` | nil | 底部插槽,通常放 `StatusBar`。 |
| `SidebarWidth` | `float32` | 240 | 展开时侧栏宽度(DIP);负数 panic。 |
| `ContentScroll` | `*ui.ScrollState` | nil | 保存主内容滚动位置;nil 时按位置保留。 |
返回 `AppShellResult`,内嵌 `*ui.Element`。
## 状态
- 展开:侧栏宽 `SidebarWidth`,顶部右侧为收起按钮。
- 折叠:侧栏收为 `28 + 4 单位` 的窄条,只保留展开按钮。宽度变化 120 ms,减少动画时直接切换。
- 切换按钮有悬停、按下和键盘焦点环;折叠不会重置主内容滚动位置。
## 事件
- `Toggled`:本帧侧栏被展开或折叠(按钮或快捷键),只触发一次。
## 键盘操作
- `Cmd+B`(macOS)/ `Ctrl+B`(其他平台):切换侧栏。焦点控件先处理该键,富文本等若占用此键则不会触发。
- Tab 依次到达切换按钮、侧栏与内容中的控件;滚动区域内容溢出时可获得焦点,方向键、Page Up/Down、Home、End 滚动。
## 限制
- 窄窗口不会自动折叠,由应用根据窗口宽度设置 `*collapsed`。
- 折叠动画期间侧栏内容立即隐藏,只有宽度过渡。
- 快捷键固定为 Cmd/Ctrl+B,不可配置。
+43
View File
@@ -0,0 +1,43 @@
# 002 TitleBar 标题栏
## 用途
窗口顶部的标题行:衬线体应用标题、前后工具插槽。空白处可拖动窗口,并为系统窗口按钮留出空间。配合 `mygo.TitleBarHidden` 使用。
## 最小示例
```go
mujica.TitleBar(c, "Court Records", mujica.TitleBarOptions{
Trailing: func() { mujica.Button(c, "Share", mujica.ButtonOptions{Variant: mujica.Ghost}) },
})
```
签名:`func TitleBar(c *ui.Context, title string, opts TitleBarOptions) *ui.Element`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `title` | `string` | 必填 | 标题文字,过长时单行省略。 |
| `Leading` | `func()` | nil | 标题前的工具,如侧栏开关。 |
| `Trailing` | `func()` | nil | 标题后的工具。 |
## 状态
- 高度取 `c.TitleBar().Height` 与 `控件高度 + 2 单位` 中较大者(默认密度 44 DIP)。
- 左右内边距在 `c.TitleBar().Left/Right` 之外再加 3 单位,不覆盖系统按钮;全屏时预留为 0。
- Surface 底色,底部 1 DIP Border 分隔线。
## 事件
TitleBar 本身无事件;插槽中控件照常报告 `Clicked` 等事件。
## 键盘操作
插槽控件照常接受 Tab、Enter、Space。标题栏本身不获取焦点。
## 限制
- 拖动、双击缩放由 MyGo `DragWindow` 实现,只作用于非交互区域;需真机验证,无窗口测试无法覆盖。
- 系统窗口按钮外观由系统决定,不换肤。
- 普通有标题栏的窗口中 `c.TitleBar()` 为零,组件只是一行普通标题。
+63
View File
@@ -0,0 +1,63 @@
# 003 StatusBar 状态栏
## 用途
窗口底部的状态条,分左右两组条目:状态文字、图标、进度与可点击操作。宽度不足时自动隐藏次要条目,并显示剩余数量。
## 最小示例
```go
bar := mujica.StatusBar(c, mujica.StatusBarOptions{
Left: []mujica.StatusItem{{ID: "sync", Text: "Syncing", ShowProgress: true, Progress: 0.4}},
Right: []mujica.StatusItem{{ID: "bell", Label: "Notifications", Icon: icons.Must("bell"), Action: true}},
})
if bar.Clicked == "bell" {
opened++
}
```
签名:`func StatusBar(c *ui.Context, opts StatusBarOptions) StatusBarResult`
## 参数
`StatusBarOptions`
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Left` | `[]StatusItem` | nil | 左侧条目,从左到右。 |
| `Right` | `[]StatusItem` | nil | 右侧条目,从左到右。 |
`StatusItem`
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `ID` | `string` | 必填 | 稳定键,也是 `Clicked` 的值;为空或重复 panic。 |
| `Text` | `string` | "" | 状态文字(12 DIP)。 |
| `Icon` | `*ui.SVG` | nil | 前置图标(14 DIP)。 |
| `Tone` | `StatusItemTone` | `StatusItemNeutral` | 语义色:Neutral、Success、Warning、Danger、Info。 |
| `ShowProgress` | `bool` | false | 显示 64 DIP 进度条。 |
| `Progress` | `float32` | 0 | 进度 0–1,超出 panic。 |
| `Action` | `bool` | false | 条目成为按钮。 |
| `Label` | `string` | "" | 无文字条目的无障碍名称;`Text` 与 `Label` 都为空时 panic。 |
| `Secondary` | `bool` | false | 空间不足时优先隐藏。 |
## 状态
- 默认:Surface 底色,顶部 Border 线,组内条目以细线分隔。
- 操作条目:悬停 SurfaceHover,按下 Selection,键盘焦点环。
- 折叠:按“右组末项 → 左组首项”的顺序隐藏 `Secondary` 条目,直到放得下;显示 `+N`,悬停提示列出被隐藏条目,无障碍名称为“另有 N 项”。主要条目永不隐藏。
- 进度:AccentText 填充,Border 轨道,描述为百分比。
## 事件
- `Clicked`:本帧被点击的操作条目 ID,没有则为空。一次点击只报告一次。
## 键盘操作
Tab 到达操作条目,Enter 或 Space 触发。纯文字条目不进入 Tab 序列。
## 限制
- 折叠依据上一帧的宽度和文字测量估算,窗口缩放后下一帧生效。
- 被隐藏条目只在 `+N` 的提示中列出,提示仅悬停可见,键盘用户通过无障碍名称得知数量。
- 不提供不确定进度动画;需要时在 `Text` 中说明。
+45
View File
@@ -0,0 +1,45 @@
# 004 Container 容器
## 用途
为一组内容提供内边距、最大宽度、水平居中、填充父级和裁剪,适合正文、设置页等需要可读行宽的区域。
## 最小示例
```go
mujica.Container(c, mujica.ContainerOptions{MaxWidth: 320, Center: true}, func() {
ui.Text(c, "A centered column of prose.")
})
```
签名:`func Container(c *ui.Context, opts ContainerOptions, children func()) *ui.Element`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Padding` | `Space` | `SpaceL`(4 单位,默认密度 16 DIP) | 四周内边距,随密度缩放。 |
| `MaxWidth` | `float32` | 0(不限) | 最大宽度 DIP;负数 panic。 |
| `Center` | `bool` | false | 占满父级宽度后受 `MaxWidth` 限制并水平居中。 |
| `Fill` | `bool` | false | 占满父级内容区(宽和高)。 |
| `Clip` | `bool` | false | 裁剪超出的内容。 |
| `children` | `func()` | 必填 | 子内容,纵向排列;nil 时 panic。 |
`Space` 取值:`SpaceDefault`(组件默认)、`SpaceNone`、`SpaceXS`(1 单位)、`SpaceS`(2)、`SpaceM`(3)、`SpaceL`(4)、`SpaceXL`(6)、`SpaceXXL`(8)。单位为 Compact 3、Default 4、Comfortable 5 DIP。非法值 panic。
## 状态
布局组件,无交互状态。不绘制背景,可在返回的元素上调用 `Background`、`Border`。
## 事件
无。
## 键盘操作
不获取焦点。
## 限制
- 只做水平居中;垂直居中请用 `Stack` 的对齐或 MyGo `Center()`。
- 子内容固定纵向排列,需要横向时在内部放 `Stack`。
+49
View File
@@ -0,0 +1,49 @@
# 005 Stack 堆叠
## 用途
按横向或纵向排列子元素,统一间距、对齐与换行。用 `StackItem` 包裹可隐藏的子项,隐藏时不占位置也不留间距。
## 最小示例
```go
mujica.Stack(c, mujica.StackOptions{Horizontal: true, Gap: mujica.SpaceM}, func() {
mujica.Button(c, "Save", mujica.ButtonOptions{})
mujica.StackItem(!showDraft, func() { mujica.Button(c, "Draft", mujica.ButtonOptions{Variant: mujica.Secondary}) })
mujica.Button(c, "Cancel", mujica.ButtonOptions{Variant: mujica.Ghost})
})
```
签名:
- `func Stack(c *ui.Context, opts StackOptions, children func()) *ui.Element`
- `func StackItem(hidden bool, build func())`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Horizontal` | `bool` | false | 横向排列;否则纵向。 |
| `Gap` | `Space` | `SpaceS`(2 单位) | 子项间距,随密度缩放。 |
| `Align` | `StackAlign` | `StackAlignAuto` | 交叉轴对齐:Auto(纵向拉伸、横向居中)、Start、Center、End、Stretch;非法值 panic。 |
| `Justify` | `ui.Align` | `ui.Start` | 主轴分布:Start、Center、End、SpaceBetween、SpaceAround、SpaceEvenly。 |
| `Wrap` | `bool` | false | 横向换行;纵向时设置会 panic。 |
`StackItem`:`hidden` 为 true 时不构建 `build`,因此既不占空间也不产生间距。`build` 为 nil 时 panic。
## 状态
布局组件,无交互状态。
## 事件
无。
## 键盘操作
不获取焦点;Tab 顺序即子项构建顺序。
## 限制
- 隐藏项不会被构建,其内部界面状态(如未提交的输入)随之丢弃;需要保留时把状态放在应用中。
- 只有横向支持换行。
+57
View File
@@ -0,0 +1,57 @@
# 006 Grid 网格
## 用途
按行列排布子元素:列宽可为固定尺寸、按内容或按比例分配剩余空间;子项可指定位置与跨行跨列。基于 MyGo 网格布局。
## 最小示例
```go
mujica.Grid(c, mujica.GridOptions{Columns: []ui.Track{ui.Fixed(96), ui.Fr(1)}}, func() {
mujica.GridCell(c, mujica.GridCellOptions{ColumnSpan: -1}, func() { ui.Text(c, "Header") })
ui.Text(c, "Name")
ui.Text(c, "Ada")
})
```
签名:
- `func Grid(c *ui.Context, opts GridOptions, children func()) *ui.Element`
- `func GridCell(c *ui.Context, opts GridCellOptions, build func()) *ui.Element`
## 参数
`GridOptions`
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Columns` | `[]ui.Track` | 一列 `Fr(1)` | 各列尺寸:`ui.Fixed(dip)`、`ui.Fr(n)`(分配剩余空间)、`ui.FitContent()`。 |
| `Rows` | `[]ui.Track` | nil | 前几行尺寸;之后自动添加的行按内容高度。 |
| `Gap` | `Space` | `SpaceM`(3 单位) | 列间距,也是默认行间距。 |
| `RowGap` | `Space` | 同 `Gap` | 行间距。 |
`GridCellOptions`
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Column`, `Row` | `int` | 0(自动放置) | 起始列、行,从 1 计;负数 panic。 |
| `ColumnSpan`, `RowSpan` | `int` | 1 | 跨越轨道数;-1 跨到最后一条;小于 -1 panic。 |
`GridCell` 内的单个子元素会拉伸铺满整个单元格,与网格直接子项一致。
## 状态
布局组件,无交互状态。
## 事件
无。
## 键盘操作
不获取焦点;Tab 顺序为构建顺序。
## 限制
- 网格会构建全部子项;大量条目请使用虚拟化列表。
- 不校验跨度是否超出列数,超出时由 MyGo 按其规则扩展。
+49
View File
@@ -0,0 +1,49 @@
# 007 ScrollArea 滚动区域
## 用途
纵向、横向或双向滚动内容。支持滚轮、触控板、滚动条拖动与键盘;可读取、设置并保留滚动位置。基于 MyGo `ui.Scroll`。
## 最小示例
```go
var offset ui.ScrollState
mujica.ScrollArea(c, &offset, mujica.ScrollAreaOptions{Label: "Log"}, func() {
for range 50 {
ui.Text(c, "A line of the log")
}
}).Height(200)
```
签名:`func ScrollArea(c *ui.Context, state *ui.ScrollState, opts ScrollAreaOptions, children func()) *ui.Element`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `state` | `*ui.ScrollState` | nil | 滚动位置。设置 `X`/`Y` 即滚动到该处,`math.MaxFloat32` 表示末尾;组件写回 `MaxX`/`MaxY`。nil 时按区域在视图中的位置保留。 |
| `Direction` | `ScrollDirection` | `ScrollVertical` | `ScrollVertical`、`ScrollHorizontal`、`ScrollBoth`;非法值 panic。 |
| `Label` | `string` | "" | 区域的无障碍名称。 |
| `children` | `func()` | 必填 | 内容;nil 时 panic。 |
需给区域尺寸(`Height`、`Grow` 等)。
## 状态
- 内容溢出时区域可获得焦点,键盘焦点环画在区域内侧(2 DIP,Focus 色),避免被父级裁剪。
- 不溢出时不进入 Tab 序列。
- 滚动条为 MyGo 叠加式滑块,颜色取主题 Scrollbar(TextMuted 50%),指针悬停时显示,不占布局空间。
- 切换主题、折叠周围布局都不重置位置。
## 事件
无独立事件;比较 `state.X`/`state.Y` 的变化即可得知滚动。
## 键盘操作
焦点在区域或其内容上时:方向键滚动 40 DIP,Page Up/Down 与 Space/Shift+Space 翻页,Home/End 到顶部/底部(macOS 另有 Cmd+↑/↓)。文本输入等自行处理这些键的控件优先。
## 限制
- 滚动条只在悬停时显示,不提供常驻滚动条(MyGo 滚动条不占空间的设计)。
- 大量行请使用虚拟化列表,ScrollArea 会构建全部子项。
+64
View File
@@ -0,0 +1,64 @@
# 008 SplitPane 分栏
## 用途
将区域分为左右(或上下)两栏,中间分隔条可拖动、可用键盘调整;两栏有各自最小尺寸,可指定一栏可折叠。
## 最小示例
```go
split := mujica.SplitPaneState{Size: 160}
mujica.SplitPane(c, &split, mujica.SplitPaneOptions{MinFirst: 120, Collapsible: mujica.SplitPaneFirst},
func() { ui.Text(c, "Files") },
func() { ui.Text(c, "Editor") },
).Fill()
```
签名:`func SplitPane(c *ui.Context, state *SplitPaneState, opts SplitPaneOptions, first, second func()) SplitPaneResult`
## 参数
`SplitPaneState`(应用持有,nil 时 panic)
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Size` | `float32` | 0(首次布局后取一半) | 第一栏宽度(纵向时为高度),DIP。每帧被限制在最小尺寸之间。 |
| `Collapsed` | `bool` | false | 可折叠栏是否折叠;折叠时保留 `Size` 以便恢复。未设置 `Collapsible` 却为 true 时 panic。 |
`SplitPaneOptions`
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Vertical` | `bool` | false | 第一栏在上。 |
| `MinFirst`, `MinSecond` | `float32` | 10 单位(默认 40 DIP) | 两栏最小尺寸;负数 panic。 |
| `Collapsible` | `SplitPaneSide` | `SplitPaneNeither` | 可折叠的栏:`SplitPaneFirst` 或 `SplitPaneSecond`。 |
返回 `SplitPaneResult`,内嵌 `*ui.Element`。
## 状态
- 分隔条为 1 DIP ControlBorder 线,命中区域 1.5 单位宽;悬停或拖动时变为 AccentText;键盘焦点时在命中区域外画焦点环。
- 折叠时该栏不构建,分隔条贴边并显示一段短标记,提示可从此处拉开。
- 无障碍:角色为 splitter,名称“分隔条”,描述为第一栏所占百分比或“已折叠”。
## 事件
- `Resized`:本帧尺寸改变(拖动或键盘)。
- `Toggled`:本帧折叠或展开。
## 键盘操作
Tab 聚焦分隔条后:
- ←/→(纵向为 ↑/↓):移动 4 单位,到达最小尺寸后停止。
- 可折叠栏已在最小尺寸时继续朝它按方向键:折叠;折叠后按反方向键:展开。
- Home / End:移到最小 / 最大位置。
- Enter:切换可折叠栏(未设置 `Collapsible` 时不占用 Enter)。
指针:拖动分隔条;拖到可折叠栏最小尺寸的一半以内即折叠,拖回超过一半即展开;双击切换折叠。
## 限制
- 未直接使用 MyGo `ui.Split`:它的最小栏宽固定为 10 个间距单位(`ui/split.go:20`),没有折叠能力,且分隔条元素不对外暴露,无法挂接 Enter、Home、End。本组件用 MyGo 公开的 `Focusable`、`Dragged`、`Shortcut`、`RoleSplitter` 重新组合,行为与 MyGo 分隔条一致并补齐上述功能。
- MyGo 没有公开的无障碍数值范围接口,当前位置通过描述文字提供。
- 键盘或拖动产生的尺寸在下一帧生效(组件会立即请求下一帧)。
+41
View File
@@ -0,0 +1,41 @@
# 009 AspectRatio 宽高比
## 用途
在父容器的宽高约束内放置一个保持指定宽高比的框,尽可能大并居中;子内容在框内居中,不被拉伸,超出部分裁剪。适合预览、视频占位、封面图。
## 最小示例
```go
ui.Box(c).Size(320, 240).Children(func() {
mujica.AspectRatio(c, mujica.AspectRatioOptions{Ratio: 16.0 / 9}, func() {
ui.Text(c, "16 : 9")
})
})
```
签名:`func AspectRatio(c *ui.Context, opts AspectRatioOptions, child func()) *ui.Element`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Ratio` | `float32` | 1 | 宽 / 高;负数 panic。 |
| `child` | `func()` | 必填 | 框内内容;nil 时 panic。需要铺满框时让子元素 `Fill()`。 |
## 状态
布局组件,无交互状态。返回的元素占满父级内容区,比例框位于其中央。
## 事件
无。
## 键盘操作
不获取焦点。
## 限制
- 父级高度不确定(随内容增长)时只按宽度计算。
- 框尺寸依据上一帧的父级尺寸计算,窗口缩放后组件请求下一帧完成调整(MyGo 布局的 `AspectRatio` 只能由宽推高,不能同时受宽高约束)。
+43
View File
@@ -0,0 +1,43 @@
# 010 Divider 分隔线
## 用途
横向或纵向的细分隔线;横向可在中间放文字;可选旧金色单个菱形装饰。永不获取焦点,装饰不进入无障碍树。
## 最小示例
```go
ui.Column(c).Padding(16).Gap(12).Children(func() {
mujica.Divider(c, mujica.DividerOptions{Ornament: true})
mujica.Divider(c, mujica.DividerOptions{Label: "Chapter II"})
})
```
签名:`func Divider(c *ui.Context, opts DividerOptions) *ui.Element`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Vertical` | `bool` | false | 纵向,放在横向行中,高度随行拉伸。 |
| `Label` | `string` | "" | 横向分隔线中间的文字(衬线 12 DIP,TextMuted)。纵向带文字时 panic。 |
| `Ornament` | `bool` | false | 线条改用 Ornament 色,并在中间画一个 7 DIP 菱形;有 `Label` 时文字取代菱形。 |
## 状态
- 默认:1 DIP Border 色细线。
- 装饰:Ornament 色线与菱形。
- 无悬停、焦点等交互状态。
## 事件
无。
## 键盘操作
不获取焦点,Tab 直接跳过。
## 限制
- 方向不会根据父级自动判断,需要显式设置 `Vertical`。
- 纵向不支持文字。
+69
View File
@@ -0,0 +1,69 @@
# 011 Text 文本
## 用途
正文文本:自动换行、按行数省略、可选择复制。`EditableText` 是 Text 的可编辑模式,就地修改一段短文本(如文件名),并展示调用方的保存进度与保存结果。
## 最小示例
```go
name := "Coronation.md"
saveErr := ""
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.Text(c, "Order ID: 4821-AX", mujica.TextOptions{Selectable: true})
mujica.Text(c, "A long note that stops after two lines.", mujica.TextOptions{MaxLines: 2})
if mujica.EditableText(c, &name, mujica.EditableTextOptions{Error: saveErr}).Changed() {
saveErr = "" // save name here; set saveErr on failure
}
}
```
## 参数
`func Text(c *ui.Context, s string, opts TextOptions) *ui.Element`
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `MaxLines` | `int` | `0` | 超过该行数时以省略号截断;`0` 不截断;`1` 为单行。负数 panic。 |
| `Selectable` | `bool` | `false` | 允许用指针或键盘选择并复制文本。 |
`func EditableText(c *ui.Context, value *string, opts EditableTextOptions) *ui.Element`
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Saving` | `bool` | `false` | 调用方正在保存:显示加载标记,并禁止再次编辑。 |
| `Error` | `string` | `""` | 调用方保存失败的说明,显示在文本下方并报告给辅助技术。 |
| `Label` | `string` | `""` | 辅助技术读出的名称。 |
## 状态
- 默认:可编辑文本带虚线下边,提示可以编辑。
- 悬停:背景变为 `SurfaceHover`,尺寸不变。
- 聚焦:2 DIP 焦点环。
- 编辑中:显示 MyGo 文本输入框,酒红边框,选中扩展名之前的部分。
- 保存中(`Saving`):显示加载标记,阻止进入编辑。
- 错误(`Error`):虚线变为 `Danger`,下方显示错误说明,保留已确认的值。
## 事件
- `EditableText(...).Changed()`:用户确认了一个新值,`*value` 已更新。调用方在此保存,并通过 `Saving` 与 `Error` 回传结果。
- 取消编辑不产生事件,`*value` 不变。
## 键盘操作
| 按键 | 作用 |
| --- | --- |
| Tab | 聚焦可编辑文本 |
| Enter / 双击 | 开始编辑 |
| Enter | 确认 |
| Escape | 取消并恢复原值 |
| 焦点移走 | 视为确认 |
| Cmd/Ctrl+A、Cmd/Ctrl+C | 在 `Selectable` 文本上全选、复制 |
## 限制
- 编辑模式基于 `ui.EditableText`。MyGo 不报告“取消”事件,组件只能保证取消后值不变,不能通知调用方。
- 编辑模式只支持单行文本。
- 值为空字符串时文本区域没有可见文字;组件保留最小宽度和虚线,保证仍可点击。
- MyGo 无法检测文本是否真的被截断,所以截断时不会自动显示完整内容的提示。
+43
View File
@@ -0,0 +1,43 @@
# 012 Heading 标题
## 用途
页面与区块的三级衬线标题,可带副标题与旧金色装饰分隔线(对称细线加中央菱形)。
## 最小示例
```go
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.Heading(c, "The Grand Hall", mujica.HeadingOptions{Subtitle: "Winter ceremonies", Divider: true})
mujica.Heading(c, "Guest Ledger", mujica.HeadingOptions{Level: 2})
}
```
## 参数
`func Heading(c *ui.Context, title string, opts HeadingOptions) *ui.Element`
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Level` | `int` | `0`(即 1) | 1、2、3 级,对应 28、22、18 DIP。其他值 panic。 |
| `Subtitle` | `string` | `""` | 标题下方的说明文字,使用 `TextMuted`。 |
| `Divider` | `bool` | `false` | 在下方绘制装饰分隔线,颜色为 `Ornament`。 |
## 状态
纯展示,仅默认状态。字号按系统文本缩放(`Preferences().TextScale`)放大。
## 事件
无。
## 键盘操作
不获取焦点。装饰线不进入无障碍树。
## 限制
- 标题字体为 `theme.SerifFont`(Georgia、宋体类回退);系统缺字时由系统回退字体显示。
- MyGo v0.2.10 没有 Heading 角色(`ui/access.go` 的 Role 列表中没有),辅助技术把标题读作普通文本,无法按标题层级导航。
- 分隔线只在 Heading 内绘制,不依赖 Divider 组件。
+47
View File
@@ -0,0 +1,47 @@
# 013 Icon 图标
## 用途
按名称显示 `icons` 包内置的 Lucide SVG 图标,可设尺寸与语义颜色。名称不存在时显示可见的回退标记并写警告日志。
## 最小示例
```go
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
ui.Row(c).Gap(8).Children(func() {
mujica.Icon(c, "star", mujica.IconOptions{})
mujica.Icon(c, "circle-check", mujica.IconOptions{Size: 20, Tone: mujica.IconSuccess, Label: "Done"})
})
}
```
## 参数
`func Icon(c *ui.Context, name string, opts IconOptions) *ui.Element`
`name` 必填,空字符串 panic。可用名称见 `icons.Names()`。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Size` | `float32` | `0`(即 16) | 宽高(DIP),建议 16、20、24。负数 panic。 |
| `Tone` | `IconTone` | `IconInherit` | `IconInherit` 沿用文字颜色;另有 `IconMuted`、`IconAccent`、`IconSuccess`、`IconWarning`、`IconDanger`、`IconInfo`。未知值 panic。 |
| `Label` | `string` | `""` | 有含义的图标的无障碍名称;为空时图标视为装饰,不进入无障碍树。 |
## 状态
- 默认:按语义颜色显示图标。
- 加载失败(名称不存在):在同尺寸方框中用 `Danger` 色绘制虚线框与斜线,提示文字为“缺少图标:名称”,无障碍名称相同。每个元素对每个缺失名称记录一次 `slog.Warn("mujica: icon missing", "name", ...)`。
## 事件
无。
## 键盘操作
不获取焦点。
## 限制
- 只能使用 `icons` 包内置的图标。要显示任意 SVG,可直接用 `ui.Icon`。
- 回退标记带悬停提示,但图标本身不获取焦点,键盘用户看不到这个提示,只能依赖无障碍名称。
+60
View File
@@ -0,0 +1,60 @@
# 014 Image 图片
## 用途
显示位图(`*ui.Bitmap`)或 SVG(`*ui.SVG`),可选包含或裁切填充;提供占位、加载中、加载失败三种状态和替代说明。
## 最小示例
```go
var photo *ui.Bitmap // decode once with ui.DecodeBitmap, outside the view
loading, loadErr := false, errors.New("timeout")
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
img := mujica.Image(c, photo, mujica.ImageOptions{
Width: 160, Height: 120, Crop: true, Alt: "Hall of mirrors",
Loading: loading, Err: loadErr,
})
if img.Retry {
loading, loadErr = true, nil // start loading again here
}
}
```
## 参数
`func Image(c *ui.Context, src ui.ImageSource, opts ImageOptions) ImageView`
`src` 为 `nil`(未赋值的接口)时显示占位。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Width`, `Height` | `float32` | `0` | 盒子尺寸(DIP)。为 0 时图片使用自身尺寸;占位、加载、错误状态为 160×120。负数 panic。 |
| `Crop` | `bool` | `false` | `true` 覆盖并裁切(`ui.Cover`);`false` 完整放入(`ui.Contain`)。 |
| `Alt` | `string` | `""` | 替代说明,供辅助技术读取;在其他状态下作为描述。 |
| `Loading` | `bool` | `false` | 调用方正在加载。 |
| `Err` | `error` | `nil` | 调用方加载失败;优先于 `Loading`。 |
返回值 `ImageView`:`Element` 为外层元素;`Retry` 表示本帧点击了重试。
## 状态
优先级:错误 > 加载中 > 占位 > 图片。
- 占位:浅色框内显示图片图标,名称“暂无图片”。
- 加载中:框内显示 Spinner,名称“正在加载图片”。
- 错误:显示错误图标、“图片加载失败”和“重试”按钮,`Err.Error()` 作为无障碍错误说明。
## 事件
- `ImageView.Retry`:用户点击了重试,或在按钮上按 Enter/Space。
## 键盘操作
只有错误状态的“重试”按钮可以聚焦(Tab),用 Enter 或 Space 触发。
## 限制
- 组件不读取文件,也不访问网络。解码(`ui.DecodeBitmap`、`ui.ParseSVG`)和异步加载由调用方完成,结果通过 `Window.Update` 回到界面线程,再设置 `Loading` 与 `Err`。
- SVG 的绘制范围以 MyGo 支持的部分为准:不支持文本、嵌入图片、pattern、marker 和 filter。
- 接口里装着 nil 指针(如 `(*ui.Bitmap)(nil)`)时不算 `nil`,不会显示占位。
+47
View File
@@ -0,0 +1,47 @@
# 015 Avatar 头像
## 用途
圆形人物头像。依次回退:图片 → 姓名首字母 → 默认人物图标。
## 最小示例
```go
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
ui.Row(c).Gap(8).Children(func() {
mujica.Avatar(c, "Sakiko Togawa", mujica.AvatarOptions{Size: 40})
mujica.Avatar(c, "", mujica.AvatarOptions{})
})
}
```
## 参数
`func Avatar(c *ui.Context, name string, opts AvatarOptions) *ui.Element`
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Image` | `*ui.Bitmap` | `nil` | 头像图片,按圆形裁切填充。 |
| `Size` | `float32` | `0`(即 32) | 直径(DIP)。负数 panic。 |
`name` 用作无障碍名称和首字母来源;为空时无障碍名称是“未命名”。
## 状态
- 图片:圆形裁切。
- 首字母:取第一个和最后一个词的首字母(大写),衬线字体,`AccentText` 文字配 `Selection` 底色。
- 无可用首字母:`SurfaceHover` 底色加人物图标。
## 事件
无。
## 键盘操作
不获取焦点。辅助技术把头像读作以 `name` 命名的图片。
## 限制
- 中文姓名没有空格时按一个词处理,只取第一个字,例如“张伟”显示为“张”。
- 头像不使用 MyGo `ui.Avatar`,因为它的尺寸固定为字号的 2.25 倍,无法配置(`ui/indicators.go:383`)。
+54
View File
@@ -0,0 +1,54 @@
# 016 AvatarGroup 头像组
## 用途
把多个头像重叠排列。超过最大数量时显示“+N”按钮,点开后在弹层中列出完整名单。
## 最小示例
```go
people := []mujica.AvatarItem{
{Name: "Sakiko Togawa"}, {Name: "Uika Misumi"}, {Name: "Mutsumi Wakaba"},
{Name: "Umiri Yahata"}, {Name: "Nyamu Yutenji"},
}
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.AvatarGroup(c, people, mujica.AvatarGroupOptions{Max: 3})
}
```
## 参数
`func AvatarGroup(c *ui.Context, items []AvatarItem, opts AvatarGroupOptions) AvatarGroupView`
`AvatarItem`:`Name string`、`Image *ui.Bitmap`。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Max` | `int` | `0`(即 4) | 最多直接显示的头像数。负数 panic。 |
| `Size` | `float32` | `0`(即 32) | 每个头像的直径。负数 panic。 |
返回值 `AvatarGroupView`:`Element`;`Open` 表示完整名单正在显示;`Toggled` 表示本帧打开或关闭了名单。
## 状态
- 默认:头像之间重叠四分之一直径,用 2 DIP 窗口背景色描边分隔。
- “+N”按钮:悬停、按下改变背景;聚焦时显示 2 DIP 焦点环。
- 展开:按钮下方弹出 6 DIP 圆角面板,列出全部头像与姓名,超过 240 DIP 时滚动;遵循减少动画设置。
## 事件
- `AvatarGroupView.Toggled` / `Open`:名单展开或关闭(点击按钮、Enter、Space、Escape、点击外部)。同时记录 `slog.Debug("mujica: avatargroup toggle")`。
## 键盘操作
| 按键 | 作用 |
| --- | --- |
| Tab | 聚焦“+N”按钮(读作“显示全部 N 人”) |
| Enter / Space | 展开或收起完整名单 |
| Escape | 关闭名单 |
## 限制
- 分隔描边使用窗口 `Background` 颜色,放在 `Surface` 卡片上时描边颜色会与卡片背景不同。
- 名单中的条目只用于展示,不可选择。
+50
View File
@@ -0,0 +1,50 @@
# 017 Badge 徽标
## 用途
显示短文字或计数。计数超过上限时显示为“上限+”。徽标可以内联排列,也可以钉在内容的某个角上。辅助技术朗读完整数值。
## 最小示例
```go
unread := 120
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.Badge(c, mujica.BadgeOptions{Text: "New", Tone: mujica.BadgeNeutral}, nil)
mujica.Badge(c, mujica.BadgeOptions{Count: unread, Label: "Unread", Position: mujica.BadgeTopRight}, func() {
mujica.Avatar(c, "Sakiko Togawa", mujica.AvatarOptions{})
})
}
```
## 参数
`func Badge(c *ui.Context, opts BadgeOptions, content func()) *ui.Element`
`Position` 为 `BadgeInline` 时 `content` 必须为 `nil`;为角落位置时 `content` 必须不为 `nil`。否则 panic。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Text` | `string` | `""` | 显示的文字;非空时忽略 `Count`。 |
| `Count` | `int` | `0` | 计数。`Text` 为空且计数为 0 时不显示徽标。负数 panic。 |
| `Max` | `int` | `0`(即 99) | 显示上限,超过时显示 `Max+`。负数 panic。 |
| `Tone` | `BadgeTone` | `BadgeAccent` | `BadgeAccent`、`BadgeNeutral`、`BadgeSuccess`、`BadgeWarning`、`BadgeDanger`、`BadgeInfo`。 |
| `Position` | `BadgePosition` | `BadgeInline` | `BadgeTopRight`、`BadgeTopLeft`、`BadgeBottomRight`、`BadgeBottomLeft`:徽标中心对准内容的对应角。 |
| `Label` | `string` | `""` | 计数的含义,朗读时放在完整数值前,如“Unread 1204”。 |
## 状态
纯展示。强调和危险色调使用实色填充(`OnAccent` 配 `Accent`,`OnDanger` 配 `DangerFill`);成功、警告、信息色调只把语义色用在文字和边框上。
## 事件
无。
## 键盘操作
不获取焦点。徽标的无障碍名称为 `Label` 加完整数值。
## 限制
- 角落徽标的位置相对于 `content` 所在的盒子。内容本身有外边距时,徽标不会跟着偏移。
- 徽标使用 `RoleStatus`,部分屏幕阅读器可能在数值变化时主动播报。
+63
View File
@@ -0,0 +1,63 @@
# 018 Tag 标签
## 用途
短标签,可带图标。可以点击,也可以关闭,点击标签和关闭标签是两个独立的操作,各有自己的焦点停靠点。
## 最小示例
```go
tags := []string{"Baroque", "Gothic"}
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
ui.Row(c).Gap(8).Children(func() {
for i, t := range tags {
v := mujica.Tag(c, t, mujica.TagOptions{Icon: "star", Clickable: true, Closable: true})
v.Element.Key(t)
if v.Closed {
tags = append(tags[:i:i], tags[i+1:]...)
}
}
})
}
```
## 参数
`func Tag(c *ui.Context, label string, opts TagOptions) TagView`
`label` 必填,空字符串 panic。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Icon` | `string` | `""` | 图标名称,见 Icon 组件。 |
| `Clickable` | `bool` | `false` | 标签文字部分作为按钮,可以聚焦和点击。 |
| `Closable` | `bool` | `false` | 显示 28×28 DIP 的关闭按钮。 |
| `Disabled` | `bool` | `false` | 禁用点击和关闭,并移出 Tab 顺序。 |
返回值 `TagView`:`Element`;`Clicked` 表示标签被激活;`Closed` 表示请求关闭。
## 状态
- 默认:`Surface` 底色、细边框、2 DIP 圆角。
- 悬停 / 按下:可点击部分和关闭按钮分别变为 `SurfaceHover` / `Selection`。
- 聚焦:对应部分显示 2 DIP 焦点环。
- 禁用:由 MyGo 统一调暗,不响应输入。
## 事件
- `TagView.Clicked`:点击标签文字,或在聚焦时按 Enter/Space。点击关闭按钮不会触发它。
- `TagView.Closed`:点击关闭按钮,或在关闭按钮上按 Enter/Space,或在聚焦的可点击标签上按 Delete/Backspace。组件不会自行移除标签,由调用方删除数据。
## 键盘操作
| 按键 | 作用 |
| --- | --- |
| Tab | 先聚焦标签文字(仅 `Clickable`),再聚焦关闭按钮 |
| Enter / Space | 激活当前聚焦的部分 |
| Delete / Backspace | 在可点击标签上请求关闭(仅 `Closable`) |
## 限制
- 不可点击的标签不获取焦点,只能通过关闭按钮操作。
- 标签不提供“选中”状态;需要可选标签时请使用 Toggle 类组件。
+53
View File
@@ -0,0 +1,53 @@
# 019 Link 链接
## 用途
带下划线的链接文本:打开外部地址、在 MyGo Router 中跳转路径,或作为应用内动作。可以显示打开失败的反馈。
## 最小示例
```go
details := false
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
mujica.Link(c, "Read the charter", mujica.LinkOptions{URL: "https://example.com/charter"})
if mujica.Link(c, "Show details", mujica.LinkOptions{}).Clicked() {
details = !details
}
}
```
## 参数
`func Link(c *ui.Context, label string, opts LinkOptions) *ui.Element`
`label` 必填,空字符串 panic。
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `URL` | `string` | `""` | 有协议的地址用系统默认应用打开。没有协议的路径(如 `/notes/42`、`?tab=info`)在 MyGo Router 中跳转。为空时是应用内动作。 |
| `Error` | `string` | `""` | 调用方提供的打开失败说明,显示在链接下方,也报告给辅助技术。 |
## 状态
- 默认:`AccentText` 颜色,始终带 1 DIP 下划线。外部地址后面带“外部链接”小图标。
- 悬停 / 按下:文字与下划线变为 `Text` 颜色,布局不变。
- 聚焦:2 DIP 焦点环。
- 错误:格式不正确的地址(无法解析,或 http/https 缺少主机名)不会打开,下方显示“无法打开此链接:地址”;`Error` 非空时优先显示 `Error`。
## 事件
- `Clicked()`:每次点击或按 Enter 都会报告,无论是否打开了地址。同时记录 `slog.Debug("mujica: link activate")`。
## 键盘操作
| 按键 | 作用 |
| --- | --- |
| Tab | 聚焦链接 |
| Enter | 激活 |
## 限制
- MyGo v0.2.10 不报告打开失败。`ui.Link` 和 `Context.OpenURL` 不返回结果(`ui/context.go:270`、`ui/window.go:583`)。窗口宿主在 goroutine 中调用 `Shell.OpenExternal` 并丢弃它的错误(`content.go:55`)。因此组件只能自行检查地址格式,系统打开失败无法自动显示。需要这种反馈时,传空 `URL`,在 `Clicked()` 后由调用方在 goroutine 中调用 `mygo.Shell.OpenExternal(url)`。它会返回 error,把结果通过 `Window.Update` 写回 `Error`。
- 路径是否交给 Router 由 MyGo 决定。没有 Router 时,路径会被当作 URL 交给系统打开。
- 链接不能嵌入 `ui.RichText` 句子中作为行内元素,因为外部图标和错误说明需要额外的行布局。行内链接请直接使用 `ui.Link`。
+55
View File
@@ -0,0 +1,55 @@
# 020 Kbd 快捷键
## 用途
把单键或组合键显示为键帽。按平台显示:macOS 用 ⌘ ⇧ ⌥ ⌃ 等符号且不加连接符;其他平台显示 Ctrl、Shift、Alt,键之间用“+”连接。只做展示,不注册快捷键。
## 最小示例
```go
view := func(c *ui.Context) {
mujica.Use(c, mujica.Settings{})
ui.Row(c).Gap(6).Children(func() {
mujica.Text(c, "Command palette", mujica.TextOptions{})
mujica.Kbd(c, "Mod", "Shift", "P")
})
}
```
## 参数
`func Kbd(c *ui.Context, keys ...string) *ui.Element`
至少要传一个键,键名不能为空,否则 panic。键名不区分大小写:
| 键名 | macOS | 其他平台 |
| --- | --- | --- |
| `Mod` | ⌘(Command) | Ctrl |
| `Ctrl` | ⌃ | Ctrl |
| `Alt` | ⌥(Option) | Alt |
| `Shift` | ⇧ | Shift |
| `Enter` | ↩ | Enter |
| `Esc` | esc | Esc |
| `Tab` | ⇥ | Tab |
| `Backspace` | ⌫ | Backspace |
| `Delete` | ⌦ | Delete |
| `Up` `Down` `Left` `Right` | ↑ ↓ ← → | ↑ ↓ ← → |
其他键名按原样显示;单个字符转为大写。
## 状态
纯展示。键帽使用等宽字体、`Surface` 底色、`ControlBorder` 边框,底边 2 DIP。
## 事件
无。
## 键盘操作
不获取焦点,也不注册任何快捷键。辅助技术读出完整的组合键文字,例如“Command+Shift+P”或“Ctrl+Shift+P”。
## 限制
- 平台在编译时由 `runtime.GOOS` 决定。Gallery 的网页镜像显示的是运行 Go 进程那台机器的平台。
- `Mod` 与 MyGo 的 `ui.Cmd` 一致:macOS 上是 Command,其他平台是 Control。
+43
View File
@@ -0,0 +1,43 @@
# 021 Button 按钮
## 用途
触发一个操作。提供主按钮、次按钮、描边、无底色和危险五种变体,可带图标,可显示加载与禁用。基于 MyGo `ui.ButtonBase`。
## 最小示例
```go
if mujica.Button(c, "Save", mujica.ButtonOptions{Icon: icons.Must("check")}).Clicked() {
fmt.Println("saved")
}
```
签名:`func Button(c *ui.Context, label string, opts ButtonOptions) *ui.Element`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `label` | `string` | 必填(仅图标时可为空) | 按钮文字。 |
| `Variant` | `ButtonVariant` | `Primary` | `Primary`、`Secondary`、`Outline`、`Ghost`、`Danger`。 |
| `Icon` | `*ui.SVG` | `nil` | 文字前的 16 DIP 图标。 |
| `Loading` | `bool` | `false` | 以菱形加载标记替换图标,保留尺寸与文字,阻止点击。 |
| `Disabled` | `bool` | `false` | 不可点击、不进入 Tab 序列。 |
| `Label` | `string` | `""` | 无文字按钮的无障碍名称。 |
## 状态
默认、悬停(底色加深或出现浅底)、按下、键盘聚焦(2 DIP 酒红焦点环,外留 2 DIP)、加载、禁用(MyGo 统一减淡)。高度不低于当前密度的控件高度(28/36/44 DIP)。
## 事件
`Clicked()`:鼠标在按钮内释放、Enter 或 Space 时为真,一次操作只报告一次。加载与禁用时始终为假。
## 键盘操作
Tab / Shift+Tab 聚焦;Enter 或 Space 触发。
## 限制
- 加载标记在减少动画模式下静止显示。
- 危险变体的悬停与按下色由 `DangerFill` 混合黑色得到,未单独定义变量。
+42
View File
@@ -0,0 +1,42 @@
# 022 IconButton 图标按钮
## 用途
只显示图标的方形按钮,用于工具栏与紧凑操作。操作名称必填,供辅助技术朗读,并作为默认提示文字。建立在 Button 之上。
## 最小示例
```go
if mujica.IconButton(c, icons.Must("settings"), "Settings", mujica.IconButtonOptions{Variant: mujica.Ghost}).Clicked() {
fmt.Println("open settings")
}
```
签名:`func IconButton(c *ui.Context, icon *ui.SVG, label string, opts IconButtonOptions) *ui.Element`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `icon` | `*ui.SVG` | 必填 | 图标;为 nil 时 panic。 |
| `label` | `string` | 必填 | 操作名称;为空时 panic。 |
| `Variant` | `ButtonVariant` | `Primary` | 与 Button 相同的五种变体;工具栏通常用 `Ghost`。 |
| `Tooltip` | `string` | 操作名称 | 悬停约 600 毫秒后显示的提示。 |
| `Loading` | `bool` | `false` | 显示加载标记并阻止点击。 |
| `Disabled` | `bool` | `false` | 禁用。 |
## 状态
同 Button:悬停、按下、聚焦、加载、禁用。边长等于当前密度的控件高度,不小于 28 DIP。
## 事件
`Clicked()`,一次操作一次。
## 键盘操作
Tab 聚焦;Enter 或 Space 触发。
## 限制
- 禁用时不显示提示:MyGo 的 `Hovered` 对禁用元素返回 false,提示随之不出现;名称仍作为无障碍描述保留。
+53
View File
@@ -0,0 +1,53 @@
# 023 ButtonGroup 按钮组
## 用途
把若干按钮拼成一条,共用边框与尺寸,只有外侧圆角。整个组是一个 Tab 停靠点,组内用方向键移动。基于 `ui.ButtonBase` 与 MyGo 焦点组 `FocusGroup`。
## 最小示例
```go
items := []mujica.ButtonGroupItem{{Label: "Day"}, {Label: "Week"}, {Label: "Month"}}
if i := mujica.ButtonGroup(c, items, mujica.ButtonGroupOptions{Label: "Range"}).ClickedItem(); i >= 0 {
fmt.Println("chose", items[i].Label)
}
```
签名:`func ButtonGroup(c *ui.Context, items []ButtonGroupItem, opts ButtonGroupOptions) ButtonGroupResult`
## 参数
`ButtonGroupItem`
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Label` | `string` | `""` | 文字;与 `Icon` 至少给一个,否则 panic。 |
| `Icon` | `*ui.SVG` | `nil` | 图标。 |
| `Name` | `string` | `""` | 仅图标项的无障碍名称。 |
| `Disabled` | `bool` | `false` | 单项禁用;方向键跳过该项。 |
`ButtonGroupOptions`
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Vertical` | `bool` | `false` | 纵向排列,使用上下方向键。 |
| `Label` | `string` | `""` | 组的无障碍名称(工具栏角色)。 |
| `Disabled` | `bool` | `false` | 禁用整组。 |
`items` 为空时 panic。
## 状态
每项有悬停、按下、聚焦、禁用;相邻项共用一条 1 DIP 分隔边。
## 事件
`ClickedItem()` 返回本帧被点击项的下标,无点击时为 -1。
## 键盘操作
Tab 进入组(回到上次聚焦项);横向组 Left/Right、纵向组 Up/Down 移动并循环;Home、End 到首末项;Enter 或 Space 触发。
## 限制
- 组内没有选中概念;需要保持选中请使用 ToggleGroup(033)。
+49
View File
@@ -0,0 +1,49 @@
# 024 TextInput 文本输入框
## 用途
单行文本编辑。支持占位、前后插槽、清空、只读与错误。编辑核心是 MyGo `ui.TextInputBase`,因此保留选择、撤销重做、剪贴板、右键菜单与输入法组合。
## 最小示例
```go
r := mujica.TextInput(c, &name, mujica.TextInputOptions{Label: "Name", Placeholder: "Your name", Clearable: true})
if r.Submitted() {
fmt.Println("hello", name)
}
```
签名:`func TextInput(c *ui.Context, value *string, opts TextInputOptions) InputResult`
`InputResult` 内嵌外层 `*ui.Element`,`Input` 字段是内部编辑元素,`Changed()`、`Submitted()` 报告事件。
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `value` | `*string` | 必填 | 编辑的字符串;nil 时 panic。 |
| `Placeholder` | `string` | `""` | 空值时的占位文字(TextMuted 色)。 |
| `Label` | `string` | `""` | 无障碍名称,也供测试查找。 |
| `Leading` / `Trailing` | `func()` | `nil` | 在框内左侧、右侧构建内容,如图标或单位。 |
| `Clearable` | `bool` | `false` | 有内容时显示清空按钮;Escape 也会清空。 |
| `Disabled` | `bool` | `false` | 禁用,不可聚焦。 |
| `ReadOnly` | `bool` | `false` | 可聚焦、选择、复制,不可修改。 |
| `Error` | `string` | `""` | 非空时边框变为 Danger,并在下方显示该文字;辅助技术同时朗读。 |
## 状态
默认(Surface 底、ControlBorder 边)、悬停(边框加深)、聚焦(边框 Focus 色;键盘聚焦另加焦点环)、只读(Background 底、Border 边)、错误、禁用。颜色变化 120 毫秒过渡,减少动画时直接切换。
## 事件
- `Changed()`:输入、粘贴、撤销或清空改变了值。只读时不会报告。
- `Submitted()`:在框内按 Enter。
## 键盘操作
Tab 聚焦(全选内容);Enter 提交;Escape 清空(仅 `Clearable` 且有内容时,否则交给外层);Cmd/Ctrl+Z、Shift+Cmd+Z 撤销重做;Cmd/Ctrl+A/C/X/V;输入法组合期间不提交。
## 限制
- MyGo 没有公开的只读输入接口(只读模式仅用于 `Text.Selectable`,`editor.go:77`)。`ReadOnly` 通过让编辑器编辑一个副本并在同帧还原实现,撤销栈里可能出现被还原的步骤。
- 清空按钮不进入 Tab 序列(与 MyGo SearchField 相同),键盘用 Escape 清空。
+49
View File
@@ -0,0 +1,49 @@
# 025 TextArea 多行文本框
## 用途
多行文本编辑,可设最小与最大高度,超出最大高度后在框内滚动;可显示字数;提交快捷键可配置。编辑核心是 MyGo `ui.TextAreaBase`,只排版可见段落,适合长文本。
## 最小示例
```go
r := mujica.TextArea(c, &notes, mujica.TextAreaOptions{Label: "Notes", MaxHeight: 160, MaxLength: 200})
if r.Submitted() {
fmt.Println("send", notes)
}
```
签名:`func TextArea(c *ui.Context, value *string, opts TextAreaOptions) InputResult`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `value` | `*string` | 必填 | 编辑的字符串。 |
| `Placeholder` | `string` | `""` | 占位文字。 |
| `Label` | `string` | `""` | 无障碍名称。 |
| `MinHeight` | `float32` | `0`(三行) | 编辑区最小高度,DIP。 |
| `MaxHeight` | `float32` | `0`(随内容增长) | 编辑区最大高度,超出后滚动;小于 `MinHeight` 时 panic。 |
| `MaxLength` | `int` | `0`(不显示) | 显示“当前 / 上限”字数(按 Unicode 字符计);超出时变红并提示超出数量。 |
| `SubmitKey` / `SubmitMods` | `ui.Key` / `ui.Modifiers` | Cmd+Enter(非 macOS 为 Ctrl+Enter) | 提交快捷键;`SubmitKey` 为零时使用默认值。 |
| `Disabled` | `bool` | `false` | 禁用。 |
| `ReadOnly` | `bool` | `false` | 只读,可选择复制。 |
| `Error` | `string` | `""` | 错误文字;为空且超出 `MaxLength` 时自动显示超出提示。 |
## 状态
默认、悬停、聚焦、只读、错误、禁用,表现同 TextInput。
## 事件
`Changed()`:内容被用户改变。`Submitted()`:按下提交快捷键。
## 键盘操作
Enter 与 Shift+Enter 换行;提交快捷键提交;方向键、PageUp/PageDown 移动光标并滚动;撤销、剪贴板与输入法同 TextInput。
## 限制
- `MaxLength` 只提示,不截断输入,以免打断输入法组合与粘贴。
- 提交快捷键不能是不带修饰键的 Enter:MyGo 编辑器先接收 Enter 并插入换行(`editor.go:161`)。
- 只读实现方式同 TextInput。
+49
View File
@@ -0,0 +1,49 @@
# 026 NumberInput 数字输入框
## 用途
输入与步进数值,支持范围、步长、精度与空值。合并 MyGo 的 Number input(输入模式)与 Stepper(`StepperOnly` 仅步进模式)。
## 最小示例
```go
if mujica.NumberInput(c, &copies, mujica.NumberInputOptions{Min: 1, Max: 99, Label: "Copies"}).Changed() {
fmt.Println("copies", copies)
}
```
签名:`func NumberInput(c *ui.Context, value *float64, opts NumberInputOptions) InputResult`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `value` | `*float64` | 必填 | 数值;空值用 `math.NaN()` 表示,仅在 `AllowEmpty` 时允许。 |
| `Min` / `Max` | `float64` | 都为 0 | 范围;相等(含零值)表示不限范围;`Min > Max` 时 panic。 |
| `Step` | `float64` | `1` | 方向键与按钮的步长;负数 panic。 |
| `Precision` | `int` | 取 `Step` 的小数位 | 保留与显示的小数位。 |
| `AllowEmpty` | `bool` | `false` | 允许清空,值变为 NaN;从空值步进时从 0(夹在范围内)开始。 |
| `StepperOnly` | `bool` | `false` | 只显示数值与上下箭头,不可输入;必须给出 `Min < Max`,且不能与 `AllowEmpty` 同用。 |
| `Placeholder` | `string` | `""` | 空值时的占位。 |
| `Label` | `string` | `""` | 无障碍名称。 |
| `Disabled` | `bool` | `false` | 禁用。 |
| `Error` | `string` | `""` | 调用方给出的错误。 |
## 状态
输入模式同 TextInput;输入非数字或超出范围时显示内置错误(“请输入数字”“请输入 a 到 b 之间的数字”),值保持上一次有效值;失去焦点后文本恢复为当前值并清除该错误。到达边界时对应按钮禁用。
## 事件
`Changed()`:值因输入、方向键、按钮或步进器改变。
## 键盘操作
输入模式:Up/Down 按步长增减。仅步进模式:Up/Right 增加、Down/Left 减少、Home 到最小、End 到最大;按住箭头持续步进。
## 限制
- 输入模式下的加减按钮不进入 Tab 序列,键盘用 Up/Down。
- 仅步进模式复用 MyGo `ui.Stepper`,箭头高度来自主题间距,不随密度的控件高度变化。
- MyGo `ui.Stepper` 的箭头不检查禁用(`indicators.go:216`),禁用时组件向它传入副本,保证值不被修改。
- MyGo 的步进器吸附依赖有限边界(`widgets.go` 中 `snap`),所以仅步进模式要求有界。
+42
View File
@@ -0,0 +1,42 @@
# 027 PasswordInput 密码输入框
## 用途
遮蔽显示的密码输入,带显示/隐藏切换。允许粘贴;遮蔽时不允许复制与剪切。基于 `ui.TextInputBase(...).Password()`,辅助技术读不到遮蔽中的值。组件从不记录密码内容。
## 最小示例
```go
if mujica.PasswordInput(c, &password, mujica.PasswordInputOptions{Label: "Password"}).Submitted() {
fmt.Println("signing in")
}
```
签名:`func PasswordInput(c *ui.Context, value *string, opts PasswordInputOptions) InputResult`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `value` | `*string` | 必填 | 密码。 |
| `Placeholder` | `string` | `""` | 占位文字。 |
| `Label` | `string` | `""` | 无障碍名称。 |
| `Disabled` | `bool` | `false` | 禁用(切换按钮同时禁用)。 |
| `Error` | `string` | `""` | 错误文字。 |
## 状态
默认、悬停、聚焦、错误、禁用;遮蔽 / 显示两种模式,切换按钮的图标与名称(“显示密码”“隐藏密码”)随之变化。
## 事件
`Changed()`:内容改变。`Submitted()`:Enter。日志只写切换事件(`mujica: password_input reveal`,含是否显示),不写内容。
## 键盘操作
Tab 依次到输入框、切换按钮;切换按钮上 Space 或 Enter 切换;输入框中 Enter 提交,Cmd/Ctrl+V 粘贴。
## 限制
- MyGo 的 `Password()` 一旦设置无法撤销(`editor.go:791`),因此遮蔽与显示两种模式各用一个编辑器,切换时撤销历史和光标位置不保留,焦点留在切换按钮上。
- 显示模式下内容是普通文本,可复制,辅助技术可朗读——这是用户主动选择的结果。
+51
View File
@@ -0,0 +1,51 @@
# 028 SearchInput 搜索框
## 用途
搜索模式:放大镜、输入、清空与提交。查找栏模式(`Find`):在此基础上显示匹配数量、上一项与下一项,对应 MyGo 的 Search field 与 Find bar。匹配由调用方计算。
## 最小示例
```go
matches := 0
if query != "" {
matches = strings.Count(text, query)
}
r := mujica.SearchInput(c, &query, mujica.SearchInputOptions{Find: true, Matches: matches, Current: &current})
if r.Moved() {
fmt.Println("show match", current)
}
```
签名:`func SearchInput(c *ui.Context, query *string, opts SearchInputOptions) SearchInputResult`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `query` | `*string` | 必填 | 查询文字。 |
| `Placeholder` | `string` | “搜索”或“查找” | 占位文字。 |
| `Label` | `string` | 占位文字 | 无障碍名称。 |
| `Disabled` | `bool` | `false` | 禁用(查找快捷键也停用)。 |
| `Find` | `bool` | `false` | 开启查找栏模式。 |
| `Matches` | `int` | `0` | 匹配数量;负数 panic。 |
| `Current` | `*int` | `nil` | 当前匹配下标;`Find` 时必填,组件会把它夹在有效范围内。 |
## 状态
同 TextInput;查找栏模式下显示“第 n 项,共 m 项”或“无匹配”(状态角色,变化时可被朗读),无匹配时上一项/下一项禁用。
## 事件
- `Changed()`:查询改变(含清空)。
- `Submitted()`:搜索模式下 Enter。
- `Moved()`:查找栏模式下当前匹配改变。
## 键盘操作
搜索模式:Enter 提交,Escape 清空。查找栏模式:Enter 下一项,Shift+Enter 上一项,macOS 上 Cmd+G / Shift+Cmd+G、其他平台 F3 / Shift+F3(窗口级),循环到首尾;Escape 清空。
## 限制
- MyGo 单行编辑器把 Shift+Enter 当作普通提交且不公开修饰键(`editor.go:489`,`submitMods` 未导出),组件用 `HandleInput` 先截获 Shift+Enter。
- 没有“完成/关闭”按钮;是否显示查找栏由调用方决定。
+51
View File
@@ -0,0 +1,51 @@
# 029 Checkbox 复选框
## 用途
切换布尔值,支持选中、未选、半选;点击方框或标签都会切换。`CheckboxGroup` 提供组内全选(对应 MyGo CheckboxGroup)。基于 `ui.CheckboxBase`。
## 最小示例
```go
mujica.CheckboxGroup(c, "Notifications", []mujica.CheckboxItem{
{Label: "Mail", Value: &mail},
{Label: "Calendar", Value: &calendar},
}, mujica.CheckboxGroupOptions{})
```
签名:
```go
func Checkbox(c *ui.Context, value *bool, label string, opts CheckboxOptions) *ui.Element
func CheckboxGroup(c *ui.Context, label string, items []CheckboxItem, opts CheckboxGroupOptions) InputResult
```
## 参数
`CheckboxOptions`
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Indeterminate` | `bool` | `false` | 显示半选横线;此时点击总是变为选中。是否半选由调用方决定。 |
| `Disabled` | `bool` | `false` | 禁用。 |
`CheckboxItem`:`Label string`、`Value *bool`(必填)、`Disabled bool`。`CheckboxGroupOptions`:`Disabled bool`。`items` 为空时 panic。
## 状态
未选(Surface 底、ControlBorder 边)、悬停与按下(AccentText 边)、选中(酒红底、象牙白勾)、半选(酒红底、象牙白横线)、键盘聚焦(方框外焦点环)、禁用。行高不低于密度控件高度。
全选框:全部选中为选中,部分选中为半选,全不选为未选。点击时若可用项未全选则全部勾选,否则全部清除;禁用项保持不变。
## 事件
- `Checkbox(...).Changed()`:用户切换了值。
- `CheckboxGroup(...).Changed()`:全选或任一项被切换。
## 键盘操作
Tab 聚焦(每个复选框一个停靠点);Space 切换。
## 限制
- MyGo 只有内部字段能把复选框报告为“mixed”(`access.go:307`,`checked` 未导出)。半选时组件在无障碍描述中加入“部分选中”,但角色状态仍报告为未选中。
+52
View File
@@ -0,0 +1,52 @@
# 030 RadioGroup 单选组
## 用途
在一组选项中选一个,横向或纵向排列;选项值是任意可比较类型,作为稳定标识。基于 `ui.RadioGroup` 与 `ui.RadioBase`,整组是一个 Tab 停靠点。
## 最小示例
```go
items := []mujica.RadioItem[string]{{Value: "s", Label: "Small"}, {Value: "m", Label: "Medium"}, {Value: "l", Label: "Large"}}
if mujica.RadioGroup(c, &size, items, mujica.RadioGroupOptions{Label: "Size"}).Changed() {
fmt.Println("size", size)
}
```
签名:`func RadioGroup[T comparable](c *ui.Context, value *T, items []RadioItem[T], opts RadioGroupOptions) InputResult`
## 参数
`RadioItem[T]`
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Value` | `T` | 必填 | 稳定选项值;重复时 panic。 |
| `Label` | `string` | `""` | 标签,点击标签也会选择。 |
| `Disabled` | `bool` | `false` | 单项禁用,方向键跳过。 |
`RadioGroupOptions`
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Horizontal` | `bool` | `false` | 横向排列。 |
| `Label` | `string` | `""` | 组的无障碍名称。 |
| `Disabled` | `bool` | `false` | 禁用整组。 |
`value` 为 nil 或 `items` 为空时 panic。`*value` 不在选项中时没有选中项。
## 状态
未选(空心圆)、悬停与按下(AccentText 边)、选中(酒红实心圆与象牙白圆点)、键盘聚焦、禁用。
## 事件
`Changed()`:用户选择了另一个值(点击、Space 或方向键)。
## 键盘操作
Tab 进入组并落在已选项;Up/Down/Left/Right 移动并直接选择,循环,跳过禁用项;Home、End 选择首末可用项。
## 限制
- 方向键对横向与纵向组都同时响应上下左右(MyGo `RadioGroup` 固定使用 `Horizontal|Vertical`)。
+51
View File
@@ -0,0 +1,51 @@
# 091 Alert 提示条
## 用途
在页面内显示一条信息、成功、警告或错误提示,可带标题、一个操作按钮和关闭按钮。严重程度同时由左侧色条、图标和无障碍名称(如“Error”)表达,不只靠颜色。
## 最小示例
```go
open := true
r := mujica.Alert(c, &open, "The archive could not be read.", mujica.AlertOptions{
Severity: mujica.SeverityError,
Title: "Import failed",
Action: "Retry",
})
if r.Action {
// retry the import
}
```
签名:`func Alert(c *ui.Context, open *bool, message string, opts AlertOptions) AlertResult`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `open` | `*bool` | `nil` | 非 nil 时显示关闭按钮,关闭后置为 `false`;为 `false` 时不构建任何元素。`nil` 表示不可关闭。 |
| `message` | `string` | 必填 | 正文;为空时 panic。 |
| `Severity` | `Severity` | `SeverityInfo` | `SeverityInfo`、`SeveritySuccess`、`SeverityWarning`、`SeverityError`。 |
| `Title` | `string` | `""` | 正文上方的粗体标题。 |
| `Action` | `string` | `""` | 操作按钮文字;为空不显示。 |
返回 `AlertResult{Element, Action, Closed}`;关闭状态下 `Element` 为 nil。
## 状态
四种严重程度;操作与关闭按钮有悬停、按下和 2 DIP 焦点环。警告与错误在出现或文字变化时通过 `Context.Announce` 播报一次。
## 事件
- `Action`:操作按钮被点击或经键盘触发。
- `Closed`:用户关闭;同时 `*open` 变为 `false`。
## 键盘操作
Tab 依次聚焦操作按钮与关闭按钮;Enter 或 Space 触发。
## 限制
- 信息与成功提示不主动播报,避免页面加载时打扰读屏用户。
- 关闭不带退出动画;需要动画时由调用方在外层加 `Transition`。
+58
View File
@@ -0,0 +1,58 @@
# 092 Toast 轻提示
## 用途
在窗口右下角短暂显示操作结果,可带一个操作(如撤销)与关闭按钮。每个窗口一条队列:按 ID 去重,同时最多显示 3 条,其余排队。
## 最小示例
```go
if mujica.Button(c, "Delete note", mujica.ButtonOptions{Variant: mujica.Danger}).Clicked() {
mujica.ShowToast(c, mujica.ToastMessage{ID: "note-1", Message: "Note deleted", Action: "Undo"})
}
// Last in the view:
if r := mujica.Toaster(c); r.Action == "note-1" {
// restore the note
}
```
接口:
- `func ShowToast(c *ui.Context, m ToastMessage)`:加入队列,须在界面线程调用(后台任务经 `Window.Update` 回到界面线程)。
- `func DismissToast(c *ui.Context, id string)`:关闭显示中或排队中的消息。
- `func Toaster(c *ui.Context) ToasterResult`:每帧在视图末尾调用一次,绘制消息并报告事件。
## 参数
`ToastMessage`:
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `ID` | `string` | `Message` | 去重键。相同 ID 再次显示时替换内容并重新计时,不新增一条。 |
| `Severity` | `Severity` | `SeverityInfo` | 图标、色条与颜色。 |
| `Message` | `string` | 必填 | 文字;为空时 panic。 |
| `Action` | `string` | `""` | 操作按钮文字。 |
| `Duration` | `time.Duration` | `ToastDuration`(5 秒) | 显示时长;负数 panic。错误消息在为 0 时一直保留到用户关闭。 |
常量:`ToastDuration = 5 * time.Second`,`ToastVisible = 3`。
## 状态
- 排队消息在显示时才开始计时。
- 指针悬停或焦点位于消息内时暂停计时,离开后从剩余时间继续。
- 出现时向读屏播报文字;进出场 160 ms 位移与淡入,减少动画时直接切换。
## 事件
`ToasterResult{Action, Closed}`:本帧被点击操作或被关闭的消息 ID;两者都会移除该消息。到时自动消失不报告。
## 键盘操作
消息从不抢夺焦点,正在输入的文本框保持焦点。Tab 在页面之后到达消息中的按钮;焦点在消息内时 Escape 关闭该消息。
## 复用与限制
MyGo 自带 `c.Toast` / `c.ToastAction`(docs/ui/toast.md),但它按文字去重、没有 ID、不限制条数、无关闭按钮、错误不能常驻、外观不可替换,计时只在悬停时暂停而不在聚焦时暂停。这些都是 PRD §5.5 的要求,因此 MujicaUI 自建队列,只复用 MyGo 的 `Overlay`、`Transition`、`Announce` 与 `After` 定时唤醒。
- 所有消息(不只是含操作的消息)都在悬停或聚焦时暂停,这是 PRD 要求的超集,便于阅读。
- 位置固定在右下角;切换到未调用 `Toaster` 的视图时消息仍在队列中,回来后继续显示。
+64
View File
@@ -0,0 +1,64 @@
# 093 Progress 进度
## 用途
显示任务进度(确定或不确定,线形或环形),以及计量值(如磁盘占用)及其阈值。归并 MyGo 的 Progress bar 与 Meter:`Progress` 为进度模式,`Meter` 为计量模式。两者分别基于 `ui.Progress` 与 `ui.Meter` 元素重绘,保留其无障碍角色与数值。
## 最小示例
```go
mujica.Progress(c, 0.62, mujica.ProgressOptions{Label: "Uploading", ShowValue: true})
mujica.Progress(c, 0, mujica.ProgressOptions{Shape: mujica.ProgressRing, Indeterminate: true, Label: "Connecting"})
mujica.Meter(c, 93, mujica.MeterOptions{
Max: 100, Label: "Disk", ShowValue: true,
Levels: &ui.MeterLevels{Warning: 70, Critical: 90},
})
```
签名:
- `func Progress(c *ui.Context, value float64, opts ProgressOptions) *ui.Element`
- `func Meter(c *ui.Context, value float64, opts MeterOptions) *ui.Element`
## 参数
`ProgressOptions`:
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `value` | `float64` | 必填 | 0 到 1;超出或 NaN 时 panic(不确定模式忽略)。 |
| `Shape` | `ProgressShape` | `ProgressLinear` | `ProgressLinear` 或 `ProgressRing`。 |
| `Indeterminate` | `bool` | `false` | 未知长度的进度。 |
| `Label` | `string` | `""` | 显示在旁边并作为无障碍名称;为空时名称为“Loading”。 |
| `ShowValue` | `bool` | `false` | 显示百分比。 |
| `Size` | `float32` | 环形 48、线形填满 | 环形直径或线形宽度;负数 panic。 |
`MeterOptions`:
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `value` | `float64` | 必填 | 须在范围内,否则 panic。 |
| `Min`, `Max` | `float64` | 0, 1(两者都为 0 时) | 范围;`Max <= Min` panic。 |
| `Levels` | `*ui.MeterLevels` | `nil` | 阈值:达到 `Warning` 为偏高、达到 `Critical` 为严重;`Critical < Warning` 时低值为坏(如电量)。须在范围内。 |
| `Label` | `string` | `""` | 名称。 |
| `ShowValue` | `bool` | `false` | 显示“值 / 最大值”。 |
| `Width` | `float32` | 填满 | 宽度。 |
## 状态
- 确定进度变化时以 120 ms 过渡,减少动画时直接跳到新值。
- 不确定进度只在绘制时移动(只重绘、不重建视图);减少动画时显示静态填充和“In progress”文字。
- 计量条按级别使用 Success / Warning / Danger 颜色,同时显示“Normal / High / Critical / Low”文字与阈值刻度,并把级别写入无障碍名称。
## 事件
无。
## 键盘操作
不可聚焦;读屏读取名称与数值。
## 限制
- 环形直径小于 44 DIP 时百分比显示在旁边,而不是环内。
- MyGo 不提供自定义无障碍数值的公开接口,因此必须基于 `ui.Progress` / `ui.Meter` 元素绘制。
+39
View File
@@ -0,0 +1,39 @@
# 094 Spinner 加载标记
## 用途
表示未知长度的加载:四个菱形绕中心旋转。可调尺寸,可显示说明文字。Button 的加载状态也使用它。标记基于 MyGo `ui.Spinner` 元素重绘,读屏视为不确定进度。
## 最小示例
```go
mujica.Spinner(c, mujica.SpinnerOptions{Size: 20, Label: "Syncing", ShowLabel: true})
```
签名:`func Spinner(c *ui.Context, opts SpinnerOptions) *ui.Element`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Size` | `float32` | 16 | 标记边长(DIP)。 |
| `Label` | `string` | 内置“Loading / 加载中” | 无障碍名称;`ShowLabel` 时也显示在旁边。 |
| `ShowLabel` | `bool` | `false` | 在标记旁显示说明。 |
| `Color` | `ui.Color` | `AccentText` | 标记颜色。 |
## 状态
- 只在被绘制时请求重绘:不再构建(隐藏或停止加载)或滚出视口后动画立即停止,不留定时器。
- 减少动画模式下静止显示,保留名称与说明。
## 事件
无。
## 键盘操作
不可聚焦。
## 限制
- 每帧重绘,而非 MyGo 自带 spinner 的分步重绘;只在显示时产生开销。
+45
View File
@@ -0,0 +1,45 @@
# 095 Skeleton 骨架屏
## 用途
内容加载前占位,形状为文字行、圆形或矩形。尺寸固定,加载完成后替换为真实内容时不跳动。
## 最小示例
```go
ui.Row(c).Gap(12).Children(func() {
mujica.Skeleton(c, mujica.SkeletonOptions{Shape: mujica.SkeletonCircle})
ui.Column(c).Grow(1).Children(func() {
mujica.Skeleton(c, mujica.SkeletonOptions{Lines: 2})
})
})
```
签名:`func Skeleton(c *ui.Context, opts SkeletonOptions) *ui.Element`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Shape` | `SkeletonShape` | `SkeletonText` | `SkeletonText`、`SkeletonCircle`、`SkeletonRect`。 |
| `Width` | `float32` | 填满父级;圆形 40 | 宽度;圆形为直径。 |
| `Height` | `float32` | 当前密度控件高度 | 矩形高度;文字形状由行数决定(每行 21 DIP)。 |
| `Lines` | `int` | 1 | 文字行数,多行时最后一行为 60% 宽。 |
负值 panic。
## 状态
明暗缓慢脉动(1.6 秒周期),只重绘不重建视图;减少动画模式使用静态填充。
## 事件
无。
## 键盘操作
不可聚焦,不进入无障碍树。
## 限制
- 骨架本身不向读屏报告加载;请在容器上配合 Spinner 或 LoadingOverlay 的说明文字。
+48
View File
@@ -0,0 +1,48 @@
# 096 EmptyState 空状态
## 用途
说明视图为何为空并给出下一步。区分“无数据”(集合本身为空)与“无搜索结果”(筛选没有匹配),两者使用不同的默认图标与文案。
## 最小示例
```go
r := mujica.EmptyState(c, mujica.EmptyStateOptions{
Kind: mujica.EmptyNoResults,
Query: query,
Action: "Clear search",
})
if r.Action {
query = ""
}
```
签名:`func EmptyState(c *ui.Context, opts EmptyStateOptions) EmptyStateResult`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Kind` | `EmptyKind` | `EmptyNoData` | `EmptyNoData` 或 `EmptyNoResults`。 |
| `Title` | `string` | 按类型的内置文案 | 衬线标题。 |
| `Description` | `string` | 按类型的内置文案 | 说明。 |
| `Query` | `string` | `""` | 仅 `EmptyNoResults`:默认说明写出该关键词。用于 `EmptyNoData` 时 panic。 |
| `Icon` | `*ui.SVG` | inbox / search | 替换图标。 |
| `NoIcon` | `bool` | `false` | 不显示图标;与 `Icon` 同时设置时 panic。 |
| `Action` | `string` | `""` | 次按钮文字。 |
## 状态
静态展示;操作按钮有悬停、按下与焦点状态。
## 事件
`EmptyStateResult.Action`:操作按钮被触发。
## 键盘操作
Tab 聚焦操作按钮;Enter 或 Space 触发。
## 限制
- 只有一个操作;需要多个下一步时使用 Result。
+46
View File
@@ -0,0 +1,46 @@
# 097 Result 结果页
## 用途
任务完成后的整页结果:成功、失败或无权限,附说明与下一步操作。组件只报告选择了哪个操作,不执行跳转。标题与操作之间用旧金色细线与菱形分隔。
## 最小示例
```go
r := mujica.Result(c, mujica.ResultOptions{
Kind: mujica.ResultForbidden,
Description: "You need the Editor role to change billing.",
Actions: []string{"Request access", "Go back"},
})
switch r.Action {
case 0: // send the request
case 1: // navigate back
}
```
签名:`func Result(c *ui.Context, opts ResultOptions) ResultResult`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `Kind` | `ResultKind` | `ResultSuccess` | `ResultSuccess`、`ResultFailure`、`ResultForbidden`;未知值 panic。 |
| `Title` | `string` | 按类型的内置文案 | 衬线标题。 |
| `Description` | `string` | `""` | 说明。 |
| `Actions` | `[]string` | 无 | 下一步操作;第一个为主按钮,其余为次按钮。 |
## 状态
图标(对勾、叉、盾牌)与标题文字共同表达结果,不只靠颜色。按钮有悬停、按下与焦点状态。
## 事件
`ResultResult.Action`:被触发的操作序号,未触发为 -1。
## 键盘操作
Tab 按顺序聚焦操作按钮;Enter 或 Space 触发。
## 限制
- 不含路由;导航由调用方完成。
+37
View File
@@ -0,0 +1,37 @@
# 098 StatusIndicator 状态标记
## 用途
以图形加文字标出状态:成功、警告、错误、离线、处理中。每种状态有独立形状(对勾圆、三角、叉圆、断开的 Wi-Fi、旋转菱形),并总是显示文字,不只靠颜色。
## 最小示例
```go
mujica.StatusIndicator(c, mujica.StatusSuccess, mujica.StatusIndicatorOptions{Label: "API online"})
mujica.StatusIndicator(c, mujica.StatusOffline, mujica.StatusIndicatorOptions{})
```
签名:`func StatusIndicator(c *ui.Context, status Status, opts StatusIndicatorOptions) *ui.Element`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `status` | `Status` | `StatusSuccess` | `StatusSuccess`、`StatusWarning`、`StatusError`、`StatusOffline`、`StatusBusy`;未知值 panic。 |
| `Label` | `string` | 内置词(Healthy、Degraded、Failing、Offline、Working) | 替换显示的文字。 |
## 状态
处理中使用 Spinner,减少动画时静止。整体为 `RoleStatus`,名称为文字。
## 事件
无。
## 键盘操作
不可聚焦。
## 限制
- 无 Badge 式的纯圆点模式;PRD 要求不能只靠颜色。
@@ -0,0 +1,51 @@
# 099 NotificationCenter 通知中心
## 用途
应用内消息列表:未读标记、已读/未读切换、单条清除、全部已读、全部清除和每条消息的操作。消息列表与持久化由调用方持有;组件就地修改调用方的切片,并报告发生了什么,供调用方保存。
## 最小示例
```go
r := mujica.NotificationCenter(c, &items, mujica.NotificationCenterOptions{})
if r.Action == "a" {
// open the build log
}
```
签名:`func NotificationCenter(c *ui.Context, items *[]Notification, opts NotificationCenterOptions) NotificationCenterResult`
## 参数
`Notification`:
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `ID` | `string` | 必填 | 列表内唯一;为空或重复时 panic。 |
| `Title` | `string` | `""` | 标题,未读时加粗。 |
| `Body` | `string` | `""` | 正文。 |
| `Time` | `string` | `""` | 按原样显示的时间,如“5 min ago”。 |
| `Read` | `bool` | `false` | 是否已读。 |
| `Action` | `string` | `""` | 操作按钮文字。 |
`NotificationCenterOptions.Title`:面板标题,默认“Notifications / 通知”。`items` 为 nil 时 panic。
## 状态
- 未读:左侧酒红菱形、粗体标题、无障碍名称前缀“Unread”。
- 行悬停加浅底;按钮有悬停、按下与焦点状态;无未读或无消息时头部按钮禁用。
- 空列表显示 EmptyState。
- 面板标题下为旧金细线。列表超出容器高度时滚动。
## 事件
`NotificationCenterResult`:`Action`、`Toggled`(已读状态切换)、`Opened`(点击正文后标为已读)、`Removed` 为对应 ID;`MarkedAllRead`、`ClearedAll` 为布尔值。
## 键盘操作
列表是一个 Tab 停靠点;方向键在各条消息及其按钮之间移动,Home/End 到首尾。焦点在消息正文上时 Enter 或 Space 标为已读;Delete 或 Backspace 清除当前消息。
## 限制
- 不分页,也不虚拟化;面向几十到几百条的应用内消息。
- 时间文字由调用方格式化。
+48
View File
@@ -0,0 +1,48 @@
# 100 LoadingOverlay 加载遮罩
## 用途
在一个容器范围内显示加载遮罩:被覆盖的内容不接收指针、按键和焦点,防止重复操作;窗口其余部分照常可用。显示说明文字与可选取消操作。
## 最小示例
```go
r := mujica.LoadingOverlay(c, loading, mujica.LoadingOverlayOptions{Cancel: "Cancel"}, func() {
ui.Text(c, "Quarterly report")
mujica.Button(c, "Export", mujica.ButtonOptions{})
})
if r.Canceled {
loading = false
}
```
签名:`func LoadingOverlay(c *ui.Context, loading bool, opts LoadingOverlayOptions, content func()) LoadingOverlayResult`
## 参数
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `loading` | `bool` | 必填 | 是否覆盖。 |
| `content` | `func()` | 必填 | 构建被覆盖的内容;nil 时 panic。 |
| `Label` | `string` | 内置“Loading… / 正在加载…” | 说明文字。 |
| `Cancel` | `string` | `""` | 取消按钮文字;为空时不显示。 |
返回 `LoadingOverlayResult{Element, Canceled}`。`Element` 即遮罩所覆盖的范围,可在其上设置宽高。
## 状态
- 加载时内容经 MyGo `Disabled` 阻止输入(MyGo 统一减淡),上方为半透明背景与居中面板。
- 开始加载时播报说明;焦点原在内容内时移到取消按钮(无取消时移到可聚焦的说明面板),焦点不会离开该区域。
- 遮罩淡入淡出,减少动画时直接切换。
## 事件
`Canceled`:点击取消,或焦点在面板内时按 Escape。
## 键盘操作
Tab 到达取消按钮;Enter、Space 或 Escape 取消。被覆盖的控件不进入 Tab 序列。
## 限制
- 只遮盖容器自身范围;整窗阻塞请使用模态对话框。