Layout: components 001-010

This commit is contained in:
ZacharyZhang-NY committed 2026-10-05 12:18:49 -04:00
1 parent 3be3cc1730
commit fe806037c7
53 files changed
+3399 -1

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`。
- 纵向不支持文字。