feat: thunar & papirus-folders theming + new schemes (#80)

* feat: GTK app theming system

- Implemented custom.css import for user-managed app themes
- process_app_themes() to dynamically update colors in imported CSS files
- Inline comment markers for color replacement (e.g, /* accent-color */)
- Papirus icon color syncing with weighted hue/saturation algorithm

This allows users to create modular app themes that automatically update when the scheme/wallpaper changes

Example usage:
  .app .element { color: #24BD5C; /* accent-color */ }
  .app .element:hover { background: rgba(36, 189, 92, 0.15); /* accent-color with 15% opacity */ }

* feat: atomic theme changes with locking and mode-specific CSS

- Implemented locking to prevent concurrent theme changes
- Added mode-light/mode-dark CSS markers for dynamic property reordering
- Made terminal writes and Papirus sync non-blocking to prevent hangs
- Only save scheme.json after successful theme application

Fixes race conditions during rapid theme switching and ensures Shell and GTK apps scheme stay in sync.

* theme: added to color mapping for custom theming, new schemes

* theme: quick fixes, cleanup

* theme: include thunar.css as template, with new theming system

* theme: modified GTK theming approach

- Dropped comment targeted theming in favor for existing {{  }} replacement
- [app].css.template file created for customization, bypassing built in default if present
- Handling *.template for added templates to be parsed and added to import

* theme: fixes for  thunar.css

* theme: remove .template file use

* theme: path button color adjustment, non-active hover

* fixes & cleanup

* thunar css fixes

* more css fixes

* format

* fix tab vert spacing

---------

Co-authored-by: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>
This commit is contained in:
Robin Seger
2026-02-14 13:23:33 +01:00
committed by GitHub
parent fe8adde6c1
commit bca7b12072
15 changed files with 1421 additions and 39 deletions
+4
View File
@@ -15,3 +15,7 @@
@define-color sidebar_fg_color @window_fg_color;
@define-color sidebar_border_color @window_bg_color;
@define-color sidebar_backdrop_color @window_bg_color;
@define-color theme_selected_bg_color alpha(@accent_color, 0.15);
@define-color theme_selected_fg_color @primary;
@import "thunar.css";
+202
View File
@@ -0,0 +1,202 @@
/* Thunar theme */
/* =============================================================================
Global Resets
============================================================================= */
.thunar * {
outline: none;
border: none;
}
/* =============================================================================
Window & Background
============================================================================= */
.thunar.background {
background: {{ $surface }};
}
.thunar .titlebar {
background: inherit;
}
.thunar .titlebutton.close {
margin: 0 15px 0 0;
}
/* =============================================================================
Layout Containers
============================================================================= */
/* Paned separator between sidebar and main view */
.thunar paned > separator {
min-width: 4px;
margin-right: -7px;
margin-left: -7px;
background: none;
background-image: none;
box-shadow: none;
}
/* Main file view frame */
.thunar .frame.standard-view {
padding: 10px;
margin: 10px 15px 0 0;
border-radius: 15px;
background-color: {{ $surfaceContainerLow }};
animation: fading 400ms ease forwards;
opacity: 0;
animation-delay: 250ms;
}
.thunar .frame.standard-view .view:not(.rubberband),
.thunar .frame.standard-view .view *:not(.rubberband) {
background-color: transparent;
}
.thunar .frame.standard-view .view *:selected {
color: {{ $primary }};
}
.thunar .rubberband {
background-color: alpha({{ $primary }}, 0.15);
border: 1px solid alpha({{ $primary }}, 0.15);
}
/* Tabs */
.thunar header.top {
background: none;
padding: 0 10px 0 0;
margin: 3px 0 -3px -2px;
}
.thunar header.top tabs .reorderable-page {
margin: 0;
transition: all ease 300ms;
}
.thunar header.top tabs .reorderable-page + .reorderable-page {
margin: 0 0 0 10px;
}
.thunar header.top tabs .reorderable-page:hover {
background-color: alpha({{ $primary }}, 0.08);
}
.thunar header.top tabs .reorderable-page:checked {
color: {{ $primary }};
background-color: alpha({{ $primary }}, 0.15);
}
/* =============================================================================
Sidebar Navigation
============================================================================= */
.thunar .sidebar {
padding: 0 20px;
background: none;
animation: fading 600ms ease forwards;
animation-delay: 100ms;
opacity: 0;
}
.thunar .sidebar .view {
padding: 8px 4px;
border-radius: 10px;
background: none;
transition: all ease 300ms;
}
.thunar .sidebar .view:hover {
background: alpha({{ $onSurface }}, 0.1);
}
.thunar .sidebar .view:selected {
background: alpha({{ $primary }}, 0.15);
color: {{ $primary }};
}
/* =============================================================================
Path Bar & Location Buttons
============================================================================= */
.thunar .path-bar-button {
margin: 0;
padding: 8px 5px;
transition: all ease 0.4s;
}
.thunar .location-button.toggle:checked,
.thunar .path-bar-button.toggle:checked {
padding: 8px 25px;
background: alpha({{ $primary }}, 0.15);
color: {{ $primary }};
box-shadow: none;
}
.thunar .location-button.path-bar-button:not(:checked) {
background-color: {{ $surfaceContainerLow }};
}
.thunar .location-button.path-bar-button:not(:checked):hover {
background: alpha({{ $primary }}, 0.08);
color: alpha({{ $primary }}, 0.8);
}
.thunar .location-button.toggle+.location-button.toggle:checked {
margin-left: 0px;
padding: 0 25px;
}
.thunar .titlebar {
padding: 15px 0 5px 0;
}
/* =============================================================================
Buttons
============================================================================= */
.thunar button.toggle:checked {
color: {{ $primary }};
}
.thunar .image-button {
padding: 8px;
margin: 0 0 0 8px;
transition: all ease 0.4s;
}
/* =============================================================================
Status Bar
============================================================================= */
.thunar statusbar {
background-color: {{ $surfaceContainerLow }};
border-radius: 15px;
padding: 10px 10px;
margin: 15px 5px 15px -10px;
color: {{ $onSurface }};
}
/* =============================================================================
Image preview
============================================================================= */
.thunar box.vertical .image {
margin: 15px;
}
/* =============================================================================
Animation
============================================================================= */
@keyframes fading {
to {
opacity: 1;
}
}