Skip to content

🎨 UX cohesion: unified overlays, z-index scale, form components, design tokens#5286

Open
clubanderson wants to merge 1 commit intomainfrom
ux-cohesion
Open

🎨 UX cohesion: unified overlays, z-index scale, form components, design tokens#5286
clubanderson wants to merge 1 commit intomainfrom
ux-cohesion

Conversation

@clubanderson
Copy link
Copy Markdown
Collaborator

@clubanderson clubanderson commented Apr 7, 2026

Adding or modifying a card/dashboard? Read the Card Development Guide first — it covers required patterns, common pitfalls, and the full file checklist.

New CNCF project card? New cards go in kubestellar/console-marketplace, not this repo. PRs adding new cards here will be redirected.

Use a coding agent. This repo is primarily developed with Claude Code (Opus 4.5/4.6). It knows all codebase patterns (isDemoData, useCardLoadingState, locale strings, DCO). Manual PRs that miss required patterns will be sent back.


📝 Summary of Changes

Addresses visual fragmentation across the console — different parts built at different times had divergent backdrop blurs, z-index layering, status colors, modal behaviors, and form styling. This PR establishes design system foundations so the console feels like ONE product.

Tier 1 — Quick Wins (56 files)

  • Z-index scale: Define 6 semantic layers (dropdown/sticky/overlay/modal/toast/critical) in tailwind.config.js. Migrate all 30+ arbitrary z-[N] values (z-[60] through z-[10010]) to semantic tokens
  • Backdrop normalization: Standardize all 27 overlay backdrops to bg-black/60 backdrop-blur-sm (was mix of blur-sm, blur-2xl, no blur, /50, /60, /70)
  • Status color tokens: Add semantic status colors to Tailwind theme. Fix StatsOverview COLOR_HEX green (#22c55e#10b981) to match --color-success
  • ConfirmDialog fix: Replace raw <button> with <Button> component for consistent confirm/cancel styling
  • Border-radius convention: Document the scale (rounded-sm through rounded-full) in tailwind config

Tier 2 — Structural Improvements (17 files)

  • Modal migration: Migrate 7 hand-rolled modals to BaseModal compound component (unified focus trapping, ESC handling, backdrop, keyboard nav)
  • Form components: Create Input, TextArea, Select in components/ui/ with size variants, error states, and accessibility
  • Typography utilities: Create TEXT constants (pageTitle, cardTitle, caption, etc.) in typography.ts

Tier 3 — Foundation

  • Design tokens: Extract tokens.ts with STATUS_COLORS, BRAND_COLORS, CHART_COLORS, Z_INDEX, LAYOUT — single source of truth for JS-side values
  • ESLint guard rails: Warn on raw <input>, <textarea>, <select> to encourage shared components; ESLint override added so the shared Input/TextArea/Select component files themselves are exempt from those guards
  • Naming convention: Document Modal vs Dialog distinction in BaseModal JSDoc

Changes Made

  • Defined semantic z-index scale and migrated all arbitrary z-[N] values to tokens
  • Normalized all overlay backdrops to consistent bg-black/60 backdrop-blur-sm
  • Created shared Input, TextArea, Select form components with size variants and accessibility
  • Migrated 7 hand-rolled modals to BaseModal compound component
  • Extracted tokens.ts as single source of truth for JS-side design values
  • Added ESLint no-restricted-syntax guards for raw form elements
  • Fixed eslint.config.js: added override block scoped to Input.tsx/TextArea.tsx/Select.tsx so those shared components are not flagged by their own guard rules
  • Fixed StockMarketTicker.tsx: corrected search results dropdown from z-overlayz-dropdown (dropdowns should not be elevated above true overlays/modals)
  • Fixed StatBlockModePicker.tsx: corrected role="menu" popover from z-overlayz-dropdown
  • Fixed StatsOverview.tsx: moved STAT_BLOCK_COLORS import to the top of the file with all other imports
  • Fixed GitHubInvite.tsx (CodeQL): introduced invitedUsername state to capture the validated username before reset, and used encodeURIComponent(invitedUsername) in the "View Profile" href — eliminates unescaped user input in DOM attribute and fixes a UX bug where the link previously resolved to https://github.com/

Checklist

  • I used a coding agent (Claude Code, Copilot, Gemini, or Codex) to generate/review this code
  • I have reviewed the project's contribution guidelines
  • New cards target console-marketplace, not this repo
  • isDemoData is wired correctly (cards show Demo badge when using demo data)
  • I have written unit tests for the changes (if applicable)
  • I have tested the changes locally and ensured they work as expected
  • All commits are signed with DCO (git commit -s)

Screenshots or Logs (if applicable)

No visual regressions expected — changes are semantic token/class name corrections and import ordering.


👀 Reviewer Notes

  • The z-dropdown < z-overlay < z-modal layering order is now consistently respected: search dropdowns and popover menus use z-dropdown, backdrops/dimmers use z-overlay, and modals use z-modal.
  • The ESLint override in eslint.config.js retains the consecutive-setState guard for the UI component files while suppressing only the raw-element selectors that would self-referentially fire on the component implementations.
  • The GitHubInvite fix resolves both the CodeQL taint-tracking alert and a pre-existing UX bug (the "View Profile" link was always empty after username state reset).

Test plan

  • Visual walkthrough: Dashboard → Clusters → drilldown → Feedback modal → Settings → Missions → Share dialog — all overlays should have identical dimming/blur
  • Verify grep -r "z-\[\d" web/src returns 0 results (no arbitrary z-index values)
  • Verify grep -r "backdrop-blur-2xl" web/src returns 0 results
  • Build passes (npm run build)
  • TypeScript passes (npx tsc --noEmit — 0 errors)
  • New ESLint warnings appear for raw form elements (intentional — gradual migration), but not inside Input.tsx, TextArea.tsx, or Select.tsx

Copilot AI review requested due to automatic review settings April 7, 2026 17:50
@kubestellar-prow kubestellar-prow bot added the dco-signoff: yes Indicates the PR's author has signed the DCO. label Apr 7, 2026
@kubestellar-prow
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign mikespreitzer for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

👋 Hey @clubanderson — thanks for opening this PR!

🤖 This project is developed exclusively using AI coding assistants.

Please do not attempt to code anything for this project manually.
All contributions should be authored using an AI coding tool such as:

This ensures consistency in code style, architecture patterns, test coverage,
and commit quality across the entire codebase.


This is an automated message.

@kubestellar-prow kubestellar-prow bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Apr 7, 2026
@netlify
Copy link
Copy Markdown

netlify bot commented Apr 7, 2026

Deploy Preview for kubestellarconsole failed. Why did it fail? →

Name Link
🔨 Latest commit 6a5037b
🔍 Latest deploy log https://app.netlify.com/projects/kubestellarconsole/deploys/69d680d9d570460008372bba

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR standardizes overlay/backdrop styling, stacking order, and UI primitives across the React console by introducing semantic Tailwind tokens (status + z-index), centralized JS design tokens, and shared modal/form/typography components.

Changes:

  • Add semantic Tailwind theme extensions (status colors, z-index scale) and a JS/TS tokens.ts source for hex/z-index/layout constants.
  • Normalize overlay backdrops and migrate many components from arbitrary z-[N] values to semantic z-* classes; migrate several hand-rolled modals to BaseModal.
  • Introduce shared form components (Input, TextArea, Select), typography constants, and ESLint guardrails discouraging raw form elements.

Reviewed changes

Copilot reviewed 63 out of 63 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
web/tailwind.config.js Adds semantic status colors and a standardized z-index scale for consistent layering.
web/src/lib/unified/stats/UnifiedStatsSection.tsx Aligns stats config modal layering/backdrop to the new overlay conventions.
web/src/lib/tokens.ts Introduces shared JS-side design tokens (status/brand/chart colors, z-index, layout constants).
web/src/lib/modals/ConfirmDialog.tsx Uses shared Button component for consistent confirm/cancel styling and loading UI.
web/src/lib/modals/BaseModal.tsx Normalizes modal backdrop + updates z-index to semantic z-modal; documents Modal vs Dialog naming.
web/src/lib/cards/CardComponents.tsx Migrates dropdown portal stacking to semantic z-dropdown.
web/src/components/widgets/WidgetExportModal.tsx Migrates tooltip layering to semantic z-dropdown.
web/src/components/ui/typography.ts Adds semantic typography class constants for consistent text styling.
web/src/components/ui/Toast.tsx Migrates toast container layering to semantic z-toast.
web/src/components/ui/TextArea.tsx Adds shared TextArea component with size/error/resizability variants.
web/src/components/ui/StatsOverview.tsx Switches chart hex colors to centralized token source.
web/src/components/ui/StatBlockModePicker.tsx Updates popover menu layering to the new z-index tokens.
web/src/components/ui/Select.tsx Adds shared Select component with size/error variants and custom chevron.
web/src/components/ui/Input.tsx Adds shared Input component with size/error variants and icon support.
web/src/components/ui/form.ts Re-exports shared form controls from a single module.
web/src/components/ui/AlertBadge.tsx Normalizes mobile backdrop blur + semantic z-index usage.
web/src/components/terminal/PodExecTerminal.tsx Migrates container picker dropdown to z-dropdown.
web/src/components/settings/UpdateSettings.tsx Migrates channel dropdown to z-dropdown.
web/src/components/settings/Settings.tsx Migrates restored toast stacking to z-toast.
web/src/components/settings/sections/ThemeSection.tsx Migrates theme dropdown stacking to z-dropdown.
web/src/components/rewards/LinkedInShare.tsx Migrates confirm modal to BaseModal for consistent overlay behavior.
web/src/components/rewards/GitHubInvite.tsx Migrates invite modal to BaseModal for consistent overlay behavior.
web/src/components/onboarding/Tour.tsx Migrates tour overlay stacking to semantic z-overlay.
web/src/components/missions/SubmitToKBDialog.tsx Migrates KB submission dialog to BaseModal structure (header/content/footer).
web/src/components/missions/ShareMissionDialog.tsx Migrates export dialog to BaseModal.
web/src/components/missions/SaveResolutionDialog.tsx Migrates save dialog to BaseModal and standardizes footer actions.
web/src/components/missions/MissionBrowser.tsx Normalizes mission browser overlay backdrop + migrates to z-modal and blur-sm.
web/src/components/missions/KagentAgentPicker.tsx Migrates picker dropdown to z-dropdown.
web/src/components/missions/ImproveMissionDialog.tsx Migrates improve dialog to BaseModal.
web/src/components/missions/ClusterSelectionDialog.tsx Migrates cluster selection dialog to BaseModal and standardizes footer buttons.
web/src/components/mission-control/PayloadCard.tsx Migrates dependency overlay stacking to semantic z-overlay.
web/src/components/mission-control/MissionControlDialog.tsx Migrates dialog/backdrop z-index values to semantic tokens.
web/src/components/mission-control/FlightPlanBlueprint.tsx Normalizes mission preview overlay to z-modal + blur-sm.
web/src/components/mission-control/FixerDefinitionPanel.tsx Migrates target cluster selector dropdown to z-dropdown.
web/src/components/marketplace/Marketplace.tsx Migrates author tooltip portal stacking to semantic z-dropdown.
web/src/components/layout/Sidebar.tsx Normalizes mobile backdrop blur + migrates sticky controls/resize handle to semantic z-index.
web/src/components/layout/navbar/SearchDropdown.tsx Migrates search results dropdown to z-dropdown.
web/src/components/layout/navbar/Navbar.tsx Normalizes mobile menu backdrop blur + uses semantic z-overlay.
web/src/components/layout/mission-sidebar/MissionSidebar.tsx Normalizes mobile backdrops and saved mission modal overlay styling + z-index tokens.
web/src/components/feedback/NPSSurvey.tsx Migrates survey panel stacking to semantic z-sticky.
web/src/components/feedback/NotificationBadge.tsx Migrates backdrop/menu stacking to z-overlay/z-dropdown.
web/src/components/feedback/FeedbackModal.tsx Normalizes feedback modal overlay styling and stacking to z-modal; updates FAB stacking.
web/src/components/feedback/FeatureRequestModal.tsx Migrates confirmation/login overlays to z-critical; normalizes preview overlays.
web/src/components/drilldown/RemediationConsole.tsx Normalizes remediation modal overlay styling and stacking to z-modal.
web/src/components/drilldown/DrillDownModal.tsx Normalizes drilldown modal overlay styling and stacking to z-modal.
web/src/components/deploy/Deploy.tsx Normalizes group picker overlay styling and stacking to z-modal.
web/src/components/dashboard/StatBlockFactoryModal.tsx Migrates icon picker dropdown to z-dropdown.
web/src/components/dashboard/MissionSuggestions.tsx Migrates suggestion dropdowns to z-dropdown.
web/src/components/dashboard/FloatingDashboardActions.tsx Migrates floating action controls to semantic z-sticky.
web/src/components/dashboard/DashboardDropZone.tsx Migrates drop-zone overlay stacking to semantic z-index tokens.
web/src/components/dashboard/CardRecommendations.tsx Migrates recommendation dropdowns to z-dropdown.
web/src/components/dashboard/CardFactoryModal.tsx Migrates template dropdown to z-dropdown.
web/src/components/clusters/AddClusterDialog.tsx Migrates dialog overlay stacking to z-modal.
web/src/components/cards/StockMarketTicker.tsx Migrates search dropdown stacking to semantic z-index tokens.
web/src/components/cards/NamespaceMonitor.tsx Migrates resource detail modal to BaseModal for consistent overlay behavior.
web/src/components/cards/llmd/shared/PortalTooltip.tsx Migrates tooltip portal stacking to z-dropdown.
web/src/components/cards/llmd/NightlyE2EStatus.tsx Migrates popup stacking to z-dropdown.
web/src/components/cards/llmd/KVCacheMonitor.tsx Migrates floating panel stacking to z-dropdown.
web/src/components/cards/GPUInventoryHistory.tsx Migrates dropdowns to z-dropdown.
web/src/components/cards/ClusterDropZone.tsx Migrates drop-zone overlay stacking to semantic z-index tokens.
web/src/components/cards/CardWrapper.tsx Migrates tooltip stacking to z-dropdown.
web/src/components/agent/AgentSelector.tsx Migrates agent panel stacking to z-dropdown and install guide overlay to z-modal.
web/eslint.config.js Adds ESLint restricted-syntax warnings to encourage shared form components.

Comment on lines +44 to +55
{
selector: 'JSXOpeningElement[name.name="input"]:not([name.name="Input"])',
message: 'Use <Input> from components/ui/Input.tsx instead of raw <input>.',
},
{
selector: 'JSXOpeningElement[name.name="textarea"]',
message: 'Use <TextArea> from components/ui/TextArea.tsx instead of raw <textarea>.',
},
{
selector: 'JSXOpeningElement[name.name="select"]',
message: 'Use <Select> from components/ui/Select.tsx instead of raw <select>.',
},
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

The new no-restricted-syntax rules for raw /<textarea>/ will also fire inside the shared Input/TextArea/Select component implementations themselves (they necessarily render native elements), creating noisy warnings and confusing messages. Consider adding an ESLint override to disable just these selectors for those component files (or use targeted eslint-disable comments on the native element lines in those three files).

Copilot uses AI. Check for mistakes.
Comment on lines 127 to 132
<div
ref={popoverRef}
role="menu"
aria-label="Display mode"
className="fixed z-[100] bg-card border border-border rounded-lg shadow-xl p-1.5 animate-in fade-in zoom-in-95 duration-150"
className="fixed z-overlay bg-card border border-border rounded-lg shadow-xl p-1.5 animate-in fade-in zoom-in-95 duration-150"
style={{ top: position.top, left: position.left, width: 160 }}
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

This element is a popover/menu (role="menu"), but it uses the semantic z-index token z-overlay, which is documented for backdrops/dimmers. To keep the z-index scale meaningful and predictable, use z-dropdown for this menu layer.

Copilot uses AI. Check for mistakes.
{/* Search results dropdown */}
{showStockDropdown && stockSearchResults.length > 0 && (
<div className="absolute top-full left-0 right-0 mt-1 bg-card border border-border rounded-lg shadow-lg z-[100] max-h-60 overflow-y-auto">
<div className="absolute top-full left-0 right-0 mt-1 bg-card border border-border rounded-lg shadow-lg z-overlay max-h-60 overflow-y-auto">
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

This is a search results dropdown, but it’s currently using z-overlay (intended for backdrops/dimmers). Using z-dropdown here would better match the semantic z-index scale and avoid unintentionally elevating the dropdown above true overlays/modals.

Suggested change
<div className="absolute top-full left-0 right-0 mt-1 bg-card border border-border rounded-lg shadow-lg z-overlay max-h-60 overflow-y-auto">
<div className="absolute top-full left-0 right-0 mt-1 bg-card border border-border rounded-lg shadow-lg z-dropdown max-h-60 overflow-y-auto">

Copilot uses AI. Check for mistakes.
Comment on lines 67 to 69
/** Hex color values for chart components — sourced from design tokens */
import { STAT_BLOCK_COLORS as COLOR_HEX } from '../../lib/tokens'

Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

The new STAT_BLOCK_COLORS import is placed mid-file after other declarations. While valid, it breaks the existing import grouping pattern in this file and makes dependencies harder to scan. Move this import up with the other imports at the top of the module.

Copilot uses AI. Check for mistakes.
@clubanderson
Copy link
Copy Markdown
Collaborator Author

🔄 Auto-Applying Copilot Code Review

Copilot code review found 1 code suggestion(s) and 3 general comment(s).

@copilot Please apply all of the following code review suggestions:

  • web/src/components/cards/StockMarketTicker.tsx (line 775): <div className="absolute top-full left-0 right-0 mt-1 bg-card border border-bord...

Also address these general comments:

  • web/eslint.config.js (line 55): The new no-restricted-syntax rules for raw /<textarea>/ will also fire inside the shared Input/TextArea/S web/src/components/ui/StatBlockModePicker.tsx (line 132): This element is a popover/menu (role="menu"), but it uses the semantic z-index token z-overlay, which is documented fo web/src/components/ui/StatsOverview.tsx (line 69): The new STAT_BLOCK_COLORS import is placed mid-file after other declarations. While valid, it breaks the existing impo Push all fixes in a single commit. Run cd web && npm run build && npm run lint before committing. Auto-generated by copilot-review-apply workflow.

@github-actions github-actions bot mentioned this pull request Apr 7, 2026
@kubestellar-prow kubestellar-prow bot added dco-signoff: no Indicates the PR's author has not signed the DCO. and removed dco-signoff: yes Indicates the PR's author has signed the DCO. labels Apr 7, 2026
Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 7, 2026

🔄 Auto-Applying Copilot Code Review

Copilot code review found 1 code suggestion(s) and 3 general comment(s)....

All four items addressed in commit 15131de:

  • StockMarketTicker.tsx (line 775): Changed z-overlayz-dropdown for the search results dropdown.
  • StatBlockModePicker.tsx (line 132): Changed z-overlayz-dropdown for the popover/menu (role="menu").
  • StatsOverview.tsx: Moved STAT_BLOCK_COLORS import to the top of the file with the other imports (removed the mid-file placement).
  • eslint.config.js: Added a second config block targeting only src/components/ui/Input.tsx, TextArea.tsx, and Select.tsx that re-declares no-restricted-syntax without the raw-element selectors, so those shared components aren't noisy/self-referential.

Also fixed the CodeQL alert in GitHubInvite.tsx (line 113): added an invitedUsername state to capture the validated username before it was reset, then used encodeURIComponent(invitedUsername) in the "View Profile" href. This also fixes a pre-existing UX bug where the link previously pointed to https://github.com/ after the username was cleared.

@kubestellar-prow kubestellar-prow bot added dco-signoff: yes Indicates the PR's author has signed the DCO. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. and removed dco-signoff: no Indicates the PR's author has not signed the DCO. labels Apr 7, 2026
…gn tokens

Tier 1 — Quick Wins:
- Define 6 semantic z-index layers (dropdown/sticky/overlay/modal/
  toast/critical) and migrate all arbitrary z-[N] values across 30+ files
- Standardize all 27 overlay backdrops to bg-black/60 backdrop-blur-sm
- Add semantic status color tokens; fix StatsOverview green hex
- Fix ConfirmDialog: use Button component for confirm action
- Document border-radius conventions

Tier 2 — Structural:
- Migrate 7 hand-rolled modals to BaseModal (ImproveMissionDialog,
  ShareMissionDialog, SubmitToKBDialog, SaveResolutionDialog,
  ClusterSelectionDialog, LinkedInShare, GitHubInvite, NamespaceMonitor)
- Create shared Input, TextArea, Select form components
- Create semantic typography constants (TEXT.pageTitle, etc.)

Tier 3 — Foundation:
- Extract design tokens to lib/tokens.ts (single source of truth)
- Add ESLint guard rails for raw form elements
- Document Modal vs Dialog naming convention

Bugfix:
- KubeVirt card: add demoWhenEmpty to show demo data without clusters

Signed-off-by: Andrew Anderson <andy@clubanderson.com>
@kubestellar-prow kubestellar-prow bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 8, 2026
@clubanderson
Copy link
Copy Markdown
Collaborator Author

Scanner agent update:

  • Rebased branch onto current main (resolved merge conflicts in Deploy.tsx, FeatureRequestModal.tsx, GitHubInvite.tsx, LinkedInShare.tsx, ThemeSection.tsx)
  • Fixed VClusterStatus.tsx card-standard failure: replaced shorthand { isLoading, ... } with explicit { isLoading: false, ... } in useCardLoadingState call (the original PR's branch had a shorthand that was introduced by an earlier rebase)
  • Merged conflict resolutions kept semantic z-index tokens (z-modal, z-dropdown, z-critical) from this PR AND accessibility attributes (role, aria-labelledby, onKeyDown) from main

CI should now pass the card-standard check. PR still requires maintainer approval (approved/lgtm labels) before merge.

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

Labels

dco-signoff: yes Indicates the PR's author has signed the DCO. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants