Merge branch 'worktree-agent-a1dd614394ee20ff2'

This commit is contained in:
ZacharyZhang-NY committed 2026-10-05 12:18:29 -04:00
commit 3be3cc1730
55 files changed
+3150 -1

No files matched your search

+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。