The shortcut opened the menu but never closed it, so the only way out was
Escape or the button.
useHotkeys registers its listener once and keeps the callback it was first
given. The callback closed over the disclosure toggle, which decides its
direction from the opened value captured at that point. That value stays
false for the life of the component, so every press took the open branch
and the menu was reopened rather than closed. Instrumenting the handler
shows it firing on each press while still reporting the menu as closed,
after the component has already re-rendered with it open.
Holding the state here and toggling from the previous value removes the
dependency on the callback being current, so the shortcut works regardless.
Covered by a spec asserting the shortcut both opens and closes, and that it
closes a menu that was opened with the button. Both fail before this change.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014L7R2LgjMSH2WQbiSP4uRn
Follow up on the drawer polish, replacing things it hand-rolled with what
the codebase already provides.
Reuse
- The navigation toggles now use the Switch component instead of ~30 lines
of CSS mirroring it, which carried a comment admitting the metrics were
kept in sync by hand. base-ui renders Switch.Root as a span, so the row
can be a label wrapping a real control, the same shape the params editor
already uses. The row stays clickable across its full width
- Remove scrollbar-width and scrollbar-color from three drawers. index.scss
already sets both on the universal selector, so these were not only
redundant, they overrode the app wide thumb and track tokens with local
values
- Collect the user facing view names in one map in viewerConfig, and derive
the navigation entries and the URL preset targets from it. The same nine
labels had been written out in three places
Simplify
- NavigationMenuToggle composes NavigationMenuItem rather than repeating its
markup and key handling, so a row reacts to input in one place only
- ViewParamsSection consulted collapsible five times in a render. Absence of
a toggle handler now represents a section which cannot collapse, and the
header owns its two shapes
- Share the small uppercase group heading through an eyebrow-label mixin,
which was copied across four stylesheets
Tests
- Cover that a collapsed section keeps its values through apply. The form
reads from the DOM, so unmounting collapsed fields would silently drop
them, and no existing test caught that
Also drops a comment claiming rows avoid being buttons because Space is a
global hotkey. Measured against the app, the hotkey does not fire while the
menu is open regardless of focus, so the rationale did not hold.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014L7R2LgjMSH2WQbiSP4uRn
* feat: create the first event from the cuesheet
* chore: cleanup css
* test: cuesheet beckground edit from empty state
* feat: only show +event button when user is in edit mode and have full write perms
* feat: update auto cue numbering
* feat: renumber from ui
* refactor: patchEntries is not used
* chore: format
* fix: correct cue at top of group
* fix: handle precision
* refactor dialog
* bump limit for performance time test
* extract type
* add class name to lable
* fix rebase
* refator: extract renumering logic
* chore: comments for getIntegerAndFraction function
* chore: add the for renumber mutation
* fix: fraction match precision
* refactor: small cleanup
* refactor: use more narrow validator
---------
Co-authored-by: alex-Arc <omnivox@LAPTOP-RC5SNBVV.localdomain>
* chore: only run release action if we have a tag
* chore: typescript 6 is out of beta
* chore: update flaky test
* chore: update pnpm
* chore: update playwright and node types
* chore: migrate tsup to tsdown
* chore: update node to node 22.22.2(LTS)
* chore: fix lockfile
---------
Co-authored-by: alex-Arc <omnivox@LAPTOP-RC5SNBVV.localdomain>
* chore: upgrade vite
* fix: inconsistentCjsInterop for ReactQR
* chore: e2e tests should use relativve path and get host from playwright config
* refactor: drop qr code dependency
---------
Co-authored-by: alex-Arc <omnivox@LAPTOP-RC5SNBVV.localdomain>
* chore: migrate eslint to oxlint
* chore: migrate prettier to oxfmt
* chore: migrate typescript
* chore: toThrow should have a expected value
* chore: cast test value as Day
* chore: small title fix
* chore: mocks should be hoisted
* chore: incorrect async useage
* chore: test should be inside description
* chore: test sohuld include an expeced
* chore: oxfmt
---------
Co-authored-by: alex-Arc <omnivox@LAPTOP-RC5SNBVV.localdomain>
* chore: remove old comment
* chore: smal lclean up of a e2e test
* chore: bump to beta.6
* chore: cleanup imports
* fix integration values com in ms
* allow linkStart and timeStrategy from API
* remove local mac dist
* feat: add group start time to state
* refactor: calculate expected times when offset mode changes
* feat: show relative data in ui
* fixup! feat: add group start time to state
* fixup! refactor: calculate expected times when offset mode changes
* fixup! feat: show relative data in ui
* try to handle multiday
* show planed/expected rundown end day offset values
* refactor: style tweaks to timers
* refactor: cleanup data use
* day offset
* update tests
* test getExpectedStart multiday
* write start epoch to restore file
* current day in relative mode
* remove todo
* move find day offset to utils
---------
Co-authored-by: arc-alex <ac@omnivox.dk>
* refactor: align header columns
* refactor: improve scrollbar visibility
* refactor: center align table elements
* refactor: make param elements stateful
* fix: issue with collapsed elements not loosing value
* fix: prevent search params containing multiple alias references
* fix: the issue where a file disappears if it is both migrated and recovered in the same load operation (#1744)
* refactor: disable group action for elements in groups
* refactor: move context menu items into the event element (#1747)
* feat: sheet import new features for v4 (#1730)
* import milestone
* fixup! import milestone
* test: milestone import
* add entries to group
stop on new group or on group-end type
* fixup! add entries to group
* cleanup
* add event target duration
* link start if undefined
* add skip import type
* extract some to the excel paresing functions
* tweaks to presentation
* move file
---------
Co-authored-by: Carlos Valente <carlosvalente@pm.me>
* fix: notify runtimeStore of events bieng groupd
* fix: improve authentication and stage detection in demo
* chore: ship logo with project
* fix: client is referenced by name
* fix: prevent reflow in event editor
* fix: stale render on selected event due to ref mismatch
* Create/Load/Delete multiple rundowns (#1696)
* refactor: restore last loaded rundown
* refactor: initialise rundown in ProjectService
* feat: allow switching rundowns
ensure on coordination between the db object and the working object
server provide list of rundowns
implement switch in the UI
implement delete
implement new rundown button
* fix: render order for floating button
* refactor: appropriate names to service
* refactor: rundown endpoints
* refactor: save last loaded rundown ID
* refactor: rundown management UI
* refactor: emit refetch all on project load
---------
Co-authored-by: Carlos Valente <carlosvalente@pm.me>
* feat: recover single event subscription
* fixup! feat: sheet import new features for v4 (#1730)
* fix: prevent dropping a group inside another
* fixup! refactor: move context menu items into the event element (#1747)
* fix: prevent stale references to custom fields
* fix: propagate updates to all rundowns
* refactor: client rundown metadata (#1728)
* generate metadata in the hook
* move test
* ensure there is always a last element
* use for-loop
* update metadata in useEfect
* fully extract metadata generation
* use direct assignment
* cleanup
---------
Co-authored-by: Carlos Valente <carlosvalente@pm.me>
* refactor: small imporvement and tests for coerce functions (#1752)
* refactor: small imporvement and tests for coerce functions
add test `coerceString`
add test `coerceBoolean`
add test `coerceColour`
* remove old todo
* fix: consistent quick add behaviour
* refactor: create flat rundown with metadata
* fix: show add buttons on top
* feat: allow editing milestones
* refactor: style tweaks to rundown elements
refactor: milestones are full width
refactor: cuesheet header alignment
fix: editor styling in cuesheet
* refactor: virtualise table
* refactor: improve overscan (#1758)
* bump version to 4.0.0-alpha.5
---------
Co-authored-by: Alex Christoffer Rasmussen <ac@omnivox.dk>
fix: close modal with button
refactor: small type improvements
refactor: migrate time inputs
refactor: migrate tooltips
refactor: prevent component resizing