Skip to content

feat(web): design system shell and navigation (lot 3) - #265

Open
jplanckeel wants to merge 9 commits into
feat/ds-componentsfrom
feat/ds-shell
Open

jplanckeel wants to merge 9 commits into
feat/ds-componentsfrom
feat/ds-shell

Conversation

@jplanckeel

Copy link
Copy Markdown
Contributor

Summary

Lot 3 of docs/design-system/IMPLEMENTATION.md: shell, navigation, shortcuts and the shared filter of the time views.

Stacked on #264 (lot 2): this PR targets feat/ds-components; once #264 is merged into main, GitHub retargets it to main.

Shell (Layout.tsx)

  • Sidebar in four groups (operations, services, infrastructure, resources) with the custom icons, the active page in signature, counts of active locks and drifts to handle (cached 60 s), and a 60 px rail remembered per page and used by default under 960 px. Theme toggle and Slack channel at the bottom.
  • Top bar: Search or jump to… ⌘K, which opens the CommandPalette (pages, creations E L D S R, and once something is typed, services from the catalog and links from the config and Homer), and a single New button with its menu (event, lock, drift, service, RPA) on CreatePanelContext, in place of the five buttons. LinksSearch is removed: its link search lives in the palette.
  • Footer without emojis.

Shortcuts (useShortcuts, lib/shortcuts.ts)

⌘K / Ctrl+K opens the palette, / focuses the page filter, G then D, T or S navigates; plain keys are ignored while typing. Esc closes the palette, menus and the QueryBar suggestions.

Filter query (lib/query.ts)

parseQuery / serializeQuery (round-trip tested) for key:value, key:a,b, -key:value, "phrase" and free text on env, status, type, owner, service, priority, impact; matchEvent, countValues, and toSearchParams.

Server vs client: SearchEvents takes one value per field, without exclusion, owner or text. So only a single positive value of env, type, priority, service, and impact:true go to the API; owner, status (a design system status covers several API statuses), several values, exclusions and text are filtered on the client. An API option would be repeated fields plus owner on SearchEventsRequest.

eventsApi.search gains impact and sends priority, status and environment as numbers: their proto names (P1, TNR, UAT, recommandation) differ from the web enums, so tnr, uat and priorities did not match before.

QueryBar, saved views, shared state

  • QueryBar: tokens, combobox with suggestions (recent queries, keys, values with their count in view, matching values, free text), ↵ adds, ⌫ removes the last token, QueryEmptyState offers which filter to remove.
  • SavedViews: tabs with counts, Save view, delete; built-in All work, Impact, Production deploys; stored in localStorage (guarded).
  • useTimeQuery: query and period in the URL (?q=&from=&to=), remembered across Timeline, Streamline and Calendar (Calendar keeps its month).
  • Timeline, Streamline and Calendar replace their filter sidebars and tag headers with these; the rest of each page is unchanged until lot 4. FiltersSidebar and PageFiltersHeader are removed.

Deferred, as agreed: a My team view (needs the user from #201) and event results in the palette (no text search in the API).

New dependency: @radix-ui/react-dropdown-menu.

Test plan

  • npm run lint, npm run build:check, npm test (196 tests) pass in web/
  • Pure logic tested: query, suggestions, saved views, shortcuts, navigation; hooks and components tested with interactions
  • Chromium, static mode: New menu, palette search, G then T, rail, QueryBar on Timeline / Streamline / Calendar with URL sync, all routes light and dark without page errors
  • Try the shell and the filters on the real backend

🤖 Generated with Claude Code

jplanckeel and others added 9 commits November 2, 2026 10:12
lib/query.ts parses and serializes the filter syntax of the time views
(key:value, key:a,b, -key:value, "phrase", free text) on the keys env,
status, type, owner, service, priority and impact. matchEvent filters on
the client, countValues gives the n in view of the suggestions, and
toSearchParams keeps for SearchEvents what it can apply: one positive
value of env, type, priority or service, and impact:true.

eventsApi.search gains impact and sends priority, status and environment
as numbers, since their proto names (P1, TNR, UAT, recommandation)
differ from the web enums. The static API applies type, priority and
impact too. Adds @radix-ui/react-dropdown-menu for the New menu of the shell.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/saved-views.ts keeps the saved views (All work, Impact and
Production deploys built in) and the five recent queries in localStorage,
with every access guarded. lib/query-suggestions.ts builds the QueryBar
suggestions of the mockups (recent queries and keys, values with their
count in view, matching values, keys and free text) and the try-without
proposals of an empty result. lib/shortcuts.ts resolves ⌘K, / and the
G then D, T or S sequences, ignoring plain keys while typing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The page filter of the mockups: removable key:value tokens (≠ for
exclusions), a combobox field whose listbox suggests recent queries and
keys, then values with their count in view, matching values, keys and
free text. Free text filters as you type; ↵ adds, ⌫ on the empty field
removes the last token, esc closes, Clear empties the query, and the
field carries data-page-filter for the / shortcut. QueryEmptyState says
what matched nothing and offers which filter to remove.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Saved views as tabs with their count, the current one underlined in
ink, Save view naming the current query inline, and a delete button on
the views of the user (built-in views stay).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
useTimeQuery keeps the filter query and the period of a time view in
the URL (?q=…&from=…&to=…), so a filtered view can be shared by link.
TimeQueryProvider remembers the last ones: a time view reached without
any, from the navigation or another page, takes them back. An explicit
query in the URL always wins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
useShortcuts listens on the window: ⌘K or Ctrl+K opens the palette,
/ focuses the element marked data-page-filter, and G then D, T or S
navigates to dashboard, timeline or streamline. Plain keys are ignored
while typing in a field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Layout now uses the Sidebar in four groups (operations, services,
infrastructure, resources) with the custom icons, the active page in
signature, counts of active locks and drifts to handle, and a rail
remembered per page and used by default under 960 px. The top bar has
a single New button with its menu (event, lock, drift, service, RPA)
in place of the five buttons, and Search or jump to… ⌘K, which opens
the command palette: pages, creations, and once something is typed,
services and links (the links search of the former LinksSearch bar,
removed). Global shortcuts are on (⌘K, /, G then D T S), the time views
keep the filters the user last had, and the footer loses its emojis.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Timeline, Streamline and Calendar drop their filter sidebars and tag
headers for TimeViewFilters: saved views with their counts, the
QueryBar, and a result line (or the try-without empty state). The query
lives in the URL and follows the user between the three views; Timeline
and Streamline also share their period, Calendar keeps its month. What
SearchEvents can apply goes to the server, the rest (owner, status,
several values, exclusions, text) is filtered on the client. The rest of
each page is unchanged until lot 4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant