Skip to main content

UI Consistency

21 requirements · 43 scenarios

Workflow Menu Options

JR-ui-consistency-008
The workflow selector SHALL display all authorized workflows returned from the backend discovery endpoint.

- The menu SHALL include the built-in options Autoselect (Default) and None
- The menu SHALL include each workflow returned by /api/v1/workflows
1 test scenario
  • Authorized workflows appear in menu JR-ui-consistency-008.1

Theme Toggle Support

JR-ui-consistency-019
The application SHALL support light and dark themes with a user-accessible toggle.

- A theme toggle button SHALL be present in the sidebar footer
- Theme preference SHALL be persisted in localStorage
- The data-theme attribute on document root SHALL reflect the current theme ("light" or "dark")
- Default theme SHALL be "light"
2 test scenarios
  • Theme toggle is accessible JR-ui-consistency-019.1
  • Theme preference persists across sessions JR-ui-consistency-019.2

Host-Based Branding

JR-ui-consistency-021
The sidebar logo and alt text SHALL be determined by the deployment hostname, not hardcoded. White-label deployments (e.g. beta.homeincentiveshub.com) SHALL display their own logo instead of the default UseJunior logo.

- Logo source and alt text SHALL be resolved via a branding configuration that maps hostnames to brand assets
- The hostname matching SHALL support both exact match and subdomain matching (e.g. homeincentiveshub.com matches beta.homeincentiveshub.com)
- Unknown hostnames SHALL fall back to the default UseJunior branding
- The branding configuration SHALL be the single source of truth for logo paths — no hardcoded logo paths in components
- Adding a new white-label brand SHALL require only a configuration entry and a logo asset, not component changes
4 test scenarios
  • White-label deployment shows custom logo JR-ui-consistency-021.1
  • Default deployment shows UseJunior logo JR-ui-consistency-021.2
  • Unknown hostname falls back to default JR-ui-consistency-021.3
  • Subdomain matching works JR-ui-consistency-021.4

Chat State Persistence

JR-ui-consistency-033
Chat conversations, messages, and the active conversation SHALL be persisted with backend sync when chat persistence is enabled, and SHALL fall back to localStorage as a cache and offline bootstrap.

- The chat state (conversations, messages, activeConversationId) SHALL be stored in localStorage under the key chatState as a cache
- For domains with backend chat persistence enabled, the backend SHALL be the source of truth on startup
- On page load, localStorage MAY be used immediately for fast render, then reconciled with backend data (backend wins conflicts)
- Messages SHALL be limited to 100 per conversation to prevent localStorage overflow (~5MB limit)
- Transient state (processingChatIds, progressState, pendingContexts) SHALL NOT be persisted
- Invalid or missing stored values SHALL default to an empty state with no conversations
- Processing status SHALL be reset to 'idle' on restore (to prevent stuck "processing" states)
- Rationale: Users expect to return to their conversation after a page refresh; losing chat history is disruptive
6 test scenarios
  • Active conversation persists after page refresh JR-ui-consistency-033.1
  • Backend is source of truth for persistence-enabled domains JR-ui-consistency-033.2
  • Chat messages persist after page refresh JR-ui-consistency-033.3
  • Multiple conversations persist JR-ui-consistency-033.4
  • Empty state when no stored data JR-ui-consistency-033.5
  • Transient state is not persisted JR-ui-consistency-033.6

Confirmation Modal Component

JR-ui-consistency-035
The application SHALL provide a reusable ConfirmationModal component for confirming destructive or significant actions.

- ConfirmationModal SHALL use the HTML <dialog> element for native modal behavior
- ConfirmationModal SHALL support customizable title, message, and button text
- ConfirmationModal SHALL support a confirmVariant prop for styling (primary or danger)
- ConfirmationModal SHALL support an isLoading prop to show processing state
- ConfirmationModal message SHALL support HTML content via dangerouslySetInnerHTML
- ConfirmationModal SHALL close on backdrop click and Escape key
- ConfirmationModal SHALL be managed via uiStore state, not window globals
2 test scenarios
  • Delete confirmation modal appears JR-ui-consistency-035.1
  • Confirmation modal closes on backdrop click JR-ui-consistency-035.2

Context Attachment Modals

JR-ui-consistency-038
The chat interface SHALL provide modals for attaching context (contracts, deals, property profiles) to conversations.

- ContractGridModal SHALL fetch and display available contract sets from the API
- ContractGridModal SHALL show set name, contract count, and prompt count
- DealContextModal SHALL fetch and display available deals from the API
- PropertyContextModal SHALL allow creating, editing, and selecting property profiles
- Selecting an item in any context modal SHALL add it to pending attachments
- Context modals SHALL be managed via uiStore state
1 test scenario
  • Attach contract grid to chat JR-ui-consistency-038.1

Citation Modal for Contract Analysis

JR-ui-consistency-039
The contract analysis view SHALL provide a modal for viewing paragraph citations in context.

- CitationModal SHALL display the full paragraph text from the contract
- CitationModal SHALL highlight the cited section if applicable
- CitationModal state SHALL be managed in the contract analysis store
- Clicking a citation link in the grid SHALL open the CitationModal
1 test scenario
  • View citation in modal JR-ui-consistency-039.1

Suggested Edit Loading Shimmer

JR-ui-consistency-040
The "Suggested Edits" column in the Review Workbench SHALL display a shimmer/pulse loading animation while edits are being generated.

- When a row's suggested edit is pending generation, the cell SHALL show an animated shimmer effect
- The shimmer SHALL replace the static em-dash (—) during loading
- The shimmer animation SHALL use animate-pulse or equivalent CSS animation
- The shimmer SHALL display descriptive text like "Generating..." alongside the animation
- Loading state SHALL be derived from: isPending prop OR (no opcodes AND review status is processing)
- Static em-dash (—) SHALL only appear when processing is complete with no suggested edit
- Rationale: Animated loading indicators communicate active processing, reducing user uncertainty
3 test scenarios
  • Shimmer displays during edit generation JR-ui-consistency-040.1
  • Shimmer clears on completion JR-ui-consistency-040.2
  • Static empty state when no shimmer needed JR-ui-consistency-040.3

Tenant-Configurable Sidebar Labels and Visibility

JR-ui-consistency-044
The sidebar SHALL support host-based configuration for section labels and visibility so tenant deployments can hide or rename sections.
2 test scenarios
  • Tenant hides Playbooks and Reviews JR-ui-consistency-044.1
  • Tenant renames chat section label JR-ui-consistency-044.2

Tenant-Filtered Workflow Selector

JR-ui-consistency-045
The workflow selector SHALL filter available workflows based on tenant configuration.
2 test scenarios
  • Tenant allowlist filters workflows JR-ui-consistency-045.1
  • Tenant priority influences workflow order JR-ui-consistency-045.2

Contract Analysis Action Loading Feedback

JR-ui-consistency-047
Contract analysis actions that trigger long-running backend work SHALL show visible loading feedback and disable repeat actions while pending.

- Actions include sync, import, add column, delete column, delete contract, and regeneration
- While a mutation is pending, the initiating control SHALL display a spinner or in-progress label
- Related controls SHALL be disabled to prevent duplicate requests
- Loading feedback SHALL clear on both success and error
1 test scenario
  • Grid sync shows loading state JR-ui-consistency-047.1

Playbook Upload Loading Feedback

JR-ui-consistency-049
Playbook upload interactions SHALL display a visible loading indicator while the upload request or subsequent playbook list refetch is in progress.

- The Upload action SHALL show a spinner or inline loading indicator while the upload mutation is pending
- The playbook selector panel SHALL treat "loading" as true when either the upload mutation is pending OR the playbooks query is fetching
- Loading feedback SHALL clear on both success and error
3 test scenarios
  • Upload shows spinner during request JR-ui-consistency-049.1
  • Selector panel shows loading during refetch JR-ui-consistency-049.2
  • Loading clears on error JR-ui-consistency-049.3

Grid Review Manual Grid Creation

JR-ui-consistency-050
The Grid Review feature SHALL provide a "New Grid" button that allows users to create an empty grid without importing from a shared folder.

- The "New Grid" button SHALL be visible in the GridSelectorPanel regardless of whether grids already exist
- Clicking "New Grid" SHALL prompt the user for a grid name
- After entering a valid name, the system SHALL call POST /api/v1/contracts/sets to create the grid
- After successful creation, the view SHALL navigate into the newly created grid
- If the user cancels the name prompt or enters an empty name, no grid SHALL be created
2 test scenarios
  • User creates a new empty grid JR-ui-consistency-050.1
  • User cancels new grid creation JR-ui-consistency-050.2

Grid Review Folder Import Uses Sync Endpoint

JR-ui-consistency-051
When a user imports a shared folder in the Grid Review, the system SHALL use the folder sync endpoint (POST /api/v1/contracts/folders/sync) which auto-creates a grid from the folder contents.

- The import handler SHALL NOT use the file import endpoint (POST /api/v1/contracts/files/import) for folder-level imports
- The sync endpoint auto-detects Google Drive vs SharePoint from the URL, so no source parameter SHALL be hardcoded
- After a successful folder sync, the grid list SHALL be refreshed and the user returned to the grid selector
2 test scenarios
  • User imports a Google Drive folder JR-ui-consistency-051.1
  • User imports a SharePoint folder JR-ui-consistency-051.2

Chat Context Persistence in Conversation

JR-ui-consistency-053
Chat context attachments SHALL remain visible and active across follow-up messages until the user removes them.
2 test scenarios
  • Context cards remain after sending JR-ui-consistency-053.1
  • Contexts are removable by the user JR-ui-consistency-053.2

User Message Attachment Summary

JR-ui-consistency-054
User messages that include uploaded files SHALL display an attachment summary in the chat history.
2 test scenarios
  • User message lists attached file names JR-ui-consistency-054.1
  • Message without attachments omits summary JR-ui-consistency-054.2

Output Attachment Download Links

JR-ui-consistency-055
Assistant messages with output attachments SHALL provide working download links using the token-based download endpoint.
2 test scenarios
  • Output attachments expose download link JR-ui-consistency-055.1
  • Download link triggers file retrieval JR-ui-consistency-055.2

Review Workbench Apply State Sync

JR-ui-consistency-056
When review edits are applied, the workbench UI SHALL immediately reflect applied status so users can navigate edits and download revised documents.

- Applied rows SHALL render the applied state (check icon + edit/bookmark links) instead of Apply/Ignore buttons.
- When there are zero open edits, "Apply All" and "Apply All + Comments" SHALL be disabled and non-interactive.
- After one or more edits are applied, the "Download Revised" action SHALL be enabled.
2 test scenarios
  • Apply-all completion hides row action buttons JR-ui-consistency-056.1
  • Download Revised enables after edits apply JR-ui-consistency-056.2

Edited Recommended Response Indicator

JR-ui-consistency-059
When a user edits the Recommended Response, the response cell SHALL display the edited text with an explicit "(edited)" indicator.

- The "(edited)" indicator SHALL appear immediately after the edited response text
- The edited response text SHALL reflect the user-provided content, not the pre-edit suggestion
- The indicator SHALL be styled consistently with other edited markers in the review table
- Rationale: Users must see which responses have been manually modified before applying edits
1 test scenario
  • Edited response shows edited indicator JR-ui-consistency-059.1

Genealogy Shows User-Edited Provenance

JR-ui-consistency-060
When a user edits the Recommended Response and then applies the edit, the edit genealogy SHALL display provenance indicating the response was user-edited.

- Genealogy SHALL include a provenance label such as "User Edited" or "User Modified"
- The provenance label SHALL appear alongside other source metadata in the genealogy popover
- This applies to edits generated from revised recommended responses as well as original AI responses
1 test scenario
  • Genealogy indicates user-edited response JR-ui-consistency-060.1

Genealogy Consistency for Apply vs Apply All

JR-ui-consistency-061
Edit genealogy SHALL render consistently regardless of whether edits are applied via "Apply" (single row) or "Apply All".

- Single-row Apply SHALL populate genealogy data in the same shape as Apply All
- The genealogy popover SHALL display the same sections and metadata for both flows
- The user SHALL NOT experience missing genealogy details when applying a single row
1 test scenario
  • Single-row Apply shows full genealogy JR-ui-consistency-061.1