From 9d682bd74168c5ba2d60193d6fc9a91ad37cd28d Mon Sep 17 00:00:00 2001 From: Loretta Date: Sun, 21 Dec 2025 08:24:40 +0100 Subject: [PATCH] DevExpress Fluent theme: grid/info panel refactor Major refactor for DevExpress Fluent theme compatibility: - InfoPanel templates now use strongly-typed context (`InfoPanelContext`) - Unified grid layout with `MgGridWithInfoPanel` wrapper - CSS updated to use Fluent theme variables and container queries - App-wide CSS cleanup and formatting improvements - `.editorconfig` added for modern CSS support - Improved InfoPanel instance resolution for nested grids - Codebase is cleaner, more maintainable, and ready for further customization --- AyCode.Blazor.Components/.editorconfig | 11 + .../Components/Grids/MgGridBase.cs | 18 +- .../Components/Grids/MgGridInfoPanel.razor | 22 +- .../Components/Grids/MgGridInfoPanel.razor.cs | 5 + .../Grids/MgGridInfoPanel.razor.css | 123 +----- .../wwwroot/css/mg-grid-info-panel.css | 385 ++++++++++-------- 6 files changed, 265 insertions(+), 299 deletions(-) create mode 100644 AyCode.Blazor.Components/.editorconfig diff --git a/AyCode.Blazor.Components/.editorconfig b/AyCode.Blazor.Components/.editorconfig new file mode 100644 index 0000000..226fb7a --- /dev/null +++ b/AyCode.Blazor.Components/.editorconfig @@ -0,0 +1,11 @@ +root = true + +# CSS files +[*.css] +# Disable warnings for modern CSS features +css_disable_validation_warnings = true +css_schema_version = css3 + +# Allow container queries and modern CSS +css_container_queries = true +css_custom_properties = true diff --git a/AyCode.Blazor.Components/Components/Grids/MgGridBase.cs b/AyCode.Blazor.Components/Components/Grids/MgGridBase.cs index 351d706..fd290bf 100644 --- a/AyCode.Blazor.Components/Components/Grids/MgGridBase.cs +++ b/AyCode.Blazor.Components/Components/Grids/MgGridBase.cs @@ -112,12 +112,24 @@ public abstract class MgGridBase - /// InfoPanel instance for displaying row details (from wrapper or direct) + /// InfoPanel instance for displaying row details. + /// First checks own wrapper, then gets InfoPanel from root grid. /// public IInfoPanelBase? InfoPanelInstance { - get => GridWrapper?.InfoPanelInstance; - set { /* Set through wrapper */ } + get + { + // First check if we have a direct wrapper with InfoPanel + if (GridWrapper?.InfoPanelInstance != null) + return GridWrapper.InfoPanelInstance; + + // Get InfoPanel from root grid (handles nested grids) + var rootGrid = GetRootGrid(); + if (rootGrid != this) + return rootGrid.InfoPanelInstance; + + return null; + } } /// diff --git a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor index 734400d..243999e 100644 --- a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor +++ b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor @@ -6,7 +6,7 @@ @* Header *@ @if (HeaderTemplate != null) { - @HeaderTemplate(GetActiveDataItem()) + @HeaderTemplate(CreateContext()) } else if (_currentGrid != null) { @@ -27,12 +27,12 @@ { @if (BeforeColumnsTemplate != null) { - @BeforeColumnsTemplate(GetActiveDataItem()) + @BeforeColumnsTemplate(CreateContext()) } @if (ColumnsTemplate != null) { - @ColumnsTemplate(GetActiveDataItem()) + @ColumnsTemplate(CreateContext()) } else { @@ -41,7 +41,7 @@ @if (AfterColumnsTemplate != null) { - @AfterColumnsTemplate(GetActiveDataItem()) + @AfterColumnsTemplate(CreateContext()) } } else @@ -55,22 +55,24 @@ @* Footer *@ @if (FooterTemplate != null) { - @FooterTemplate(GetActiveDataItem()) + @FooterTemplate(CreateContext()) } @code { - [Parameter] public RenderFragment? HeaderTemplate { get; set; } - [Parameter] public RenderFragment? BeforeColumnsTemplate { get; set; } - [Parameter] public RenderFragment? ColumnsTemplate { get; set; } - [Parameter] public RenderFragment? AfterColumnsTemplate { get; set; } - [Parameter] public RenderFragment? FooterTemplate { get; set; } + [Parameter] public RenderFragment? HeaderTemplate { get; set; } + [Parameter] public RenderFragment? BeforeColumnsTemplate { get; set; } + [Parameter] public RenderFragment? ColumnsTemplate { get; set; } + [Parameter] public RenderFragment? AfterColumnsTemplate { get; set; } + [Parameter] public RenderFragment? FooterTemplate { get; set; } /// /// Called when the data item changes (row selection changed) /// [Parameter] public EventCallback OnDataItemChanged { get; set; } + private InfoPanelContext CreateContext() => new(GetActiveDataItem(), _isEditMode); + private string GetColumnCountClass() => FixedColumnCount switch { 1 => "mg-columns-1", diff --git a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.cs b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.cs index ab90d50..4f497ba 100644 --- a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.cs +++ b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.cs @@ -14,6 +14,11 @@ public interface IInfoPanelBase void RefreshData(IMgGridBase grid, object? dataItem, int visibleIndex = -1); } +/// +/// Context for InfoPanel templates containing data item and edit mode state +/// +public record InfoPanelContext(object? DataItem, bool IsEditMode); + /// /// InfoPanel component for displaying and editing grid row details /// diff --git a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.css b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.css index 78839b3..3d0ae84 100644 --- a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.css +++ b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.css @@ -1,110 +1,34 @@ -/* Shared edit mode background color configuration - change only here */ +/* MgGridInfoPanel scoped styles - component-specific overrides only */ +/* Base styles are in wwwroot/css/mg-grid-info-panel.css */ + +/* Shared edit mode background color configuration */ /* Grid row background: #fffbeb (see MgGridBase.cs OnCustomizeElement) */ /* InfoPanel background: #fffbeb (see below .edit-mode) */ /* Border color: #f59e0b */ -/* Main panel - contained within splitter pane */ +/* Edit/View mode transitions and specific colors */ .mg-grid-info-panel { - container-type: inline-size; - container-name: infopanel; - background-color: var(--dxbl-bg-secondary, #f8f9fa); transition: background-color 0.3s ease, border-color 0.3s ease; - display: flex; - flex-direction: column; - overflow: hidden; - /* Prevent panel from pushing out the splitter */ - min-height: 0; - max-height: 100%; - /* Default breakpoints - can be overridden via style attribute */ - --mg-bp-2col: 500px; - --mg-bp-3col: 800px; - --mg-bp-4col: 1200px; -} - -.mg-grid-info-panel.edit-mode { - background-color: #fffbeb !important; - border-left: 3px solid #f59e0b !important; } .mg-grid-info-panel.view-mode { - background-color: #f8f9fa !important; + background-color: var(--DS-color-surface-neutral-subdued-rest, #f8f9fa) !important; border-left: 3px solid transparent !important; } -/* Content area - scrollable, takes remaining space */ -.mg-info-panel-content { - flex: 1 1 0; - overflow-y: auto; - overflow-x: hidden; - padding: 1rem; - min-height: 0; /* Critical for flex child to allow shrinking */ -} - -/* Grid layout with responsive column wrapping based on panel width */ -.mg-info-panel-grid { - display: grid; - grid-template-columns: 1fr; - gap: 0.75rem; -} - -/* Fixed column count classes - override responsive behavior */ -.mg-columns-1 .mg-info-panel-grid { - grid-template-columns: 1fr !important; -} - -.mg-columns-2 .mg-info-panel-grid { - grid-template-columns: repeat(2, 1fr) !important; -} - -.mg-columns-3 .mg-info-panel-grid { - grid-template-columns: repeat(3, 1fr) !important; -} - -.mg-columns-4 .mg-info-panel-grid { - grid-template-columns: repeat(4, 1fr) !important; -} - -/* Responsive layouts using container queries (when no fixed column count) */ -/* 1 column for narrow panels (< 2col breakpoint) - default above */ - -/* 2 columns for medium width */ -@container infopanel (min-width: 500px) { - .mg-grid-info-panel:not(.mg-columns-1):not(.mg-columns-2):not(.mg-columns-3):not(.mg-columns-4) .mg-info-panel-grid { - grid-template-columns: repeat(2, 1fr); - } -} - -/* 3 columns for wider panels */ -@container infopanel (min-width: 800px) { - .mg-grid-info-panel:not(.mg-columns-1):not(.mg-columns-2):not(.mg-columns-3):not(.mg-columns-4) .mg-info-panel-grid { - grid-template-columns: repeat(3, 1fr); - } -} - -/* 4 columns for very wide panels */ -@container infopanel (min-width: 1200px) { - .mg-grid-info-panel:not(.mg-columns-1):not(.mg-columns-2):not(.mg-columns-3):not(.mg-columns-4) .mg-info-panel-grid { - grid-template-columns: repeat(4, 1fr); - } -} - -.mg-info-panel-item { - min-width: 0; /* Prevent grid blowout */ -} - -/* Fallback styles */ +/* Fallback styles for info-panel-form (not in global CSS) */ .info-panel-form { width: 100%; } .info-panel-form .fw-semibold { font-weight: 600; - color: var(--dxbl-text-secondary, #495057); + color: var(--DS-color-content-neutral-subdued-rest, #495057); font-size: 0.875rem; } .info-panel-form .fw-semibold.text-primary { - color: var(--dxbl-primary, #0d6efd); + color: var(--DS-color-content-primary-default-rest, #0d6efd); } /* Text overflow handling - show ellipsis and full text in tooltip */ @@ -112,37 +36,12 @@ width: 100%; } - .info-panel-text-wrapper input[readonly] { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - } - -/* View mode value styling - matches DevExpress theme */ -.mg-info-panel-value { - padding: 0.375rem 0.75rem; - min-height: 2rem; - display: flex; - align-items: center; - justify-content: flex-start; - background-color: var(--dxbl-bg, #fff); - border: 1px solid var(--dxbl-border-color, #dee2e6); - border-radius: var(--dxbl-border-radius, 0.25rem); - font-size: var(--dxbl-font-size, 0.875rem); - color: var(--dxbl-text, #212529); - overflow: hidden; +.info-panel-text-wrapper input[readonly] { text-overflow: ellipsis; + overflow: hidden; white-space: nowrap; } -.mg-info-panel-value-numeric { - font-variant-numeric: tabular-nums; -} - .mg-info-panel-value-bool { /* Keep left aligned */ } - -.mg-info-panel-value-date { - font-variant-numeric: tabular-nums; -} diff --git a/AyCode.Blazor.Components/wwwroot/css/mg-grid-info-panel.css b/AyCode.Blazor.Components/wwwroot/css/mg-grid-info-panel.css index d2157e0..9fde37d 100644 --- a/AyCode.Blazor.Components/wwwroot/css/mg-grid-info-panel.css +++ b/AyCode.Blazor.Components/wwwroot/css/mg-grid-info-panel.css @@ -1,287 +1,324 @@ -/* MgGridInfoPanel styles - DevExpress theme compatible */ +/* MgGridInfoPanel styles - DevExpress Fluent theme compatible */ -/* Main panel - uses DevExpress theme variables */ +/* + DevExpress Fluent theme uses --DS-* CSS variables (Design System tokens). + These are defined on .dxbl-theme-fluent class and inherited by child elements. +*/ + +/* Main panel - uses DevExpress Design System variables */ .mg-grid-info-panel { - container-type: inline-size; - container-name: infopanel; - background-color: var(--dxbl-bg-secondary); - color: var(--dxbl-text); - font-family: var(--dxbl-font-family); - font-size: var(--dxbl-font-size); - display: flex; - flex-direction: column; - overflow: hidden; - min-height: 0; - max-height: 100%; - border-left: 1px solid var(--dxbl-border-color); + background-color: var(--DS-color-surface-neutral-subdued-rest, #f8f9fa); + color: var(--DS-color-content-neutral-default-rest, #212529); + font-family: var(--DS-font-family-sans-serif, inherit); + font-size: var(--DS-font-size-body-1, 14px); + display: flex; + flex-direction: column; + overflow: hidden; + min-height: 0; + max-height: 100%; + border: 1px solid var(--DS-color-border-neutral-default-rest, #dee2e6); } -.mg-grid-info-panel.edit-mode { - background-color: var(--dxbl-warning-bg, #fffbeb); - border-left: 3px solid var(--dxbl-warning, #f59e0b); + .mg-grid-info-panel.edit-mode { + background-color: var(--DS-color-surface-warning-subdued-rest, #fffbeb); + border: 1px solid var(--DS-color-border-neutral-default-rest, #dee2e6); + border-left: 3px solid var(--DS-color-border-warning-default-rest, #f59e0b); + } + +/* Container queries support - progressive enhancement */ +@supports (container-type: inline-size) { + .mg-grid-info-panel { + container-type: inline-size; + container-name: infopanel; + } } /* Header styling */ .mg-grid-info-panel .mg-info-panel-header { - padding: var(--dxbl-spacer-sm) var(--dxbl-spacer); - background-color: var(--dxbl-bg); - border-bottom: 1px solid var(--dxbl-border-color); - font-weight: 600; + padding: var(--DS-sizing-80, 0.5rem) var(--DS-sizing-160, 1rem); + background-color: var(--DS-color-surface-neutral-default-rest, #ffffff); + border-bottom: 1px solid var(--DS-color-border-neutral-default-rest, #dee2e6); + font-weight: var(--DS-font-weight-subtitle-2, 600); } /* Toolbar styling */ .mg-info-panel-toolbar { - padding: var(--dxbl-spacer-xs) var(--dxbl-spacer-sm); - background-color: var(--dxbl-bg); - border-bottom: 1px solid var(--dxbl-border-color); + padding: var(--DS-sizing-40, 0.25rem) var(--DS-sizing-80, 0.5rem); + background-color: var(--DS-color-surface-neutral-default-rest, #ffffff); + border-bottom: 1px solid var(--DS-color-border-neutral-default-rest, #dee2e6); } /* Content area - scrollable */ .mg-info-panel-content { - flex: 1 1 0; - overflow-y: auto; - overflow-x: hidden; - padding: var(--dxbl-spacer); - min-height: 0; + flex: 1 1 0; + overflow-y: auto; + overflow-x: hidden; + padding: var(--DS-sizing-160, 1rem); + min-height: 0; } /* Grid layout for columns */ .mg-info-panel-grid { - display: grid; - grid-template-columns: 1fr; - gap: var(--dxbl-spacer-sm); + display: grid; + grid-template-columns: 1fr; + gap: var(--DS-sizing-80, 0.5rem); } /* Fixed column count classes */ -.mg-columns-1 .mg-info-panel-grid { grid-template-columns: 1fr !important; } -.mg-columns-2 .mg-info-panel-grid { grid-template-columns: repeat(2, 1fr) !important; } -.mg-columns-3 .mg-info-panel-grid { grid-template-columns: repeat(3, 1fr) !important; } -.mg-columns-4 .mg-info-panel-grid { grid-template-columns: repeat(4, 1fr) !important; } +.mg-columns-1 .mg-info-panel-grid { + grid-template-columns: 1fr !important; +} + +.mg-columns-2 .mg-info-panel-grid { + grid-template-columns: repeat(2, 1fr) !important; +} + +.mg-columns-3 .mg-info-panel-grid { + grid-template-columns: repeat(3, 1fr) !important; +} + +.mg-columns-4 .mg-info-panel-grid { + grid-template-columns: repeat(4, 1fr) !important; +} /* Responsive layouts using container queries */ @container infopanel (min-width: 400px) { - .mg-grid-info-panel:not(.mg-columns-1):not(.mg-columns-2):not(.mg-columns-3):not(.mg-columns-4) .mg-info-panel-grid { - grid-template-columns: repeat(2, 1fr); - } + .mg-grid-info-panel:not(.mg-columns-1):not(.mg-columns-2):not(.mg-columns-3):not(.mg-columns-4) .mg-info-panel-grid { + grid-template-columns: repeat(2, 1fr); + } } @container infopanel (min-width: 800px) { - .mg-grid-info-panel:not(.mg-columns-1):not(.mg-columns-2):not(.mg-columns-3):not(.mg-columns-4) .mg-info-panel-grid { - grid-template-columns: repeat(3, 1fr); - } + .mg-grid-info-panel:not(.mg-columns-1):not(.mg-columns-2):not(.mg-columns-3):not(.mg-columns-4) .mg-info-panel-grid { + grid-template-columns: repeat(3, 1fr); + } } @container infopanel (min-width: 1300px) { - .mg-grid-info-panel:not(.mg-columns-1):not(.mg-columns-2):not(.mg-columns-3):not(.mg-columns-4) .mg-info-panel-grid { - grid-template-columns: repeat(4, 1fr); - } + .mg-grid-info-panel:not(.mg-columns-1):not(.mg-columns-2):not(.mg-columns-3):not(.mg-columns-4) .mg-info-panel-grid { + grid-template-columns: repeat(4, 1fr); + } } /* Grid item */ .mg-info-panel-item { - min-width: 0; + min-width: 0; } /* Label styling */ .mg-info-panel-label { - display: block; - margin-bottom: var(--dxbl-spacer-xs); - font-size: calc(var(--dxbl-font-size) * 0.875); - font-weight: 600; - color: var(--dxbl-text-secondary); + display: block; + margin-bottom: var(--DS-sizing-40, 0.25rem); + font-size: var(--DS-font-size-caption-1, 12px); + font-weight: var(--DS-font-weight-caption-1-strong, 600); + color: var(--DS-color-content-neutral-subdued-rest, #6c757d); } -.mg-info-panel-label.editable { - color: var(--dxbl-primary); -} + .mg-info-panel-label.editable { + color: var(--DS-color-content-primary-default-rest, #0d6efd); + } /* View mode value styling */ .mg-info-panel-value { - display: block; - padding: var(--dxbl-spacer-xs) 0; - color: var(--dxbl-text); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + display: block; + padding: var(--DS-sizing-40, 0.25rem) 0; + color: var(--DS-color-content-neutral-default-rest, #212529); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .mg-info-panel-value-numeric { - font-variant-numeric: tabular-nums; + font-variant-numeric: tabular-nums; } .mg-info-panel-value-date { - font-variant-numeric: tabular-nums; + font-variant-numeric: tabular-nums; } /* Empty state */ .mg-info-panel-empty { - display: flex; - align-items: center; - justify-content: center; - height: 100%; - color: var(--dxbl-text-muted); - padding: var(--dxbl-spacer-lg); - text-align: center; + display: flex; + align-items: center; + justify-content: center; + height: 100%; + color: var(--DS-color-content-neutral-subdued-disabled, #adb5bd); + padding: var(--DS-sizing-240, 1.5rem); + text-align: center; } /* ======================================== Tables inside info panel - Default Base Styling - Auto-responsive table layout that fits container width - Can be overridden with inline styles if needed ======================================== */ .mg-info-panel-content table { - width: 100%; - max-width: 100%; - table-layout: fixed; - border-collapse: collapse; - font-size: var(--dxbl-font-size); - color: var(--dxbl-text); - margin-bottom: var(--dxbl-spacer); + width: 100%; + max-width: 100%; + table-layout: fixed; + border-collapse: collapse; + font-size: var(--DS-font-size-body-1, 14px); + color: var(--DS-color-content-neutral-default-rest, #212529); + margin-bottom: var(--DS-sizing-160, 1rem); } -.mg-info-panel-content table th, -.mg-info-panel-content table td { - padding: var(--dxbl-spacer-xs) var(--dxbl-spacer-sm); - border: 1px solid var(--dxbl-border-color); - text-align: left; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - vertical-align: middle; -} + .mg-info-panel-content table th, + .mg-info-panel-content table td { + padding: var(--DS-sizing-40, 0.25rem) var(--DS-sizing-80, 0.5rem); + border: 1px solid var(--DS-color-border-neutral-default-rest, #dee2e6); + text-align: left; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: middle; + } -.mg-info-panel-content table th { - background-color: var(--dxbl-bg-secondary); - font-weight: 600; - color: var(--dxbl-text-secondary); -} + .mg-info-panel-content table th { + background-color: var(--DS-color-surface-neutral-subdued-rest, #f8f9fa); + font-weight: var(--DS-font-weight-body-1-strong, 600); + color: var(--DS-color-content-neutral-subdued-rest, #6c757d); + } -.mg-info-panel-content table tbody tr:nth-child(odd) { - background-color: var(--dxbl-bg); -} + .mg-info-panel-content table tbody tr:nth-child(odd) { + background-color: var(--DS-color-surface-neutral-default-rest, #ffffff); + } -.mg-info-panel-content table tbody tr:nth-child(even) { - background-color: var(--dxbl-bg-secondary); -} + .mg-info-panel-content table tbody tr:nth-child(even) { + background-color: var(--DS-color-surface-neutral-subdued-rest, #f8f9fa); + } -.mg-info-panel-content table tbody tr:hover { - background-color: var(--dxbl-row-hover-bg); -} + .mg-info-panel-content table tbody tr:hover { + background-color: var(--DS-color-surface-neutral-default-hovered, #f5f5f5); + } /* Responsive: make table more compact on smaller screens */ @media (max-width: 768px) { - .mg-info-panel-content table { - font-size: 0.875rem; - } + .mg-info-panel-content table { + font-size: 0.875rem; + } - .mg-info-panel-content table th, - .mg-info-panel-content table td { - padding: 0.375rem; - } + .mg-info-panel-content table th, + .mg-info-panel-content table td { + padding: 0.375rem; + } } -/* Splitter pane styling */ +/* Splitter pane styling - no padding/margin */ .mg-grid-with-info-panel { - height: 100%; + height: 100%; + /* Override DevExpress splitter pane padding variables */ + --dxbl-splitter-pane-padding-x: 0; + --dxbl-splitter-pane-padding-y: 0; + --dxbl-splitter-pane-padding-x-s: 0; + --dxbl-splitter-pane-padding-x-m: 0; + --dxbl-splitter-pane-padding-x-l: 0; + --dxbl-splitter-pane-padding-y-s: 0; + --dxbl-splitter-pane-padding-y-m: 0; + --dxbl-splitter-pane-padding-y-l: 0; +} + +.mg-grid-with-info-panel > .dxbl-splitter-pane { + padding: 0 !important; + margin: 0; } .mg-info-panel-pane { - background-color: var(--dxbl-bg-secondary); + background-color: var(--DS-color-surface-neutral-subdued-rest, #f8f9fa); + padding: 0 !important; + margin: 0; } /* Fullscreen overlay styling (Bootstrap 5 based) */ .mg-fullscreen-overlay { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - width: 100vw; - height: 100vh; - z-index: 1050; - background-color: var(--dxbl-bg, #fff); - display: flex; - flex-direction: column; - overflow: hidden; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + width: 100vw; + height: 100vh; + z-index: 1050; + background-color: var(--DS-color-surface-neutral-default-rest, #ffffff); + display: flex; + flex-direction: column; + overflow: hidden; } .mg-fullscreen-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0.75rem 1rem; - background-color: var(--dxbl-primary, #0d6efd); - color: #fff; - border-bottom: 1px solid var(--dxbl-border-color); - flex-shrink: 0; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.75rem 1rem; + background-color: var(--DS-color-surface-primary-default-rest, #0d6efd); + color: var(--DS-color-content-neutral-static-inverted-rest, #fff); + border-bottom: 1px solid var(--DS-color-border-neutral-default-rest, #dee2e6); + flex-shrink: 0; } .mg-fullscreen-title { - font-size: 1.1rem; - font-weight: 600; - margin: 0; + font-size: var(--DS-font-size-subtitle-2, 1.1rem); + font-weight: var(--DS-font-weight-subtitle-2, 600); + margin: 0; } .mg-fullscreen-header .btn-close-white { - filter: brightness(0) invert(1); - opacity: 0.8; + filter: brightness(0) invert(1); + opacity: 0.8; } -.mg-fullscreen-header .btn-close-white:hover { - opacity: 1; -} + .mg-fullscreen-header .btn-close-white:hover { + opacity: 1; + } .mg-fullscreen-body { - flex: 1; - overflow: hidden; - display: flex; - flex-direction: column; + flex: 1; + overflow: hidden; + display: flex; + flex-direction: column; } -.mg-fullscreen-body .mg-grid-with-info-panel, -.mg-fullscreen-body .dxbl-grid { - flex: 1; - height: 100%; -} + .mg-fullscreen-body .mg-grid-with-info-panel, + .mg-fullscreen-body .dxbl-grid { + flex: 1; + height: 100%; + } /* Legacy DxWindow styling (kept for backwards compatibility) */ .mg-fullscreen-window { - position: fixed !important; - top: 0 !important; - left: 0 !important; - margin: 0 !important; - border-radius: 0 !important; + position: fixed !important; + top: 0 !important; + left: 0 !important; + margin: 0 !important; + border-radius: 0 !important; } -.mg-fullscreen-window .dxbl-window-body { - height: 100%; - overflow: hidden; - display: flex; - flex-direction: column; -} + .mg-fullscreen-window .dxbl-window-body { + height: 100%; + overflow: hidden; + display: flex; + flex-direction: column; + } .mg-fullscreen-content { - flex: 1; - height: 100%; - overflow: hidden; - display: flex; - flex-direction: column; + flex: 1; + height: 100%; + overflow: hidden; + display: flex; + flex-direction: column; } -.mg-fullscreen-content .mg-grid-with-info-panel, -.mg-fullscreen-content .dxbl-grid { - flex: 1; - height: 100%; -} + .mg-fullscreen-content .mg-grid-with-info-panel, + .mg-fullscreen-content .dxbl-grid { + flex: 1; + height: 100%; + } /* Fullscreen icon classes */ .grid-fullscreen::before { - content: "\e90c"; - font-family: 'devextreme-icons'; + content: "\e90c"; + font-family: 'devextreme-icons'; } .grid-fullscreen-exit::before { - content: "\e90d"; - font-family: 'devextreme-icons'; + content: "\e90d"; + font-family: 'devextreme-icons'; }