A Self-Service Overrides Tab: Create Moves Into the Filter Box
A primary action should be in the same place whether or not there is any data. Creating an override is a self-service action: a person bypasses a schedule themselves, without asking anyone. On ZopNight’s Schedules page, the Overrides tab used to put + Create Override on its own row above the filters, and when the list was empty the button floated there alone. It now sits at the right end of the filter box, the same position as + Create Schedule on the Schedules tab, and it stays there while the list is empty or loading.
The Old Layout Depended on the Data
The earlier layout drew two separate things: a right-aligned row holding only the Create button, and below it a filter box holding search and filters. That was fine when a list had rows. It looked wrong in the two states where a person most needs to know what to do next.
In an empty state, the filter box had nothing to filter, so the Create button was the only element on screen, floating with nothing around it. While the list loaded, the filter area could be missing entirely, leaving the button without its context. From a usability point of view, an action whose position changes with the state of the data is harder to find exactly when it matters.
One Stable Slot at the End of the Filter Box
Create Override is now the last item in the filter box. Just to its left sits the Clear control with a count of active filters, so a person who has narrowed the list can remove those filters without moving their hand far. The search box on this tab is slightly narrower so that Clear and Create fit together on one line.
Matching the Schedules tab matters as much as the move itself. A person who has created a schedule already knows where the button is on that tab, and now finds the same control in the same place on the neighbouring one.
| List state | Create Override before | Create Override now |
|---|---|---|
| Rows loaded | Own row above the filters | End of the filter box |
| Empty list | Floating alone | End of the filter box |
| Loading | Own row, filters missing | End of the filter box |
| Failed to load | Own row, filters missing | End of the filter box |
The Filter Box Renders Even When the List Does Not
The row that changes most is the last two. The filter box now always renders on the tab, including while the list is loading and after a load fails. The button lives inside the box, so it is always there too.
This works because the box does not depend on the rows. It holds search and filters, which can exist before any data arrives, and a button, which does not depend on the data at all. A load error removes the rows, not the way to create an override.
What Did Not Change
This is a layout change, and it is scoped as one. The button is the same button, with the same permission gate that decides who can create overrides, the same tooltip, and the same drawer that opens when it is clicked. The standalone Overrides page, which the internal console uses, is unchanged. No API, permission or MCP behaviour changed, and nothing moved on the server.
Keeping the permission gate and the drawer exactly as they were is what lets the change be reviewed as layout alone. A reviewer only needs to confirm that the button appears in the right place in each state, not that creating an override still works, since no part of creating one was touched.
