🎨 UX cohesion: unified overlays, z-index scale, form components, design tokens#5286
🎨 UX cohesion: unified overlays, z-index scale, form components, design tokens#5286clubanderson wants to merge 1 commit intomainfrom
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
👋 Hey @clubanderson — thanks for opening this PR!
This is an automated message. |
❌ Deploy Preview for kubestellarconsole failed. Why did it fail? →
|
There was a problem hiding this comment.
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.tssource for hex/z-index/layout constants. - Normalize overlay backdrops and migrate many components from arbitrary
z-[N]values to semanticz-*classes; migrate several hand-rolled modals toBaseModal. - 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. |
| { | ||
| 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>.', | ||
| }, |
There was a problem hiding this comment.
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).
| <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 }} |
There was a problem hiding this comment.
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.
| {/* 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"> |
There was a problem hiding this comment.
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.
| <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"> |
| /** Hex color values for chart components — sourced from design tokens */ | ||
| import { STAT_BLOCK_COLORS as COLOR_HEX } from '../../lib/tokens' | ||
|
|
There was a problem hiding this comment.
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.
🔄 Auto-Applying Copilot Code ReviewCopilot code review found 1 code suggestion(s) and 3 general comment(s). @copilot Please apply all of the following code review suggestions:
Also address these general comments:
|
All four items addressed in commit
Also fixed the CodeQL alert in |
9a90579 to
37ac94c
Compare
…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>
3e38485 to
6a5037b
Compare
|
Scanner agent update:
CI should now pass the card-standard check. PR still requires maintainer approval (approved/lgtm labels) before merge. |
📝 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-[N]values (z-[60] through z-[10010]) to semantic tokensbg-black/60 backdrop-blur-sm(was mix of blur-sm, blur-2xl, no blur, /50, /60, /70)StatsOverview COLOR_HEXgreen (#22c55e→#10b981) to match--color-success<button>with<Button>component for consistent confirm/cancel stylingTier 2 — Structural Improvements (17 files)
BaseModalcompound component (unified focus trapping, ESC handling, backdrop, keyboard nav)Input,TextArea,Selectincomponents/ui/with size variants, error states, and accessibilityTEXTconstants (pageTitle, cardTitle, caption, etc.) intypography.tsTier 3 — Foundation
tokens.tswith STATUS_COLORS, BRAND_COLORS, CHART_COLORS, Z_INDEX, LAYOUT — single source of truth for JS-side values<input>,<textarea>,<select>to encourage shared components; ESLint override added so the sharedInput/TextArea/Selectcomponent files themselves are exempt from those guardsChanges Made
z-[N]values to tokensbg-black/60 backdrop-blur-smInput,TextArea,Selectform components with size variants and accessibilityBaseModalcompound componenttokens.tsas single source of truth for JS-side design valuesno-restricted-syntaxguards for raw form elementseslint.config.js: added override block scoped toInput.tsx/TextArea.tsx/Select.tsxso those shared components are not flagged by their own guard rulesStockMarketTicker.tsx: corrected search results dropdown fromz-overlay→z-dropdown(dropdowns should not be elevated above true overlays/modals)StatBlockModePicker.tsx: correctedrole="menu"popover fromz-overlay→z-dropdownStatsOverview.tsx: movedSTAT_BLOCK_COLORSimport to the top of the file with all other importsGitHubInvite.tsx(CodeQL): introducedinvitedUsernamestate to capture the validated username before reset, and usedencodeURIComponent(invitedUsername)in the "View Profile" href — eliminates unescaped user input in DOM attribute and fixes a UX bug where the link previously resolved tohttps://github.com/Checklist
git commit -s)Screenshots or Logs (if applicable)
No visual regressions expected — changes are semantic token/class name corrections and import ordering.
👀 Reviewer Notes
z-dropdown<z-overlay<z-modallayering order is now consistently respected: search dropdowns and popover menus usez-dropdown, backdrops/dimmers usez-overlay, and modals usez-modal.eslint.config.jsretains 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.GitHubInvitefix 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
grep -r "z-\[\d" web/srcreturns 0 results (no arbitrary z-index values)grep -r "backdrop-blur-2xl" web/srcreturns 0 resultsnpm run build)npx tsc --noEmit— 0 errors)Input.tsx,TextArea.tsx, orSelect.tsx