Skip to content

[cueweb/docs/images] Add CueGUI-style navigation framework, safety mode, attributes panel, and comprehensive UI/docs refresh#2353

Draft
ramonfigueiredo wants to merge 5 commits into
AcademySoftwareFoundation:masterfrom
ramonfigueiredo:cueweb/professional-ui-foundations
Draft

[cueweb/docs/images] Add CueGUI-style navigation framework, safety mode, attributes panel, and comprehensive UI/docs refresh#2353
ramonfigueiredo wants to merge 5 commits into
AcademySoftwareFoundation:masterfrom
ramonfigueiredo:cueweb/professional-ui-foundations

Conversation

@ramonfigueiredo
Copy link
Copy Markdown
Collaborator

@ramonfigueiredo ramonfigueiredo commented May 20, 2026

Related Issues

Summarize your change.

[cueweb/docs] Add CueGUI-style navigation framework, safety mode, attributes panel, and comprehensive UI/docs refresh

  • Add global application header with grouped CueGUI navigation:

    • Cuetopia / CueCommander dropdowns
    • File, Cuebot Facility, Other, and Help menus
    • Theme-aware OpenCue branding, ThemeToggle, Sign out, and global Help search
    • Shared menu registry infrastructure via app/utils/menus.ts and use_menu_registry.ts
    • SessionProvider integration and login-aware header behavior
  • Add persistent collapsible left sidebar:

    • Accordion groups mirroring top-level menus
    • Icons-only collapse mode
    • Persistent open/collapsed state via localStorage
    • Hidden on /login
  • Add Disable Job Interaction safety mode:

    • Persisted read-only state with storage + CustomEvent synchronization
    • Auto-disable destructive job/layer/frame actions
    • Read-only banner with re-enable action
  • Add dockable Attributes panel:

    • Right/bottom/left/top docking support
    • Filterable collapsible key/value tree
    • Shared attribute selection state populated from jobs table
  • Add Cuebot Facility selector:

    • Persisted facility selection
    • NEXT_PUBLIC_CUEBOT_FACILITIES support with local/dev/cloud/external defaults
  • Add Help menu infrastructure:

    • Online User Guide, Make a Suggestion, and Report a Bug actions
    • Environment-variable overrides for external URLs
    • Searchable command palette-style menu lookup
  • Improve dark mode accessibility and consistency:

    • Replace hard-coded search dropdown colors with semantic Tailwind tokens
    • Improve monitored-row highlighting
    • Remove remaining MUI list usage from job search dropdown
  • Refresh CueWeb branding and assets:

    • Add theme-aware OpenCue logos and favicon
    • Remove deprecated icon assets
    • Refresh UI screenshots for light/dark themes
  • Refresh CueWeb documentation across README and docs/_docs/:

    • Document the full header/menu architecture
    • Document sidebar behavior and persistence
    • Document safety mode and Attributes panel
    • Expand developer guide with new hooks, components, env vars, and project structure
    • Update reference docs with menu items, hooks, localStorage keys, and CustomEvent details
    • Refresh deployment/configuration documentation

Summary by CodeRabbit

Release Notes

  • New Features

    • Added persistent global header with navigation, theme toggle, and user menu.
    • Added collapsible left sidebar with saved state and facility selector.
    • Added "Disable Job Interaction" read-only safety mode with amber banner—dims and disables destructive job actions.
    • Added searchable Attributes panel with docking and filtering capabilities.
    • Job row selection now populates the Attributes panel.
    • Added searchable help menu with external documentation links.
  • Improvements

    • UI preferences now sync across browser tabs via localStorage.
  • Documentation

    • Updated guides, tutorials, and reference docs to cover new UI features.

Review Change Stack

- New cueweb/components/ui/app-header.tsx: theme-aware OpenCue logo, two dropdowns mirroring CueGUI (Cuetopia -> Monitor Jobs; CueCommander -> Allocations, Limits, Monitor Cue, Monitor Hosts, Redirect, Services, Shows, Stuck Frame, Subscription Graphs, Subscriptions), ThemeToggle, and a Sign out button that always routes to /login. Hidden on /login.
- /login already handles both auth modes: empty NEXT_PUBLIC_AUTH_PROVIDER shows the "CueWeb Home" button; configured providers show their sign-in buttons.
- Unimplemented CueCommander routes 404 gracefully until their Category D tasks land.
- New cueweb/app/providers/session-provider.tsx wraps NextAuth's SessionProvider so useSession() works in the header.
- cueweb/app/layout.tsx mounts SessionProvider + AppHeader between ThemeProvider and {children}.
- cueweb/app/jobs/data-table.tsx: remove duplicate inline logo, theme toggle, and signout now that the global header owns them.
- Dark-mode contrast: elevated zinc-900 surface, stronger border, translucent foreground-based nav pills that read on either theme.
- cueweb/components/ui/cuewebicon.tsx: render the OpenCue icon followed by the "CueWeb" text. Drives the login, LDAP login, frame log, and comments pages.
- Favicon swapped to OpenCue logo (app/favicon.ico -> app/icon.png).
- Delete the now-unreferenced app/iconlight.png and app/icondark.png.
- Add the OpenCue brand kit to images/ (icon, horizontal, stacked x PNG + SVG x black + white) and the header logos to cueweb/public/.
- Replace hard-coded `white` / `lightgreen` and MUI ListItem with Tailwind semantic tokens: `bg-popover text-popover-foreground border-border` (matches shadcn DropdownMenuContent).
- Already-monitored rows use `bg-green-500/20` (and `dark:bg-green-500/15`) for a subtle tint that reads on both themes.
- Swap MUI ListItem for plain `<div role="button">` with Enter/Space activation; inter-row borders via `border-b border-border`.
- Drop MUI imports (Box, Divider, ListItem, ListItemText) and truncate long job names.
- Update cueweb/README.md and all 8 docs under docs/_docs/ to describe the persistent header (theme-aware OpenCue logo + CueWeb wordmark, grouped Cuetopia / CueCommander dropdowns mirroring the CueGUI Views/Plugins menu, theme toggle, always-visible Sign out).
- README: switch the masthead image to a <picture> element pointing at public/opencue-icon-{black,white}.png and add a note above the existing screenshots that they predate the header.
- user-guide / tutorial / quick-start: replace the generic "Header" bullet with a full breakdown of the header's contents and behavior.
- reference: add a "Global Application Header" section listing every Cuetopia / CueCommander route and the /login behavior under each NEXT_PUBLIC_AUTH_PROVIDER configuration.
- developer-guide: expand the project structure tree to include app/icon.png, app/providers/session-provider.tsx, the new components/ui/app-header.tsx, and public/opencue-icon-{black,white}.png; add AppHeader / AppSessionProvider / CueWebIcon to the Core Components list.
- other-guides: insert the persistent-header bullet at the top of the numbered feature list (renumbered 2–16).
- concepts/cueweb-rest-gateway, getting-started/deploying-cueweb: smaller touch-ups (added LDAP, header note in Key Features, comment block above NEXT_PUBLIC_AUTH_PROVIDER in the prod .env sample).
- Refresh interface_screenshots/ (light + dark variants) so the README gallery matches the current UI.
…uebot Facility / Other / Help)

- New cueweb/components/ui/app-sidebar.tsx: persistent left sidebar mounted in app/layout.tsx with grouped accordions (File, Cuebot Facility, Cuetopia, CueCommander, Other, Help). Collapsible to icons-only; expanded/collapsed state and each group's open/closed state persist via cueweb.sidebar.collapsed and cueweb.sidebar.openGroups. Hidden on /login.
- AppHeader: shared nav now sourced from new cueweb/app/utils/menus.ts. Added File -> Disable Job Interaction, Cuebot Facility (local/dev/cloud/ external), Other -> Attributes, and Help dropdowns. The Help search box searches across every menu command via the new useMenuRegistry hook (matches render as "Group > Label"). Sign in / Sign out unchanged.
- New cueweb/app/utils/use_disable_job_interaction.ts: persisted safety flag with CustomEvent + storage-event sync. JobActionButton in the jobs data table and every destructive entry in components/ui/context_menus/action-context-menu.tsx (job Pause/Retry Dead Frames/Eat Dead Frames/Kill; layer Kill/Eat/Retry/Retry Dead Frames; frame Retry/Eat/Kill) auto-disable when the flag is on. New cueweb/components/ui/read-only-banner.tsx renders an amber strip under the header with a "Re-enable" button.
- New cueweb/app/utils/use_cuebot_facility.ts: selected facility persisted to cueweb.facility.selected, list from NEXT_PUBLIC_CUEBOT_FACILITIES (default local/dev/cloud/external).
- New cueweb/app/utils/use_attributes_panel.ts + cueweb/components/ui/attributes-panel.tsx: docked Attributes drawer with selectable position (right/bottom/left/top), filter input, and a collapsible key/value tree for the currently-selected entity. New cueweb/app/utils/use_attribute_selection.ts holds the transient selection; clicking a row in app/jobs/data-table.tsx populates it.
- New cueweb/app/utils/help_menu.ts: Online User Guide / Make a Suggestion / Report a Bug URLs matching CueGUI's cuegui.yaml defaults; overridable via NEXT_PUBLIC_DOCS_URL / SUGGESTIONS_URL / BUGS_URL.
- New cueweb/app/utils/use_menu_registry.ts: aggregates every menu command (File / Cuebot Facility / Cuetopia / CueCommander / Other / Help) into a flat, filterable list for the Help search box.
- Refresh cueweb/README.md and docs/_docs/reference/cueweb.md to describe the new menu bar, sidebar, panel and safety flag.
…Attributes panel

- cueweb/README.md and docs/_docs/quick-starts/quick-start-cueweb.md, tutorials/cueweb-tutorial.md, user-guides/cueweb-user-guide.md, other-guides/cueweb.md, concepts/cueweb-rest-gateway.md: describe the full six-menu header (File, Cuebot Facility, Cuetopia, CueCommander, Other, Help with global search), the collapsible left sidebar (same six groups, accordion behavior, persistent collapsed state), the Disable Job Interaction safety mode with read-only banner, and the
docked Attributes panel (right/bottom/left/top dock positions, live filter input).
- docs/_docs/other-guides/cueweb.md: feature list renumbered 1-19 with the four new items at the top.
- docs/_docs/reference/cueweb.md: extended "Global Application Header" with every menu and its items, plus new "Left Sidebar", "Disable Job Interaction (safety mode)", and "Attributes Panel" sections that cite source files, hooks, localStorage keys, and CustomEvent names.
- docs/_docs/developer-guide/cueweb-development.md: expanded the project-structure tree with the new app/utils/* hooks and components/ui/{app-sidebar,attributes-panel,read-only-banner}.tsx; added AppSidebar, AttributesPanel, ReadOnlyBanner to Core Components; added an "Application state hooks" subsection documenting useDisableJobInteraction, useCuebotFacility, useAttributesPanel, useAttributeSelection, useMenuRegistry and the shared menus.ts / help_menu.ts modules.
- docs/_docs/getting-started/deploying-cueweb.md: documented the new build-time env vars (NEXT_PUBLIC_CUEBOT_FACILITIES, NEXT_PUBLIC_DOCS_URL, NEXT_PUBLIC_SUGGESTIONS_URL, NEXT_PUBLIC_BUGS_URL) with the CueGUI canonical defaults.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

📝 Walkthrough

Walkthrough

This PR modernizes CueWeb's user interface by introducing a persistent global layout layer with state synchronization across tabs. It adds a top-level header with navigation menus, a collapsible sidebar, an attributes detail panel, and a read-only safety mode for destructive job actions. Individual pages are simplified by removing duplicate header chrome.

Changes

CueWeb UI Modernization with Persistent State Management

Layer / File(s) Summary
Session provider and layout foundation
cueweb/app/providers/session-provider.tsx, cueweb/app/layout.tsx
RootLayout wraps the application in AppSessionProvider and includes new top-level UI components: AppHeader, ReadOnlyBanner, a flex layout with AppSidebar and main, and AttributesPanel.
Persistent UI state hooks
cueweb/app/utils/use_attribute_selection.ts, cueweb/app/utils/use_disable_job_interaction.ts, cueweb/app/utils/use_attributes_panel.ts, cueweb/app/utils/use_cuebot_facility.ts
Five custom React hooks manage application state via localStorage, custom CustomEvent dispatch, and browser storage event listeners to synchronize state across same-tab components and cross-tab instances. Hooks include SSR-safe initialization and hydration.
Navigation data and menu registry
cueweb/app/utils/menus.ts, cueweb/app/utils/help_menu.ts, cueweb/app/utils/use_menu_registry.ts
Defines navigation menus ("Cuetopia", "CueCommander") and help items (docs, suggestions, bug reports) with environment-variable URL overrides. useMenuRegistry builds a memoized, searchable command array combining toggles, facility entries, routes, and external links.
App header with navigation dropdowns and menus
cueweb/components/ui/app-header.tsx
Sticky global header with logo link, desktop primary navigation dropdowns (File, Cuebot Facility, searchable Help), theme toggle, user label, and sign-out button. Sign-out clears localStorage cache and redirects to login. Hides on /login route.
Collapsible sidebar with persisted state
cueweb/components/ui/app-sidebar.tsx
Left navigation sidebar with collapsible sections, accordion-style sub-navigation, and persisted collapse/open state in localStorage. Auto-expands the group containing the active route post-hydration. Includes File, Cuebot Facility, Attributes toggle, and Help sections. Hides on /login.
Dockable attributes detail panel
cueweb/components/ui/attributes-panel.tsx
Collapsible panel displaying selected entity (job/layer/frame) attributes as a recursive key-value tree with live filtering. Supports docking to four edges (right/bottom/left/top) with position and open-state persistence.
Supporting UI components and header refactoring
cueweb/components/ui/cuewebicon.tsx, cueweb/components/ui/read-only-banner.tsx, cueweb/README.md, cueweb/app/frames/[frame-name]/page.tsx, cueweb/app/jobs/[job-name]/comments/page.tsx
CueWebIcon refactored to include "CueWeb" text label and uses OpenCue logos from public/. ReadOnlyBanner displays when job interaction is disabled. Individual page templates remove duplicate icon/theme-toggle headers. README icon uses dark-mode-aware <picture> element.
Search dropdown Tailwind refactor
cueweb/components/ui/search-dropdown.tsx
Removes MUI Box/ListItem/Divider in favor of Tailwind-styled DOM elements inside react-window's FixedSizeList. Adds explicit keyboard handling (Enter/space), theme-aware styling for "already added" jobs (green tint), and role="button" semantics.
Job interaction disable integration
cueweb/app/jobs/data-table.tsx, cueweb/components/ui/context_menus/action-context-menu.tsx
useDisableJobInteraction integrated into jobs table to disable destructive action button clicks (with dimmed styling and tooltip) and context menus to dim destructive menu items. Removes old header chrome from data-table. Row-level onClick handler calls setAttributeSelection to populate the attributes panel.
Documentation updates
docs/_docs/developer-guide/*, docs/_docs/getting-started/*, docs/_docs/concepts/*, docs/_docs/other-guides/*, docs/_docs/quick-starts/*, docs/_docs/reference/*, docs/_docs/tutorials/*, docs/_docs/user-guides/*
Comprehensive updates across all documentation describing the new persistent header, collapsible sidebar, read-only safety mode with localStorage + cross-tab sync, attributes panel with docking/filtering, and underlying state hook architecture with specific localStorage keys and custom event names.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested reviewers

  • lithorus
  • DiegoTavares

Poem

🐰 Behold the CueWeb crown now gleams so bright,
With headers persistent and sidebars in sight,
State flows cross-tabs in localStorage's keep,
While attributes dance and safe toggles run deep,
A modern UI tapestry, scrolled clean and right! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.93% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The PR title accurately summarizes the main changes: introducing a CueGUI-style navigation framework (header, sidebar, menus), a safety mode to disable job interactions, a dockable Attributes panel, and comprehensive UI/documentation updates. It is specific, clear, and directly reflects the primary intent of the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
cueweb/components/ui/search-dropdown.tsx (2)

110-110: ⚡ Quick win

Use a stable key instead of index.

Using index as the key in a virtualized list that changes (e.g., when filtered) is an anti-pattern. React may reuse components incorrectly during reconciliation. Use a stable identifier like job.name for more predictable rendering.

🔑 Proposed fix
           <div
-              key={index}
+              key={job.name}
               role="button"
               tabIndex={0}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cueweb/components/ui/search-dropdown.tsx` at line 110, Replace the unstable
key={index} used in the virtualized list render inside the SearchDropdown
component with a stable identifier from the item (e.g., use job.name or another
unique field on the job object). Update the element that currently sets
key={index} to instead set key={job.name} (or key={job.id} if available) so
React can reconcile filtered/changed lists correctly; ensure the referenced
symbol is the same item variable used in the map/rowRenderer where key is
assigned.

104-106: ⚡ Quick win

Optimize the added-job lookup with a memoized Set.

The tableData.some() call runs a linear scan for every rendered item. With a large tableData, this can cause performance issues even in a virtualized list. Create a Set of added job names outside the item renderer for O(1) lookups.

⚡ Proposed optimization

Add this useMemo hook after line 46 (after listRef declaration):

 const listRef = React.useRef<FixedSizeList | null>(null);
+
+const addedJobNames = React.useMemo(
+  () => new Set(tableData.map((job) => job.name)),
+  [tableData],
+);

Then replace the isJobAdded calculation:

-          const isJobAdded = tableData.some(
-            (existingJob: Job) => existingJob.name === job.name,
-          );
+          const isJobAdded = addedJobNames.has(job.name);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cueweb/components/ui/search-dropdown.tsx` around lines 104 - 106, Create a
memoized Set of added job names to avoid repeated linear scans: use React's
useMemo to build a Set from tableData (e.g., new Set(tableData.map(j =>
j.name))) declared near listRef (after its declaration) and then replace the
per-item some() call that computes isJobAdded with a constant-time lookup using
set.has(job.name). Update any references to the old variable name (isJobAdded)
to use the new lookup and ensure the memo depends on tableData so it rebuilds
when the list changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cueweb/components/ui/app-header.tsx`:
- Around line 153-158: The input's onKeyDown currently calls e.stopPropagation()
for every key, which prevents dropdown keyboard handling; update the onKeyDown
handler (the input with value={query} and setQuery) to conditionally stop
propagation only for keys that should not affect the parent menu (e.g., regular
character keys and Enter) and allow navigation/escape keys (Escape, ArrowUp,
ArrowDown, ArrowLeft, ArrowRight, Tab if desired) to bubble so the menu's
keyboard controls continue to work.

In `@cueweb/components/ui/app-sidebar.tsx`:
- Around line 364-376: The facility list uses custom role="radiogroup" and
role="radio" on buttons but lacks full radio keyboard semantics; update the
facilities.map rendering (the button that calls setFacility) to implement
complete radio behavior: either render native <input type="radio"> elements for
each facility bound to the facility state (or wrap a visually styled label
around such an input), or add the missing keyboard handlers on the button
(manage tabIndex, onKeyDown to handle
ArrowLeft/ArrowRight/ArrowUp/ArrowDown/Home/End to move focus and call
setFacility, ensure aria-checked is provided and focus is placed correctly).
Make these changes in the component that contains facilities.map and setFacility
so keyboard navigation and screen-reader semantics match an actual radio group.

In `@cueweb/components/ui/attributes-panel.tsx`:
- Around line 110-123: The toggle button in attributes-panel (the button using
setOpen and reading open to render ChevronDown/ChevronRight and label) is
missing an accessibility state; add aria-expanded={open} to that button so
assistive technologies announce the open/closed state of the attribute tree node
(keep the existing onClick, style, and className behavior and place
aria-expanded alongside them).

---

Nitpick comments:
In `@cueweb/components/ui/search-dropdown.tsx`:
- Line 110: Replace the unstable key={index} used in the virtualized list render
inside the SearchDropdown component with a stable identifier from the item
(e.g., use job.name or another unique field on the job object). Update the
element that currently sets key={index} to instead set key={job.name} (or
key={job.id} if available) so React can reconcile filtered/changed lists
correctly; ensure the referenced symbol is the same item variable used in the
map/rowRenderer where key is assigned.
- Around line 104-106: Create a memoized Set of added job names to avoid
repeated linear scans: use React's useMemo to build a Set from tableData (e.g.,
new Set(tableData.map(j => j.name))) declared near listRef (after its
declaration) and then replace the per-item some() call that computes isJobAdded
with a constant-time lookup using set.has(job.name). Update any references to
the old variable name (isJobAdded) to use the new lookup and ensure the memo
depends on tableData so it rebuilds when the list changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1a22e861-2b8f-436c-b294-ceea1a5ce6d9

📥 Commits

Reviewing files that changed from the base of the PR and between bb6bd61 and 69d8092.

⛔ Files ignored due to path filters (43)
  • cueweb/app/favicon.ico is excluded by !**/*.ico
  • cueweb/app/icon.png is excluded by !**/*.png
  • cueweb/app/icondark.png is excluded by !**/*.png
  • cueweb/app/iconlight.png is excluded by !**/*.png
  • cueweb/interface_screenshots/column _visibility_dropdown.png is excluded by !**/*.png
  • cueweb/interface_screenshots/column _visibility_dropdown_dark.png is excluded by !**/*.png
  • cueweb/interface_screenshots/frame.png is excluded by !**/*.png
  • cueweb/interface_screenshots/frame_context_menu_open.png is excluded by !**/*.png
  • cueweb/interface_screenshots/frame_context_menu_open_and_success_notification.png is excluded by !**/*.png
  • cueweb/interface_screenshots/frame_context_menu_open_dark.png is excluded by !**/*.png
  • cueweb/interface_screenshots/frame_dark.png is excluded by !**/*.png
  • cueweb/interface_screenshots/job_context_menu_open.png is excluded by !**/*.png
  • cueweb/interface_screenshots/job_context_menu_open_and_success_notification.png is excluded by !**/*.png
  • cueweb/interface_screenshots/job_context_menu_open_dark.png is excluded by !**/*.png
  • cueweb/interface_screenshots/job_data_table_filtering.png is excluded by !**/*.png
  • cueweb/interface_screenshots/job_data_table_filtering_dark.png is excluded by !**/*.png
  • cueweb/interface_screenshots/job_search_functionality.png is excluded by !**/*.png
  • cueweb/interface_screenshots/job_search_functionality_dark.png is excluded by !**/*.png
  • cueweb/interface_screenshots/layer_context_menu_open.png is excluded by !**/*.png
  • cueweb/interface_screenshots/layer_context_menu_open_and_success_notification.png is excluded by !**/*.png
  • cueweb/interface_screenshots/layer_context_menu_open_dark.png is excluded by !**/*.png
  • cueweb/interface_screenshots/layersframes.png is excluded by !**/*.png
  • cueweb/interface_screenshots/layersframes_dark.png is excluded by !**/*.png
  • cueweb/interface_screenshots/login.png is excluded by !**/*.png
  • cueweb/interface_screenshots/mainpage.png is excluded by !**/*.png
  • cueweb/interface_screenshots/mainpage_dark.png is excluded by !**/*.png
  • cueweb/interface_screenshots/un-monitoring_selected_jobs-after.png is excluded by !**/*.png
  • cueweb/interface_screenshots/un-monitoring_selected_jobs-before.png is excluded by !**/*.png
  • cueweb/public/opencue-icon-black.png is excluded by !**/*.png
  • cueweb/public/opencue-icon-white.png is excluded by !**/*.png
  • cueweb/public/opencue_logo_small.png is excluded by !**/*.png
  • images/opencue-horizontal-black.png is excluded by !**/*.png
  • images/opencue-horizontal-black.svg is excluded by !**/*.svg
  • images/opencue-horizontal-white.png is excluded by !**/*.png
  • images/opencue-horizontal-white.svg is excluded by !**/*.svg
  • images/opencue-icon-black.png is excluded by !**/*.png
  • images/opencue-icon-black.svg is excluded by !**/*.svg
  • images/opencue-icon-white.png is excluded by !**/*.png
  • images/opencue-icon-white.svg is excluded by !**/*.svg
  • images/opencue-stacked-black.png is excluded by !**/*.png
  • images/opencue-stacked-black.svg is excluded by !**/*.svg
  • images/opencue-stacked-white.png is excluded by !**/*.png
  • images/opencue-stacked-white.svg is excluded by !**/*.svg
📒 Files selected for processing (28)
  • cueweb/README.md
  • cueweb/app/frames/[frame-name]/page.tsx
  • cueweb/app/jobs/[job-name]/comments/page.tsx
  • cueweb/app/jobs/data-table.tsx
  • cueweb/app/layout.tsx
  • cueweb/app/providers/session-provider.tsx
  • cueweb/app/utils/help_menu.ts
  • cueweb/app/utils/menus.ts
  • cueweb/app/utils/use_attribute_selection.ts
  • cueweb/app/utils/use_attributes_panel.ts
  • cueweb/app/utils/use_cuebot_facility.ts
  • cueweb/app/utils/use_disable_job_interaction.ts
  • cueweb/app/utils/use_menu_registry.ts
  • cueweb/components/ui/app-header.tsx
  • cueweb/components/ui/app-sidebar.tsx
  • cueweb/components/ui/attributes-panel.tsx
  • cueweb/components/ui/context_menus/action-context-menu.tsx
  • cueweb/components/ui/cuewebicon.tsx
  • cueweb/components/ui/read-only-banner.tsx
  • cueweb/components/ui/search-dropdown.tsx
  • docs/_docs/concepts/cueweb-rest-gateway.md
  • docs/_docs/developer-guide/cueweb-development.md
  • docs/_docs/getting-started/deploying-cueweb.md
  • docs/_docs/other-guides/cueweb.md
  • docs/_docs/quick-starts/quick-start-cueweb.md
  • docs/_docs/reference/cueweb.md
  • docs/_docs/tutorials/cueweb-tutorial.md
  • docs/_docs/user-guides/cueweb-user-guide.md
💤 Files with no reviewable changes (2)
  • cueweb/app/frames/[frame-name]/page.tsx
  • cueweb/app/jobs/[job-name]/comments/page.tsx

Comment on lines +153 to +158
<input
type="search"
value={query}
onChange={(e) => setQuery(e.target.value)}
onKeyDown={(e) => e.stopPropagation()}
placeholder="Search menus"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Preserve dropdown keyboard controls in Help search

Stopping propagation for every key also swallows Escape/navigation keys for the menu while the input is focused.

Proposed fix
           <input
             type="search"
             value={query}
             onChange={(e) => setQuery(e.target.value)}
-            onKeyDown={(e) => e.stopPropagation()}
+            onKeyDown={(e) => {
+              // Keep Radix typeahead disabled for text editing keys,
+              // but preserve menu keyboard controls (Esc/arrows/tab/etc).
+              if (
+                e.key.length === 1 ||
+                e.key === "Backspace" ||
+                e.key === "Delete"
+              ) {
+                e.stopPropagation();
+              }
+            }}
             placeholder="Search menus"
             aria-label="Search menus"
             className="h-7 w-full bg-transparent text-xs text-foreground placeholder:text-muted-foreground focus:outline-none"
           />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<input
type="search"
value={query}
onChange={(e) => setQuery(e.target.value)}
onKeyDown={(e) => e.stopPropagation()}
placeholder="Search menus"
<input
type="search"
value={query}
onChange={(e) => setQuery(e.target.value)}
onKeyDown={(e) => {
// Keep Radix typeahead disabled for text editing keys,
// but preserve menu keyboard controls (Esc/arrows/tab/etc).
if (
e.key.length === 1 ||
e.key === "Backspace" ||
e.key === "Delete"
) {
e.stopPropagation();
}
}}
placeholder="Search menus"
aria-label="Search menus"
className="h-7 w-full bg-transparent text-xs text-foreground placeholder:text-muted-foreground focus:outline-none"
/>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cueweb/components/ui/app-header.tsx` around lines 153 - 158, The input's
onKeyDown currently calls e.stopPropagation() for every key, which prevents
dropdown keyboard handling; update the onKeyDown handler (the input with
value={query} and setQuery) to conditionally stop propagation only for keys that
should not affect the parent menu (e.g., regular character keys and Enter) and
allow navigation/escape keys (Escape, ArrowUp, ArrowDown, ArrowLeft, ArrowRight,
Tab if desired) to bubble so the menu's keyboard controls continue to work.

Comment on lines +364 to +376
role="radiogroup"
aria-label="Cuebot Facility"
className="ml-2 mt-1 space-y-1 border-l border-border pl-2 dark:border-zinc-800"
>
{facilities.map((f) => {
const active = f === facility;
return (
<li key={f}>
<button
type="button"
role="radio"
aria-checked={active}
onClick={() => setFacility(f)}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Avoid incomplete radio semantics for facility selection

Custom radiogroup/radio roles should include full radio keyboard behavior; otherwise accessibility semantics are inconsistent.

Proposed fix
               <ul
-                role="radiogroup"
                 aria-label="Cuebot Facility"
                 className="ml-2 mt-1 space-y-1 border-l border-border pl-2 dark:border-zinc-800"
               >
                 {facilities.map((f) => {
                   const active = f === facility;
                   return (
                     <li key={f}>
                       <button
                         type="button"
-                        role="radio"
-                        aria-checked={active}
+                        aria-pressed={active}
                         onClick={() => setFacility(f)}
                         className={cn(
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
role="radiogroup"
aria-label="Cuebot Facility"
className="ml-2 mt-1 space-y-1 border-l border-border pl-2 dark:border-zinc-800"
>
{facilities.map((f) => {
const active = f === facility;
return (
<li key={f}>
<button
type="button"
role="radio"
aria-checked={active}
onClick={() => setFacility(f)}
<ul
aria-label="Cuebot Facility"
className="ml-2 mt-1 space-y-1 border-l border-border pl-2 dark:border-zinc-800"
>
{facilities.map((f) => {
const active = f === facility;
return (
<li key={f}>
<button
type="button"
aria-pressed={active}
onClick={() => setFacility(f)}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cueweb/components/ui/app-sidebar.tsx` around lines 364 - 376, The facility
list uses custom role="radiogroup" and role="radio" on buttons but lacks full
radio keyboard semantics; update the facilities.map rendering (the button that
calls setFacility) to implement complete radio behavior: either render native
<input type="radio"> elements for each facility bound to the facility state (or
wrap a visually styled label around such an input), or add the missing keyboard
handlers on the button (manage tabIndex, onKeyDown to handle
ArrowLeft/ArrowRight/ArrowUp/ArrowDown/Home/End to move focus and call
setFacility, ensure aria-checked is provided and focus is placed correctly).
Make these changes in the component that contains facilities.map and setFacility
so keyboard navigation and screen-reader semantics match an actual radio group.

Comment on lines +110 to +123
<button
type="button"
onClick={() => setOpen((prev) => !prev)}
style={{ paddingLeft: depth * 12 }}
className="flex w-full items-center gap-1 rounded px-2 py-1 text-left text-xs font-semibold uppercase tracking-wide text-foreground hover:bg-foreground/5"
>
{open ? (
<ChevronDown className="h-3 w-3 shrink-0" aria-hidden="true" />
) : (
<ChevronRight className="h-3 w-3 shrink-0" aria-hidden="true" />
)}
<span>{label}</span>
</button>
{open && <div>{childRows}</div>}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Expose expand/collapse state on attribute tree toggles

Add aria-expanded so assistive tech can announce node state.

Proposed fix
         <button
           type="button"
           onClick={() => setOpen((prev) => !prev)}
+          aria-expanded={open}
           style={{ paddingLeft: depth * 12 }}
           className="flex w-full items-center gap-1 rounded px-2 py-1 text-left text-xs font-semibold uppercase tracking-wide text-foreground hover:bg-foreground/5"
         >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button
type="button"
onClick={() => setOpen((prev) => !prev)}
style={{ paddingLeft: depth * 12 }}
className="flex w-full items-center gap-1 rounded px-2 py-1 text-left text-xs font-semibold uppercase tracking-wide text-foreground hover:bg-foreground/5"
>
{open ? (
<ChevronDown className="h-3 w-3 shrink-0" aria-hidden="true" />
) : (
<ChevronRight className="h-3 w-3 shrink-0" aria-hidden="true" />
)}
<span>{label}</span>
</button>
{open && <div>{childRows}</div>}
<button
type="button"
onClick={() => setOpen((prev) => !prev)}
aria-expanded={open}
style={{ paddingLeft: depth * 12 }}
className="flex w-full items-center gap-1 rounded px-2 py-1 text-left text-xs font-semibold uppercase tracking-wide text-foreground hover:bg-foreground/5"
>
{open ? (
<ChevronDown className="h-3 w-3 shrink-0" aria-hidden="true" />
) : (
<ChevronRight className="h-3 w-3 shrink-0" aria-hidden="true" />
)}
<span>{label}</span>
</button>
{open && <div>{childRows}</div>}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cueweb/components/ui/attributes-panel.tsx` around lines 110 - 123, The toggle
button in attributes-panel (the button using setOpen and reading open to render
ChevronDown/ChevronRight and label) is missing an accessibility state; add
aria-expanded={open} to that button so assistive technologies announce the
open/closed state of the attribute tree node (keep the existing onClick, style,
and className behavior and place aria-expanded alongside them).

@ramonfigueiredo ramonfigueiredo marked this pull request as draft May 20, 2026 08:09
@ramonfigueiredo ramonfigueiredo changed the title [cueweb/docs] Add CueGUI-style navigation framework, safety mode, attributes panel, and comprehensive UI/docs refresh [cueweb/docs/images] Add CueGUI-style navigation framework, safety mode, attributes panel, and comprehensive UI/docs refresh May 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant