Commit 3771d24
fix(web): clean up now view shortcuts — labels, key sequences, and platform tooltip (#1807)
* fix(web): update shortcut labels, keys, and tooltip for now view
- Remove Logout shortcut from day/week sidebar (accessible via cmd palette)
- Rename 'Toggle sidebar' to 'Close sidebar'
- Rename 'Toggle shortcuts' to 'Show shortcuts'
- Change edit description shortcut from e to e d sequence
- Change edit reminder shortcut from r to e r sequence
- Move reminder shortcut from global to now view
- Show platform-aware key (⌘ or Ctrl) on save tooltip
- Remove unused isAuthenticated from getShortcuts and callers
* fix(web): add appLocked guard to hotkey sequences and fix stale tests
- Add `useAppHotkeySequence` wrapper that checks `document.body.dataset.appLocked`
before firing, matching the guard already on `useAppHotkey`
- Use `useAppHotkeySequence` for E D and E R in `useNowShortcuts` instead of raw
`useHotkeySequence`, which bypassed the app-lock check
- Add missing negative test: E alone must not trigger the E R reminder sequence
- Fix `shortcuts.data.test.ts` assertions to match removed isAuthenticated param,
removed z/r global shortcuts, renamed labels, and new e d / e r now shortcut keys
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(web): fix TaskDescription tooltip test for platform-aware shortcut rendering
The tooltip shortcut was changed from the string "Mod+Enter" to ShortCutLabel
components that render a platform-specific modifier icon (SVG) plus an Enter
span. The old getByText("Mod+Enter") query found nothing on CI (Linux renders
control-icon, not the text "Mod"). Update to query by the data-testid attributes
that ShortCutLabel already provides, using getModifierKeyTestId() so the
assertion works on both Mac and Linux without hard-coding a platform.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(web): let Escape blur description field instead of navigating away
TanStack hotkeys defaults ignoreInputs:false for Escape, so the global
Escape handler in useNowShortcuts was firing even when the description
textarea had focus, causing navigation to the Day view instead of the
expected a11y behavior (blur/revert the field).
Pass ignoreInputs:true so the global handler is suppressed whenever any
input-like element is focused. TaskDescription already owns its own
onKeyDown Escape handler that reverts the value and exits editing mode;
the global handler now only fires when no input has focus (idle Now view).
Also:
- Rename the existing Escape test to clarify it covers the no-input case
- Add a test that dispatches Escape from a focused textarea (using the
pressKey target argument) to verify the handler is suppressed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(web): switch Escape to keydown so ignoreInputs fires before textarea unmounts
The previous keyup-based Escape handler had a race condition:
1. Escape keydown → TaskDescription.handleKeyDown → setIsEditing(false) queued
2. React flushes state between keydown and keyup → textarea unmounts → focus moves to body
3. Escape keyup fires with event.target = document.body (browser reassigns
target when the focused element is removed)
4. isInputElement(body) = false → ignoreInputs:true check passes → handler runs → navigate
Switching to keydown ensures TanStack fires during the same event cycle as
the React onKeyDown handler, before any state flush. The textarea is still
mounted and focused at that point, so event.target = textarea,
isInputElement = true, and the handler is correctly suppressed.
This is consistent with every other Escape handler in the codebase
(useGlobalShortcuts, Reminder) which also use keydown.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: sync focus so Escape after E→D blurs description instead of navigating
When the user pressed E→D then Escape quickly, the global Escape handler
would navigate to /day instead of letting the textarea handle the key.
Root cause: React schedules state updates via MessageChannel (a separate
macrotask). The browser delivers D keyup and Escape keydown before that
macrotask fires, so the textarea was never rendered or focused when Escape
arrived — meaning ignoreInputs:true couldn't suppress the global handler.
Fix: call flushSync when handling FOCUS_TASK_DESCRIPTION so React renders
synchronously within the D keydown macrotask, and switch the focus call to
useLayoutEffect so it runs inside the same synchronous flush. By the time
D keydown returns, the textarea is in the DOM and focused, so any following
Escape keydown has event.target = textarea and is correctly suppressed.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix(web): keep Escape inside now description editor
* chore: remove unnecessary comment in TaskDescription test
---------
Co-authored-by: Tyler Dane <tyler@switchback.tech>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>1 parent 3f68ac0 commit 3771d24
12 files changed
Lines changed: 158 additions & 55 deletions
File tree
- packages/web/src
- common
- hooks
- utils/shortcut/data
- views
- Day/view
- Now
- components/TaskDescription
- context
- shortcuts
- view
- Week
- hooks/shortcuts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
| 5 | + | |
4 | 6 | | |
| 7 | + | |
5 | 8 | | |
6 | 9 | | |
7 | 10 | | |
| |||
53 | 56 | | |
54 | 57 | | |
55 | 58 | | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
Lines changed: 11 additions & 15 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
| 13 | + | |
| 14 | + | |
17 | 15 | | |
18 | 16 | | |
19 | 17 | | |
| |||
34 | 32 | | |
35 | 33 | | |
36 | 34 | | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | 35 | | |
44 | 36 | | |
45 | 37 | | |
| |||
121 | 113 | | |
122 | 114 | | |
123 | 115 | | |
124 | | - | |
| 116 | + | |
125 | 117 | | |
126 | | - | |
| 118 | + | |
127 | 119 | | |
128 | 120 | | |
129 | 121 | | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
130 | 126 | | |
131 | 127 | | |
132 | 128 | | |
133 | | - | |
| 129 | + | |
134 | 130 | | |
135 | 131 | | |
136 | 132 | | |
137 | | - | |
138 | | - | |
| 133 | + | |
| 134 | + | |
139 | 135 | | |
140 | 136 | | |
141 | 137 | | |
| |||
Lines changed: 5 additions & 13 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
8 | 7 | | |
9 | 8 | | |
10 | 9 | | |
11 | 10 | | |
12 | 11 | | |
13 | 12 | | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
| 13 | + | |
21 | 14 | | |
22 | 15 | | |
23 | 16 | | |
24 | 17 | | |
25 | 18 | | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
| 19 | + | |
| 20 | + | |
30 | 21 | | |
31 | 22 | | |
32 | 23 | | |
| |||
73 | 64 | | |
74 | 65 | | |
75 | 66 | | |
76 | | - | |
| 67 | + | |
| 68 | + | |
77 | 69 | | |
78 | 70 | | |
79 | 71 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
4 | 3 | | |
5 | 4 | | |
6 | 5 | | |
| |||
38 | 37 | | |
39 | 38 | | |
40 | 39 | | |
41 | | - | |
42 | 40 | | |
43 | 41 | | |
44 | 42 | | |
| |||
64 | 62 | | |
65 | 63 | | |
66 | 64 | | |
67 | | - | |
68 | 65 | | |
69 | 66 | | |
70 | 67 | | |
| |||
Lines changed: 3 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
| |||
59 | 60 | | |
60 | 61 | | |
61 | 62 | | |
62 | | - | |
| 63 | + | |
| 64 | + | |
63 | 65 | | |
64 | 66 | | |
65 | 67 | | |
| |||
Lines changed: 25 additions & 9 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
| |||
140 | 141 | | |
141 | 142 | | |
142 | 143 | | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
143 | 152 | | |
144 | 153 | | |
145 | 154 | | |
| |||
199 | 208 | | |
200 | 209 | | |
201 | 210 | | |
202 | | - | |
| 211 | + | |
203 | 212 | | |
204 | 213 | | |
205 | 214 | | |
206 | | - | |
| 215 | + | |
207 | 216 | | |
208 | 217 | | |
209 | 218 | | |
210 | | - | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
211 | 222 | | |
212 | 223 | | |
213 | 224 | | |
214 | 225 | | |
215 | 226 | | |
216 | 227 | | |
217 | | - | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
218 | 231 | | |
219 | 232 | | |
220 | 233 | | |
| |||
230 | 243 | | |
231 | 244 | | |
232 | 245 | | |
233 | | - | |
234 | | - | |
235 | | - | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
236 | 249 | | |
237 | 250 | | |
238 | 251 | | |
| |||
242 | 255 | | |
243 | 256 | | |
244 | 257 | | |
245 | | - | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
246 | 262 | | |
247 | 263 | | |
248 | 264 | | |
| |||
256 | 272 | | |
257 | 273 | | |
258 | 274 | | |
259 | | - | |
| 275 | + | |
260 | 276 | | |
261 | 277 | | |
262 | 278 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
| 11 | + | |
10 | 12 | | |
11 | 13 | | |
12 | 14 | | |
| |||
35 | 37 | | |
36 | 38 | | |
37 | 39 | | |
| 40 | + | |
38 | 41 | | |
39 | 42 | | |
40 | 43 | | |
| |||
135 | 138 | | |
136 | 139 | | |
137 | 140 | | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
138 | 149 | | |
139 | 150 | | |
140 | 151 | | |
141 | 152 | | |
142 | 153 | | |
143 | 154 | | |
144 | 155 | | |
| 156 | + | |
| 157 | + | |
145 | 158 | | |
146 | 159 | | |
147 | 160 | | |
| |||
Lines changed: 57 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | | - | |
| 33 | + | |
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
| 42 | + | |
42 | 43 | | |
43 | 44 | | |
44 | 45 | | |
45 | 46 | | |
46 | 47 | | |
47 | 48 | | |
48 | | - | |
| 49 | + | |
49 | 50 | | |
50 | 51 | | |
51 | 52 | | |
| |||
70 | 71 | | |
71 | 72 | | |
72 | 73 | | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
73 | 128 | | |
0 commit comments