From e3eaef743779981ea28a0dc947f122ab7a8fe655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 5 Oct 2026 13:17:52 -0400 Subject: [PATCH] Date & Time: review r3 fixes --- date_picker.go | 5 ++- datetime.go | 2 + datetime_review2_test.go | 60 +++++++++++++++++++++++++++++ docs/components/051-calendar.md | 2 +- docs/components/057-month-picker.md | 2 +- docs/components/058-year-picker.md | 2 +- examples/gallery/composite_form.go | 2 +- examples/gallery/composite_test.go | 2 +- 8 files changed, 70 insertions(+), 7 deletions(-) diff --git a/date_picker.go b/date_picker.go index bec7d78..57ae24a 100644 --- a/date_picker.go +++ b/date_picker.go @@ -102,11 +102,12 @@ func DatePicker(c *ui.Context, value *Date, opts DatePickerOptions) DateTimeResu if placeholder == "" { placeholder = msg(c, "date_picker.placeholder") } - var field *ui.Element + var field, input *ui.Element col.Children(func() { field = datetimeField(c, ui.Row(c), *problem != "", opts.ReadOnly) field.Children(func() { in := textInputEditor(c, field, text, opts.ReadOnly, ui.TextInputBase).Grow(1).Shrink(1).Placeholder(placeholder).FontFeatures("tnum") + input = in label := opts.Label if label == "" { label = placeholder @@ -149,7 +150,7 @@ func DatePicker(c *ui.Context, value *Date, opts DatePickerOptions) DateTimeResu }) datetimeError(c, *problem) }) - return DateTimeResult{Element: col, changed: changed} + return DateTimeResult{Element: col, Input: input, changed: changed} } // datePickerProblem explains why an existing day d cannot be chosen, or returns "". diff --git a/datetime.go b/datetime.go index 4fef3cc..6a9bf2c 100644 --- a/datetime.go +++ b/datetime.go @@ -69,6 +69,8 @@ func (d Date) within(lo, hi Date) bool { // DateTimeResult is a date or time component and what happened to it this frame. type DateTimeResult struct { *ui.Element + // Input is the text field inside, for labels and focus; nil without one. + Input *ui.Element changed bool cancelled bool } diff --git a/datetime_review2_test.go b/datetime_review2_test.go index 88a74ba..5654eb2 100644 --- a/datetime_review2_test.go +++ b/datetime_review2_test.go @@ -5,6 +5,8 @@ import ( "time" "github.com/egoist/mygo/ui" + + "mujicaui/theme" ) func TestTimePickerDisabledIgnoresSegmentKeys(t *testing.T) { @@ -159,3 +161,61 @@ func TestTimePickerPopupPickClearsSegmentError(t *testing.T) { t.Fatalf("popup pick: value %v, %d changes, %v", v, n, tt.Texts()) } } + +func TestFormFocusesDatePickerInput(t *testing.T) { + var st FormState + day := Date{} + var input *ui.Element + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + Form(c, &st, FormOptions{}, func(f *FormScope) { + FormItem(f, "debut", &day, FormItemOptions[Date]{Label: "Debut date", Required: true}, func() *ui.Element { + r := DatePicker(c, &day, DatePickerOptions{Today: calendarToday}) + input = r.Input + return r.Input + }) + }) + }, 600, 500) + if err := tt.Click("Submit"); err != nil { + t.Fatal(err) + } + if input == nil || !input.Focused() || !tt.Focused("Debut date") { + t.Fatal("a failed submit should focus the DatePicker's text box") + } + tt.Type("2026-10-12") + tt.Key(0, ui.KeyEnter) + if day != oct(12) { + t.Fatalf("typing after the focus jump gave %v", day) + } +} + +func TestSelectedCellsHaveTheirOwnMark(t *testing.T) { + k := theme.Light() + check := func(name string, tt *ui.Tester, label string, shift int) { + t.Helper() + r, ok := tt.Find(label) + if !ok { + t.Fatalf("%s: no cell %q", name, label) + } + r.X += float32(shift) * r.W + img := tt.Image() + y := int(r.Y + r.H/2) + frame, fill := img.RGBAAt(int(r.X)+2, y), img.RGBAAt(int(r.X)+5, y) + if !datetimeNear(frame, k.OnAccent) || !datetimeNear(fill, k.Accent) { + t.Fatalf("%s: selected cell frame %v fill %v", name, frame, fill) + } + } + v := oct(14) + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{Mode: Light}) + Calendar(c, &v, CalendarOptions{Today: calendarToday}) + }, 400, 400) + tt.SetPreferences(ui.Preferences{ReduceMotion: true, TextScale: 1}) + check("calendar", tt, datetimeTestLabel(oct(14)), 0) + y := 2024 + ty := yearPickerTester(&y, YearPickerOptions{}, new(int)) + ty.SetPreferences(ui.Preferences{ReduceMotion: true, TextScale: 1}) + _ = ty.Click("Vintage") + // The field also shows "2024", so locate the cell beside 2023. + check("year", ty, "2023", 1) +} diff --git a/docs/components/051-calendar.md b/docs/components/051-calendar.md index c891a73..e30d0cd 100644 --- a/docs/components/051-calendar.md +++ b/docs/components/051-calendar.md @@ -33,7 +33,7 @@ ui.Render(view, 400, 300, 1) ## 状态 -默认、悬停、按下、聚焦(键盘焦点环)、选中(酒红填充 + 单选语义)、今日(加粗 + 菱形)、不可选(删除线并由 MyGo 置灰)、非本月(弱化文字)、禁用。 +默认、悬停、按下、聚焦(键盘焦点环)、选中(酒红填充 + 内嵌细框 + 单选语义)、今日(加粗 + 菱形)、不可选(删除线并由 MyGo 置灰)、非本月(弱化文字)、禁用。 ## 事件 diff --git a/docs/components/057-month-picker.md b/docs/components/057-month-picker.md index 1a701c1..562bf37 100644 --- a/docs/components/057-month-picker.md +++ b/docs/components/057-month-picker.md @@ -35,7 +35,7 @@ ui.Render(view, 400, 300, 1) ## 状态 -默认、悬停、聚焦、选中(酒红填充)、当前月(加粗 + 菱形)、不可选(删除线)、禁用。 +默认、悬停、聚焦、选中(酒红填充 + 内嵌细框)、当前月(加粗 + 菱形)、不可选(删除线)、禁用。 ## 事件 diff --git a/docs/components/058-year-picker.md b/docs/components/058-year-picker.md index 2b10e5a..d832172 100644 --- a/docs/components/058-year-picker.md +++ b/docs/components/058-year-picker.md @@ -35,7 +35,7 @@ ui.Render(view, 400, 300, 1) ## 状态 -默认、悬停、聚焦、选中、当前年、不可选、相邻十年(弱化)、禁用。 +默认、悬停、聚焦、选中(酒红填充 + 内嵌细框)、当前年(加粗 + 菱形)、不可选、相邻十年(弱化)、禁用。 ## 事件 diff --git a/examples/gallery/composite_form.go b/examples/gallery/composite_form.go index 2894c3b..cb66bd3 100644 --- a/examples/gallery/composite_form.go +++ b/examples/gallery/composite_form.go @@ -152,7 +152,7 @@ func (g *gallery) formFields(c *ui.Context, f *mujica.FormScope, log func(string if r.Changed() { log("debut " + s.debut.Format("2006-01-02")) } - return r.Element + return r.Input }) mujica.FormItem(f, "roles", &s.tags, mujica.FormItemOptions[[]string]{Label: g.t("Roles", "担当"), Required: true, Description: g.t("Up to 4; press Enter after each.", "最多 4 个;每个后按 Enter。")}, func() *ui.Element { diff --git a/examples/gallery/composite_test.go b/examples/gallery/composite_test.go index 4b2be4e..1526d8e 100644 --- a/examples/gallery/composite_test.go +++ b/examples/gallery/composite_test.go @@ -102,7 +102,7 @@ func TestCompositeFormInvalidThenValid(t *testing.T) { tt.Type("Mortis") click(t, tt, "Password") tt.Type("hunter22secret") - click(t, tt, "Select date") // the date field itself; its FormItem label focuses the picker's column + click(t, tt, "Debut date") // the FormItem label now reaches the picker's text box tt.Type("2026-12-24") tt.Key(0, ui.KeyEnter) click(t, tt, "Roles")