Files
DbFirst/DbFirst.BlazorWebApp/wwwroot/app.css
OlgunR 8933deec96 Add dark mode override for non-native DevExpress themes
Implements a dark mode override system for DevExpress Blazor themes lacking native dark support. Adds a JS function to toggle a dx-dark class on <html>, updates ThemeState to detect native dark themes, and applies targeted CSS variable overrides for consistent dark styling. Disables prerendering to ensure JS interop, and improves theme switching logic and documentation.
2026-05-05 16:41:15 +02:00

290 lines
8.1 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
:root {
--global-size: 16px;
}
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: var(--global-size);
}
/* Theme-Variablen */
.app-light {
--band-editor-bg: #f8f9fa;
--band-editor-border: #dee2e6;
--band-toggle-hover-bg: #e9ecef;
--grid-stripe-bg: rgba(0, 0, 0, 0.03);
}
.app-dark {
background-color: #1b1b1b;
color: #f1f1f1;
--band-editor-bg: #2d2d2d;
--band-editor-border: #444444;
--band-toggle-hover-bg: #3a3a3a;
--grid-stripe-bg: rgba(255, 255, 255, 0.04);
}
a, .btn-link {
color: #006bb7;
}
.app-dark a, .app-dark .btn-link {
color: #6cb6ff;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}
.content {
padding-top: 1.1rem;
}
h1:focus {
outline: none;
}
.valid.modified:not([type=checkbox]) {
outline: 1px solid #26b050;
}
.invalid {
outline: 1px solid #e50000;
}
.validation-message {
color: #e50000;
}
.blazor-error-boundary {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDg2IDY2LjAxODMgMjYzLjU4NiA2Ni4wMTgzWk0yNjMuNTc2IDg2LjA1NDdDMjYxLjA0OSA4Ni4wNTQ3IDI1OS43ODUgODcuMzAwNSAyNTkuNzg2IDg5Ljc5MjEgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
padding: 1rem 1rem 1rem 3.7rem;
color: white;
}
.blazor-error-boundary::after {
content: "An error has occurred."
}
.darker-border-checkbox.form-check-input {
border-color: #929292;
}
/* Grid Band-Editor */
.band-editor {
margin-top: 4px;
margin-bottom: 16px;
border: 1px solid var(--band-editor-border);
border-radius: 4px;
background-color: var(--band-editor-bg);
overflow: hidden;
}
.band-editor-toggle {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
padding: 8px 12px;
background: none;
border: none;
cursor: pointer;
font-size: inherit;
color: inherit;
text-align: left;
}
.band-editor-toggle:hover {
background-color: var(--band-toggle-hover-bg);
}
.band-editor-toggle-icon {
font-size: 0.7rem;
transition: transform 0.2s ease;
display: inline-block;
}
.band-editor-toggle-icon.expanded {
transform: rotate(90deg);
}
.band-editor-body {
display: flex;
flex-direction: column;
gap: 12px;
padding: 0 12px 12px 12px;
}
.band-controls {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
.band-row {
display: flex;
gap: 8px;
align-items: center;
}
.band-columns {
max-width: 720px;
margin-top: 4px;
}
.grid-section {
margin-top: 4px;
}
/* Grid Zebra-Striping */
dxbl-grid tbody tr:nth-child(even) td {
background-color: var(--grid-stripe-bg) !important;
}
/* ?? Dark-Mode-Overrides für nicht-native Themes ?????????????????????????????
Strategie: CSS-Custom-Properties werden von DevExpress DIREKT auf den
Komponenten-Elementen definiert (z. B. --dxbl-popup-bg:#fff auf .dxbl-modal).
Eine geerbte Variable aus html.dx-dark würde durch die direkte Zuweisung
überschrieben. Deshalb targeten wir exakt dieselben Elemente, aber mit einem
zusätzlichen Vorfahren-Selektor (html.dx-dark) für höhere Spezifizität:
html.dx-dark .dxbl-modal = (0,2,1) > .dxbl-modal = (0,1,0) ?
html.dx-dark wird per JS gesetzt, wenn IsDarkMode && !IsNativeDarkTheme.
?? */
/* Popup / Modal (CRUD-Dialoge) Variablen-Quelle: .dxbl-modal */
html.dx-dark .dxbl-modal {
--dxbl-popup-bg: #2d2d2d;
--dxbl-popup-color: #e8e8e8;
--dxbl-popup-border-color: #555;
--dxbl-popup-header-bg: #333;
--dxbl-popup-header-color: #e8e8e8;
--dxbl-popup-footer-bg: #333;
--dxbl-popup-footer-color: #e8e8e8;
}
/* Flyout (Column Chooser, Filter-Panel) Variablen-Quelle: .dxbl-flyout */
html.dx-dark .dxbl-flyout {
--dxbl-flyout-bg: #2d2d2d;
--dxbl-flyout-color: #e8e8e8;
--dxbl-flyout-border-color: #555;
--dxbl-flyout-header-bg: #333;
--dxbl-flyout-header-color: #e8e8e8;
--dxbl-flyout-footer-bg: #333;
}
/* Dropdown (ComboBox-Klappliste, Band-Dropdowns) Quelle: .dxbl-dropdown */
html.dx-dark .dxbl-dropdown,
html.dx-dark .dxbl-itemlist-dropdown {
--dxbl-dropdown-bg: #2d2d2d;
--dxbl-dropdown-color: #e8e8e8;
--dxbl-dropdown-border-color: #555;
--dxbl-dropdown-header-bg: #333;
--dxbl-dropdown-footer-bg: #333;
}
/* Edit-Dropdown (ComboBox-Popup wenn als Modal gerendert) Quelle: .dxbl-edit-dropdown */
html.dx-dark .dxbl-edit-dropdown {
--dxbl-edit-dropdown-bg: #2d2d2d;
--dxbl-edit-dropdown-color: #e8e8e8;
--dxbl-edit-dropdown-border-color: #555;
}
/* ListBox (Einträge in Dropdowns) Quelle: .dxbl-list-box */
html.dx-dark .dxbl-list-box,
html.dx-dark .dxbl-list-box-render-container {
--dxbl-list-box-bg: #2d2d2d;
--dxbl-list-box-color: #e8e8e8;
--dxbl-list-box-border-color: #555;
--dxbl-list-box-item-hover-bg: #3a3a3a;
--dxbl-list-box-item-hover-color: #e8e8e8;
}
/* TextEdit / ComboBox Eingabefeld Quelle: .dxbl-text-edit */
html.dx-dark .dxbl-text-edit {
--dxbl-text-edit-bg: #2d2d2d;
--dxbl-text-edit-color: #e8e8e8;
--dxbl-text-edit-border-color: #555;
--dxbl-text-edit-btn-bg: #3a3a3a;
--dxbl-text-edit-btn-color: #e8e8e8;
--dxbl-text-edit-btn-hover-bg: #444;
--dxbl-text-edit-btn-hover-color: #e8e8e8;
}
/* Buttons */
html.dx-dark .dxbl-btn {
--dxbl-btn-color: #e8e8e8;
--dxbl-btn-bg: #3a3a3a;
--dxbl-btn-border-color: #555;
--dxbl-btn-hover-bg: #444;
--dxbl-btn-hover-color: #e8e8e8;
--dxbl-btn-hover-border-color: #666;
}
/* FormLayout */
html.dx-dark .dxbl-fl {
--dxbl-fl-caption-color: #bbb;
--dxbl-fl-group-bg: #242424;
--dxbl-fl-group-color: #e8e8e8;
}
/* Grid */
html.dx-dark .dxbl-grid {
background-color: #242424;
color: #e8e8e8;
border-color: #444;
}
html.dx-dark .dxbl-grid > .dxbl-scroll-viewer,
html.dx-dark .dxbl-grid > .dxbl-grid-top-panel {
background-color: #242424;
color: #e8e8e8;
}
/* MassData-spezifisch */
.page-size-selector {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: nowrap;
margin-bottom: 12px;
}
.page-size-label {
white-space: nowrap;
}
.page-size-combo {
width: 13ch;
min-width: 13ch;
max-width: 13ch;
}
.page-size-combo input {
text-align: left;
}
.pager-container {
display: flex;
justify-content: center;
margin-top: 12px;
margin-bottom: 16px;
}
/* Lade-Spinner */
.loading-container {
min-height: 160px;
display: flex;
align-items: center;
justify-content: center;
}
.top-row .btn-gap {
margin-left: 8px;
}