The settings UI had accumulated three inconsistencies. This addresses all
three without renaming any group or breaking `?settings=` deep links.
Empty states
- Add `Panel.EmptyState` / `Panel.TableEmpty` (title + description + action),
promoting the treatment previously local to the spreadsheet PreviewTable.
- Add missing empty states to Custom fields, Projects, Rundowns and both
Client tables, which previously rendered bare column headers.
- Convert the remaining `TableEmpty` call sites off the generic "No data yet".
- Rename `.empty` to `.loaderBox` in ProjectPanel, where it meant a loader box
rather than an empty state.
Entity forms in modals
- Add `useEntityModal`, replacing six different open/close mechanisms.
- Move the multi-field create/edit forms into `Modal`: automations (wide),
triggers, URL presets, custom fields, custom views, new rundown and project
merge. Single-field row renames stay inline.
- Create and edit now share one surface instead of rendering above the table
and in-place respectively, and the list is no longer interactive underneath.
- Remove the duplicate project create form; the "New" button now routes to the
existing QuickStart modal.
Sidebar
- Add a search box with per-section keywords, so sections are reachable by the
term users have in mind (osc, alias, google sheet, pin...).
- Nav items are real buttons in a nav landmark with aria-current; secondary
items were previously unreachable by keyboard.
- Fix duplicated `manage__sheets` id, which highlighted two entries at once.
Also
- Re-scroll to a section when its nav item is selected again, and align to the
top rather than the centre.
- Close button no longer floats over content; drop the 300px padding hack.
- Tables scroll with the panel instead of owning a nested scroll area.
- Derive divider/table/list padding from a card padding custom property.
- Fix an unreachable branch that stopped duplicate custom field labels from
being rejected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UP4knuna8kLe79NAuNDhUJ
Surface {{groupNow.*}} template variables (title, note, colour, times,
custom fields) in the automation template autocomplete so events inside a
group can reference their group. The runtime store already carries
groupNow, so substitution and filters worked already; this makes it
discoverable.
Extend the message-secondary action with an optional text field so an
automation can set the secondary message content, not just its source.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LZYPZVdZLWowU7DyzGkWyy
* 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
* refactor: allow secondary rundowns
* ui: move dropdown
* feat: follow loaded
* ui: background edit warning
ui: fix disable radio button
* feat(ui): add loaded sufix in the rundown list
* feat(ui): add direct link to background edit from rundown manager
* fix: better fallback
* fix: default to is isCurrentRundown for nav bar colour
* chore: rename navigate to cuesheet
---------
Co-authored-by: alex-arc <ac@omnivox.dk>
* fix: prevent add filter from submitting form
* refactor: event clarifies whether automations exist but are disabled
* refactor: improve readability of automation form
* refactor: add affordance for field warnings
* refactor: improve visibility of automation off state
* refactor: apply warning styles to other feature toggles
* Adding playback actions to automations (#2024)
* adding intial automation actions
* cleaning up
* fixing formatting
* ran oxfmt
* switching action names to playback- to match the dropdown strings
* fixing flicker that was caused by scroll arrows gettting unmounted
---------
Co-authored-by: Cameron Slipp <cdslipp@gmail.com>
* 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>
* feat: get server port from app satate or env
optional startup port from env will always override
function for parsing port from env
populate default port in app state
add test for migration
* bump version