Frontmatter
| id | 8727 |
| title | Epic: Portal App Dark Theme |
| state | Closed |
| labels | enhancementepicdesignai |
| assignees | tobiu |
| createdAt | Jan 16, 2026, 9:34 PM |
| updatedAt | Jan 21, 2026, 10:05 PM |
| githubUrl | https://github.com/neomjs/neo/issues/8727 |
| author | tobiu |
| commentsCount | 10 |
| parentIssue | null |
| subIssues | 8728 Implement Neo Dark Theme Tokens 8729 Update Portal Header Toolbar for Theme Switching 8730 Enable Neo Dark Theme in Portal Config 8731 Replicate Light Theme Structure to Dark Theme 8732 Implement Dark Theme for General Components 8733 Implement Dark Theme for Container and Form Components 8734 Implement Dark Theme for Data Views 8735 Implement Dark Theme for Navigation Components 8736 Implement Dark Theme for Complex Components 8737 Implement Dark Theme for Application Styles 8738 Refactor Portal App Source SCSS for Theming 8739 Implement Dark Theme for Portal Content Components 8740 Refactor Portal Header Toolbar for Dark Theme 8741 Refactor Portal App Subdirectories for Dark Theme 8742 Refactor Portal TabContainer for Dark Theme 8746 Refine HeaderToolbar SCSS Specificity 8745 Optimize and Document HeaderCanvas Semantic Effects 8744 Implement Canvas-based Hover Effects for Portal Header 8743 Refactor Portal HeaderCanvas View for Theme Propagation 8747 Fix TreeList specificity preventing hover state 8748 Update Portal TabContainer Dark Theme Colors 8749 Update Global Dark Theme Inline Code Background 8750 Refactor Markdown SCSS for Theming 8751 Refine Markdown Details Icon Color 8752 Refine Dark Theme Markdown Blockquote Background 8753 Refine Dark Theme Link Color 8754 Implement Theme-Aware Mermaid Diagram Rendering 8768 Refine Dark Theme Paragraph Text Contrast 8769 Formalize Dark Theme Blockquote Background Token 8770 Refine Dark Theme Markdown Table Header Background 8771 Refine Portal Header Canvas Ribbon Opacity for Dark Theme 8772 Refine Dark Theme Markdown Text Color Consistency 8773 Refine Portal Home Feature Section Dark Theme 8774 Refine Dark Theme for Ticket Timeline Components 8775 Implement Dark Theme for Ticket Canvas 8776 Integrate Theme Switching for Home and Ticket Canvases 8777 Robust Theme Switching for Portal Canvases 8778 Integrate Robust Theme Switching for Services Canvas 8779 Standardize HeaderCanvas Configuration 8788 Refine Portal News TreeList Dark Theme Styling 8843 Persist Portal Theme Selection 8844 Auto-detect System Theme Preference 8845 Sync Monaco Editor Theme in Portal 8846 Fix Monaco Editor Background Glitch 8847 Fix Dark Theme for HighlightJS 8848 Propagate Theme to Embedded Markdown Components 8852 Refactor Portal Footer SCSS for Theming 8853 Modernize Portal Footer Layout with CSS Grid 8854 Implement Footer OffscreenCanvas Overlay |
| subIssuesCompleted | 49 |
| subIssuesTotal | 49 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Jan 21, 2026, 10:05 PM |
Epic: Portal App Dark Theme

Input from Gemini 3 Pro:
✦ I have completed the implementation of the Portal App Dark Theme infrastructure and initial switching logic.
Summary of Changes:
Theme Infrastructure:
- Created
resources/scss/theme-neo-darkand populateddesign-tokens.- Inverted
Semantic.scssmappings to map semantic variables to dark core tokens (e.g., backgrounds are nowgray-900).- Updated root selectors in
Core.scss,Semantic.scss, andComponent.scssto.neo-theme-neo-dark.UI Updates:
- Refactored
apps/portal/view/HeaderToolbar.mjs:
- Removed the Slack icon.
- Added a "Switch Theme" button (Moon icon) with
handler: 'onSwitchTheme'.Controller Logic:
- Updated
apps/portal/view/ViewportController.mjswithonSwitchTheme.- The logic toggles
this.component.themebetweenneo-theme-neo-lightandneo-theme-neo-dark.- Updates the button icon dynamically (Sun/Moon).
Configuration:
- Added
neo-theme-neo-darktoapps/portal/neo-config.jsonto ensure the CSS is loaded.The foundation is now in place. Future iterations can focus on fine-tuning the visual assets (logos) and specific component overrides if needed.

Input from Gemini 3 Pro:
✦ Progress Update: Dark Theme Implementation
We have successfully established the dark theme infrastructure and updated the core form and container components.
Completed:
- Infrastructure: Created
theme-neo-darkstructure and replicated all SCSS files fromtheme-neo-light.- General Components: Updated
Toast,Chip,StatusBadge,Process,Progress,Splitter,DateSelector,Video,BoxLabel.- Containers: Updated
Accordion,AccordionItem,Viewport,Panel.- Forms: Updated
Fieldset,Text,CheckBox,Picker,Switch,Triggers.Remaining Work (To Be Done in Next Session): The following component categories still contain hardcoded light-theme colors and need to be updated to use dark theme semantic tokens:
Data Views:
grid/(Container, Body, Header)table/(Container, Body, Header)list/(Base)tree/(List)Navigation:
tab/(Container, Strip, Header)menu/(List, Panel)toolbar/(Base)Complex Components:
calendar/(Views, Containers)dialog/(Base)tooltip/(Base)draggable/(SortZones)Application Specifics:
apps/(Portal, Docs, etc. need review for specific overrides)Next Steps: Start a new session to tackle the Data Views (
grid,table,list,tree) as the next logical chunk.

Input from Gemini 3 Pro:
✦ Progress Update & Handoff Instructions
We have completed the implementation of dark theme support for all core component categories (Data Views, Navigation, Complex) and the main application overrides.
Completed:
- #8734 Data Views
- #8735 Navigation
- #8736 Complex Components
- #8737 Apps (Portal, Docs, AgentOS, Covid)
In Progress: Portal App Refactoring (#8738) We started refactoring the Portal App's source SCSS to support theming, but significant work remains. Many source files (e.g., in
shared/content/) still use hardcoded hex values.Instructions for Next Session:
- Scan & Refactor: Continue scanning
resources/scss/src/apps/portal/(especiallyshared/content/) for hardcoded colors.- Strategy:
- Do NOT change the Light Theme: Create app-specific CSS variables. In
resources/scss/theme-neo-light/apps/portal/..., define these variables using the original hardcoded hex values.- Dark Theme Mapping: In
resources/scss/theme-neo-dark/apps/portal/..., map these same variables to our semantic tokens (e.g.,var(--sem-color-bg-neutral-default)).- Flexibility: This indirection allows us to tweak the dark theme implementation without risking any regressions in the default light theme.
Next Targets:
resources/scss/src/apps/portal/shared/content/SectionsContainer.scssresources/scss/src/apps/portal/shared/content/TreeList.scss- Any other files in
src/apps/portalwith hardcoded colors.

Input from Gemini 3 Pro:
✦ Refactoring complete. All identified SCSS files in the Portal App have been updated to support theming via CSS variables.
Summary of Refactoring:
- Core Components:
shared/content/(SectionsContainer,TreeList,Container,PageContainer)- Header:
HeaderToolbar- Sub-apps:
about,services,home(BaseContainer,How),news(tickets/Component)- Navigation:
shared/TabContainerApproach:
- Light Theme: Variables map to original hardcoded hex values to ensure zero visual regression.
- Dark Theme: Variables map to semantic tokens (e.g.,
--sem-color-bg-neutral-default).Remaining:
FooterContainer(Black by design)examples/List&medium/List(Dark overlays by design)We are now ready to tackle offscreen canvas theming in a separate effort.

Input from Gemini 3 Pro:
✦ Task complete. Theme persistence is implemented and refactored.

Input from Gemini 3 Pro:
✦ I have implemented the auto-detection logic.
Changes:
- Updated
DefaultConfig.mjs: AddedprefersDarkTheme(default:false) with clear documentation.- Updated
src/worker/Manager.mjs: EnhanceddetectFeaturesto checkmatchMedia('(prefers-color-scheme: dark)')and updateNeo.config.prefersDarkThemebefore workers are created. This ensures the correct value is propagated during the initial worker handshake without requiring a secondary remote call.- Updated
ViewportController.mjs: ModifiedonConstructedto useNeo.config.prefersDarkThemeas the fallback if no local storage preference exists.The implementation is efficient, avoiding unnecessary post-startup configuration synchronization.

Input from Gemini 3 Pro:
✦ I have implemented the automatic theme synchronization for the Monaco Editor wrapper.
Changes:
- New Config: Added
useThemeAwareness_(Boolean, defaulttrue) tosrc/component/wrapper/MonacoEditor.mjs. This allows developers to opt-out of automatic theme mapping if they need a specific, fixed editor theme regardless of the application theme.- Theme Mapping Logic: Implemented
afterSetTheme. It detects changes to the inheritedthemeconfig (propagated bycontainer.Base), maps it (dark->vs-dark,light->vs), and updates theeditorThemeconfig accordingly. This ensures both initial rendering and runtime switches are handled correctly.- Dynamic Toggling: Implemented
afterSetUseThemeAwarenessto immediately apply the current theme if the feature is enabled at runtime.This solution provides a "batteries-included" experience for the Portal App and all other Neo.mjs applications using this wrapper, while maintaining flexibility.

Input from Gemini 3 Pro:
✦ I have resolved the 1px background glitch.
Changes:
- Refactored SCSS: Updated
resources/scss/src/component/wrapper/MonacoEditor.scssto use the CSS variablevar(--monaco-editor-background-color).- Theme Definitions: Created the following theme files using the correct
:root .neo-theme-...scoping pattern:
resources/scss/theme-neo-dark/component/wrapper/MonacoEditor.scss: Sets variable to#1e1e1e.resources/scss/theme-neo-light/component/wrapper/MonacoEditor.scss: Sets variable to#fffffe.This ensures the wrapper background visually matches the editor canvas, masking the sub-pixel rendering artifact.

Input from Gemini 3 Pro:
✦ I have corrected the dark theme colors for HighlightJS.
Changes:
- Updated
resources/scss/theme-neo-dark/util/HighlightJs.scss: Applied a GitHub Dark inspired palette (dark background#0d1117, light syntax highlighting colors) to replace the incorrect light theme values.- Updated
resources/scss/theme-neo-dark/util/HighlightJsLineNumbers.scss: Applied dark background and dim text colors for line numbers.Since the SCSS variables are scoped to
.neo-theme-neo-dark, andNeo.util.HighlightJsensures the CSS files are loaded, switching the theme on the Portal Viewport will now automatically apply these corrected styles to all markdown code blocks.

Input from Gemini 3 Pro:
✦ I have fixed the theme propagation issue for embedded Markdown components.
Changes:
- Updated
src/component/Markdown.mjs: Modified therendermethod to includetheme: me.themein thebaseConfigsobject.Impact: All components instantiated by the Markdown renderer (LivePreview, Mermaid, custom components) will now inherit the current theme of the Markdown component upon creation. This ensures that when a user navigates to a new view (triggering a fresh Markdown render), the embedded components correctly initialize in Dark Mode if active, instead of falling back to the Light Mode default. This completes the loop with the
useThemeAwarenessfeature added to the Monaco wrapper.
Implement a comprehensive Dark Theme for the Portal App, utilizing the Neo.mjs Design Token system to ensure maintainability and nesting capability.
Child Tasks:
resources/scss/theme-neo-dark.design-tokensstructure fromtheme-neo-light.Semantic.scss(e.g., map backgrounds to dark gray tokens).apps/portal/view/HeaderToolbar.mjs.apps/portal/neo-config.jsonto include the newneo-theme-neo-dark.