diff --git a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor index dc91d4a..0dbb3b0 100644 --- a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor +++ b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor @@ -2,7 +2,8 @@ @using Microsoft.AspNetCore.Components.Rendering @using System.Reflection -
+
@* Header *@ @if (HeaderTemplate != null) { @@ -90,6 +91,27 @@ /// [Parameter] public RenderFragment? FooterTemplate { get; set; } + private string GetColumnCountClass() + { + if (FixedColumnCount.HasValue) + { + return FixedColumnCount.Value switch + { + 1 => "mg-columns-1", + 2 => "mg-columns-2", + 3 => "mg-columns-3", + 4 => "mg-columns-4", + _ => "" + }; + } + return ""; + } + + private string GetBreakpointStyles() + { + return $"--mg-bp-2col: {TwoColumnBreakpoint}px; --mg-bp-3col: {ThreeColumnBreakpoint}px; --mg-bp-4col: {FourColumnBreakpoint}px;"; + } + private RenderFragment RenderDefaultColumns() => builder => { var dataItem = GetActiveDataItem()!; @@ -516,8 +538,8 @@ { var seq = 0; - // View mode: simple text display with DevExpress-like styling (no editors) - builder.OpenElement(seq++, "div"); + // View mode: simple span display with DevExpress theme styling + builder.OpenElement(seq++, "span"); builder.AddAttribute(seq++, "class", GetViewModeCssClass(value, settingsType)); builder.AddAttribute(seq++, "title", displayText); @@ -539,7 +561,7 @@ private static string GetViewModeCssClass(object? value, EditSettingsType settingsType) { - var baseCss = "mg-info-panel-value"; + var baseCss = "mg-info-panel-value text-body"; return value switch { diff --git a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.cs b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.cs index 97d4ae0..e59848b 100644 --- a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.cs +++ b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.cs @@ -26,6 +26,26 @@ public partial class MgGridInfoPanel : ComponentBase, IAsyncDisposable, IInfoPan /// [Parameter] public bool ShowReadOnlyFieldsInEditMode { get; set; } = false; + /// + /// Minimum width for 2 columns layout. Default is 500px. + /// + [Parameter] public int TwoColumnBreakpoint { get; set; } = 400; + + /// + /// Minimum width for 3 columns layout. Default is 800px. + /// + [Parameter] public int ThreeColumnBreakpoint { get; set; } = 800; + + /// + /// Minimum width for 4 columns layout. Default is 1200px. + /// + [Parameter] public int FourColumnBreakpoint { get; set; } = 1300; + + /// + /// Fixed column count. If set (1-4), overrides responsive breakpoints. Default is null (responsive). + /// + [Parameter] public int? FixedColumnCount { get; set; } + /// /// Reference to the wrapper component - automatically registers this InfoPanel /// diff --git a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.css b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.css index b070bc9..78839b3 100644 --- a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.css +++ b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.css @@ -3,11 +3,6 @@ /* InfoPanel background: #fffbeb (see below .edit-mode) */ /* Border color: #f59e0b */ -/* Breakpoint configuration - CHANGE ONLY THESE VALUES */ -/* 2 column breakpoint: 500px */ -/* 3 column breakpoint: 800px */ -/* 4 column breakpoint: 1200px (for 1920px+ screens) */ - /* Main panel - contained within splitter pane */ .mg-grid-info-panel { container-type: inline-size; @@ -20,6 +15,10 @@ /* 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 { @@ -48,30 +47,43 @@ gap: 0.75rem; } -/* 1 column for narrow panels (< 500px) */ -@container infopanel (max-width: 499px) { - .mg-info-panel-grid { - grid-template-columns: 1fr; - } +/* Fixed column count classes - override responsive behavior */ +.mg-columns-1 .mg-info-panel-grid { + grid-template-columns: 1fr !important; } -/* 2 columns for medium width (500px - 799px) */ -@container infopanel (min-width: 500px) and (max-width: 799px) { - .mg-info-panel-grid { +.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 (800px - 1199px) */ -@container infopanel (min-width: 800px) and (max-width: 1199px) { - .mg-info-panel-grid { +/* 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 (>= 1200px, typically on 1920px+ screens) */ +/* 4 columns for very wide panels */ @container infopanel (min-width: 1200px) { - .mg-info-panel-grid { + .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); } } @@ -105,13 +117,14 @@ 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; /* Always align left */ + 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); diff --git a/AyCode.Blazor.Components/wwwroot/css/mg-grid-info-panel.css b/AyCode.Blazor.Components/wwwroot/css/mg-grid-info-panel.css new file mode 100644 index 0000000..2c15dfa --- /dev/null +++ b/AyCode.Blazor.Components/wwwroot/css/mg-grid-info-panel.css @@ -0,0 +1,117 @@ +/* MgGridInfoPanel styles - Global CSS for proper container query support */ + +/* Main panel - contained within splitter pane */ +.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; + min-height: 0; + max-height: 100%; +} + +.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; + 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; +} + +/* 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 */ +/* 2 columns for medium width (>= 400px) */ +@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); + } +} + +/* 3 columns for wider panels (>= 800px) */ +@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 (>= 1300px) */ +@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-info-panel-item { + min-width: 0; +} + +/* Toolbar styling */ +.mg-info-panel-toolbar { + padding: 0.25rem 0.5rem; + background-color: var(--dxbl-bg, #fff); +} + +/* View mode value styling - simple span with DevExpress theme */ +.mg-info-panel-value { + display: block; + padding: 0.25rem 0; + font-size: var(--dxbl-font-size, 0.875rem); + color: var(--dxbl-text, #212529); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.mg-info-panel-value-numeric { + font-variant-numeric: tabular-nums; +} + +.mg-info-panel-value-date { + font-variant-numeric: tabular-nums; +} + +/* Splitter pane styling */ +.mg-grid-with-info-panel { + height: 100%; +} + +.mg-info-panel-pane { + background-color: var(--dxbl-bg-secondary, #f8f9fa); +}