Add Light Mode Support #450

Merged
PeetMcK merged 2 commits from _100-LightMode into dev-1.10.0 2025-12-23 22:35:50 +00:00
PeetMcK commented 2025-12-17 03:28:15 +00:00 (Migrated from github.com)

Overview

This PR implements light mode support for Termix, adding a comprehensive theme system that enables automatic switching between light and dark modes based on user preference or system settings.

Rebased onto dev-1.10.0 - This branch is now a single squashed commit cleanly rebased onto the latest upstream development branch.

What's Changed

Theme Infrastructure

  • CSS Variable System: Added semantic CSS variables in index.css with separate definitions for light (:root) and dark (.dark) modes
  • Terminal Themes: Introduced termixDark and termixLight variants with optimized ANSI color palettes for each mode
  • Auto-Switching: Terminal theme automatically adapts when "Termix Default" is selected, switching between light/dark variants based on app theme

Scrollbar Theming

  • Theme-Aware Scrollbars: Updated thin-scrollbar class to use CSS variables that adapt to light/dark mode
  • Consistent Application: Applied thin-scrollbar to all overflow elements across ~84 files for unified appearance
  • CodeMirror Support: Added inline scrollbar styling to CodeMirror editors using scrollbarWidth and scrollbarColor CSS properties
Element CSS Variable Light Value Dark Value
Scrollbar thumb --scrollbar-thumb #c1c1c3 #434345
Scrollbar thumb hover --scrollbar-thumb-hover #a1a1a3 #5a5a5d
Scrollbar track --scrollbar-track #f3f4f6 #18181b

Component Updates

Updated components across desktop and mobile to use semantic CSS classes instead of hard-coded dark mode values:

Desktop

  • Terminal, File Manager, Server Stats widgets, Dashboard, Host Manager, Credentials Manager
  • Navigation: TopNavbar, LeftSidebar, Tab system with theme-aware borders
  • Authentication forms and dialogs
  • User Profile with redesigned tabbed interface

Mobile

  • Terminal with theme auto-switching
  • New kb-light-theme.css for mobile keyboard
  • Navigation components and host cards
  • Authentication screens

UI Components

  • Alert, Badge, Button, Input, Resizable

Technical Approach

  • Replaced hard-coded classes (bg-dark-*, border-dark-*) with semantic alternatives (bg-canvas, bg-elevated, border-edge)
  • Integrated useTheme hook for runtime theme detection
  • Added system theme detection via window.matchMedia("(prefers-color-scheme: dark)")
  • Theme-aware scrollbars using CSS custom properties

Class Migration Reference

Background Classes

Old Class New Class Light Value Dark Value Usage
bg-dark-bg bg-canvas #fcfcfc #18181b Main canvas/container backgrounds
bg-dark-bg-darker bg-canvas #fcfcfc #18181b Also maps to canvas
bg-dark-bg-darkest bg-deepest #e5e7eb #09090b Deepest background layer
bg-dark-bg-panel bg-surface #f3f4f6 #1b1b1e Panel and surface backgrounds
bg-dark-bg-input bg-field #ffffff #222225 Input field backgrounds
bg-dark-bg-button bg-button #f3f4f6 #23232a Button backgrounds
bg-dark-bg-active bg-active #e5e7eb #1d1d1f Active state backgrounds
bg-dark-bg-header bg-header #eeeeef #131316 Header backgrounds
bg-dark-hover bg-hover #f3f4f6 #2d2d30 Hover state backgrounds
bg-dark-bg-panel-hover bg-surface-hover #e5e7eb #232327 Panel hover states
bg-dark-bg-light bg-light #fafafa #141416 Light background variant
bg-dark-bg-very-light bg-subtle #f5f5f5 #101014 Very subtle backgrounds
bg-dark-active bg-interact #d1d5db #2a2a2c Interactive/active states
bg-dark-hover-alt bg-hover-alt #e5e7eb #2a2a2d Alternative hover state
bg-dark-pressed bg-pressed #d1d5db #1a1a1c Pressed/clicked state
bg-elevated #ffffff #0e0e10 Elevated surfaces (new semantic)

Border Classes

Old Class New Class Light Value Dark Value Usage
border-dark-border border-edge #e5e7eb #303032 Standard borders
border-dark-border-panel border-edge-panel #d1d5db #222224 Panel borders
border-dark-border-light border-edge-subtle #f3f4f6 #5a5a5d Subtle borders
border-dark-border-medium border-edge-medium #d1d5db #373739 Medium emphasis borders
border-dark-border-hover border-edge-hover #d1d5db #434345 Hover state borders
border-dark-border-active border-edge-active #9ca3af #2d2d30 Active state borders

Text Classes

Old Class New Class Light Value Dark Value Usage
text-white text-foreground #18181b #fafafa Primary text
text-gray-300 text-foreground-secondary #334155 #d1d5db Secondary descriptive text
text-gray-400 text-muted-foreground #71717a #9ca3af Muted/secondary text
text-gray-500 text-foreground-subtle #94a3b8 #6b7280 Subtle/placeholder text
text-dark-text-secondary text-muted-foreground #71717a #9ca3af Secondary text (legacy)

Core shadcn/ui Variables (Also Updated)

Variable Light Value Dark Value Usage
--background #ffffff #09090b App background
--foreground #18181b #fafafa App foreground text
--card #ffffff #18181b Card backgrounds
--muted #f4f4f5 #27272a Muted backgrounds
--sidebar #f9f9f9 #18181b Sidebar background
--input #e4e4e7 #ffffff26 Input borders

Usage Examples

Before:

<div className="bg-dark-bg border border-dark-border text-white hover:bg-dark-hover">
  <p className="text-gray-400">Description</p>
</div>

After:

<div className="bg-canvas border border-edge text-foreground hover:bg-hover">
  <p className="text-muted-foreground">Description</p>
</div>

Tabs Example:

<TabsList className="bg-button border border-edge-medium">
  <TabsTrigger className="bg-button data-[state=active]:bg-elevated data-[state=active]:border data-[state=active]:border-edge-medium">
    General
  </TabsTrigger>
</TabsList>

Notes

  • Rebased onto upstream/dev-1.10.0 as a single squashed commit
  • Chart widgets (CPU, Memory, Disk) retain their current styling for data visualization
  • Light mode color palette designed for accessibility and readability
  • Dark mode maintains its existing visual appearance
  • Scrollbars now use consistent 6px thin styling with theme-aware colors

Testing Suggestions

  • Verify theme switching in Settings works correctly
  • Test with system theme preference (light/dark/auto)
  • Check terminal rendering in both themes
  • Review mobile keyboard appearance in light mode
  • Test navigation and dialogs in both themes
  • Verify scrollbars appear correctly in both light and dark modes

Co-Authored-By: Claude noreply@anthropic.com

## Overview This PR implements light mode support for Termix, adding a comprehensive theme system that enables automatic switching between light and dark modes based on user preference or system settings. **Rebased onto `dev-1.10.0`** - This branch is now a single squashed commit cleanly rebased onto the latest upstream development branch. ## What's Changed ### Theme Infrastructure - **CSS Variable System**: Added semantic CSS variables in `index.css` with separate definitions for light (`:root`) and dark (`.dark`) modes - **Terminal Themes**: Introduced `termixDark` and `termixLight` variants with optimized ANSI color palettes for each mode - **Auto-Switching**: Terminal theme automatically adapts when "Termix Default" is selected, switching between light/dark variants based on app theme ### Scrollbar Theming - **Theme-Aware Scrollbars**: Updated `thin-scrollbar` class to use CSS variables that adapt to light/dark mode - **Consistent Application**: Applied `thin-scrollbar` to all overflow elements across ~84 files for unified appearance - **CodeMirror Support**: Added inline scrollbar styling to CodeMirror editors using `scrollbarWidth` and `scrollbarColor` CSS properties | Element | CSS Variable | Light Value | Dark Value | |---------|--------------|-------------|------------| | Scrollbar thumb | `--scrollbar-thumb` | `#c1c1c3` | `#434345` | | Scrollbar thumb hover | `--scrollbar-thumb-hover` | `#a1a1a3` | `#5a5a5d` | | Scrollbar track | `--scrollbar-track` | `#f3f4f6` | `#18181b` | ### Component Updates Updated components across desktop and mobile to use semantic CSS classes instead of hard-coded dark mode values: **Desktop** - Terminal, File Manager, Server Stats widgets, Dashboard, Host Manager, Credentials Manager - Navigation: TopNavbar, LeftSidebar, Tab system with theme-aware borders - Authentication forms and dialogs - User Profile with redesigned tabbed interface **Mobile** - Terminal with theme auto-switching - New `kb-light-theme.css` for mobile keyboard - Navigation components and host cards - Authentication screens **UI Components** - Alert, Badge, Button, Input, Resizable ### Technical Approach - Replaced hard-coded classes (`bg-dark-*`, `border-dark-*`) with semantic alternatives (`bg-canvas`, `bg-elevated`, `border-edge`) - Integrated `useTheme` hook for runtime theme detection - Added system theme detection via `window.matchMedia("(prefers-color-scheme: dark)")` - Theme-aware scrollbars using CSS custom properties ## Class Migration Reference ### Background Classes | Old Class | New Class | Light Value | Dark Value | Usage | |-----------|-----------|-------------|------------|-------| | `bg-dark-bg` | `bg-canvas` | `#fcfcfc` | `#18181b` | Main canvas/container backgrounds | | `bg-dark-bg-darker` | `bg-canvas` | `#fcfcfc` | `#18181b` | Also maps to canvas | | `bg-dark-bg-darkest` | `bg-deepest` | `#e5e7eb` | `#09090b` | Deepest background layer | | `bg-dark-bg-panel` | `bg-surface` | `#f3f4f6` | `#1b1b1e` | Panel and surface backgrounds | | `bg-dark-bg-input` | `bg-field` | `#ffffff` | `#222225` | Input field backgrounds | | `bg-dark-bg-button` | `bg-button` | `#f3f4f6` | `#23232a` | Button backgrounds | | `bg-dark-bg-active` | `bg-active` | `#e5e7eb` | `#1d1d1f` | Active state backgrounds | | `bg-dark-bg-header` | `bg-header` | `#eeeeef` | `#131316` | Header backgrounds | | `bg-dark-hover` | `bg-hover` | `#f3f4f6` | `#2d2d30` | Hover state backgrounds | | `bg-dark-bg-panel-hover` | `bg-surface-hover` | `#e5e7eb` | `#232327` | Panel hover states | | `bg-dark-bg-light` | `bg-light` | `#fafafa` | `#141416` | Light background variant | | `bg-dark-bg-very-light` | `bg-subtle` | `#f5f5f5` | `#101014` | Very subtle backgrounds | | `bg-dark-active` | `bg-interact` | `#d1d5db` | `#2a2a2c` | Interactive/active states | | `bg-dark-hover-alt` | `bg-hover-alt` | `#e5e7eb` | `#2a2a2d` | Alternative hover state | | `bg-dark-pressed` | `bg-pressed` | `#d1d5db` | `#1a1a1c` | Pressed/clicked state | | — | `bg-elevated` | `#ffffff` | `#0e0e10` | Elevated surfaces (new semantic) | ### Border Classes | Old Class | New Class | Light Value | Dark Value | Usage | |-----------|-----------|-------------|------------|-------| | `border-dark-border` | `border-edge` | `#e5e7eb` | `#303032` | Standard borders | | `border-dark-border-panel` | `border-edge-panel` | `#d1d5db` | `#222224` | Panel borders | | `border-dark-border-light` | `border-edge-subtle` | `#f3f4f6` | `#5a5a5d` | Subtle borders | | `border-dark-border-medium` | `border-edge-medium` | `#d1d5db` | `#373739` | Medium emphasis borders | | `border-dark-border-hover` | `border-edge-hover` | `#d1d5db` | `#434345` | Hover state borders | | `border-dark-border-active` | `border-edge-active` | `#9ca3af` | `#2d2d30` | Active state borders | ### Text Classes | Old Class | New Class | Light Value | Dark Value | Usage | |-----------|-----------|-------------|------------|-------| | `text-white` | `text-foreground` | `#18181b` | `#fafafa` | Primary text | | `text-gray-300` | `text-foreground-secondary` | `#334155` | `#d1d5db` | Secondary descriptive text | | `text-gray-400` | `text-muted-foreground` | `#71717a` | `#9ca3af` | Muted/secondary text | | `text-gray-500` | `text-foreground-subtle` | `#94a3b8` | `#6b7280` | Subtle/placeholder text | | `text-dark-text-secondary` | `text-muted-foreground` | `#71717a` | `#9ca3af` | Secondary text (legacy) | ### Core shadcn/ui Variables (Also Updated) | Variable | Light Value | Dark Value | Usage | |----------|-------------|------------|-------| | `--background` | `#ffffff` | `#09090b` | App background | | `--foreground` | `#18181b` | `#fafafa` | App foreground text | | `--card` | `#ffffff` | `#18181b` | Card backgrounds | | `--muted` | `#f4f4f5` | `#27272a` | Muted backgrounds | | `--sidebar` | `#f9f9f9` | `#18181b` | Sidebar background | | `--input` | `#e4e4e7` | `#ffffff26` | Input borders | ### Usage Examples **Before:** ```tsx <div className="bg-dark-bg border border-dark-border text-white hover:bg-dark-hover"> <p className="text-gray-400">Description</p> </div> ``` **After:** ```tsx <div className="bg-canvas border border-edge text-foreground hover:bg-hover"> <p className="text-muted-foreground">Description</p> </div> ``` **Tabs Example:** ```tsx <TabsList className="bg-button border border-edge-medium"> <TabsTrigger className="bg-button data-[state=active]:bg-elevated data-[state=active]:border data-[state=active]:border-edge-medium"> General </TabsTrigger> </TabsList> ``` ## Notes - Rebased onto `upstream/dev-1.10.0` as a single squashed commit - Chart widgets (CPU, Memory, Disk) retain their current styling for data visualization - Light mode color palette designed for accessibility and readability - Dark mode maintains its existing visual appearance - Scrollbars now use consistent 6px thin styling with theme-aware colors ## Testing Suggestions - [ ] Verify theme switching in Settings works correctly - [ ] Test with system theme preference (light/dark/auto) - [ ] Check terminal rendering in both themes - [ ] Review mobile keyboard appearance in light mode - [ ] Test navigation and dialogs in both themes - [ ] Verify scrollbars appear correctly in both light and dark modes --- Co-Authored-By: Claude <noreply@anthropic.com>
PeetMcK commented 2025-12-17 03:30:50 +00:00 (Migrated from github.com)

I have a problem staying focued on dark mode ... probably because I can't see worth a crap after 40. Please let me know if i missed anything or you'd like anything tweeked.

I have a problem staying focued on dark mode ... probably because I can't see worth a crap after 40. Please let me know if i missed anything or you'd like anything tweeked.
LukeGus commented 2025-12-17 04:26:47 +00:00 (Migrated from github.com)

Looks decent in light mode, however, the regular dark mode color scheme was mostly messed up.
image
As you can see in the image, some background colors were changed, borders were messed up, etc. This exists across many of the components

Another thing is that a light mode terminal theme option should be added. Right now, it defaults to this:
image
However, when in light mode, there should be a new terminal option for Termix Light Default that uses the new light mode background color. Then the Termix Default should be renamed to Termix Dark Default.

Looks decent in light mode, however, the regular dark mode color scheme was mostly messed up. <img width="1911" height="915" alt="image" src="https://github.com/user-attachments/assets/211253e3-5d3d-4d22-b58b-531482d28cfd" /> As you can see in the image, some background colors were changed, borders were messed up, etc. This exists across many of the components Another thing is that a light mode terminal theme option should be added. Right now, it defaults to this: <img width="299" height="111" alt="image" src="https://github.com/user-attachments/assets/6131e03f-67bb-4aa7-8bf7-53d055adb65a" /> However, when in light mode, there should be a new terminal option for Termix Light Default that uses the new light mode background color. Then the Termix Default should be renamed to Termix Dark Default.
PeetMcK commented 2025-12-18 19:32:28 +00:00 (Migrated from github.com)

Boy did I ever come at that wrong. I could have walked into an unlocked front door, but decided it would be easier to dig a tunel from the street into the basement ¯\_(ツ)_/¯ ...

All that said, this is probably feature complete. Its possible I missed something or didn't dig deep enoug into a sub menu to find something that did't quite work. (60f624341a turns out to be just such a miss).

let me know if you have any questions or need a change.

Boy did I ever come at that wrong. I could have walked into an unlocked front door, but decided it would be easier to dig a tunel from the street into the basement ¯\\\_(ツ)\_/¯ ... All that said, this is *probably* feature complete. Its possible I missed something or didn't dig deep enoug into a sub menu to find something that did't quite work. (https://github.com/Termix-SSH/Termix/pull/450/commits/60f624341a2156eb8fa40607c144774e766eba0e turns out to be just such a miss). let me know if you have any questions or need a change.
LukeGus commented 2025-12-20 02:17:47 +00:00 (Migrated from github.com)

Lighmode is good, dark mode still needs much improvement.

Here is what Termix currently looks like in Dark mode:
Screenshot 2025-12-19 at 20-16-12 Termix

The color scheme is consistent, visible, and looks nice. Heres the new dark mode:
Screenshot 2025-12-19 at 20-17-42 Termix

The colors don't match, the app bg color was changed, the sidebars are oddly light, and many other stuff was changed too like this:
image
Which now uses a completely different background color that's never used anywhere else in the app.

Lighmode is good, dark mode still needs much improvement. Here is what Termix currently looks like in Dark mode: <img width="3840" height="1918" alt="Screenshot 2025-12-19 at 20-16-12 Termix" src="https://github.com/user-attachments/assets/f67b0bfc-209a-42de-b03c-af395bca2bf5" /> The color scheme is consistent, visible, and looks nice. Heres the new dark mode: <img width="3840" height="1918" alt="Screenshot 2025-12-19 at 20-17-42 Termix" src="https://github.com/user-attachments/assets/e826d473-aa28-49e9-8fa5-e8384699d9e1" /> The colors don't match, the app bg color was changed, the sidebars are oddly light, and many other stuff was changed too like this: <img width="590" height="86" alt="image" src="https://github.com/user-attachments/assets/8461f8b9-29e8-4edf-824d-7d681e7ba080" /> Which now uses a completely different background color that's never used anywhere else in the app.
LukeGus commented 2025-12-20 03:19:07 +00:00 (Migrated from github.com)

Also, i've changed your PR to use the latest dev-x.x.x version. This includes several new features like RBAC/Docker, which all added new components. Would you mind updating the new files, and resolving some of the merge conflicts that came with it?

Also, i've changed your PR to use the latest dev-x.x.x version. This includes several new features like RBAC/Docker, which all added new components. Would you mind updating the new files, and resolving some of the merge conflicts that came with it?
PeetMcK commented 2025-12-20 09:25:06 +00:00 (Migrated from github.com)

@LukeGus I've addressed the visual inconsistancies. If you find any more feel free to apply your prefered colors to the variables/classes. Virtually all of the inconsistencies were from poor conversions of oklch() conversions to hex.

The PR's been rebased onto Termix-SSH:dev-1.10.0, and while i didn't find anything that stood out as an immediat issue all other added features need testing and it absolutely should have another set of eyes or two to ensure there are no visual regressions.

@LukeGus I've addressed the visual inconsistancies. If you find any more feel free to apply your prefered colors to the variables/classes. Virtually all of the inconsistencies were from poor conversions of oklch() conversions to hex. The PR's been rebased onto Termix-SSH:dev-1.10.0, and while i didn't find anything that stood out as an immediat issue all other added features need testing and it absolutely should have another set of eyes or two to ensure there are no visual regressions.
LukeGus commented 2025-12-23 20:16:37 +00:00 (Migrated from github.com)

Thanks for fixing the merge issues. I'll check it out later today. I just finished updating thousands of hardcoded text into translations, which may cause some merge issues, but I can sort that out easily. I should also be able to take care of any visual issues. Thanks for the help!

Thanks for fixing the merge issues. I'll check it out later today. I just finished updating thousands of hardcoded text into translations, which may cause some merge issues, but I can sort that out easily. I should also be able to take care of any visual issues. Thanks for the help!
PeetMcK commented 2025-12-23 20:19:59 +00:00 (Migrated from github.com)

@LukeGus No worries. I guess I spent a bunch of time rebasing to the wrong commit, then to the right one. In the future, were would you like PR's to be based to have the best chance to avoid the extra lift and possible conflicts?

@LukeGus No worries. I guess I spent a bunch of time rebasing to the wrong commit, then to the right one. In the future, were would you like PR's to be based to have the best chance to avoid the extra lift and possible conflicts?
Sign in to join this conversation.