From 7345f823cf0c5f028b9fce214e657a578db50de5 Mon Sep 17 00:00:00 2001 From: Jan Steinke Date: Sat, 10 Feb 2024 21:55:48 +0200 Subject: [PATCH] improve UI response to clicks --- button.go | 18 +++++++++++++----- logic.go | 16 ++++++++-------- main.go | 6 +++--- styles.css | 6 +----- ui.go | 14 +++++++------- 5 files changed, 32 insertions(+), 28 deletions(-) diff --git a/button.go b/button.go index 4b499ed..1cff3b4 100644 --- a/button.go +++ b/button.go @@ -21,7 +21,7 @@ func NewButton(id int64) *button { } func (b *button) OnMount(ctx app.Context) { - ctx.Handle(fmt.Sprintf(playButton, b.id), b.handleActivate) + ctx.Handle(fmt.Sprintf(eventPlayButton, b.id), b.handleActivate) } func (b *button) Render() app.UI { @@ -29,17 +29,25 @@ func (b *button) Render() app.UI { Class("simon-button"). Body(app.Span().Text("")). ID("button%d", b.id). - OnClick(func(ctx app.Context, _ app.Event) { - ctx.NewActionWithValue(click, b.id) - }) + OnClick(b.handleClick) if b.Active { e.Class("active") } return e } +func (b *button) handleClick(ctx app.Context, _ app.Event) { + // Needs a short delay because it doesn't work if it is done directly on click + ctx.After(50*time.Millisecond, func(_ app.Context) { + b.Active = true + ctx.After(400*time.Millisecond, func(_ app.Context) { + b.Active = false + ctx.NewActionWithValue(eventClick, b.id) + }) + }) +} + func (b *button) handleActivate(ctx app.Context, a app.Action) { - fmt.Println("playing", b.id) ctx.Dispatch(func(_ app.Context) { b.Active = true }) diff --git a/logic.go b/logic.go index 116f112..13ad4b0 100644 --- a/logic.go +++ b/logic.go @@ -36,11 +36,11 @@ func (g *logic) simonSays(ctx app.Context, a app.Action) { <-time.After(200 * time.Millisecond) for _, btnIndex := range sequence { fmt.Println("sending", btnIndex) - ctx.NewAction(fmt.Sprintf(playButton, btnIndex)) + ctx.NewAction(fmt.Sprintf(eventPlayButton, btnIndex)) <-time.After(time.Second) } g.state = gameStatePlayerSays - ctx.NewActionWithValue(stateChange, g.state) + ctx.NewActionWithValue(eventStateChange, g.state) }() } @@ -51,8 +51,8 @@ func (g *logic) handleNewGame(ctx app.Context, a app.Action) { g.sequence = GenerateSequence(4) g.stage = 1 g.state = gameStateSimonSays - ctx.NewActionWithValue(stateChange, g.state) - ctx.NewActionWithValue(simonSays, g.sequence[:1]) + ctx.NewActionWithValue(eventStateChange, g.state) + ctx.NewActionWithValue(eventSimonSays, g.sequence[:1]) } func (g *logic) handleClick(ctx app.Context, a app.Action) { @@ -69,22 +69,22 @@ func (g *logic) handleClick(ctx app.Context, a app.Action) { fmt.Println("received click:", click) if g.sequence[g.clicks] != click { g.state = gameStateLost - ctx.NewActionWithValue(stateChange, g.state) + ctx.NewActionWithValue(eventStateChange, g.state) return } g.clicks++ if len(g.sequence) == g.clicks { g.state = gameStateWon - ctx.NewActionWithValue(stateChange, g.state) + ctx.NewActionWithValue(eventStateChange, g.state) return } if g.clicks == g.stage { g.clicks = 0 g.stage++ g.state = gameStateSimonSays - ctx.NewActionWithValue(stateChange, g.state) + ctx.NewActionWithValue(eventStateChange, g.state) ctx.After(1*time.Second, func(ctx app.Context) { - ctx.NewActionWithValue(simonSays, g.sequence[:g.stage]) + ctx.NewActionWithValue(eventSimonSays, g.sequence[:g.stage]) }) } } diff --git a/main.go b/main.go index e741e8f..bbe7fd4 100644 --- a/main.go +++ b/main.go @@ -14,9 +14,9 @@ func main() { l := NewLogic() // TODO: remove logs everywhere - app.Handle(simonSays, l.simonSays) - app.Handle(click, l.handleClick) - app.Handle(newGame, l.handleNewGame) + app.Handle(eventSimonSays, l.simonSays) + app.Handle(eventClick, l.handleClick) + app.Handle(eventNewGame, l.handleNewGame) g := NewUI() app.Route("/", g) diff --git a/styles.css b/styles.css index b9d85b8..e374eea 100644 --- a/styles.css +++ b/styles.css @@ -71,17 +71,13 @@ html, body { cursor: pointer; } -.simon-button:active span { - background: none; -} - .simon-button span { background-color: rgb(5, 6, 45); padding: 16px 24px; border-radius: 6px; width: 100%; height: 100%; - transition: 300ms; + transition: 200ms; } .simon-button.active span { diff --git a/ui.go b/ui.go index 2c9403c..94c2eae 100644 --- a/ui.go +++ b/ui.go @@ -9,11 +9,11 @@ import ( type events = string const ( - click events = "click" - simonSays events = "playSequence" - playButton events = "play%d" - newGame events = "newGame" - stateChange events = "stateChange" + eventClick events = "click" + eventSimonSays events = "playSequence" + eventPlayButton events = "play%d" + eventNewGame events = "newGame" + eventStateChange events = "stateChange" ) type gameState int @@ -37,7 +37,7 @@ type ui struct { } func (g *ui) OnMount(ctx app.Context) { - ctx.Handle(stateChange, g.handleStateChange) + ctx.Handle(eventStateChange, g.handleStateChange) } func (g *ui) Render() app.UI { @@ -62,7 +62,7 @@ func (g *ui) Render() app.UI { } gameStateText := app.Div().Class("game-state").Text(g.Text) newGameButton := app.Button().Class("simon-button").Body(app.Span().Text("New Game")).OnClick(func(ctx app.Context, _ app.Event) { - ctx.NewAction(newGame) + ctx.NewAction(eventNewGame) }) return app.Div().Class("fill", "background").Body( gameField,