diff --git a/cascader.go b/cascader.go index 74d4c34..9be885f 100644 --- a/cascader.go +++ b/cascader.go @@ -227,7 +227,7 @@ func cascaderRow(c *ui.Context, st *cascaderState, path *[]string, opts Cascader ui.Text(c, n.Label).SingleLine().Grow(1).Shrink(1) if !n.Leaf { ui.Box(c).Size(14, 14).Shrink(0).Draw(func(p *ui.Painter, r ui.Rect) { - internal.Chevron(p, r, true, k.TextMuted) + internal.Mark(p, r, "chevron-right", k.TextMuted) }) } }) diff --git a/combobox.go b/combobox.go index 314aa26..8322289 100644 --- a/combobox.go +++ b/combobox.go @@ -69,12 +69,7 @@ func Combobox(c *ui.Context, value *string, options []string, opts ComboboxOptio p.Input.Focus() } open := p.Open() - arrow.Draw(func(pt *ui.Painter, r ui.Rect) { - if open { - r.Y, r.H = r.Y+r.H, -r.H - } - internal.Chevron(pt, r, false, k.TextMuted) - }) + arrow.Draw(func(pt *ui.Painter, r ui.Rect) { internal.Mark(pt, r, selectChevron(open), k.TextMuted) }) }) in := p.Input if f.Clicked() { diff --git a/internal/choice.go b/internal/choice.go index 36ec838..d758776 100644 --- a/internal/choice.go +++ b/internal/choice.go @@ -3,6 +3,7 @@ package internal import ( "github.com/egoist/mygo/ui" + "mujicaui/icons" "mujicaui/theme" ) @@ -31,30 +32,16 @@ func CheckBox(p *ui.Painter, r ui.Rect, s CheckState, k theme.Tokens, hover bool bg = k.AccentHover } p.Fill(r, bg, theme.ControlRadius) - var path ui.Path + mark := "check" if s == Mixed { - path.MoveTo(r.X+r.W*0.25, r.Y+r.H/2).LineTo(r.X+r.W*0.75, r.Y+r.H/2) - } else { - path.MoveTo(r.X+r.W*0.22, r.Y+r.H*0.52).LineTo(r.X+r.W*0.42, r.Y+r.H*0.72).LineTo(r.X+r.W*0.78, r.Y+r.H*0.3) + mark = "minus" } - p.StrokePath(&path, 1.75, k.OnAccent) + Mark(p, r, mark, k.OnAccent) } -// Chevron strokes an arrow in r pointing down, or right when right. -func Chevron(p *ui.Painter, r ui.Rect, right bool, c ui.Color) { - var path ui.Path - if right { - path.MoveTo(r.X+r.W*0.38, r.Y+r.H*0.22).LineTo(r.X+r.W*0.66, r.Y+r.H/2).LineTo(r.X+r.W*0.38, r.Y+r.H*0.78) - } else { - path.MoveTo(r.X+r.W*0.22, r.Y+r.H*0.38).LineTo(r.X+r.W/2, r.Y+r.H*0.66).LineTo(r.X+r.W*0.78, r.Y+r.H*0.38) - } - p.StrokePath(&path, 1.5, c) -} - -// Cross strokes an x in r. -func Cross(p *ui.Painter, r ui.Rect, c ui.Color) { - var path ui.Path - k := r.W * 0.28 - path.MoveTo(r.X+k, r.Y+k).LineTo(r.X+r.W-k, r.Y+r.H-k).MoveTo(r.X+r.W-k, r.Y+k).LineTo(r.X+k, r.Y+r.H-k) - p.StrokePath(&path, 1.5, c) +// Mark paints the Lucide icon name inset in r. Icons sit on the pixel grid, +// so their cached masks never differ between frames or tests. +func Mark(p *ui.Painter, r ui.Rect, name string, c ui.Color) { + in := r.W * 0.12 + p.Icon(icons.Must(name), ui.Rect{X: r.X + in, Y: r.Y + in, W: r.W - 2*in, H: r.H - 2*in}, c) } diff --git a/multi_select.go b/multi_select.go index 50c6200..f141120 100644 --- a/multi_select.go +++ b/multi_select.go @@ -229,10 +229,7 @@ func selectSearch(c *ui.Context, query *string, placeholder string) *ui.Element var in *ui.Element f.Children(func() { ui.Box(c).Size(14, 14).Shrink(0).Draw(func(p *ui.Painter, r ui.Rect) { - var path ui.Path - path.Circle(r.X+r.W*0.42, r.Y+r.H*0.42, r.W*0.32) - path.MoveTo(r.X+r.W*0.66, r.Y+r.H*0.66).LineTo(r.X+r.W*0.92, r.Y+r.H*0.92) - p.StrokePath(&path, 1.5, k.TextMuted) + internal.Mark(p, r, "search", k.TextMuted) }) in = ui.TextInputBase(c, query).Grow(1).Placeholder(placeholder).Label(placeholder).AutoFocus() }) diff --git a/select.go b/select.go index eed04a4..1a6e1ef 100644 --- a/select.go +++ b/select.go @@ -178,15 +178,19 @@ func selectField(c *ui.Context, tr *ui.Element, open bool, content func()) { tr.Children(func() { content() ui.Box(c).Size(16, 16).Shrink(0).Draw(func(p *ui.Painter, r ui.Rect) { - if open { - // Mirrored: the chevron points up while the popup shows. - r.Y, r.H = r.Y+r.H, -r.H - } - internal.Chevron(p, r, false, k.TextMuted) + internal.Mark(p, r, selectChevron(open), k.TextMuted) }) }) } +// selectChevron names the arrow of a field: up while its popup shows. +func selectChevron(open bool) string { + if open { + return "chevron-up" + } + return "chevron-down" +} + // selectClear draws a small clear button that takes no Tab stop; it reports a click. func selectClear(c *ui.Context, k theme.Tokens, name string) bool { x := ui.Box(c).Size(18, 18).Shrink(0).Radius(theme.ControlRadius).Role(ui.RoleButton).Label(name) @@ -194,7 +198,7 @@ func selectClear(c *ui.Context, k theme.Tokens, name string) bool { if x.Hovered() { x.Background(k.SurfaceHover) } - x.Draw(func(p *ui.Painter, r ui.Rect) { internal.Cross(p, r, k.TextMuted) }) + x.Draw(func(p *ui.Painter, r ui.Rect) { internal.Mark(p, r, "x", k.TextMuted) }) return clicked } @@ -220,9 +224,7 @@ func selectRow(c *ui.Context, row *ui.Element, highlighted, chosen bool, label s row.Children(func() { ui.Box(c).Size(14, 14).Shrink(0).Draw(func(p *ui.Painter, r ui.Rect) { if chosen { - var path ui.Path - path.MoveTo(r.X+r.W*0.15, r.Y+r.H*0.52).LineTo(r.X+r.W*0.4, r.Y+r.H*0.76).LineTo(r.X+r.W*0.85, r.Y+r.H*0.26) - p.StrokePath(&path, 1.75, k.AccentText) + internal.Mark(p, r, "check", k.AccentText) } }) ui.Text(c, label).SingleLine() diff --git a/select_test.go b/select_test.go index d2ddff6..1978715 100644 --- a/select_test.go +++ b/select_test.go @@ -137,7 +137,7 @@ func TestSelectEmptyAndDisabled(t *testing.T) { } func TestSelectSnapshot(t *testing.T) { - snapshot(t, "select", 460, 110, func(c *ui.Context) { + snapshot(t, "select", 660, 90, func(c *ui.Context) { a, b, d := "", "banana", "apple" ui.Row(c).Padding(20).Gap(16).Wrap().Children(func() { Select(c, &a, selectTestOptions, SelectOptions{}) diff --git a/testdata/snapshots/darwin/cascader-dark.png b/testdata/snapshots/darwin/cascader-dark.png index 54bebdd..fbfab03 100644 Binary files a/testdata/snapshots/darwin/cascader-dark.png and b/testdata/snapshots/darwin/cascader-dark.png differ diff --git a/testdata/snapshots/darwin/cascader-light.png b/testdata/snapshots/darwin/cascader-light.png index 556f871..12bfc38 100644 Binary files a/testdata/snapshots/darwin/cascader-light.png and b/testdata/snapshots/darwin/cascader-light.png differ diff --git a/testdata/snapshots/darwin/combobox-dark.png b/testdata/snapshots/darwin/combobox-dark.png index 00df2ae..8817795 100644 Binary files a/testdata/snapshots/darwin/combobox-dark.png and b/testdata/snapshots/darwin/combobox-dark.png differ diff --git a/testdata/snapshots/darwin/combobox-light.png b/testdata/snapshots/darwin/combobox-light.png index 193ed0a..fb9d148 100644 Binary files a/testdata/snapshots/darwin/combobox-light.png and b/testdata/snapshots/darwin/combobox-light.png differ diff --git a/testdata/snapshots/darwin/multi_select-dark.png b/testdata/snapshots/darwin/multi_select-dark.png index 3c7667f..01941b7 100644 Binary files a/testdata/snapshots/darwin/multi_select-dark.png and b/testdata/snapshots/darwin/multi_select-dark.png differ diff --git a/testdata/snapshots/darwin/multi_select-light.png b/testdata/snapshots/darwin/multi_select-light.png index c4be8cb..1caa04f 100644 Binary files a/testdata/snapshots/darwin/multi_select-light.png and b/testdata/snapshots/darwin/multi_select-light.png differ diff --git a/testdata/snapshots/darwin/range_slider-dark.png b/testdata/snapshots/darwin/range_slider-dark.png index 55aaabe..d403d3a 100644 Binary files a/testdata/snapshots/darwin/range_slider-dark.png and b/testdata/snapshots/darwin/range_slider-dark.png differ diff --git a/testdata/snapshots/darwin/range_slider-light.png b/testdata/snapshots/darwin/range_slider-light.png index 4c60eec..8878d15 100644 Binary files a/testdata/snapshots/darwin/range_slider-light.png and b/testdata/snapshots/darwin/range_slider-light.png differ diff --git a/testdata/snapshots/darwin/select-dark.png b/testdata/snapshots/darwin/select-dark.png index 13b23d2..0141a4e 100644 Binary files a/testdata/snapshots/darwin/select-dark.png and b/testdata/snapshots/darwin/select-dark.png differ diff --git a/testdata/snapshots/darwin/select-light.png b/testdata/snapshots/darwin/select-light.png index 71a432c..9175808 100644 Binary files a/testdata/snapshots/darwin/select-light.png and b/testdata/snapshots/darwin/select-light.png differ diff --git a/testdata/snapshots/darwin/slider-dark.png b/testdata/snapshots/darwin/slider-dark.png index d5cab20..727d64c 100644 Binary files a/testdata/snapshots/darwin/slider-dark.png and b/testdata/snapshots/darwin/slider-dark.png differ diff --git a/testdata/snapshots/darwin/slider-light.png b/testdata/snapshots/darwin/slider-light.png index b5456ea..f7bd23a 100644 Binary files a/testdata/snapshots/darwin/slider-light.png and b/testdata/snapshots/darwin/slider-light.png differ diff --git a/testdata/snapshots/darwin/switch-dark.png b/testdata/snapshots/darwin/switch-dark.png index dc478f0..d9c095b 100644 Binary files a/testdata/snapshots/darwin/switch-dark.png and b/testdata/snapshots/darwin/switch-dark.png differ diff --git a/testdata/snapshots/darwin/switch-light.png b/testdata/snapshots/darwin/switch-light.png index 2ba459c..fba34d7 100644 Binary files a/testdata/snapshots/darwin/switch-light.png and b/testdata/snapshots/darwin/switch-light.png differ diff --git a/testdata/snapshots/darwin/tree_select-dark.png b/testdata/snapshots/darwin/tree_select-dark.png index a17ba4a..aba3b73 100644 Binary files a/testdata/snapshots/darwin/tree_select-dark.png and b/testdata/snapshots/darwin/tree_select-dark.png differ diff --git a/testdata/snapshots/darwin/tree_select-light.png b/testdata/snapshots/darwin/tree_select-light.png index 82d5bf8..6fdfd09 100644 Binary files a/testdata/snapshots/darwin/tree_select-light.png and b/testdata/snapshots/darwin/tree_select-light.png differ diff --git a/tree_select.go b/tree_select.go index 9d54b1d..1bc09ef 100644 --- a/tree_select.go +++ b/tree_select.go @@ -217,7 +217,9 @@ func treeSelectRowView(c *ui.Context, st *treeSelectState, selected *[]string, r if arrow.Hovered() { arrow.Background(k.SurfaceHover) } - arrow.Draw(func(p *ui.Painter, rc ui.Rect) { internal.Chevron(p, rc, !open, k.TextMuted) }) + arrow.Draw(func(p *ui.Painter, rc ui.Rect) { + internal.Mark(p, rc, map[bool]string{true: "chevron-down", false: "chevron-right"}[open], k.TextMuted) + }) } state := treeSelectCheck(n, *selected, opts) var b *ui.Element