WIP feedback 3
This commit is contained in:
17 files changed
+1148
-3
No files matched your search
@@ -1,3 +1,113 @@
|
||||
package main
|
||||
|
||||
var feedbackPages = []page{}
|
||||
var feedbackPages = []page{
|
||||
{
|
||||
ID: "091", Name: "Alert", ZhName: "提示条 警告 通知横幅", Category: "Feedback",
|
||||
Demo: alertDemo,
|
||||
Code: `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
|
||||
}`,
|
||||
Keys: "Tab moves to the action and the dismiss button; Enter or Space presses them.",
|
||||
},
|
||||
{
|
||||
ID: "092", Name: "Toast", ZhName: "轻提示 消息队列 吐司", Category: "Feedback",
|
||||
Demo: toastDemo,
|
||||
Code: `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
|
||||
}`,
|
||||
Keys: "Toasts never take the focus. Tab reaches their buttons after the page; Escape closes the focused toast. Hover or focus pauses its timer.",
|
||||
},
|
||||
{
|
||||
ID: "093", Name: "Progress", ZhName: "进度条 环形进度 计量条", Category: "Feedback",
|
||||
Demo: progressDemo,
|
||||
Code: `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},
|
||||
})`,
|
||||
Keys: "Not focusable; assistive technology reads its name and value.",
|
||||
},
|
||||
{
|
||||
ID: "094", Name: "Spinner", ZhName: "加载标记 加载中 转圈", Category: "Feedback",
|
||||
Demo: spinnerDemo,
|
||||
Code: `mujica.Spinner(c, mujica.SpinnerOptions{Size: 20, Label: "Syncing", ShowLabel: true})`,
|
||||
Keys: "Not focusable; read as an indeterminate progress indicator named by Label.",
|
||||
},
|
||||
{
|
||||
ID: "095", Name: "Skeleton", ZhName: "骨架屏 占位", Category: "Feedback",
|
||||
Demo: skeletonDemo,
|
||||
Code: `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})
|
||||
})
|
||||
})`,
|
||||
Keys: "Decorative; not focusable and hidden from assistive technology.",
|
||||
},
|
||||
{
|
||||
ID: "096", Name: "EmptyState", ZhName: "空状态 无数据 无搜索结果", Category: "Feedback",
|
||||
Demo: emptyStateDemo,
|
||||
Code: `r := mujica.EmptyState(c, mujica.EmptyStateOptions{
|
||||
Kind: mujica.EmptyNoResults,
|
||||
Query: query,
|
||||
Action: "Clear search",
|
||||
})
|
||||
if r.Action {
|
||||
query = ""
|
||||
}`,
|
||||
Keys: "Tab reaches the action button; Enter or Space presses it.",
|
||||
},
|
||||
{
|
||||
ID: "097", Name: "Result", ZhName: "结果页 成功 失败 无权限", Category: "Feedback",
|
||||
Demo: resultDemo,
|
||||
Code: `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
|
||||
}`,
|
||||
Keys: "Tab moves through the actions, primary first; Enter or Space presses one.",
|
||||
},
|
||||
{
|
||||
ID: "098", Name: "StatusIndicator", ZhName: "状态标记 在线 离线", Category: "Feedback",
|
||||
Demo: statusDemo,
|
||||
Code: `mujica.StatusIndicator(c, mujica.StatusSuccess, mujica.StatusIndicatorOptions{Label: "API online"})
|
||||
mujica.StatusIndicator(c, mujica.StatusOffline, mujica.StatusIndicatorOptions{})`,
|
||||
Keys: "Not focusable; read as a status with its word.",
|
||||
},
|
||||
{
|
||||
ID: "099", Name: "NotificationCenter", ZhName: "通知中心 消息列表", Category: "Feedback",
|
||||
Demo: notificationDemo,
|
||||
Code: `r := mujica.NotificationCenter(c, &items, mujica.NotificationCenterOptions{})
|
||||
if r.Action == "a" {
|
||||
// open the build log
|
||||
}`,
|
||||
Keys: "The list is one Tab stop. Arrows move among notifications and their buttons; Enter marks the focused one read; Delete or Backspace removes it.",
|
||||
},
|
||||
{
|
||||
ID: "100", Name: "LoadingOverlay", ZhName: "加载遮罩 区域加载", Category: "Feedback",
|
||||
Demo: loadingOverlayDemo,
|
||||
Code: `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
|
||||
}`,
|
||||
Keys: "While loading, the covered region takes no input; focus inside moves to Cancel, and Escape there cancels. The rest of the window stays usable.",
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
mujica "mujicaui"
|
||||
"mujicaui/theme"
|
||||
)
|
||||
|
||||
// feedbackSection titles a part of a demo.
|
||||
func feedbackSection(c *ui.Context, title string, fn func()) {
|
||||
ui.Column(c).Gap(8).FillWidth().Children(func() {
|
||||
ui.Text(c, title).FontSize(theme.CaptionSize).TextColor(mujica.Tokens(c).TextMuted)
|
||||
fn()
|
||||
})
|
||||
}
|
||||
|
||||
var feedbackSeverities = []mujica.Severity{mujica.SeverityInfo, mujica.SeveritySuccess, mujica.SeverityWarning, mujica.SeverityError}
|
||||
|
||||
func alertDemo(c *ui.Context, log func(string)) {
|
||||
type state struct {
|
||||
sev int
|
||||
title, action bool
|
||||
closable bool
|
||||
open bool
|
||||
}
|
||||
s := ui.Local(c.Root(), "091", func() state { return state{sev: 3, title: true, action: true, closable: true, open: true} })
|
||||
ui.Column(c).Gap(16).FillWidth().Children(func() {
|
||||
feedbackSection(c, "Parameters", func() {
|
||||
ui.Segmented(c, &s.sev, "Info", "Success", "Warning", "Error")
|
||||
ui.Row(c).Gap(16).Children(func() {
|
||||
ui.Checkbox(c, &s.title, "Title")
|
||||
ui.Checkbox(c, &s.action, "Action")
|
||||
ui.Checkbox(c, &s.closable, "Closable")
|
||||
})
|
||||
})
|
||||
feedbackSection(c, "Live", func() {
|
||||
opts := mujica.AlertOptions{Severity: feedbackSeverities[s.sev]}
|
||||
if s.title {
|
||||
opts.Title = "Import failed"
|
||||
}
|
||||
if s.action {
|
||||
opts.Action = "Retry"
|
||||
}
|
||||
var open *bool
|
||||
if s.closable {
|
||||
open = &s.open
|
||||
}
|
||||
r := mujica.Alert(c, open, "The archive could not be read.", opts)
|
||||
if r.Action {
|
||||
log("alert: action Retry")
|
||||
}
|
||||
if r.Closed {
|
||||
log("alert: closed")
|
||||
}
|
||||
if s.closable && !s.open && mujica.Button(c, "Show again", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() {
|
||||
s.open = true
|
||||
log("alert: reopened")
|
||||
}
|
||||
})
|
||||
feedbackSection(c, "Severities", func() {
|
||||
for _, sev := range feedbackSeverities {
|
||||
mujica.Alert(c, nil, "Severity "+sev.String()+" uses its own icon, bar and name.", mujica.AlertOptions{Severity: sev}).Element.Key(sev)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func toastDemo(c *ui.Context, log func(string)) {
|
||||
type state struct {
|
||||
sev int
|
||||
action bool
|
||||
seconds float64
|
||||
n int
|
||||
note string
|
||||
}
|
||||
s := ui.Local(c.Root(), "092", func() state { return state{seconds: 5} })
|
||||
ui.Column(c).Gap(16).FillWidth().Children(func() {
|
||||
feedbackSection(c, "Parameters", func() {
|
||||
ui.Segmented(c, &s.sev, "Info", "Success", "Warning", "Error")
|
||||
ui.Checkbox(c, &s.action, "Undo action")
|
||||
ui.Row(c).Gap(12).AlignItems(ui.Center).Children(func() {
|
||||
ui.Text(c, fmt.Sprintf("Duration %.0f s (errors stay until closed)", s.seconds))
|
||||
ui.Slider(c, &s.seconds, 1, 10).Width(200)
|
||||
})
|
||||
})
|
||||
feedbackSection(c, "Actions", func() {
|
||||
ui.Row(c).Gap(12).Wrap().Children(func() {
|
||||
if mujica.Button(c, "Show toast", mujica.ButtonOptions{}).Clicked() {
|
||||
s.n++
|
||||
m := mujica.ToastMessage{ID: fmt.Sprint(s.n), Severity: feedbackSeverities[s.sev], Message: fmt.Sprintf("Message %d", s.n)}
|
||||
if s.action {
|
||||
m.Action = "Undo"
|
||||
}
|
||||
if m.Severity != mujica.SeverityError {
|
||||
m.Duration = time.Duration(s.seconds * float64(time.Second))
|
||||
}
|
||||
mujica.ShowToast(c, m)
|
||||
log("toast: show " + m.ID)
|
||||
}
|
||||
if mujica.Button(c, "Show five at once", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() {
|
||||
for range 5 {
|
||||
s.n++
|
||||
mujica.ShowToast(c, mujica.ToastMessage{ID: fmt.Sprint(s.n), Message: fmt.Sprintf("Queued %d", s.n)})
|
||||
}
|
||||
log("toast: five queued, three visible")
|
||||
}
|
||||
if mujica.Button(c, "Repeat same ID", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() {
|
||||
s.n++
|
||||
mujica.ShowToast(c, mujica.ToastMessage{ID: "sync", Message: fmt.Sprintf("Synced %d times", s.n)})
|
||||
log("toast: dedupe id sync")
|
||||
}
|
||||
})
|
||||
ui.Text(c, "Type here while toasts appear; the focus stays:")
|
||||
ui.TextInput(c, &s.note).Width(320)
|
||||
})
|
||||
})
|
||||
if r := mujica.Toaster(c); r.Action != "" {
|
||||
log("toast: action " + r.Action)
|
||||
} else if r.Closed != "" {
|
||||
log("toast: closed " + r.Closed)
|
||||
}
|
||||
}
|
||||
|
||||
func progressDemo(c *ui.Context, log func(string)) {
|
||||
type state struct {
|
||||
value, meter float64
|
||||
indet, showValue bool
|
||||
ring int
|
||||
}
|
||||
s := ui.Local(c.Root(), "093", func() state { return state{value: 0.62, meter: 72, showValue: true} })
|
||||
ui.Column(c).Gap(16).FillWidth().Children(func() {
|
||||
feedbackSection(c, "Parameters", func() {
|
||||
ui.Segmented(c, &s.ring, "Linear", "Ring")
|
||||
ui.Row(c).Gap(16).Children(func() {
|
||||
if ui.Checkbox(c, &s.indet, "Indeterminate").Changed() {
|
||||
log(fmt.Sprintf("progress: indeterminate %v", s.indet))
|
||||
}
|
||||
ui.Checkbox(c, &s.showValue, "Show value")
|
||||
})
|
||||
ui.Row(c).Gap(12).AlignItems(ui.Center).Children(func() {
|
||||
ui.Text(c, "Value")
|
||||
if ui.Slider(c, &s.value, 0, 1).Width(240).Changed() {
|
||||
log(fmt.Sprintf("progress: value %.2f", s.value))
|
||||
}
|
||||
})
|
||||
})
|
||||
feedbackSection(c, "Progress", func() {
|
||||
mujica.Progress(c, s.value, mujica.ProgressOptions{
|
||||
Shape: mujica.ProgressShape(s.ring), Indeterminate: s.indet, Label: "Uploading", ShowValue: s.showValue,
|
||||
})
|
||||
})
|
||||
feedbackSection(c, "Meter with thresholds 70 and 90", func() {
|
||||
ui.Row(c).Gap(12).AlignItems(ui.Center).Children(func() {
|
||||
ui.Text(c, "Level")
|
||||
if ui.Slider(c, &s.meter, 0, 100).Width(240).Changed() {
|
||||
log(fmt.Sprintf("meter: value %.0f", s.meter))
|
||||
}
|
||||
})
|
||||
v := float64(int(s.meter))
|
||||
mujica.Meter(c, v, mujica.MeterOptions{Max: 100, Label: "Disk", ShowValue: true, Levels: &ui.MeterLevels{Warning: 70, Critical: 90}})
|
||||
mujica.Meter(c, 100-v, mujica.MeterOptions{Max: 100, Label: "Battery (low is bad)", ShowValue: true, Levels: &ui.MeterLevels{Warning: 30, Critical: 10}})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func spinnerDemo(c *ui.Context, log func(string)) {
|
||||
type state struct {
|
||||
size float64
|
||||
showLabel, active bool
|
||||
}
|
||||
s := ui.Local(c.Root(), "094", func() state { return state{size: 20, showLabel: true, active: true} })
|
||||
ui.Column(c).Gap(16).FillWidth().Children(func() {
|
||||
feedbackSection(c, "Parameters", func() {
|
||||
ui.Row(c).Gap(12).AlignItems(ui.Center).Children(func() {
|
||||
ui.Text(c, fmt.Sprintf("Size %.0f", s.size))
|
||||
ui.Slider(c, &s.size, 12, 48).Width(200)
|
||||
})
|
||||
ui.Row(c).Gap(16).Children(func() {
|
||||
ui.Checkbox(c, &s.showLabel, "Show label")
|
||||
if ui.Checkbox(c, &s.active, "Loading (unchecked stops the animation)").Changed() {
|
||||
log(fmt.Sprintf("spinner: loading %v", s.active))
|
||||
}
|
||||
})
|
||||
})
|
||||
feedbackSection(c, "Live", func() {
|
||||
if s.active {
|
||||
mujica.Spinner(c, mujica.SpinnerOptions{Size: float32(s.size), Label: "Syncing", ShowLabel: s.showLabel})
|
||||
} else {
|
||||
ui.Text(c, "Done")
|
||||
}
|
||||
})
|
||||
feedbackSection(c, "In a button", func() {
|
||||
mujica.Button(c, "Saving", mujica.ButtonOptions{Loading: true})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func skeletonDemo(c *ui.Context, log func(string)) {
|
||||
type state struct {
|
||||
lines float64
|
||||
loading bool
|
||||
}
|
||||
s := ui.Local(c.Root(), "095", func() state { return state{lines: 3, loading: true} })
|
||||
ui.Column(c).Gap(16).FillWidth().Children(func() {
|
||||
feedbackSection(c, "Parameters", func() {
|
||||
ui.Row(c).Gap(12).AlignItems(ui.Center).Children(func() {
|
||||
ui.Text(c, fmt.Sprintf("Lines %.0f", s.lines))
|
||||
ui.Slider(c, &s.lines, 1, 6).Width(200)
|
||||
})
|
||||
if ui.Checkbox(c, &s.loading, "Loading").Changed() {
|
||||
log(fmt.Sprintf("skeleton: loading %v", s.loading))
|
||||
}
|
||||
})
|
||||
feedbackSection(c, "Card (same size loading and loaded)", func() {
|
||||
ui.Row(c).Gap(12).Padding(16).Width(420).Background(mujica.Tokens(c).Surface).Radius(theme.CardRadius).Children(func() {
|
||||
if s.loading {
|
||||
mujica.Skeleton(c, mujica.SkeletonOptions{Shape: mujica.SkeletonCircle})
|
||||
ui.Column(c).Grow(1).Children(func() {
|
||||
mujica.Skeleton(c, mujica.SkeletonOptions{Lines: int(s.lines)})
|
||||
})
|
||||
return
|
||||
}
|
||||
ui.Box(c).Size(40, 40).Radius(20).Background(mujica.Tokens(c).Selection)
|
||||
ui.Column(c).Grow(1).Children(func() {
|
||||
for i := range int(s.lines) {
|
||||
ui.Text(c, fmt.Sprintf("Loaded line %d", i+1)).LineHeight(theme.LineHeight)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
feedbackSection(c, "Rect", func() {
|
||||
mujica.Skeleton(c, mujica.SkeletonOptions{Shape: mujica.SkeletonRect, Width: 420, Height: 96})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func emptyStateDemo(c *ui.Context, log func(string)) {
|
||||
type state struct {
|
||||
kind int
|
||||
query string
|
||||
icon, action bool
|
||||
}
|
||||
s := ui.Local(c.Root(), "096", func() state { return state{kind: 1, query: "quarterly", icon: true, action: true} })
|
||||
ui.Column(c).Gap(16).FillWidth().Children(func() {
|
||||
feedbackSection(c, "Parameters", func() {
|
||||
ui.Segmented(c, &s.kind, "No data", "No results")
|
||||
ui.Row(c).Gap(16).AlignItems(ui.Center).Children(func() {
|
||||
ui.Checkbox(c, &s.icon, "Icon")
|
||||
ui.Checkbox(c, &s.action, "Action")
|
||||
if s.kind == 1 {
|
||||
ui.TextInput(c, &s.query).Width(200)
|
||||
}
|
||||
})
|
||||
})
|
||||
feedbackSection(c, "Live", func() {
|
||||
opts := mujica.EmptyStateOptions{Kind: mujica.EmptyKind(s.kind), NoIcon: !s.icon}
|
||||
if s.kind == 1 {
|
||||
opts.Query = s.query
|
||||
}
|
||||
if s.action {
|
||||
opts.Action = []string{"New project", "Clear search"}[s.kind]
|
||||
}
|
||||
if mujica.EmptyState(c, opts).Action {
|
||||
log("empty state: action " + opts.Action)
|
||||
s.query = ""
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func resultDemo(c *ui.Context, log func(string)) {
|
||||
type state struct{ kind int }
|
||||
s := ui.Local(c.Root(), "097", func() state { return state{kind: 2} })
|
||||
descs := []string{"Your order has been placed.", "The payment was declined by the bank.", "You need the Editor role to change billing."}
|
||||
actions := [][]string{{"View order", "Keep shopping"}, {"Try again", "Back to cart"}, {"Request access", "Go back"}}
|
||||
ui.Column(c).Gap(16).FillWidth().Children(func() {
|
||||
feedbackSection(c, "Parameters", func() {
|
||||
ui.Segmented(c, &s.kind, "Success", "Failure", "Forbidden")
|
||||
})
|
||||
r := mujica.Result(c, mujica.ResultOptions{Kind: mujica.ResultKind(s.kind), Description: descs[s.kind], Actions: actions[s.kind]})
|
||||
if r.Action >= 0 {
|
||||
log("result: action " + actions[s.kind][r.Action])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func statusDemo(c *ui.Context, log func(string)) {
|
||||
type state struct {
|
||||
status int
|
||||
custom bool
|
||||
}
|
||||
s := ui.Local(c.Root(), "098", func() state { return state{} })
|
||||
ui.Column(c).Gap(16).FillWidth().Children(func() {
|
||||
feedbackSection(c, "Parameters", func() {
|
||||
if ui.Segmented(c, &s.status, "Success", "Warning", "Error", "Offline", "Busy").Changed() {
|
||||
log("status: " + mujica.Status(s.status).String())
|
||||
}
|
||||
ui.Checkbox(c, &s.custom, "Custom label")
|
||||
})
|
||||
feedbackSection(c, "Live", func() {
|
||||
opts := mujica.StatusIndicatorOptions{}
|
||||
if s.custom {
|
||||
opts.Label = "Database replica"
|
||||
}
|
||||
mujica.StatusIndicator(c, mujica.Status(s.status), opts)
|
||||
})
|
||||
feedbackSection(c, "All states (shape and word, not color alone)", func() {
|
||||
ui.Row(c).Gap(20).Wrap().Children(func() {
|
||||
for st := mujica.StatusSuccess; st <= mujica.StatusBusy; st++ {
|
||||
mujica.StatusIndicator(c, st, mujica.StatusIndicatorOptions{}).Key(st)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func notificationDemo(c *ui.Context, log func(string)) {
|
||||
type state struct {
|
||||
items []mujica.Notification
|
||||
n int
|
||||
}
|
||||
s := ui.Local(c.Root(), "099", func() state {
|
||||
return state{items: []mujica.Notification{
|
||||
{ID: "a", Title: "Build failed", Body: "main · 3 tests failing", Time: "2 min ago", Action: "View log"},
|
||||
{ID: "b", Title: "Invite accepted", Body: "Mira joined the workspace", Time: "1 h ago"},
|
||||
{ID: "c", Title: "Backup complete", Time: "Yesterday", Read: true},
|
||||
}}
|
||||
})
|
||||
ui.Column(c).Gap(16).FillWidth().Children(func() {
|
||||
feedbackSection(c, "Caller-owned list", func() {
|
||||
if mujica.Button(c, "Add notification", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() {
|
||||
s.n++
|
||||
id := fmt.Sprintf("new-%d", s.n)
|
||||
s.items = append([]mujica.Notification{{ID: id, Title: fmt.Sprintf("Comment %d on the design doc", s.n), Time: "now"}}, s.items...)
|
||||
log("notifications: added " + id)
|
||||
}
|
||||
})
|
||||
ui.Column(c).Width(520).Height(420).Children(func() {
|
||||
r := mujica.NotificationCenter(c, &s.items, mujica.NotificationCenterOptions{})
|
||||
for _, ev := range [][2]string{{"action", r.Action}, {"toggled", r.Toggled}, {"opened", r.Opened}, {"removed", r.Removed}} {
|
||||
if ev[1] != "" {
|
||||
log("notifications: " + ev[0] + " " + ev[1])
|
||||
}
|
||||
}
|
||||
if r.MarkedAllRead {
|
||||
log("notifications: marked all read")
|
||||
}
|
||||
if r.ClearedAll {
|
||||
log("notifications: cleared all")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func loadingOverlayDemo(c *ui.Context, log func(string)) {
|
||||
type state struct {
|
||||
loading, cancel bool
|
||||
saves int
|
||||
}
|
||||
s := ui.Local(c.Root(), "100", func() state { return state{loading: true, cancel: true} })
|
||||
ui.Column(c).Gap(16).FillWidth().Children(func() {
|
||||
feedbackSection(c, "Parameters", func() {
|
||||
ui.Row(c).Gap(16).Children(func() {
|
||||
if ui.Checkbox(c, &s.loading, "Loading").Changed() {
|
||||
log(fmt.Sprintf("overlay: loading %v", s.loading))
|
||||
}
|
||||
ui.Checkbox(c, &s.cancel, "Cancel action")
|
||||
})
|
||||
})
|
||||
feedbackSection(c, "Covered region", func() {
|
||||
opts := mujica.LoadingOverlayOptions{Label: "Generating report…"}
|
||||
if s.cancel {
|
||||
opts.Cancel = "Cancel"
|
||||
}
|
||||
r := mujica.LoadingOverlay(c, s.loading, opts, func() {
|
||||
ui.Column(c).Gap(8).Padding(16).FillWidth().AlignItems(ui.Start).Background(mujica.Tokens(c).Surface).Radius(theme.CardRadius).Children(func() {
|
||||
ui.Text(c, "Quarterly report").Font(theme.SerifFont).FontSize(theme.H3Size)
|
||||
ui.Text(c, fmt.Sprintf("Exported %d times.", s.saves))
|
||||
if mujica.Button(c, "Export", mujica.ButtonOptions{}).Clicked() {
|
||||
s.saves++
|
||||
log("overlay: export clicked")
|
||||
}
|
||||
})
|
||||
})
|
||||
r.Element.Width(420)
|
||||
if r.Canceled {
|
||||
s.loading = false
|
||||
log("overlay: canceled")
|
||||
}
|
||||
})
|
||||
feedbackSection(c, "Outside the region (always usable)", func() {
|
||||
if mujica.Button(c, "Outside button", mujica.ButtonOptions{Variant: mujica.Secondary}).AlignSelf(ui.Start).Clicked() {
|
||||
log("overlay: outside clicked")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user