From cf077c5c4491b638f18e2d2a9ed7a66c2b0b499b Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 31 Aug 2026 13:41:41 +0530 Subject: [PATCH 01/14] Add version tags, update nav, and improve form docs Added [AddedVersion] to all form inputs. Updated navigation IDs and order for "Forms" and "Components" in layouts. Refreshed screenshot URLs for several inputs. Updated all demo/doc links to new /demos/ route. Improved SplitView docs and added OTPInput docs. Adjusted sidebar positions and ensured correct version context in doc tables. Clarified content and accessibility in file input docs. Made minor text improvements throughout documentation. --- .../Layout/DemosMainLayout.razor.cs | 14 +-- .../Components/Layout/DocsMainLayout.razor.cs | 10 +- .../SplitView/SplitViewDocumentation.razor | 2 +- ...ndDropFileInput_Doc_01_Documentation.razor | 2 +- .../FileInput_Doc_01_Documentation.razor | 2 +- .../OTPInput_Doc_01_Documentation.razor | 2 +- .../RichTextEditor_Doc_01_Documentation.razor | 4 +- .../DocxTable/DocxEventCallbackRow.razor.cs | 5 +- .../Shared/DocxTable/DocxTable.razor | 6 +- .../Constants/DemoScreenshotSrcConstants.cs | 3 + .../Form/AutoComplete/AutoComplete.razor.cs | 1 + .../Form/CheckboxInput/CheckboxInput.razor.cs | 1 + .../Form/CurrencyInput/CurrencyInput.razor.cs | 1 + .../Form/DateInput/DateInput.razor.cs | 1 + .../Form/EnumInput/EnumInput.razor.cs | 1 + .../Form/NumberInput/NumberInput.razor.cs | 1 + .../Form/PasswordInput/PasswordInput.razor.cs | 1 + .../Form/RadioInput/RadioInput.razor.cs | 1 + .../Form/RangeInput/RangeInput.razor.cs | 1 + .../Components/Form/Switch/Switch.razor.cs | 1 + .../Form/TextAreaInput/TextAreaInput.razor.cs | 1 + .../Form/TextInput/TextInput.razor.cs | 1 + .../Form/TimeInput/TimeInput.razor.cs | 1 + docs/blog/2025-12-01-blazorbootstrap-4.0.0.md | 1 + .../04-forms/drag-and-drop-file-input.mdx | 12 +- docs/docs/04-forms/enum-input.mdx | 2 +- docs/docs/04-forms/file-input.mdx | 18 ++- docs/docs/04-forms/number-input.mdx | 2 +- docs/docs/04-forms/otp-input.mdx | 103 ++++++++++++++++++ docs/docs/04-forms/password-input.mdx | 2 +- docs/docs/04-forms/radio-input.mdx | 2 +- docs/docs/04-forms/range-input.mdx | 2 +- docs/docs/04-forms/rich-text-editor.mdx | 4 +- docs/docs/04-forms/switch.mdx | 2 +- docs/docs/04-forms/text-input.mdx | 2 +- docs/docs/04-forms/textarea-input.mdx | 2 +- docs/docs/04-forms/time-input.mdx | 2 +- docs/docs/05-components/carousel.mdx | 2 +- docs/docs/05-components/charts.mdx | 2 +- docs/docs/05-components/collapse.mdx | 2 +- docs/docs/05-components/confirm-dialog.mdx | 2 +- docs/docs/05-components/dropdown.mdx | 2 +- docs/docs/05-components/google-map.mdx | 2 +- docs/docs/05-components/grid.mdx | 2 +- docs/docs/05-components/markdown.mdx | 2 +- docs/docs/05-components/modal.mdx | 2 +- docs/docs/05-components/offcanvas.mdx | 2 +- docs/docs/05-components/pagination.mdx | 2 +- docs/docs/05-components/pdf-viewer.mdx | 2 +- docs/docs/05-components/placeholders.mdx | 2 +- docs/docs/05-components/preload.mdx | 2 +- docs/docs/05-components/progress.mdx | 2 +- docs/docs/05-components/ribbon.mdx | 2 +- docs/docs/05-components/script-loader.mdx | 2 +- docs/docs/05-components/sidebar.mdx | 2 +- docs/docs/05-components/sidebar2.mdx | 2 +- docs/docs/05-components/sortable-list.mdx | 2 +- docs/docs/05-components/spinners.mdx | 2 +- docs/docs/05-components/split-view.mdx | 26 ++--- docs/docs/05-components/tabs.mdx | 2 +- docs/docs/05-components/theme-switcher.mdx | 2 +- docs/docs/05-components/toasts.mdx | 2 +- docs/docs/05-components/tooltips.mdx | 2 +- 63 files changed, 213 insertions(+), 82 deletions(-) create mode 100644 docs/docs/04-forms/otp-input.mdx diff --git a/BlazorBootstrap.Demo.RCL/Components/Layout/DemosMainLayout.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Layout/DemosMainLayout.razor.cs index fee9c9793..2121bed2b 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Layout/DemosMainLayout.razor.cs +++ b/BlazorBootstrap.Demo.RCL/Components/Layout/DemosMainLayout.razor.cs @@ -9,8 +9,8 @@ internal override IEnumerable GetNavItems() new (){ Id = "1", Text = "Getting Started", Href = DemoRouteConstants.Demos_URL_GettingStarted, IconName = IconName.HouseDoorFill }, new (){ Id = "2", Text = "Layout", IconName = IconName.LayoutTextWindowReverse, IconColor = IconColor.Success }, - new (){ Id = "200", Text = "Blazor WebAssembly", Href = DemoRouteConstants.Demos_URL_Layout_BlazorWebAssembly, IconName = IconName.BrowserEdge, ParentId = "2" }, new (){ Id = "201", Text = "Blazor Server", Href = DemoRouteConstants.Demos_URL_Layout_Blazor_Server, IconName = IconName.Server, ParentId = "2" }, + new (){ Id = "200", Text = "Blazor WebAssembly", Href = DemoRouteConstants.Demos_URL_Layout_BlazorWebAssembly, IconName = IconName.BrowserEdge, ParentId = "2" }, new (){ Id = "3", Text = "Content", IconName = IconName.BodyText, IconColor = IconColor.Primary }, new (){ Id = "300", Text = "Icons", Href = DemoRouteConstants.Demos_URL_Icons, IconName = IconName.PersonSquare, ParentId = "3" }, @@ -21,20 +21,20 @@ internal override IEnumerable GetNavItems() new (){ Id = "401", Text = "Checkbox Input", Href = DemoRouteConstants.Demos_URL_CheckboxInput, IconName = IconName.CheckSquareFill, ParentId = "4" }, new (){ Id = "402", Text = "Currency Input", Href = DemoRouteConstants.Demos_URL_CurrencyInput, IconName = IconName.CurrencyDollar, ParentId = "4" }, new (){ Id = "403", Text = "Date Input", Href = DemoRouteConstants.Demos_URL_DateInput, IconName = IconName.CalendarDate, ParentId = "4" }, + new (){ Id = "415", Text = "Drag and Drop File Input", Href = DemoRouteConstants.Demos_URL_DragAndDropFileInput, IconName = IconName.FileEarmarkArrowUp, ParentId = "4" }, new (){ Id = "404", Text = "Enum Input", Href = DemoRouteConstants.Demos_URL_EnumInput, IconName = IconName.MenuButtonWideFill, ParentId = "4" }, new (){ Id = "414", Text = "File Input", Href = DemoRouteConstants.Demos_URL_FileInput, IconName = IconName.FileEarmarkArrowUp, ParentId = "4" }, - new (){ Id = "415", Text = "Drag and Drop File Input", Href = DemoRouteConstants.Demos_URL_DragAndDropFileInput, IconName = IconName.FileEarmarkArrowUp, ParentId = "4" }, new (){ Id = "405", Text = "Number Input", Href = DemoRouteConstants.Demos_URL_NumberInput, IconName = IconName.InputCursor, ParentId = "4" }, new (){ Id = "406", Text = "OTP Input", Href = DemoRouteConstants.Demos_URL_OTPInput, IconName = IconName.Asterisk, ParentId = "4" }, new (){ Id = "407", Text = "Password Input", Href = DemoRouteConstants.Demos_URL_PasswordInput, IconName = IconName.EyeSlashFill, ParentId = "4" }, new (){ Id = "408", Text = "Radio Input", Href = DemoRouteConstants.Demos_URL_RadioInput, IconName = IconName.RecordCircle, ParentId = "4" }, new (){ Id = "409", Text = "Range Input", Href = DemoRouteConstants.Demos_URL_RangeInput, IconName = IconName.Sliders, ParentId = "4" }, //new (){ Id = "404", Text = "Select Input", Href = DemoRouteConstants.Demos_URL_SelectInput, IconName = IconName.MenuButtonWideFill, ParentId = "4" }, + new (){ Id = "416", Text = "RichTextEditor", Href = DemoRouteConstants.Demos_URL_RichTextEditor, IconName = IconName.Type, ParentId = "4" }, new (){ Id = "410", Text = "Switch", Href = DemoRouteConstants.Demos_URL_Switch, IconName = IconName.ToggleOn, ParentId = "4" }, - new (){ Id = "411", Text = "Text Input", Href = DemoRouteConstants.Demos_URL_TextInput, IconName = IconName.InputCursorText, ParentId = "4" }, new (){ Id = "412", Text = "Text Area Input", Href = DemoRouteConstants.Demos_URL_TextAreaInput, IconName = IconName.InputCursorText, ParentId = "4" }, + new (){ Id = "411", Text = "Text Input", Href = DemoRouteConstants.Demos_URL_TextInput, IconName = IconName.InputCursorText, ParentId = "4" }, new (){ Id = "413", Text = "Time Input", Href = DemoRouteConstants.Demos_URL_TimeInput, IconName = IconName.ClockFill, ParentId = "4" }, - new (){ Id = "416", Text = "RichTextEditor", Href = DemoRouteConstants.Demos_URL_RichTextEditor, IconName = IconName.Type, ParentId = "4" }, new (){ Id = "5", Text = "Components", IconName = IconName.GearFill, IconColor = IconColor.Danger }, new (){ Id = "500", Text = "Accordion", Href = DemoRouteConstants.Demos_URL_Accordion, IconName = IconName.ChevronBarExpand, ParentId = "5" }, @@ -60,7 +60,7 @@ internal override IEnumerable GetNavItems() new (){ Id = "51304", Text = "Data Binding", Href = DemoRouteConstants.Demos_URL_Grid_DataBinding, IconName = IconName.GridFill, ParentId = "513" }, new (){ Id = "51306", Text = "Detail View", Href = DemoRouteConstants.Demos_URL_Grid_DetailView, IconName = IconName.ListNested, ParentId = "513" }, new (){ Id = "51307", Text = "Events", Href = DemoRouteConstants.Demos_URL_Grid_Events, IconName = IconName.LightningChargeFill, ParentId = "513" }, - new (){ Id = "51307", Text = "Filters", Href = DemoRouteConstants.Demos_URL_Grid_Filters, IconName = IconName.FunnelFill, ParentId = "513" }, + new (){ Id = "51317", Text = "Filters", Href = DemoRouteConstants.Demos_URL_Grid_Filters, IconName = IconName.FunnelFill, ParentId = "513" }, new (){ Id = "51308", Text = "Fixed Header", Href = DemoRouteConstants.Demos_URL_Grid_FixedHeader, IconName = IconName.Table, ParentId = "513" }, new (){ Id = "51309", Text = "Freeze Columns", Href = DemoRouteConstants.Demos_URL_Grid_FreezeColumns, IconName = IconName.LayoutThreeColumns, ParentId = "513" }, new (){ Id = "51310", Text = "Grid Settings", Href = DemoRouteConstants.Demos_URL_Grid_Settings, IconName = IconName.GearFill, ParentId = "513" }, @@ -75,7 +75,7 @@ internal override IEnumerable GetNavItems() #endregion Grid new (){ Id = "514", Text = "Markdown", Href = DemoRouteConstants.Demos_URL_Markdown, IconName = IconName.MarkdownFill, ParentId = "5" }, - new (){ Id = "514", Text = "Modals", Href = DemoRouteConstants.Demos_URL_Modal, IconName = IconName.WindowStack, ParentId = "5" }, + new (){ Id = "5145", Text = "Modals", Href = DemoRouteConstants.Demos_URL_Modal, IconName = IconName.WindowStack, ParentId = "5" }, new (){ Id = "515", Text = "Offcanvas", Href = DemoRouteConstants.Demos_URL_Offcanvas, IconName = IconName.LayoutSidebarReverse, ParentId = "5" }, new (){ Id = "516", Text = "Pagination", Href = DemoRouteConstants.Demos_URL_Pagination, IconName = IconName.ThreeDots, ParentId = "5" }, new (){ Id = "517", Text = "PDF Viewer", Href = DemoRouteConstants.Demos_URL_PDFViewer, IconName = IconName.FilePdfFill, ParentId = "5" }, @@ -86,9 +86,9 @@ internal override IEnumerable GetNavItems() new (){ Id = "522", Text = "Script Loader", Href = DemoRouteConstants.Demos_URL_ScriptLoader, IconName = IconName.CodeSlash, ParentId = "5" }, new (){ Id = "523", Text = "Sidebar", Href = DemoRouteConstants.Demos_URL_Sidebar, IconName = IconName.LayoutSidebar, ParentId = "5" }, new (){ Id = "524", Text = "Sidebar 2", Href = DemoRouteConstants.Demos_URL_Sidebar2, IconName = IconName.ListNested, ParentId = "5" }, - new (){ Id = "5245", Text = "Split View", Href = DemoRouteConstants.Demos_URL_SplitView, IconName = IconName.LayoutSplit, ParentId = "5" }, new (){ Id = "525", Text = "Sortable List", Href = DemoRouteConstants.Demos_URL_SortableList, IconName = IconName.ArrowsMove, ParentId = "5" }, new (){ Id = "526", Text = "Spinner", Href = DemoRouteConstants.Demos_URL_Spinners, IconName = IconName.ArrowRepeat, ParentId = "5" }, + new (){ Id = "5245", Text = "Split View", Href = DemoRouteConstants.Demos_URL_SplitView, IconName = IconName.LayoutSplit, ParentId = "5" }, new (){ Id = "527", Text = "Tabs", Href = DemoRouteConstants.Demos_URL_Tabs, IconName = IconName.WindowPlus, ParentId = "5" }, new (){ Id = "528", Text = "Theme Switcher", Href = DemoRouteConstants.Demos_URL_ThemeSwitcher, IconName = IconName.NintendoSwitch, ParentId = "5" }, new (){ Id = "529", Text = "Toasts", Href = DemoRouteConstants.Demos_URL_Toasts, IconName = IconName.ExclamationTriangleFill, ParentId = "5" }, diff --git a/BlazorBootstrap.Demo.RCL/Components/Layout/DocsMainLayout.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Layout/DocsMainLayout.razor.cs index 1a704d39f..5efd1fb9f 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Layout/DocsMainLayout.razor.cs +++ b/BlazorBootstrap.Demo.RCL/Components/Layout/DocsMainLayout.razor.cs @@ -20,20 +20,20 @@ internal override IEnumerable GetNavItems() new (){ Id = "401", Text = "Checkbox Input", Href = DemoRouteConstants.Docs_URL_CheckboxInput, IconName = IconName.CheckSquareFill, ParentId = "4" }, new (){ Id = "402", Text = "Currency Input", Href = DemoRouteConstants.Docs_URL_CurrencyInput, IconName = IconName.CurrencyDollar, ParentId = "4" }, new (){ Id = "403", Text = "Date Input", Href = DemoRouteConstants.Docs_URL_DateInput, IconName = IconName.CalendarDate, ParentId = "4" }, + new (){ Id = "415", Text = "Drag and Drop File Input", Href = DemoRouteConstants.Docs_URL_DragAndDropFileInput, IconName = IconName.FileEarmarkArrowUp, ParentId = "4" }, new (){ Id = "404", Text = "Enum Input", Href = DemoRouteConstants.Docs_URL_EnumInput, IconName = IconName.MenuButtonWideFill, ParentId = "4" }, new (){ Id = "414", Text = "File Input", Href = DemoRouteConstants.Docs_URL_FileInput, IconName = IconName.FileEarmarkArrowUp, ParentId = "4" }, - new (){ Id = "415", Text = "Drag and Drop File Input", Href = DemoRouteConstants.Docs_URL_DragAndDropFileInput, IconName = IconName.FileEarmarkArrowUp, ParentId = "4" }, new (){ Id = "405", Text = "Number Input", Href = DemoRouteConstants.Docs_URL_NumberInput, IconName = IconName.InputCursor, ParentId = "4" }, new (){ Id = "406", Text = "OTP Input", Href = DemoRouteConstants.Docs_URL_OTPInput, IconName = IconName.Asterisk, ParentId = "4" }, new (){ Id = "407", Text = "Password Input", Href = DemoRouteConstants.Docs_URL_PasswordInput, IconName = IconName.EyeSlashFill, ParentId = "4" }, new (){ Id = "408", Text = "Radio Input", Href = DemoRouteConstants.Docs_URL_RadioInput, IconName = IconName.RecordCircle, ParentId = "4" }, new (){ Id = "409", Text = "Range Input", Href = DemoRouteConstants.Docs_URL_RangeInput, IconName = IconName.Sliders, ParentId = "4" }, //new (){ Id = "404", Text = "Select Input", Href = DemoRouteConstants.Docs_URL_SelectInput, IconName = IconName.MenuButtonWideFill, ParentId = "4" }, + new (){ Id = "416", Text = "RichTextEditor", Href = DemoRouteConstants.Docs_URL_RichTextEditor, IconName = IconName.Type, ParentId = "4" }, new (){ Id = "410", Text = "Switch", Href = DemoRouteConstants.Docs_URL_Switch, IconName = IconName.ToggleOn, ParentId = "4" }, - new (){ Id = "411", Text = "Text Input", Href = DemoRouteConstants.Docs_URL_TextInput, IconName = IconName.InputCursorText, ParentId = "4" }, new (){ Id = "412", Text = "Text Area Input", Href = DemoRouteConstants.Docs_URL_TextAreaInput, IconName = IconName.InputCursorText, ParentId = "4" }, + new (){ Id = "411", Text = "Text Input", Href = DemoRouteConstants.Docs_URL_TextInput, IconName = IconName.InputCursorText, ParentId = "4" }, new (){ Id = "413", Text = "Time Input", Href = DemoRouteConstants.Docs_URL_TimeInput, IconName = IconName.ClockFill, ParentId = "4" }, - new (){ Id = "416", Text = "RichTextEditor", Href = DemoRouteConstants.Docs_URL_RichTextEditor, IconName = IconName.Type, ParentId = "4" }, new (){ Id = "5", Text = "Components", IconName = IconName.GearFill, IconColor = IconColor.Danger }, new (){ Id = "500", Text = "Accordion", Href = DemoRouteConstants.Docs_URL_Accordion, IconName = IconName.ChevronBarExpand, ParentId = "5" }, @@ -50,7 +50,7 @@ internal override IEnumerable GetNavItems() new (){ Id = "512", Text = "Google Map", Href = DemoRouteConstants.Docs_URL_GoogleMap, IconName = IconName.Map, ParentId = "5" }, new (){ Id = "513", Text = "Grid", Href = DemoRouteConstants.Docs_URL_Grid, IconName = IconName.Grid, ParentId = "5" }, new (){ Id = "514", Text = "Markdown", Href = DemoRouteConstants.Docs_URL_Markdown, IconName = IconName.MarkdownFill, ParentId = "5" }, - new (){ Id = "514", Text = "Modals", Href = DemoRouteConstants.Docs_URL_Modal, IconName = IconName.WindowStack, ParentId = "5" }, + new (){ Id = "5145", Text = "Modals", Href = DemoRouteConstants.Docs_URL_Modal, IconName = IconName.WindowStack, ParentId = "5" }, new (){ Id = "515", Text = "Offcanvas", Href = DemoRouteConstants.Docs_URL_Offcanvas, IconName = IconName.LayoutSidebarReverse, ParentId = "5" }, new (){ Id = "516", Text = "Pagination", Href = DemoRouteConstants.Docs_URL_Pagination, IconName = IconName.ThreeDots, ParentId = "5" }, new (){ Id = "517", Text = "PDF Viewer", Href = DemoRouteConstants.Docs_URL_PDFViewer, IconName = IconName.FilePdfFill, ParentId = "5" }, @@ -61,9 +61,9 @@ internal override IEnumerable GetNavItems() new (){ Id = "522", Text = "Script Loader", Href = DemoRouteConstants.Docs_URL_ScriptLoader, IconName = IconName.CodeSlash, ParentId = "5" }, new (){ Id = "523", Text = "Sidebar", Href = DemoRouteConstants.Docs_URL_Sidebar, IconName = IconName.LayoutSidebar, ParentId = "5" }, new (){ Id = "524", Text = "Sidebar 2", Href = DemoRouteConstants.Docs_URL_Sidebar2, IconName = IconName.ListNested, ParentId = "5" }, - new (){ Id = "5245", Text = "Split View", Href = DemoRouteConstants.Docs_URL_SplitView, IconName = IconName.LayoutSplit, ParentId = "5" }, new (){ Id = "525", Text = "Sortable List", Href = DemoRouteConstants.Docs_URL_SortableList, IconName = IconName.ArrowsMove, ParentId = "5" }, new (){ Id = "526", Text = "Spinner", Href = DemoRouteConstants.Docs_URL_Spinners, IconName = IconName.ArrowRepeat, ParentId = "5" }, + new (){ Id = "5245", Text = "Split View", Href = DemoRouteConstants.Docs_URL_SplitView, IconName = IconName.LayoutSplit, ParentId = "5" }, new (){ Id = "527", Text = "Tabs", Href = DemoRouteConstants.Docs_URL_Tabs, IconName = IconName.WindowPlus, ParentId = "5" }, new (){ Id = "528", Text = "Theme Switcher", Href = DemoRouteConstants.Docs_URL_ThemeSwitcher, IconName = IconName.NintendoSwitch, ParentId = "5" }, new (){ Id = "529", Text = "Toasts", Href = DemoRouteConstants.Docs_URL_Toasts, IconName = IconName.ExclamationTriangleFill, ParentId = "5" }, diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitViewDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitViewDocumentation.razor index df6b46b19..ee8e951e4 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitViewDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitViewDocumentation.razor @@ -89,7 +89,7 @@
- SplitView supports nested layouts, enabling IDE-style and dashboard-style workspaces. + SplitView supports nested layouts for IDE-style, dashboard-style, and app-shell workspaces with navigation, content, and inspector panes.
diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/DragAndDropFileInput/DragAndDropFileInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/DragAndDropFileInput/DragAndDropFileInput_Doc_01_Documentation.razor index 2dfc38b51..0a6a85ca7 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/DragAndDropFileInput/DragAndDropFileInput_Doc_01_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/DragAndDropFileInput/DragAndDropFileInput_Doc_01_Documentation.razor @@ -25,5 +25,5 @@ private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; private const string metaTitle = $"Blazor {componentName} Component"; private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; - private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Forms_Prefix; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_DragAndDropFileInput; } diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/FileInput/FileInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/FileInput/FileInput_Doc_01_Documentation.razor index d272d3d6c..e98cca97f 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/FileInput/FileInput_Doc_01_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/FileInput/FileInput_Doc_01_Documentation.razor @@ -25,5 +25,5 @@ private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; private const string metaTitle = $"Blazor {componentName} Component"; private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; - private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Forms_Prefix; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_FileInput; } diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/OTPInput/OTPInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/OTPInput/OTPInput_Doc_01_Documentation.razor index 1efb8d2cc..277421558 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/OTPInput/OTPInput_Doc_01_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/OTPInput/OTPInput_Doc_01_Documentation.razor @@ -33,5 +33,5 @@ private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; private const string metaTitle = $"Blazor {componentName} Component"; private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; - private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_NumberInput; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_OTPInput; } \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/RichTextEditor/RichTextEditor_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/RichTextEditor/RichTextEditor_Doc_01_Documentation.razor index 7341e8ee5..04d47ff1c 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/RichTextEditor/RichTextEditor_Doc_01_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/RichTextEditor/RichTextEditor_Doc_01_Documentation.razor @@ -5,7 +5,8 @@ PageTitle="@componentName" PageDescription="@pageDescription" MetaTitle="@metaTitle" - MetaDescription="@metaDescription" /> + MetaDescription="@metaDescription" + ImageUrl="@imageUrl" /> @@ -26,4 +27,5 @@ private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; private const string metaTitle = $"Blazor {componentName} Component"; private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_RichTextEditor; } diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEventCallbackRow.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEventCallbackRow.razor.cs index 077b0283a..5e2b27c9a 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEventCallbackRow.razor.cs +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEventCallbackRow.razor.cs @@ -6,7 +6,7 @@ /// public partial class DocxEventCallbackRow : BlazorBootstrapComponentBase { - private string AddedVersion => PropertyInfo.GetPropertyAddedVersion(); + private string AddedVersion => PropertyInfo.GetPropertyAddedVersion(VersionContextType); private string Description => PropertyInfo.GetPropertyDescription(); @@ -16,4 +16,7 @@ public partial class DocxEventCallbackRow : BlazorBootstrapComponentBase [Parameter] public PropertyInfo PropertyInfo { get; set; } = default!; + [Parameter] + public Type? VersionContextType { get; set; } + } diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxTable.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxTable.razor index 4a2a0f45b..f422166d3 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxTable.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxTable.razor @@ -20,7 +20,7 @@ @foreach (var propertyInfo in typeof(TItem).GetComponentParametersOnly()) { - + } @@ -64,7 +64,7 @@ @foreach (var methodInfo in typeof(TItem).GetComponentMethods()) { - + } @@ -85,7 +85,7 @@ @foreach (var propertyInfo in typeof(TItem).GetComponentEventCallbacks()) { - + } diff --git a/BlazorBootstrap.Demo.RCL/Constants/DemoScreenshotSrcConstants.cs b/BlazorBootstrap.Demo.RCL/Constants/DemoScreenshotSrcConstants.cs index 127097a7b..1a06c1222 100644 --- a/BlazorBootstrap.Demo.RCL/Constants/DemoScreenshotSrcConstants.cs +++ b/BlazorBootstrap.Demo.RCL/Constants/DemoScreenshotSrcConstants.cs @@ -23,12 +23,15 @@ public class DemoScreenshotSrcConstants public const string Demos_URL_CurrencyInput = DemoScreenshotSrcPrefix + "currency-input.png"; public const string Demos_URL_DateInput = DemoScreenshotSrcPrefix + "date-input.png"; public const string Demos_URL_EnumInput = DemoScreenshotSrcPrefix + "enum-input.png"; // TODO: pending + public const string Demos_URL_DragAndDropFileInput = DemoScreenshotSrcPrefix + "drag-and-drop-file-input.png"; public const string Demos_URL_NumberInput = DemoScreenshotSrcPrefix + "number-input.png"; + public const string Demos_URL_FileInput = DemoScreenshotSrcPrefix + "file-input.png"; public const string Demos_URL_OTPInput = DemoScreenshotSrcPrefix + "otp-input.png"; public const string Demos_URL_PasswordInput = DemoScreenshotSrcPrefix + "password-input.png"; public const string Demos_URL_RadioInput = DemoScreenshotSrcPrefix + "radio-input.png"; public const string Demos_URL_RangeInput = DemoScreenshotSrcPrefix + "range-input.png"; public const string Demos_URL_SelectInput = DemoScreenshotSrcPrefix + "select-input.png"; + public const string Demos_URL_RichTextEditor = DemoScreenshotSrcPrefix + "rich-text-editor.png"; public const string Demos_URL_Switch = DemoScreenshotSrcPrefix + "switch.png"; public const string Demos_URL_TextAreaInput = DemoScreenshotSrcPrefix + "textarea-input.png"; public const string Demos_URL_TextInput = DemoScreenshotSrcPrefix + "text-input.png"; diff --git a/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs b/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs index c549d569e..e226250bd 100644 --- a/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs +++ b/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("0.4.0")] public partial class AutoComplete : BlazorBootstrapComponentBase { #region Fields and Constants diff --git a/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs b/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs index 0c9588f8a..f29d4b3dc 100644 --- a/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs +++ b/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("3.3.0")] public partial class CheckboxInput : BlazorBootstrapComponentBase { #region Fields and Constants diff --git a/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs b/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs index 08d993584..fb1158a4f 100644 --- a/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs +++ b/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("1.0.0")] public partial class CurrencyInput : BlazorBootstrapComponentBase { #region Fields and Constants diff --git a/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs b/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs index 2c24410c5..14d95c216 100644 --- a/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs +++ b/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("1.5.0")] public partial class DateInput : BlazorBootstrapComponentBase { #region Fields and Constants diff --git a/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs b/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs index 50e3e57ba..7e34e0dac 100644 --- a/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs +++ b/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("3.5.0")] public partial class EnumInput : BlazorBootstrapComponentBase where TEnum : Enum { #region Fields and Constants diff --git a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs index a462d5abe..03001d511 100644 --- a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs +++ b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("1.0.0")] public partial class NumberInput : BlazorBootstrapComponentBase { #region Fields and Constants diff --git a/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs b/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs index 24d050c3d..a2a0d9a93 100644 --- a/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs +++ b/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("3.3.0")] public partial class PasswordInput : BlazorBootstrapComponentBase { #region Fields and Constants diff --git a/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs index 4fb9c4fb3..8e094ef64 100644 --- a/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs +++ b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("3.3.0")] public partial class RadioInput : BlazorBootstrapComponentBase { #region Fields and Constants diff --git a/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs b/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs index d3661c438..f792ac7e5 100644 --- a/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs +++ b/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs @@ -8,6 +8,7 @@ /// Supported types for TValue: sbyte, sbyte?, short, short?, int, int?, long, long?, float, float?, double, double?, /// decimal, decimal? /// +[AddedVersion("1.10.6")] public partial class RangeInput : BlazorBootstrapComponentBase { #region Fields and Constants diff --git a/blazorbootstrap/Components/Form/Switch/Switch.razor.cs b/blazorbootstrap/Components/Form/Switch/Switch.razor.cs index 38483c0bf..6a79b3ede 100644 --- a/blazorbootstrap/Components/Form/Switch/Switch.razor.cs +++ b/blazorbootstrap/Components/Form/Switch/Switch.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("1.3.0")] public partial class Switch : BlazorBootstrapComponentBase { #region Fields and Constants diff --git a/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs index e0ca5cfcd..a444151f0 100644 --- a/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs +++ b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("3.3.0")] public partial class TextAreaInput : BlazorBootstrapComponentBase { #region Fields and Constants diff --git a/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs b/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs index 2a03fe4e8..91eee5cc5 100644 --- a/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs +++ b/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("3.3.0")] public partial class TextInput : BlazorBootstrapComponentBase { #region Fields and Constants diff --git a/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs b/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs index 973814c2d..419886fea 100644 --- a/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs +++ b/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("1.6.0")] public partial class TimeInput : BlazorBootstrapComponentBase { #region Fields and Constants diff --git a/docs/blog/2025-12-01-blazorbootstrap-4.0.0.md b/docs/blog/2025-12-01-blazorbootstrap-4.0.0.md index 4168fdb13..42e34a27a 100644 --- a/docs/blog/2025-12-01-blazorbootstrap-4.0.0.md +++ b/docs/blog/2025-12-01-blazorbootstrap-4.0.0.md @@ -56,6 +56,7 @@ A resizable split-panel layout component that lets users drag a divider to resiz A one-time password (OTP) input component providing individual digit boxes and auto-advance behavior — ideal for verification code flows. - PR [#1238](https://github.com/vikramlearning/blazorbootstrap/pull/1238) +- Docs: [OTP Input](https://docs.blazorbootstrap.com/forms/otp-input) --- diff --git a/docs/docs/04-forms/drag-and-drop-file-input.mdx b/docs/docs/04-forms/drag-and-drop-file-input.mdx index e0a0e8c58..00375118a 100644 --- a/docs/docs/04-forms/drag-and-drop-file-input.mdx +++ b/docs/docs/04-forms/drag-and-drop-file-input.mdx @@ -2,7 +2,7 @@ title: Blazor Drag and Drop File Input Component description: The Blazor Bootstrap DragAndDropFileInput component supports desktop drag and drop with a touch-friendly native file-picker fallback. sidebar_label: Drag and Drop File Input -sidebar_position: 7 +sidebar_position: 5 --- import CarbonAd from '/carbon-ad.mdx' @@ -45,7 +45,7 @@ Drop a file onto the area in desktop browsers. On tablet and mobile touch browse ``` -[See demo here](https://demos.blazorbootstrap.com/form/drag-and-drop-file-input#basic-usage) +[See demo here](https://demos.blazorbootstrap.com/demos/form/drag-and-drop-file-input#basic-usage) ### Validation @@ -63,7 +63,7 @@ Drop a file onto the area in desktop browsers. On tablet and mobile touch browse } ``` -[See demo here](https://demos.blazorbootstrap.com/form/drag-and-drop-file-input#validation) +[See demo here](https://demos.blazorbootstrap.com/demos/form/drag-and-drop-file-input#validation) ### Validation message templates @@ -87,5 +87,11 @@ Use `BackgroundColor` to match the drop area to the surrounding Bootstrap interf ``` ## Accessibility +### Form validation + +`DragAndDropFileInput` participates in an `EditForm` and retains the same validation behavior whether files are dropped or selected through the native picker. + +[See demo here](https://demos.blazorbootstrap.com/demos/form/drag-and-drop-file-input#form-validation) + The native file input is visually hidden within the drop area but remains the selection control. It is therefore operable through touch, pointer, and keyboard activation. DragAndDropFileInput announces validation errors through an alert region, and each selected file has an accessible, keyboard-operable remove button. diff --git a/docs/docs/04-forms/enum-input.mdx b/docs/docs/04-forms/enum-input.mdx index b5eb999db..be641705e 100644 --- a/docs/docs/04-forms/enum-input.mdx +++ b/docs/docs/04-forms/enum-input.mdx @@ -4,7 +4,7 @@ description: The Blazor Bootstrap EnumInput component renders a dropdown list fr image: https://private-user-images.githubusercontent.com/2337067/517874250-8a624590-1dfc-470a-8f9d-7636851d6c95.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NjM5MjAxNzEsIm5iZiI6MTc2MzkxOTg3MSwicGF0aCI6Ii8yMzM3MDY3LzUxNzg3NDI1MC04YTYyNDU5MC0xZGZjLTQ3MGEtOGY5ZC03NjM2ODUxZDZjOTUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MTEyMyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTExMjNUMTc0NDMxWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZmVlNDlmZDZkNGQ5ZWUxMjE5MGM3NmEzMzc2OTdhYzk0MjY4YTU3NTk5M2JmMGIxNDNkYjI0ZWYyM2UwMDA5YyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.hvU9-57w9n41vwE3eyy3ZcDPDYXbQ3p_JW1RmDmT-c8 sidebar_label: Enum Input -sidebar_position: 5 +sidebar_position: 6 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/04-forms/file-input.mdx b/docs/docs/04-forms/file-input.mdx index c68961db5..c2d7c1de2 100644 --- a/docs/docs/04-forms/file-input.mdx +++ b/docs/docs/04-forms/file-input.mdx @@ -2,7 +2,7 @@ title: Blazor File Input Component description: The Blazor Bootstrap FileInput component provides a standard Bootstrap file control with validation, feedback, and removal. sidebar_label: File Input -sidebar_position: 6 +sidebar_position: 7 --- import CarbonAd from '/carbon-ad.mdx' @@ -45,7 +45,7 @@ Use the visible Bootstrap file control to open the native file picker. ``` -[See demo here](https://demos.blazorbootstrap.com/form/file-input#basic-usage) +[See demo here](https://demos.blazorbootstrap.com/demos/form/file-input#basic-usage) ### Multiple files and removal @@ -56,7 +56,7 @@ Set `Multiple` to show every accepted file. Each file has its own keyboard-acces HintText="Select multiple files and remove them individually." /> ``` -[See demo here](https://demos.blazorbootstrap.com/form/file-input#multiple-files-and-removal) +[See demo here](https://demos.blazorbootstrap.com/demos/form/file-input#multiple-files-and-removal) ### Validation @@ -74,7 +74,7 @@ Set `Multiple` to show every accepted file. Each file has its own keyboard-acces } ``` -[See demo here](https://demos.blazorbootstrap.com/form/file-input#validation) +[See demo here](https://demos.blazorbootstrap.com/demos/form/file-input#validation) ### Validation message templates @@ -103,7 +103,7 @@ Use an empty `AllowedFileTypes` collection when every extension is permitted. Ot } ``` -[See demo here](https://demos.blazorbootstrap.com/form/file-input#hint-text-and-unrestricted-extensions) +[See demo here](https://demos.blazorbootstrap.com/demos/form/file-input#hint-text-and-unrestricted-extensions) ### Sizes @@ -114,8 +114,14 @@ Use `Size` to apply Bootstrap's `form-control-lg` or `form-control-sm` classes. HintText="Large file input." /> ``` -[See demo here](https://demos.blazorbootstrap.com/form/file-input#sizes) +[See demo here](https://demos.blazorbootstrap.com/demos/form/file-input#sizes) ## Accessibility +### Form validation + +`FileInput` participates in an `EditForm` and reports file-selection validation errors alongside the form. + +[See demo here](https://demos.blazorbootstrap.com/demos/form/file-input#form-validation) + Provide a clear `AriaLabel` when the default label does not describe the expected files. FileInput announces validation errors through an alert region, and each selected file has an accessible, keyboard-operable remove button. For drag-and-drop with a touch-friendly native-picker fallback, use [DragAndDropFileInput](./drag-and-drop-file-input). diff --git a/docs/docs/04-forms/number-input.mdx b/docs/docs/04-forms/number-input.mdx index 42ac5da5e..8a7b85990 100644 --- a/docs/docs/04-forms/number-input.mdx +++ b/docs/docs/04-forms/number-input.mdx @@ -4,7 +4,7 @@ description: Blazor Bootstrap `NumberInput` component is built around HTML input image: https://i.imgur.com/iUNBkki.png sidebar_label: Number Input -sidebar_position: 6 +sidebar_position: 8 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/04-forms/otp-input.mdx b/docs/docs/04-forms/otp-input.mdx new file mode 100644 index 000000000..475921c31 --- /dev/null +++ b/docs/docs/04-forms/otp-input.mdx @@ -0,0 +1,103 @@ +--- +title: Blazor OTP Input Component +description: The Blazor Bootstrap OTPInput component provides a focused, keyboard-friendly interface for entering one-time passwords and verification codes. +sidebar_label: OTP Input +sidebar_position: 9 +--- + +import CarbonAd from '/carbon-ad.mdx' + +# Blazor OTPInput + +The Blazor Bootstrap `OTPInput` component presents a one-time password as separate numeric input fields. It supports keyboard navigation, paste distribution, change and completion callbacks, and clearing the entered code. + + + +Blazor Bootstrap OTPInput component + +## Parameters + +| Name | Type | Default | Description | Added Version | +|:--|:--|:--|:--|:--| +| ContainerCssClass | string? | null | CSS class applied to the element that contains the OTP fields. | 4.0.0 | +| ContainerCssStyle | string? | null | Inline CSS style applied to the element that contains the OTP fields. | 4.0.0 | +| Length | int | 6 | Number of numeric fields in the one-time password. | 4.0.0 | + +## Methods + +| Name | Description | Added Version | +|:--|:--|:--| +| ClearAsync() | Clears the OTP fields, publishes the updated value, and focuses the first field. | 4.0.0 | + +## Events + +| Name | Type | Description | Added Version | +|:--|:--|:--|:--| +| OnOTPChanged | EventCallback<string> | Fires whenever the entered OTP changes. | 4.0.0 | +| OnOTPCompleted | EventCallback<string> | Fires after every OTP field contains a digit. | 4.0.0 | + +## Examples + +### Basic usage + +Handle `OnOTPChanged` to observe the current value and `OnOTPCompleted` to submit or verify a complete code. + +```cshtml showLineNumbers + + +

Current value: @otp

+ +@code { + private string otp = string.Empty; + + private Task OnOtpChanged(string value) + { + otp = value; + return Task.CompletedTask; + } + + private Task OnOtpCompleted(string value) + { + otp = value; + return Task.CompletedTask; + } +} +``` + +[See demo here](https://demos.blazorbootstrap.com/demos/form/otp-input#how-it-works) + +### Custom length + +Set `Length` to the number of numeric characters required by the verification flow. Pasted digits fill the remaining fields from the active position. + +```cshtml showLineNumbers + + +@code { + private Task VerifyAsync(string code) + { + return Task.CompletedTask; + } +} +``` + +[See demo here](https://demos.blazorbootstrap.com/demos/form/otp-input#length) + +### Clear the code + +Use a component reference when a retry, resend, or cancel action needs to clear the entered code. + +```cshtml showLineNumbers + + + +@code { + private OTPInput otpInput = default!; + + private Task ClearAsync() => otpInput.ClearAsync(); +} +``` + +## Accessibility diff --git a/docs/docs/04-forms/password-input.mdx b/docs/docs/04-forms/password-input.mdx index 172d7711a..4547daa9d 100644 --- a/docs/docs/04-forms/password-input.mdx +++ b/docs/docs/04-forms/password-input.mdx @@ -4,7 +4,7 @@ description: The Blazor Bootstrap PasswordInput component is constructed using a image: https://i.imgur.com/0k1C2XS.png sidebar_label: Password Input -sidebar_position: 7 +sidebar_position: 10 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/04-forms/radio-input.mdx b/docs/docs/04-forms/radio-input.mdx index 1dbb2bbbf..df1602fc7 100644 --- a/docs/docs/04-forms/radio-input.mdx +++ b/docs/docs/04-forms/radio-input.mdx @@ -4,7 +4,7 @@ description: The Blazor Bootstrap RadioInput component is constructed using an H image: https://i.imgur.com/8koE00q.png sidebar_label: Radio Input -sidebar_position: 8 +sidebar_position: 11 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/04-forms/range-input.mdx b/docs/docs/04-forms/range-input.mdx index 1334a5eef..dc74637c1 100644 --- a/docs/docs/04-forms/range-input.mdx +++ b/docs/docs/04-forms/range-input.mdx @@ -4,7 +4,7 @@ description: Blazor Bootstrap `NumberInput` component is built around HTML input image: https://i.imgur.com/rWDDHaf.png sidebar_label: Range Input -sidebar_position: 9 +sidebar_position: 12 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/04-forms/rich-text-editor.mdx b/docs/docs/04-forms/rich-text-editor.mdx index 88470d50a..39fef19b1 100644 --- a/docs/docs/04-forms/rich-text-editor.mdx +++ b/docs/docs/04-forms/rich-text-editor.mdx @@ -62,7 +62,7 @@ Use `Disabled` as the sole inactive-state parameter. When it is `true`, the edit ## Demo walkthrough -The [RichTextEditor demo](https://demos.blazorbootstrap.com/rich-text-editor) keeps seven scenarios in order: Full toolbar, Article draft, Publish rich update, Host-controlled image upload, Disabled, Form validation, and Events. Each scenario includes a short explanation and ordered `How to use` steps before its runnable source. +The [RichTextEditor demo](https://demos.blazorbootstrap.com/demos/form/rich-text-editor) keeps seven scenarios in order: Full toolbar, Article draft, Publish rich update, Host-controlled image upload, Disabled, Form validation, and Events. Each scenario includes a short explanation and ordered `How to use` steps before its runnable source. ## Host-controlled image upload @@ -99,7 +99,7 @@ The default limit is 5 MB. Supported raster formats are JPEG (`.jpg`/`.jpeg`), P Set `AllowedImageDomains` when returned image URLs must come from specific HTTPS domains; subdomains are accepted. The component rejects non-HTTPS URLs, URLs containing credentials, returned URLs outside the configured allow-list, and images that fail to load in the preview. Closing the dialog or starting a newer upload cancels the earlier callback safely. Handler failures, cancellation, and rejected URLs remain visible feedback states rather than insertable images. -See the shared [host-controlled image upload demo](https://demos.blazorbootstrap.com/rich-text-editor#host-controlled-image-upload) for successful, failed, cancelled, and off-policy returned-URL flows. Its callback counter also demonstrates that a file rejected before callback validation does not invoke the host handler. The same Demo RCL example is consumed by both the Server and WebAssembly demo hosts. +See the shared [host-controlled image upload demo](https://demos.blazorbootstrap.com/demos/form/rich-text-editor#host-controlled-image-upload) for successful, failed, cancelled, and off-policy returned-URL flows. Its callback counter also demonstrates that a file rejected before callback validation does not invoke the host handler. The same Demo RCL example is consumed by both the Server and WebAssembly demo hosts. Temporary preview uploads are a host concern: expire or clean up temporary objects if the author cancels or abandons the dialog, and promote them only after the application accepts the final content. The host must also sanitize persisted HTML before rendering it again. diff --git a/docs/docs/04-forms/switch.mdx b/docs/docs/04-forms/switch.mdx index 295546bdd..cb469c15f 100644 --- a/docs/docs/04-forms/switch.mdx +++ b/docs/docs/04-forms/switch.mdx @@ -4,7 +4,7 @@ description: Use the Blazor Bootstrap `Switch` component to show the consistent image: https://i.imgur.com/ALKzreq.png sidebar_label: Switch -sidebar_position: 10 +sidebar_position: 14 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/04-forms/text-input.mdx b/docs/docs/04-forms/text-input.mdx index b28c9a30f..2c09d5cd3 100644 --- a/docs/docs/04-forms/text-input.mdx +++ b/docs/docs/04-forms/text-input.mdx @@ -4,7 +4,7 @@ description: The Blazor Bootstrap TextInput component is constructed using an HT image: https://i.imgur.com/N2VUHIn.png sidebar_label: Text Input -sidebar_position: 11 +sidebar_position: 16 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/04-forms/textarea-input.mdx b/docs/docs/04-forms/textarea-input.mdx index 4b973d2f8..be870173d 100644 --- a/docs/docs/04-forms/textarea-input.mdx +++ b/docs/docs/04-forms/textarea-input.mdx @@ -4,7 +4,7 @@ description: The Blazor Bootstrap TextAreaInput component provides a multi-line image: https://i.imgur.com/aSVKMqv.png sidebar_label: TextArea Input -sidebar_position: 12 +sidebar_position: 15 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/04-forms/time-input.mdx b/docs/docs/04-forms/time-input.mdx index 3304d3c10..86757cfd0 100644 --- a/docs/docs/04-forms/time-input.mdx +++ b/docs/docs/04-forms/time-input.mdx @@ -4,7 +4,7 @@ description: The Blazor Bootstrap `TimeInput` component is constructed using an image: https://i.imgur.com/TlvjRlP.png sidebar_label: Time Input -sidebar_position: 13 +sidebar_position: 17 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/carousel.mdx b/docs/docs/05-components/carousel.mdx index a6eef0ecb..8b40af122 100644 --- a/docs/docs/05-components/carousel.mdx +++ b/docs/docs/05-components/carousel.mdx @@ -4,7 +4,7 @@ description: Blazor Carousel component is a slideshow component that cycles thro image: https://i.imgur.com/YoZd9Hy.png sidebar_label: Carousel -sidebar_position: 7 +sidebar_position: 8 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/charts.mdx b/docs/docs/05-components/charts.mdx index 7e7dd47f7..9affa39ba 100644 --- a/docs/docs/05-components/charts.mdx +++ b/docs/docs/05-components/charts.mdx @@ -4,7 +4,7 @@ description: BlazorBootstrap chart components have moved to the dedicated Blazor image: https://i.imgur.com/ATtFiUZ.png sidebar_label: Charts -sidebar_position: 8 +sidebar_position: 9 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/collapse.mdx b/docs/docs/05-components/collapse.mdx index 90ac5585d..f5ce43d32 100644 --- a/docs/docs/05-components/collapse.mdx +++ b/docs/docs/05-components/collapse.mdx @@ -4,7 +4,7 @@ description: Toggle the visibility of content across your project with the Blazo image: https://i.imgur.com/8A0emQe.png sidebar_label: Collapse -sidebar_position: 9 +sidebar_position: 10 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/confirm-dialog.mdx b/docs/docs/05-components/confirm-dialog.mdx index 01df286c5..12f1ae770 100644 --- a/docs/docs/05-components/confirm-dialog.mdx +++ b/docs/docs/05-components/confirm-dialog.mdx @@ -4,7 +4,7 @@ description: Use Blazor Bootstrap confirm dialog component if you want the user image: https://i.imgur.com/B5Hf85u.png sidebar_label: Confirm Dialog -sidebar_position: 10 +sidebar_position: 11 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/dropdown.mdx b/docs/docs/05-components/dropdown.mdx index e64c703b7..d24fe5718 100644 --- a/docs/docs/05-components/dropdown.mdx +++ b/docs/docs/05-components/dropdown.mdx @@ -4,7 +4,7 @@ description: Dropdowns are toggleable, contextual overlays for displaying lists image: https://i.imgur.com/beAr31J.png sidebar_label: Dropdown -sidebar_position: 11 +sidebar_position: 12 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/google-map.mdx b/docs/docs/05-components/google-map.mdx index 16c20e2d6..4864214ed 100644 --- a/docs/docs/05-components/google-map.mdx +++ b/docs/docs/05-components/google-map.mdx @@ -4,7 +4,7 @@ description: Blazor Bootstrap Google Map component will create maps to show loca image: https://i.imgur.com/beAr31J.png sidebar_label: Google Map -sidebar_position: 12 +sidebar_position: 13 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/grid.mdx b/docs/docs/05-components/grid.mdx index 59624a553..5fbb06c69 100644 --- a/docs/docs/05-components/grid.mdx +++ b/docs/docs/05-components/grid.mdx @@ -4,7 +4,7 @@ description: Use Blazor Bootstrap grid component to display tabular data from th image: https://i.imgur.com/kKNgo2I.png sidebar_label: Grid -sidebar_position: 13 +sidebar_position: 14 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/markdown.mdx b/docs/docs/05-components/markdown.mdx index 41951fba3..af4b13ba5 100644 --- a/docs/docs/05-components/markdown.mdx +++ b/docs/docs/05-components/markdown.mdx @@ -4,7 +4,7 @@ description: Use Blazor Bootstrap Markdown component to add formatting, tables, image: https://i.imgur.com/FhN1caj.png sidebar_label: Markdown -sidebar_position: 14 +sidebar_position: 15 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/modal.mdx b/docs/docs/05-components/modal.mdx index 829af77b4..af282d79d 100644 --- a/docs/docs/05-components/modal.mdx +++ b/docs/docs/05-components/modal.mdx @@ -4,7 +4,7 @@ description: Use Blazor Bootstrap modal component to add dialogs to your site fo image: https://i.imgur.com/tLiaEs6.jpg sidebar_label: Modal -sidebar_position: 14 +sidebar_position: 16 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/offcanvas.mdx b/docs/docs/05-components/offcanvas.mdx index ee6b6de1a..9e8144ad3 100644 --- a/docs/docs/05-components/offcanvas.mdx +++ b/docs/docs/05-components/offcanvas.mdx @@ -4,7 +4,7 @@ description: Build hidden sidebars into your project for navigation, shopping ca image: https://i.imgur.com/ev2Q8ON.jpg sidebar_label: Offcanvas -sidebar_position: 15 +sidebar_position: 17 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/pagination.mdx b/docs/docs/05-components/pagination.mdx index 585bdeb6a..eb840d9b7 100644 --- a/docs/docs/05-components/pagination.mdx +++ b/docs/docs/05-components/pagination.mdx @@ -4,7 +4,7 @@ description: Use Blazor Bootstrap pagination component to indicate a series of r image: https://i.imgur.com/SCbZVd4.jpg sidebar_label: Pagination -sidebar_position: 16 +sidebar_position: 18 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/pdf-viewer.mdx b/docs/docs/05-components/pdf-viewer.mdx index 38a27f9a9..1e668ea21 100644 --- a/docs/docs/05-components/pdf-viewer.mdx +++ b/docs/docs/05-components/pdf-viewer.mdx @@ -4,7 +4,7 @@ description: The Blazor PDF Viewer component allows users to view PDF files dire image: https://i.imgur.com/7Vz9Efi.png sidebar_label: PDF Viewer -sidebar_position: 17 +sidebar_position: 19 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/placeholders.mdx b/docs/docs/05-components/placeholders.mdx index d01e04743..5db8dab5e 100644 --- a/docs/docs/05-components/placeholders.mdx +++ b/docs/docs/05-components/placeholders.mdx @@ -4,7 +4,7 @@ description: Use Blazor Bootstrap loading placeholders for your components or pa image: https://i.imgur.com/Mw13qfX.png sidebar_label: Placeholders -sidebar_position: 18 +sidebar_position: 20 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/preload.mdx b/docs/docs/05-components/preload.mdx index dfe1c963d..3afbb8dbb 100644 --- a/docs/docs/05-components/preload.mdx +++ b/docs/docs/05-components/preload.mdx @@ -4,7 +4,7 @@ description: Indicate the loading state of a page with Blazor Bootstrap preload image: https://i.imgur.com/2cPuqFa.png sidebar_label: Preload -sidebar_position: 19 +sidebar_position: 21 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/progress.mdx b/docs/docs/05-components/progress.mdx index 27a337455..58a5a18e1 100644 --- a/docs/docs/05-components/progress.mdx +++ b/docs/docs/05-components/progress.mdx @@ -4,7 +4,7 @@ description: Documentation and examples for using the Blazor Bootstrap progress image: https://i.imgur.com/MK142lQ.png sidebar_label: Progress -sidebar_position: 20 +sidebar_position: 22 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/ribbon.mdx b/docs/docs/05-components/ribbon.mdx index 3d05d7062..72f9d4c01 100644 --- a/docs/docs/05-components/ribbon.mdx +++ b/docs/docs/05-components/ribbon.mdx @@ -4,7 +4,7 @@ description: Documentation and examples for using the Blazor Bootstrap Ribbon co image: https://i.imgur.com/LpZVLbF.png sidebar_label: Ribbon -sidebar_position: 21 +sidebar_position: 23 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/script-loader.mdx b/docs/docs/05-components/script-loader.mdx index e001f9fa1..e083c2f7a 100644 --- a/docs/docs/05-components/script-loader.mdx +++ b/docs/docs/05-components/script-loader.mdx @@ -4,7 +4,7 @@ description: Documentation and examples for using the Blazor Bootstrap Script Lo image: https://i.imgur.com/sBiYPeQ.png sidebar_label: Script Loader -sidebar_position: 22 +sidebar_position: 24 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/sidebar.mdx b/docs/docs/05-components/sidebar.mdx index 8d897726c..a53db212e 100644 --- a/docs/docs/05-components/sidebar.mdx +++ b/docs/docs/05-components/sidebar.mdx @@ -4,7 +4,7 @@ description: Use the Blazor Bootstrap Sidebar component to show consistent cross image: https://i.imgur.com/d91Q9Zt.png sidebar_label: Sidebar -sidebar_position: 23 +sidebar_position: 25 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/sidebar2.mdx b/docs/docs/05-components/sidebar2.mdx index 0bb26e1c7..986010789 100644 --- a/docs/docs/05-components/sidebar2.mdx +++ b/docs/docs/05-components/sidebar2.mdx @@ -4,7 +4,7 @@ description: Use the Blazor Bootstrap Sidebar2 component to display consistent, image: https://i.imgur.com/vs8kl7G.png sidebar_label: Sidebar2 -sidebar_position: 24 +sidebar_position: 26 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/sortable-list.mdx b/docs/docs/05-components/sortable-list.mdx index fce01c43e..57bec2e8c 100644 --- a/docs/docs/05-components/sortable-list.mdx +++ b/docs/docs/05-components/sortable-list.mdx @@ -4,7 +4,7 @@ description: The Blazor Bootstrap Sortable List component, built on top of Sorta image: https://i.imgur.com/bfzP8Yi.png sidebar_label: Sortable List -sidebar_position: 25 +sidebar_position: 27 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/spinners.mdx b/docs/docs/05-components/spinners.mdx index bf68434e2..6e6e0b3d1 100644 --- a/docs/docs/05-components/spinners.mdx +++ b/docs/docs/05-components/spinners.mdx @@ -4,7 +4,7 @@ description: Visualize the loading state of a component or page using the Blazor image: https://i.imgur.com/G4wyEd6.png sidebar_label: Spinners -sidebar_position: 26 +sidebar_position: 28 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/split-view.mdx b/docs/docs/05-components/split-view.mdx index 9bbb2b790..c53e7df0e 100644 --- a/docs/docs/05-components/split-view.mdx +++ b/docs/docs/05-components/split-view.mdx @@ -3,7 +3,7 @@ title: Blazor Split View Component description: The Blazor Bootstrap Split View component arranges two resizable panes horizontally or vertically with live drag updates. sidebar_label: Split View -sidebar_position: 26 +sidebar_position: 29 --- import CarbonAd from '/carbon-ad.mdx' @@ -80,7 +80,7 @@ The Blazor Bootstrap **Split View** component arranges two panes with a draggabl ``` -[See demo here.](https://demos.blazorbootstrap.com/split-view#pane-content) +[See demo here.](https://demos.blazorbootstrap.com/demos/split-view#pane-content) ### Orientation @@ -98,7 +98,7 @@ The Blazor Bootstrap **Split View** component arranges two panes with a draggabl ``` -[See demo here.](https://demos.blazorbootstrap.com/split-view#orientation) +[See demo here.](https://demos.blazorbootstrap.com/demos/split-view#orientation) ### PrimaryPaneSizeChanged @@ -120,7 +120,7 @@ The Blazor Bootstrap **Split View** component arranges two panes with a draggabl } ``` -[See demo here.](https://demos.blazorbootstrap.com/split-view#primary-pane-size-changed) +[See demo here.](https://demos.blazorbootstrap.com/demos/split-view#primary-pane-size-changed) ### Semantic Color @@ -138,7 +138,7 @@ The Blazor Bootstrap **Split View** component arranges two panes with a draggabl Hover and dragging states are derived automatically in shared CSS from the resolved base divider color. -[See demo here.](https://demos.blazorbootstrap.com/split-view#semantic-color) +[See demo here.](https://demos.blazorbootstrap.com/demos/split-view#semantic-color) ### CustomColor @@ -154,7 +154,7 @@ Hover and dragging states are derived automatically in shared CSS from the resol ``` -[See demo here.](https://demos.blazorbootstrap.com/split-view#custom-color) +[See demo here.](https://demos.blazorbootstrap.com/demos/split-view#custom-color) ### Resize events @@ -188,9 +188,9 @@ Hover and dragging states are derived automatically in shared CSS from the resol } ``` -[See demo here.](https://demos.blazorbootstrap.com/split-view#onresizestarted) -[See demo here.](https://demos.blazorbootstrap.com/split-view#onresized) -[See demo here.](https://demos.blazorbootstrap.com/split-view#onresizeended) +[See demo here.](https://demos.blazorbootstrap.com/demos/split-view#onresizestarted) +[See demo here.](https://demos.blazorbootstrap.com/demos/split-view#onresized) +[See demo here.](https://demos.blazorbootstrap.com/demos/split-view#onresizeended) ### Nested layouts @@ -216,10 +216,4 @@ Hover and dragging states are derived automatically in shared CSS from the resol ``` -[See demo here.](https://demos.blazorbootstrap.com/split-view#nested-layouts) - -### App shell layout - -You can combine multiple SplitView instances to build an app shell with navigation, content, and inspector panes. - -[See demo here.](https://demos.blazorbootstrap.com/split-view#app-shell) \ No newline at end of file +[See demo here.](https://demos.blazorbootstrap.com/demos/split-view#nested-layouts) diff --git a/docs/docs/05-components/tabs.mdx b/docs/docs/05-components/tabs.mdx index fd50827c7..f6840cb14 100644 --- a/docs/docs/05-components/tabs.mdx +++ b/docs/docs/05-components/tabs.mdx @@ -4,7 +4,7 @@ description: Documentation and examples for using Blazor Bootstrap Tabs componen image: https://i.imgur.com/KelXx6Z.png sidebar_label: Tabs -sidebar_position: 27 +sidebar_position: 30 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/theme-switcher.mdx b/docs/docs/05-components/theme-switcher.mdx index 87ea87e82..5a462e0ae 100644 --- a/docs/docs/05-components/theme-switcher.mdx +++ b/docs/docs/05-components/theme-switcher.mdx @@ -4,7 +4,7 @@ description: Documentation and examples for using Blazor Bootstrap Theme Switche image: https://i.imgur.com/2eixWho.png sidebar_label: Theme Switcher -sidebar_position: 28 +sidebar_position: 31 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/toasts.mdx b/docs/docs/05-components/toasts.mdx index 606c23fcd..8435bdb6c 100644 --- a/docs/docs/05-components/toasts.mdx +++ b/docs/docs/05-components/toasts.mdx @@ -4,7 +4,7 @@ description: Push notifications to your visitors with a toast, a lightweight and image: https://i.imgur.com/W1YkmJH.png sidebar_label: Toasts -sidebar_position: 29 +sidebar_position: 32 --- import CarbonAd from '/carbon-ad.mdx' diff --git a/docs/docs/05-components/tooltips.mdx b/docs/docs/05-components/tooltips.mdx index f597120ba..926863d2e 100644 --- a/docs/docs/05-components/tooltips.mdx +++ b/docs/docs/05-components/tooltips.mdx @@ -4,7 +4,7 @@ description: Use Blazor Bootstrap tooltip component to add custom tooltips to yo image: https://i.imgur.com/uqvqb2i.jpg sidebar_label: Tooltips -sidebar_position: 30 +sidebar_position: 33 --- import CarbonAd from '/carbon-ad.mdx' From f6d1603e3ce98993ae4098c072ab316f8adeb6f2 Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 31 Aug 2026 13:58:10 +0530 Subject: [PATCH 02/14] Enhance Blazor components with XML docs and metadata Add and improve XML documentation and metadata attributes (e.g., [AddedVersion], [Description], [DefaultValue]) for various Blazor components. Document and decorate public properties, especially [Parameter]s, to clarify usage, default values, and versioning. Introduce and document Disable()/Enable() methods for programmatic control. Update [JSInvokable] methods with XML docs. Improve ValueExpression property documentation and metadata. Refine property and event callback docs for better API clarity and maintainability. --- .../Form/AutoComplete/AutoComplete.razor.cs | 24 ++++++++++ .../Form/CheckboxInput/CheckboxInput.razor.cs | 24 +++++++++- .../Form/CurrencyInput/CurrencyInput.razor.cs | 47 ++++++++++++++++++- .../Form/DateInput/DateInput.razor.cs | 27 +++++++++++ .../Form/EnumInput/EnumInput.razor.cs | 29 ++++++++++++ .../Form/FileInput/FileInputBase.cs | 1 + .../Form/NumberInput/NumberInput.razor.cs | 39 ++++++++++++++- .../Form/PasswordInput/PasswordInput.razor.cs | 24 +++++++++- .../Form/RadioInput/RadioInput.razor.cs | 31 +++++++++++- .../Form/RangeInput/RangeInput.razor.cs | 35 +++++++++++++- .../RichTextEditor/RichTextEditor.razor.cs | 8 ++++ .../Components/Form/Switch/Switch.razor.cs | 26 +++++++++- .../Form/TextAreaInput/TextAreaInput.razor.cs | 34 +++++++++++++- .../Form/TextInput/TextInput.razor.cs | 30 +++++++++++- .../Form/TimeInput/TimeInput.razor.cs | 27 +++++++++++ 15 files changed, 397 insertions(+), 9 deletions(-) diff --git a/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs b/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs index e226250bd..850834e41 100644 --- a/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs +++ b/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs @@ -71,6 +71,11 @@ protected override async Task OnInitializedAsync() await base.OnInitializedAsync(); } + /// + /// Handles the autocomplete dropdown hidden notification from JavaScript. + /// + [Description("Handles the autocomplete dropdown hidden notification from JavaScript.")] + [AddedVersion("0.4.0")] [JSInvokable] public void bsHiddenAutocomplete() { @@ -85,12 +90,27 @@ public void bsHiddenAutocomplete() } } + /// + /// Handles the autocomplete dropdown hide notification from JavaScript. + /// + [Description("Handles the autocomplete dropdown hide notification from JavaScript.")] + [AddedVersion("0.4.0")] [JSInvokable] public void bsHideAutocomplete() { } + /// + /// Handles the autocomplete dropdown show notification from JavaScript. + /// + [Description("Handles the autocomplete dropdown show notification from JavaScript.")] + [AddedVersion("0.4.0")] [JSInvokable] public void bsShowAutocomplete() { } + /// + /// Handles the autocomplete dropdown shown notification from JavaScript. + /// + [Description("Handles the autocomplete dropdown shown notification from JavaScript.")] + [AddedVersion("0.4.0")] [JSInvokable] public void bsShownAutocomplete() { } @@ -467,6 +487,9 @@ private async Task ShowAsync() /// /// Gets or sets the value expression. /// + /// + /// Default value is . + /// [AddedVersion("1.0.0")] [DefaultValue(null)] [Description("Gets or sets the value expression.")] @@ -475,3 +498,4 @@ private async Task ShowAsync() #endregion } + diff --git a/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs b/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs index f29d4b3dc..447b8a9b8 100644 --- a/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs +++ b/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs @@ -23,11 +23,15 @@ protected override void OnInitialized() /// /// Disables checkbox input. /// + [AddedVersion("3.3.0")] + [Description("Disables checkbox input.")] public void Disable() => Disabled = true; /// /// Enables checkbox input. /// + [AddedVersion("3.3.0")] + [Description("Enables checkbox input.")] public void Enable() => Disabled = false; private async Task OnChange(ChangeEventArgs e) @@ -57,6 +61,8 @@ private async Task OnChange(ChangeEventArgs e) /// /// Default value is false. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } @@ -69,22 +75,38 @@ private async Task OnChange(ChangeEventArgs e) /// /// Gets or sets the label. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the label.")] [Parameter] public string? Label { get; set; } /// /// Gets or sets the value. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the value.")] [Parameter] public bool Value { get; set; } /// /// This event fires when the value changes. /// + [AddedVersion("3.3.0")] + [Description("This event fires when the value changes.")] [Parameter] public EventCallback ValueChanged { get; set; } - [Parameter] public Expression> ValueExpression { get; set; } = default!; + /// + /// Gets or sets an expression that identifies the bound value. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets an expression that identifies the bound value.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; #endregion } diff --git a/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs b/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs index fb1158a4f..be83565a5 100644 --- a/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs +++ b/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs @@ -94,11 +94,15 @@ protected override async Task OnParametersSetAsync() /// /// Disables currency input. /// + [AddedVersion("1.0.0")] + [Description("Disables currency input.")] public void Disable() => Disabled = true; /// /// Enables currency input. /// + [AddedVersion("1.0.0")] + [Description("Enables currency input.")] public void Enable() => Disabled = false; private string ExtractValue(object value, CultureInfo cultureInfo) @@ -406,6 +410,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.0.0")] + [Description("If , allows negative numbers.")] [Parameter] public bool AllowNegativeNumbers { get; set; } @@ -417,6 +423,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.0.0")] + [Description("If , CurrencyInput can complete the values automatically by the browser.")] [Parameter] public bool AutoComplete { get; set; } @@ -426,6 +434,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is . /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the currency sign.")] [Parameter] public CurrencySign CurrencySign { get; set; } = CurrencySign.Standard; @@ -435,9 +445,12 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } + [AddedVersion("1.0.0")] [CascadingParameter] private EditContext EditContext { get; set; } = default!; /// @@ -447,6 +460,7 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [Description("Determines whether to restrict the user input to Min and Max range. If , restricts the user input between the Min and Max range. Else accepts the user input.")] [Parameter] public bool EnableMinMax { get; set; } @@ -458,6 +472,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.0.0")] + [Description("Determines whether to hide the currency symbol are not.")] [Parameter] public bool HideCurrencySymbol { get; set; } @@ -469,12 +485,15 @@ private bool TryParseValue(object value, out TValue newValue) /// [Parameter] //[EditorRequired] + [AddedVersion("1.0.0")] public string Locale { get; set; } = "en-US"; /// /// Gets or sets the max. /// Max ignored if EnableMinMax="false". /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the max. Max ignored if EnableMinMax=\"false\".")] [Parameter] public TValue Max { get; set; } = default!; @@ -484,6 +503,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is null. /// + [AddedVersion("1.0.0")] + [Description("The maximum number of fraction digits to use.")] [Parameter] public byte? MaximumFractionDigits { get; set; } @@ -491,6 +512,8 @@ private bool TryParseValue(object value, out TValue newValue) /// Gets or sets the min. /// Min ignored if EnableMinMax="false". /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the min. Min ignored if EnableMinMax=\"false\".")] [Parameter] public TValue Min { get; set; } = default!; @@ -500,6 +523,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is null. /// + [AddedVersion("1.0.0")] + [Description("The minimum number of fraction digits to use.")] [Parameter] public byte? MinimumFractionDigits { get; set; } @@ -510,6 +535,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is 1. /// + [AddedVersion("1.0.0")] + [Description("The minimum number of integer digits to use. A value with a smaller number of integer digits than this number will be left-padded with zeros (to the specified length) when formatted.")] [Parameter] public byte MinimumIntegerDigits { get; set; } = 1; @@ -519,6 +546,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is null. /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the placeholder.")] [Parameter] public string? Placeholder { get; set; } @@ -528,22 +557,38 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is . /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the text alignment.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.None; /// /// Gets or sets the value. /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the value.")] [Parameter] public TValue Value { get; set; } = default!; /// /// This event fired on every user keystroke that changes the CurrencyInput value. /// + [AddedVersion("1.0.0")] + [Description("This event fired on every user keystroke that changes the CurrencyInput value.")] [Parameter] public EventCallback ValueChanged { get; set; } - [Parameter] public Expression> ValueExpression { get; set; } = default!; + /// + /// Gets or sets an expression that identifies the bound value. + /// + /// + /// Default value is . + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets an expression that identifies the bound value.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; #endregion } diff --git a/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs b/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs index 14d95c216..3c469248f 100644 --- a/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs +++ b/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs @@ -119,11 +119,15 @@ protected override async Task OnParametersSetAsync() /// /// Disables currency input. /// + [AddedVersion("1.5.0")] + [Description("Disables currency input.")] public void Disable() => Disabled = true; /// /// Enables currency input. /// + [AddedVersion("1.5.0")] + [Description("Enables currency input.")] public void Enable() => Disabled = false; private string GetFormattedValue(object value) @@ -292,6 +296,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.5.0")] + [Description("If , DateInput can complete the values automatically by the browser.")] [Parameter] public bool AutoComplete { get; set; } @@ -301,9 +307,12 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.5.0")] + [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } + [AddedVersion("1.5.0")] [CascadingParameter] private EditContext EditContext { get; set; } = default!; /// @@ -313,6 +322,7 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [Description("Determines whether to restrict the user input to Min and Max range. If , restricts the user input between the Min and Max range. Else accepts the user input.")] [Parameter] public bool EnableMinMax { get; set; } @@ -322,6 +332,8 @@ private bool TryParseValue(object value, out TValue newValue) /// Gets or sets the max. /// Allowed format is yyyy-mm-dd. /// + [AddedVersion("1.5.0")] + [Description("Gets or sets the max. Allowed format is yyyy-mm-dd.")] [Parameter] public TValue Max { get; set; } = default!; @@ -329,6 +341,8 @@ private bool TryParseValue(object value, out TValue newValue) /// Gets or sets the min. /// Allowed format is yyyy-mm-dd. /// + [AddedVersion("1.5.0")] + [Description("Gets or sets the min. Allowed format is yyyy-mm-dd.")] [Parameter] public TValue Min { get; set; } = default!; @@ -338,26 +352,39 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is null. /// + [AddedVersion("1.5.0")] + [Description("Gets or sets the placeholder.")] [Parameter] public string? Placeholder { get; set; } /// /// Gets or sets the value. /// + [AddedVersion("1.5.0")] + [Description("Gets or sets the value.")] [Parameter] public TValue Value { get; set; } = default!; /// /// This event fired on every user keystroke that changes the DateInput value. /// + [AddedVersion("1.5.0")] + [Description("This event fired on every user keystroke that changes the DateInput value.")] [Parameter] public EventCallback ValueChanged { get; set; } /// /// Gets or sets the expression. /// + /// + /// Default value is . + /// + [DefaultValue(null)] + [AddedVersion("1.5.0")] + [Description("Gets or sets the expression.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; #endregion } + diff --git a/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs b/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs index 7e34e0dac..d04308d6a 100644 --- a/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs +++ b/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs @@ -34,11 +34,15 @@ protected override void OnParametersSet() /// /// Disables the . /// + [AddedVersion("3.5.0")] + [Description("Disables the .")] public void Disable() => Disabled = true; /// /// Enables the . /// + [AddedVersion("3.5.0")] + [Description("Enables the .")] public void Enable() => Disabled = false; private void OnChange(ChangeEventArgs e) @@ -81,6 +85,8 @@ private void OnChange(ChangeEventArgs e) /// Default value is false. /// /// + [AddedVersion("3.5.0")] + [Description("Gets or sets the disabled state. Default value is false.")] [Parameter] public bool Disabled { get; set; } = false; @@ -95,6 +101,8 @@ private void OnChange(ChangeEventArgs e) /// Default value is . /// /// + [AddedVersion("3.5.0")] + [Description("Gets or sets the size. Default value is .")] [Parameter] public EnumInputSize Size { get; set; } = EnumInputSize.None; @@ -104,18 +112,28 @@ private void OnChange(ChangeEventArgs e) /// Default value is . /// /// + [AddedVersion("3.5.0")] + [Description("Gets or sets the text. Default value is .")] [Parameter] public string Text { get; set; } = default!; /// /// This event fires when the text changes. /// + [AddedVersion("3.5.0")] + [Description("This event fires when the text changes.")] [Parameter] public EventCallback TextChanged { get; set; } /// /// Gets or sets the expression. /// + /// + /// Default value is . + /// + [DefaultValue(null)] + [AddedVersion("3.5.0")] + [Description("Gets or sets the expression.")] [Parameter] public Expression> TextExpression { get; set; } = default!; @@ -125,20 +143,31 @@ private void OnChange(ChangeEventArgs e) /// Default value is 0. /// /// + [AddedVersion("3.5.0")] + [Description("Gets or sets the value. Default value is 0.")] [Parameter] public int Value { get; set; } /// /// This event fires when the value changes. /// + [AddedVersion("3.5.0")] + [Description("This event fires when the value changes.")] [Parameter] public EventCallback ValueChanged { get; set; } /// /// Gets or sets the expression. /// + /// + /// Default value is . + /// + [DefaultValue(null)] + [AddedVersion("3.5.0")] + [Description("Gets or sets the expression.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; #endregion } + diff --git a/blazorbootstrap/Components/Form/FileInput/FileInputBase.cs b/blazorbootstrap/Components/Form/FileInput/FileInputBase.cs index b292199c1..149895cb0 100644 --- a/blazorbootstrap/Components/Form/FileInput/FileInputBase.cs +++ b/blazorbootstrap/Components/Form/FileInput/FileInputBase.cs @@ -212,6 +212,7 @@ private static string FormatValidationMessage(string template, params (string To /// /// Gets the currently selected files. /// + [Description("Gets the currently selected files.")] public IReadOnlyList SelectedFiles => files.AsReadOnly(); /// diff --git a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs index 03001d511..ae0220459 100644 --- a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs +++ b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs @@ -81,11 +81,15 @@ protected override async Task OnInitializedAsync() /// /// Disables number input. /// + [AddedVersion("1.0.0")] + [Description("Disables number input.")] public void Disable() => Disabled = true; /// /// Enables number input. /// + [AddedVersion("1.0.0")] + [Description("Enables number input.")] public void Enable() => Disabled = false; private string GetInvariantNumber(TValue value) @@ -357,6 +361,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.0.0")] + [Description("If , allows negative numbers.")] [Parameter] public bool AllowNegativeNumbers { get; set; } @@ -368,6 +374,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.0.0")] + [Description("If , NumberInput can complete the values automatically by the browser.")] [Parameter] public bool AutoComplete { get; set; } @@ -377,9 +385,12 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the disabled state .")] [Parameter] public bool Disabled { get; set; } + [AddedVersion("1.0.0")] [CascadingParameter] private EditContext EditContext { get; set; } = default!; /// @@ -389,6 +400,7 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [Description("Determines whether to restrict the user input to Min and Max range. If , restricts the user input between the Min and Max range. Else accepts the user input.")] [Parameter] public bool EnableMinMax { get; set; } @@ -402,12 +414,15 @@ private bool TryParseValue(object value, out TValue newValue) /// [Parameter] //[EditorRequired] + [AddedVersion("1.0.0")] public string Locale { get; set; } = "en-US"; /// /// Gets or sets the max. /// Max ignored if EnableMinMax="false". /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the max. Max ignored if EnableMinMax=\"false\".")] [Parameter] public TValue Max { get; set; } = default!; @@ -415,6 +430,8 @@ private bool TryParseValue(object value, out TValue newValue) /// Gets or sets the min. /// Min ignored if EnableMinMax="false". /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the min. Min ignored if EnableMinMax=\"false\".")] [Parameter] public TValue Min { get; set; } = default!; @@ -424,6 +441,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is null. /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the placeholder.")] [Parameter] public string? Placeholder { get; set; } @@ -433,6 +452,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is null. /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the step.")] [Parameter] public double? Step { get; set; } @@ -442,22 +463,38 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is . /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the text alignment.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.None; /// /// Gets or sets the value. /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the value.")] [Parameter] public TValue Value { get; set; } = default!; /// /// This event fired on every user keystroke that changes the NumberInput value. /// + [AddedVersion("1.0.0")] + [Description("This event fired on every user keystroke that changes the NumberInput value.")] [Parameter] public EventCallback ValueChanged { get; set; } - [Parameter] public Expression> ValueExpression { get; set; } = default!; + /// + /// Gets or sets an expression that identifies the bound value. + /// + /// + /// Default value is . + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets an expression that identifies the bound value.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; #endregion } diff --git a/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs b/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs index a2a0d9a93..b26619456 100644 --- a/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs +++ b/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs @@ -41,11 +41,15 @@ protected override async Task OnParametersSetAsync() /// /// Disables InputPassword. /// + [AddedVersion("3.3.0")] + [Description("Disables InputPassword.")] public void Disable() => Disabled = true; /// /// Enables InputPassword. /// + [AddedVersion("3.3.0")] + [Description("Enables InputPassword.")] public void Enable() => Disabled = false; /// @@ -82,6 +86,8 @@ private async Task OnChange(ChangeEventArgs args) /// /// Default value is false. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } @@ -99,6 +105,8 @@ private async Task OnChange(ChangeEventArgs args) /// /// Default value is `btn btn-primary btn-sm`. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the show/hide password button CSS class.")] [Parameter] public string? ShowHidePasswordButtonCssClass { get; set; } = "btn border-top border-end border-bottom border border-start-0"; //""btn btn-light border"; @@ -110,16 +118,30 @@ private async Task OnChange(ChangeEventArgs args) /// /// Default value is null. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the value.")] [Parameter] public string? Value { get; set; } /// /// This event is fired when the PasswordInput value changes. /// + [AddedVersion("3.3.0")] + [Description("This event is fired when the PasswordInput value changes.")] [Parameter] public EventCallback ValueChanged { get; set; } - [Parameter] public Expression> ValueExpression { get; set; } = default!; + /// + /// Gets or sets an expression that identifies the bound value. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets an expression that identifies the bound value.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; #endregion } diff --git a/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs index 8e094ef64..bc83b5178 100644 --- a/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs +++ b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs @@ -34,6 +34,11 @@ protected override void OnInitialized() base.OnInitialized(); } + /// + /// Updates the radio input value from JavaScript. + /// + [Description("Updates the radio input value from JavaScript.")] + [AddedVersion("3.3.0")] [JSInvokable] public async Task OnChangeJS(bool newValue) { @@ -47,11 +52,15 @@ public async Task OnChangeJS(bool newValue) /// /// Disables number input. /// + [AddedVersion("3.3.0")] + [Description("Disables number input.")] public void Disable() => Disabled = true; /// /// Enables number input. /// + [AddedVersion("3.3.0")] + [Description("Enables number input.")] public void Enable() => Disabled = false; #endregion @@ -71,6 +80,8 @@ public async Task OnChangeJS(bool newValue) /// /// Default value is false. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } @@ -83,28 +94,46 @@ public async Task OnChangeJS(bool newValue) /// /// Gets or sets the label. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the label.")] [Parameter] public string? Label { get; set; } /// /// Gets or sets the name. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the name.")] [Parameter] public string? Name { get; set; } /// /// Gets or sets the value. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the value.")] [Parameter] public bool Value { get; set; } = default!; /// /// This event fired on every user keystroke that changes the NumberInput value. /// + [AddedVersion("3.3.0")] + [Description("This event fired on every user keystroke that changes the NumberInput value.")] [Parameter] public EventCallback ValueChanged { get; set; } - [Parameter] public Expression> ValueExpression { get; set; } = default!; + /// + /// Gets or sets an expression that identifies the bound value. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets an expression that identifies the bound value.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; #endregion } diff --git a/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs b/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs index f792ac7e5..809bcc353 100644 --- a/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs +++ b/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs @@ -81,6 +81,11 @@ protected override async Task OnInitializedAsync() await base.OnInitializedAsync(); } + /// + /// Updates the range input value from JavaScript. + /// + [Description("Updates the range input value from JavaScript.")] + [AddedVersion("1.10.6")] [JSInvokable] public async Task bsOnInput(object? newValue) { @@ -91,11 +96,15 @@ public async Task bsOnInput(object? newValue) /// /// Disables the range input. /// + [AddedVersion("1.10.6")] + [Description("Disables the range input.")] public void Disable() => Disabled = true; /// /// Enables the range input. /// + [AddedVersion("1.10.6")] + [Description("Enables the range input.")] public void Enable() => Disabled = false; private string GetInvariantNumber(TValue value) @@ -378,6 +387,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.10.6")] + [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } @@ -388,12 +399,16 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Gets or sets the maximum value of the range input. /// + [AddedVersion("1.10.6")] + [Description("Gets or sets the maximum value of the range input.")] [Parameter] public TValue Max { get; set; } = default!; /// /// Gets or sets the minimum value of the range input. /// + [AddedVersion("1.10.6")] + [Description("Gets or sets the minimum value of the range input.")] [Parameter] public TValue Min { get; set; } = default!; @@ -405,6 +420,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is 1. /// + [AddedVersion("1.10.6")] + [Description("Gets or sets the step value of the range input.")] [Parameter] public double Step { get; set; } = 1; @@ -414,22 +431,38 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is null. /// + [AddedVersion("1.10.6")] + [Description("Gets or sets the tick marks.")] [Parameter] public IEnumerable TickMarks { get; set; } = default!; /// /// Gets or sets the value of the range input. /// + [AddedVersion("1.10.6")] + [Description("Gets or sets the value of the range input.")] [Parameter] public TValue Value { get; set; } = default!; /// /// This event fires when the user specifies a numeric value. /// + [AddedVersion("1.10.6")] + [Description("This event fires when the user specifies a numeric value.")] [Parameter] public EventCallback ValueChanged { get; set; } - [Parameter] public Expression> ValueExpression { get; set; } = default!; + /// + /// Gets or sets an expression that identifies the bound value. + /// + /// + /// Default value is . + /// + [AddedVersion("1.10.6")] + [DefaultValue(null)] + [Description("Gets or sets an expression that identifies the bound value.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; #endregion } diff --git a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs index 43b7a00bb..a7591d596 100644 --- a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs +++ b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs @@ -561,6 +561,9 @@ private Task SetImageUploadInProgressAsync(bool value) [AddedVersion("4.0.0")] [DefaultValue(null)] + /// + /// Gets or sets the toolbar items. + /// [Description("Gets or sets the toolbar items.")] [Parameter] public RichTextEditorToolbarItem[]? ToolbarItems { get; set; } @@ -579,6 +582,10 @@ private Task SetImageUploadInProgressAsync(bool value) public EventCallback ValueChanged { get; set; } /// Gets or sets the expression that identifies the bound value. + /// + /// Default value is . + /// + [DefaultValue(null)] [AddedVersion("4.0.0")] [Description("Gets or sets the expression that identifies the bound value.")] [Parameter] @@ -586,3 +593,4 @@ private Task SetImageUploadInProgressAsync(bool value) #endregion } + diff --git a/blazorbootstrap/Components/Form/Switch/Switch.razor.cs b/blazorbootstrap/Components/Form/Switch/Switch.razor.cs index 6a79b3ede..99236fbe7 100644 --- a/blazorbootstrap/Components/Form/Switch/Switch.razor.cs +++ b/blazorbootstrap/Components/Form/Switch/Switch.razor.cs @@ -39,11 +39,15 @@ protected override async Task OnParametersSetAsync() /// /// Disables switch. /// + [AddedVersion("1.3.0")] + [Description("Disables switch.")] public void Disable() => Disabled = true; /// /// Enables switch. /// + [AddedVersion("1.3.0")] + [Description("Enables switch.")] public void Enable() => Disabled = false; /// @@ -78,6 +82,8 @@ private async Task OnChange(ChangeEventArgs args) /// /// Default value is false. /// + [AddedVersion("1.3.0")] + [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } @@ -91,6 +97,8 @@ private async Task OnChange(ChangeEventArgs args) /// /// Default value is null. /// + [AddedVersion("1.3.0")] + [Description("Gets or sets the label.")] [Parameter] public string Label { get; set; } = default!; @@ -102,6 +110,8 @@ private async Task OnChange(ChangeEventArgs args) /// /// Default value is false. /// + [AddedVersion("1.3.0")] + [Description("Determines whether to put the switch on the opposite side.")] [Parameter] public bool Reverse { get; set; } @@ -111,16 +121,30 @@ private async Task OnChange(ChangeEventArgs args) /// /// Default value is false. /// + [AddedVersion("1.3.0")] + [Description("Gets or sets the value.")] [Parameter] public bool Value { get; set; } /// /// This event is fired when the switch selection changes. /// + [AddedVersion("1.3.0")] + [Description("This event is fired when the switch selection changes.")] [Parameter] public EventCallback ValueChanged { get; set; } = default!; - [Parameter] public Expression> ValueExpression { get; set; } = default!; + /// + /// Gets or sets an expression that identifies the bound value. + /// + /// + /// Default value is . + /// + [AddedVersion("1.3.0")] + [DefaultValue(null)] + [Description("Gets or sets an expression that identifies the bound value.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; #endregion } diff --git a/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs index a444151f0..c8cf3ee2d 100644 --- a/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs +++ b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs @@ -23,11 +23,15 @@ protected override void OnInitialized() /// /// Disables number input. /// + [AddedVersion("3.3.0")] + [Description("Disables number input.")] public void Disable() => Disabled = true; /// /// Enables number input. /// + [AddedVersion("3.3.0")] + [Description("Enables number input.")] public void Enable() => Disabled = false; private async Task OnChange(ChangeEventArgs e) @@ -59,12 +63,16 @@ private async Task OnChange(ChangeEventArgs e) /// /// Default value is false. /// + [AddedVersion("3.3.0")] + [Description("If , NumberInput can complete the values automatically by the browser.")] [Parameter] public bool AutoComplete { get; set; } /// /// Gets or sets the number of columns. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the number of columns.")] [Parameter] public int? Cols { get; set; } @@ -74,6 +82,8 @@ private async Task OnChange(ChangeEventArgs e) /// /// Default value is false. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } @@ -84,6 +94,8 @@ private async Task OnChange(ChangeEventArgs e) /// /// Gets or sets the maximum number of characters that can be entered. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the maximum number of characters that can be entered.")] [Parameter] public int? MaxLength { get; set; } @@ -93,12 +105,16 @@ private async Task OnChange(ChangeEventArgs e) /// /// Default value is null. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the placeholder text.")] [Parameter] public string? Placeholder { get; set; } /// /// Gets or sets the number of rows. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the number of rows.")] [Parameter] public int? Rows { get; set; } @@ -108,22 +124,38 @@ private async Task OnChange(ChangeEventArgs e) /// /// Default value is . /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the text alignment.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.None; /// /// Gets or sets the value. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the value.")] [Parameter] public string Value { get; set; } = default!; /// /// This event fires when the value changes. /// + [AddedVersion("3.3.0")] + [Description("This event fires when the value changes.")] [Parameter] public EventCallback ValueChanged { get; set; } - [Parameter] public Expression> ValueExpression { get; set; } = default!; + /// + /// Gets or sets an expression that identifies the bound value. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets an expression that identifies the bound value.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; #endregion } diff --git a/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs b/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs index 91eee5cc5..a1532ec8c 100644 --- a/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs +++ b/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs @@ -23,11 +23,15 @@ protected override void OnInitialized() /// /// Disables number input. /// + [AddedVersion("3.3.0")] + [Description("Disables number input.")] public void Disable() => Disabled = true; /// /// Enables number input. /// + [AddedVersion("3.3.0")] + [Description("Enables number input.")] public void Enable() => Disabled = false; private async Task OnChange(ChangeEventArgs e) @@ -59,6 +63,8 @@ private async Task OnChange(ChangeEventArgs e) /// /// Default value is false. /// + [AddedVersion("3.3.0")] + [Description("If , TextInput can complete the values automatically by the browser.")] [Parameter] public bool AutoComplete { get; set; } @@ -68,6 +74,8 @@ private async Task OnChange(ChangeEventArgs e) /// /// Default value is false. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } @@ -78,6 +86,8 @@ private async Task OnChange(ChangeEventArgs e) /// /// Gets or sets the maximum number of characters that can be entered. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the maximum number of characters that can be entered.")] [Parameter] public int? MaxLength { get; set; } @@ -87,6 +97,8 @@ private async Task OnChange(ChangeEventArgs e) /// /// Default value is null. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the placeholder text.")] [Parameter] public string? Placeholder { get; set; } @@ -96,22 +108,38 @@ private async Task OnChange(ChangeEventArgs e) /// /// Default value is . /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the text alignment.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.None; /// /// Gets or sets the value. /// + [AddedVersion("3.3.0")] + [Description("Gets or sets the value.")] [Parameter] public string Value { get; set; } = default!; /// /// This event fires when the value changes. /// + [AddedVersion("3.3.0")] + [Description("This event fires when the value changes.")] [Parameter] public EventCallback ValueChanged { get; set; } - [Parameter] public Expression> ValueExpression { get; set; } = default!; + /// + /// Gets or sets an expression that identifies the bound value. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets an expression that identifies the bound value.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; #endregion } diff --git a/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs b/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs index 419886fea..c69e01d33 100644 --- a/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs +++ b/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs @@ -115,11 +115,15 @@ protected override async Task OnParametersSetAsync() /// /// Disables currency input. /// + [AddedVersion("1.6.0")] + [Description("Disables currency input.")] public void Disable() => Disabled = true; /// /// Enables currency input. /// + [AddedVersion("1.6.0")] + [Description("Enables currency input.")] public void Enable() => Disabled = false; private string GetFormattedValue(object value) @@ -257,6 +261,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.6.0")] + [Description("If , DateInput can complete the values automatically by the browser.")] [Parameter] public bool AutoComplete { get; set; } @@ -266,9 +272,12 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.6.0")] + [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } + [AddedVersion("1.6.0")] [CascadingParameter] private EditContext EditContext { get; set; } = default!; /// @@ -278,6 +287,7 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [Description("Determines whether to restrict the user input to Min and Max range. If , restricts the user input between the Min and Max range. Else accepts the user input.")] [Parameter] public bool EnableMinMax { get; set; } @@ -287,6 +297,8 @@ private bool TryParseValue(object value, out TValue newValue) /// Gets or sets the max. /// Allowed format is hh:mm. /// + [AddedVersion("1.6.0")] + [Description("Gets or sets the max. Allowed format is hh:mm.")] [Parameter] public TValue Max { get; set; } = default!; @@ -294,6 +306,8 @@ private bool TryParseValue(object value, out TValue newValue) /// Gets or sets the min. /// Allowed format is hh:mm. /// + [AddedVersion("1.6.0")] + [Description("Gets or sets the min. Allowed format is hh:mm.")] [Parameter] public TValue Min { get; set; } = default!; @@ -303,26 +317,39 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is null. /// + [AddedVersion("1.6.0")] + [Description("Gets or sets the placeholder.")] [Parameter] public string? Placeholder { get; set; } /// /// Gets or sets the value. /// + [AddedVersion("1.6.0")] + [Description("Gets or sets the value.")] [Parameter] public TValue Value { get; set; } = default!; /// /// This event fired on every user keystroke that changes the TimeInput value. /// + [AddedVersion("1.6.0")] + [Description("This event fired on every user keystroke that changes the TimeInput value.")] [Parameter] public EventCallback ValueChanged { get; set; } /// /// Gets or sets the expression. /// + /// + /// Default value is . + /// + [DefaultValue(null)] + [AddedVersion("1.6.0")] + [Description("Gets or sets the expression.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; #endregion } + From f12da0a4fb3763f0275a40c4a953222b4b1fe117 Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 31 Aug 2026 14:01:10 +0530 Subject: [PATCH 03/14] Enhance Blazor inputs with new params and documentation Add Disabled and other parameters to input components for improved configurability. Annotate with [DefaultValue] and [Description] for better API clarity. Introduce EditContext as [CascadingParameter] in some components. Focus on usability, accessibility, and documentation improvements. --- .../Form/AutoComplete/AutoComplete.razor.cs | 11 ++++---- .../Form/CheckboxInput/CheckboxInput.razor.cs | 1 + .../Form/CurrencyInput/CurrencyInput.razor.cs | 11 ++++++++ .../Form/DateInput/DateInput.razor.cs | 5 +++- .../Form/EnumInput/EnumInput.razor.cs | 5 +++- .../Form/NumberInput/NumberInput.razor.cs | 7 +++++ .../Form/PasswordInput/PasswordInput.razor.cs | 2 ++ .../Form/RadioInput/RadioInput.razor.cs | 1 + .../Form/RangeInput/RangeInput.razor.cs | 3 +++ .../RichTextEditor/RichTextEditor.razor.cs | 1 - .../Components/Form/Switch/Switch.razor.cs | 4 +++ .../Form/TextAreaInput/TextAreaInput.razor.cs | 4 +++ .../Form/TextInput/TextInput.razor.cs | 4 +++ .../Form/TimeInput/TimeInput.razor.cs | 5 +++- docs/docs/04-forms/autocomplete.mdx | 26 +++++++++---------- 15 files changed, 67 insertions(+), 23 deletions(-) diff --git a/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs b/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs index 850834e41..f6dc37f30 100644 --- a/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs +++ b/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs @@ -1,6 +1,6 @@ namespace BlazorBootstrap; -[AddedVersion("0.4.0")] +[AddedVersion("1.0.0")] public partial class AutoComplete : BlazorBootstrapComponentBase { #region Fields and Constants @@ -75,7 +75,7 @@ protected override async Task OnInitializedAsync() /// Handles the autocomplete dropdown hidden notification from JavaScript. /// [Description("Handles the autocomplete dropdown hidden notification from JavaScript.")] - [AddedVersion("0.4.0")] + [AddedVersion("1.0.0")] [JSInvokable] public void bsHiddenAutocomplete() { @@ -94,7 +94,7 @@ public void bsHiddenAutocomplete() /// Handles the autocomplete dropdown hide notification from JavaScript. /// [Description("Handles the autocomplete dropdown hide notification from JavaScript.")] - [AddedVersion("0.4.0")] + [AddedVersion("1.0.0")] [JSInvokable] public void bsHideAutocomplete() { } @@ -102,7 +102,7 @@ public void bsHideAutocomplete() { } /// Handles the autocomplete dropdown show notification from JavaScript. /// [Description("Handles the autocomplete dropdown show notification from JavaScript.")] - [AddedVersion("0.4.0")] + [AddedVersion("1.0.0")] [JSInvokable] public void bsShowAutocomplete() { } @@ -110,7 +110,7 @@ public void bsShowAutocomplete() { } /// Handles the autocomplete dropdown shown notification from JavaScript. /// [Description("Handles the autocomplete dropdown shown notification from JavaScript.")] - [AddedVersion("0.4.0")] + [AddedVersion("1.0.0")] [JSInvokable] public void bsShownAutocomplete() { } @@ -498,4 +498,3 @@ private async Task ShowAsync() #endregion } - diff --git a/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs b/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs index 447b8a9b8..fd12b60bc 100644 --- a/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs +++ b/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs @@ -62,6 +62,7 @@ private async Task OnChange(ChangeEventArgs e) /// Default value is false. /// [AddedVersion("3.3.0")] + [DefaultValue(false)] [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } diff --git a/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs b/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs index be83565a5..15bdf5e48 100644 --- a/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs +++ b/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs @@ -411,6 +411,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is false. /// [AddedVersion("1.0.0")] + [DefaultValue(false)] [Description("If , allows negative numbers.")] [Parameter] public bool AllowNegativeNumbers { get; set; } @@ -424,6 +425,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is false. /// [AddedVersion("1.0.0")] + [DefaultValue(false)] [Description("If , CurrencyInput can complete the values automatically by the browser.")] [Parameter] public bool AutoComplete { get; set; } @@ -435,6 +437,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is . /// [AddedVersion("1.0.0")] + [DefaultValue(CurrencySign.Standard)] [Description("Gets or sets the currency sign.")] [Parameter] public CurrencySign CurrencySign { get; set; } = CurrencySign.Standard; @@ -446,11 +449,13 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is false. /// [AddedVersion("1.0.0")] + [DefaultValue(false)] [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } [AddedVersion("1.0.0")] + [DefaultValue(false)] [CascadingParameter] private EditContext EditContext { get; set; } = default!; /// @@ -473,6 +478,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is false. /// [AddedVersion("1.0.0")] + [DefaultValue(false)] [Description("Determines whether to hide the currency symbol are not.")] [Parameter] public bool HideCurrencySymbol { get; set; } @@ -504,6 +510,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is null. /// [AddedVersion("1.0.0")] + [DefaultValue(null)] [Description("The maximum number of fraction digits to use.")] [Parameter] public byte? MaximumFractionDigits { get; set; } @@ -524,6 +531,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is null. /// [AddedVersion("1.0.0")] + [DefaultValue(null)] [Description("The minimum number of fraction digits to use.")] [Parameter] public byte? MinimumFractionDigits { get; set; } @@ -536,6 +544,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is 1. /// [AddedVersion("1.0.0")] + [DefaultValue(1)] [Description("The minimum number of integer digits to use. A value with a smaller number of integer digits than this number will be left-padded with zeros (to the specified length) when formatted.")] [Parameter] public byte MinimumIntegerDigits { get; set; } = 1; @@ -547,6 +556,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is null. /// [AddedVersion("1.0.0")] + [DefaultValue(null)] [Description("Gets or sets the placeholder.")] [Parameter] public string? Placeholder { get; set; } @@ -558,6 +568,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is . /// [AddedVersion("1.0.0")] + [DefaultValue(Alignment.None)] [Description("Gets or sets the text alignment.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.None; diff --git a/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs b/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs index 3c469248f..ce773931f 100644 --- a/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs +++ b/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs @@ -297,6 +297,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is false. /// [AddedVersion("1.5.0")] + [DefaultValue(false)] [Description("If , DateInput can complete the values automatically by the browser.")] [Parameter] public bool AutoComplete { get; set; } @@ -308,11 +309,13 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is false. /// [AddedVersion("1.5.0")] + [DefaultValue(false)] [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } [AddedVersion("1.5.0")] + [DefaultValue(false)] [CascadingParameter] private EditContext EditContext { get; set; } = default!; /// @@ -353,6 +356,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is null. /// [AddedVersion("1.5.0")] + [DefaultValue(null)] [Description("Gets or sets the placeholder.")] [Parameter] public string? Placeholder { get; set; } @@ -387,4 +391,3 @@ private bool TryParseValue(object value, out TValue newValue) #endregion } - diff --git a/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs b/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs index d04308d6a..8ae1dcd94 100644 --- a/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs +++ b/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs @@ -86,6 +86,7 @@ private void OnChange(ChangeEventArgs e) /// /// [AddedVersion("3.5.0")] + [DefaultValue(false)] [Description("Gets or sets the disabled state. Default value is false.")] [Parameter] public bool Disabled { get; set; } = false; @@ -102,6 +103,7 @@ private void OnChange(ChangeEventArgs e) /// /// [AddedVersion("3.5.0")] + [DefaultValue(EnumInputSize.None)] [Description("Gets or sets the size. Default value is .")] [Parameter] public EnumInputSize Size { get; set; } = EnumInputSize.None; @@ -113,6 +115,7 @@ private void OnChange(ChangeEventArgs e) /// /// [AddedVersion("3.5.0")] + [DefaultValue(null)] [Description("Gets or sets the text. Default value is .")] [Parameter] public string Text { get; set; } = default!; @@ -144,6 +147,7 @@ private void OnChange(ChangeEventArgs e) /// /// [AddedVersion("3.5.0")] + [DefaultValue(0)] [Description("Gets or sets the value. Default value is 0.")] [Parameter] public int Value { get; set; } @@ -170,4 +174,3 @@ private void OnChange(ChangeEventArgs e) #endregion } - diff --git a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs index ae0220459..168b427c4 100644 --- a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs +++ b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs @@ -362,6 +362,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is false. /// [AddedVersion("1.0.0")] + [DefaultValue(false)] [Description("If , allows negative numbers.")] [Parameter] public bool AllowNegativeNumbers { get; set; } @@ -375,6 +376,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is false. /// [AddedVersion("1.0.0")] + [DefaultValue(false)] [Description("If , NumberInput can complete the values automatically by the browser.")] [Parameter] public bool AutoComplete { get; set; } @@ -386,11 +388,13 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is false. /// [AddedVersion("1.0.0")] + [DefaultValue(false)] [Description("Gets or sets the disabled state .")] [Parameter] public bool Disabled { get; set; } [AddedVersion("1.0.0")] + [DefaultValue(false)] [CascadingParameter] private EditContext EditContext { get; set; } = default!; /// @@ -442,6 +446,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is null. /// [AddedVersion("1.0.0")] + [DefaultValue(null)] [Description("Gets or sets the placeholder.")] [Parameter] public string? Placeholder { get; set; } @@ -453,6 +458,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is null. /// [AddedVersion("1.0.0")] + [DefaultValue(null)] [Description("Gets or sets the step.")] [Parameter] public double? Step { get; set; } @@ -464,6 +470,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is . /// [AddedVersion("1.0.0")] + [DefaultValue(Alignment.None)] [Description("Gets or sets the text alignment.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.None; diff --git a/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs b/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs index b26619456..32a542514 100644 --- a/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs +++ b/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs @@ -87,6 +87,7 @@ private async Task OnChange(ChangeEventArgs args) /// Default value is false. /// [AddedVersion("3.3.0")] + [DefaultValue(false)] [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } @@ -119,6 +120,7 @@ private async Task OnChange(ChangeEventArgs args) /// Default value is null. /// [AddedVersion("3.3.0")] + [DefaultValue(null)] [Description("Gets or sets the value.")] [Parameter] public string? Value { get; set; } diff --git a/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs index bc83b5178..e13331541 100644 --- a/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs +++ b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs @@ -81,6 +81,7 @@ public async Task OnChangeJS(bool newValue) /// Default value is false. /// [AddedVersion("3.3.0")] + [DefaultValue(false)] [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } diff --git a/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs b/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs index 809bcc353..687e7e5eb 100644 --- a/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs +++ b/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs @@ -388,6 +388,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is false. /// [AddedVersion("1.10.6")] + [DefaultValue(false)] [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } @@ -421,6 +422,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is 1. /// [AddedVersion("1.10.6")] + [DefaultValue(1)] [Description("Gets or sets the step value of the range input.")] [Parameter] public double Step { get; set; } = 1; @@ -432,6 +434,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is null. /// [AddedVersion("1.10.6")] + [DefaultValue(null)] [Description("Gets or sets the tick marks.")] [Parameter] public IEnumerable TickMarks { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs index a7591d596..a5f0be983 100644 --- a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs +++ b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs @@ -593,4 +593,3 @@ private Task SetImageUploadInProgressAsync(bool value) #endregion } - diff --git a/blazorbootstrap/Components/Form/Switch/Switch.razor.cs b/blazorbootstrap/Components/Form/Switch/Switch.razor.cs index 99236fbe7..77786c299 100644 --- a/blazorbootstrap/Components/Form/Switch/Switch.razor.cs +++ b/blazorbootstrap/Components/Form/Switch/Switch.razor.cs @@ -83,6 +83,7 @@ private async Task OnChange(ChangeEventArgs args) /// Default value is false. /// [AddedVersion("1.3.0")] + [DefaultValue(false)] [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } @@ -98,6 +99,7 @@ private async Task OnChange(ChangeEventArgs args) /// Default value is null. /// [AddedVersion("1.3.0")] + [DefaultValue(null)] [Description("Gets or sets the label.")] [Parameter] public string Label { get; set; } = default!; @@ -111,6 +113,7 @@ private async Task OnChange(ChangeEventArgs args) /// Default value is false. /// [AddedVersion("1.3.0")] + [DefaultValue(false)] [Description("Determines whether to put the switch on the opposite side.")] [Parameter] public bool Reverse { get; set; } @@ -122,6 +125,7 @@ private async Task OnChange(ChangeEventArgs args) /// Default value is false. /// [AddedVersion("1.3.0")] + [DefaultValue(false)] [Description("Gets or sets the value.")] [Parameter] public bool Value { get; set; } diff --git a/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs index c8cf3ee2d..9a029be41 100644 --- a/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs +++ b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs @@ -64,6 +64,7 @@ private async Task OnChange(ChangeEventArgs e) /// Default value is false. /// [AddedVersion("3.3.0")] + [DefaultValue(false)] [Description("If , NumberInput can complete the values automatically by the browser.")] [Parameter] public bool AutoComplete { get; set; } @@ -83,6 +84,7 @@ private async Task OnChange(ChangeEventArgs e) /// Default value is false. /// [AddedVersion("3.3.0")] + [DefaultValue(false)] [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } @@ -106,6 +108,7 @@ private async Task OnChange(ChangeEventArgs e) /// Default value is null. /// [AddedVersion("3.3.0")] + [DefaultValue(null)] [Description("Gets or sets the placeholder text.")] [Parameter] public string? Placeholder { get; set; } @@ -125,6 +128,7 @@ private async Task OnChange(ChangeEventArgs e) /// Default value is . /// [AddedVersion("3.3.0")] + [DefaultValue(Alignment.None)] [Description("Gets or sets the text alignment.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.None; diff --git a/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs b/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs index a1532ec8c..fcba746ea 100644 --- a/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs +++ b/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs @@ -64,6 +64,7 @@ private async Task OnChange(ChangeEventArgs e) /// Default value is false. /// [AddedVersion("3.3.0")] + [DefaultValue(false)] [Description("If , TextInput can complete the values automatically by the browser.")] [Parameter] public bool AutoComplete { get; set; } @@ -75,6 +76,7 @@ private async Task OnChange(ChangeEventArgs e) /// Default value is false. /// [AddedVersion("3.3.0")] + [DefaultValue(false)] [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } @@ -98,6 +100,7 @@ private async Task OnChange(ChangeEventArgs e) /// Default value is null. /// [AddedVersion("3.3.0")] + [DefaultValue(null)] [Description("Gets or sets the placeholder text.")] [Parameter] public string? Placeholder { get; set; } @@ -109,6 +112,7 @@ private async Task OnChange(ChangeEventArgs e) /// Default value is . /// [AddedVersion("3.3.0")] + [DefaultValue(Alignment.None)] [Description("Gets or sets the text alignment.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.None; diff --git a/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs b/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs index c69e01d33..0e8deb533 100644 --- a/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs +++ b/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs @@ -262,6 +262,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is false. /// [AddedVersion("1.6.0")] + [DefaultValue(false)] [Description("If , DateInput can complete the values automatically by the browser.")] [Parameter] public bool AutoComplete { get; set; } @@ -273,11 +274,13 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is false. /// [AddedVersion("1.6.0")] + [DefaultValue(false)] [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } [AddedVersion("1.6.0")] + [DefaultValue(false)] [CascadingParameter] private EditContext EditContext { get; set; } = default!; /// @@ -318,6 +321,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Default value is null. /// [AddedVersion("1.6.0")] + [DefaultValue(null)] [Description("Gets or sets the placeholder.")] [Parameter] public string? Placeholder { get; set; } @@ -352,4 +356,3 @@ private bool TryParseValue(object value, out TValue newValue) #endregion } - diff --git a/docs/docs/04-forms/autocomplete.mdx b/docs/docs/04-forms/autocomplete.mdx index 2e1241e46..590ab5eb7 100644 --- a/docs/docs/04-forms/autocomplete.mdx +++ b/docs/docs/04-forms/autocomplete.mdx @@ -18,33 +18,33 @@ Blazor Bootstrap autocomplete component is a textbox that offers the users sugge ## Parameters | Name | Type | Default | Required | Description | Added Version | |:--|:--|:--|:--|:--|:--| -| DataProvider | `AutoCompleteDataProviderDelegate` | null | ✔️ | Gets or sets the data provider. | 0.4.0 | -| Disabled | bool | false | | Gets or sets the disabled state. | 0.4.0 | +| DataProvider | `AutoCompleteDataProviderDelegate` | null | ✔️ | Gets or sets the data provider. | 1.0.0 | +| Disabled | bool | false | | Gets or sets the disabled state. | 1.0.0 | | EmptyText | string | `No records found.` | | Gets or sets the empty text. | 1.10.2 | | LoadingText | string | `Loading...` | | Gets or sets the loading text. | 1.10.2 | -| Placeholder | string | null | | Gets or sets the placeholder. | 0.4.0 | -| PropertyName | string | null | ✔️ | Gets or sets the property name. | 0.4.0 | -| Size | `AutoCompleteSize` | `AutoCompleteSize.Default` | | Gets or sets the autocomplete size. | 0.4.0 | +| Placeholder | string | null | | Gets or sets the placeholder. | 1.0.0 | +| PropertyName | string | null | ✔️ | Gets or sets the property name. | 1.0.0 | +| Size | `AutoCompleteSize` | `AutoCompleteSize.Default` | | Gets or sets the autocomplete size. | 1.0.0 | | StringComparison | `StringComparison` | `StringComparison.OrdinalIgnoreCase` | | Gets or sets the StringComparison. | 0.4.1 | | StringFilterOperator | `StringFilterOperator` | `StringFilterOperator.Contains` | | Gets or sets the string filter operator. | 0.4.1 | -| Value | string | null | | Gets or sets the value. | 0.4.0 | -| ValueExpression | expression | null | | AutoComplete value expression. | 0.4.0 | +| Value | string | null | | Gets or sets the value. | 1.0.0 | +| ValueExpression | expression | null | | AutoComplete value expression. | 1.0.0 | ## Methods | Name | Returns | Description | Added Version | |:--|:--|:--|:--| -| Disable() | void | Disables autocomplete. | 0.4.0 | -| Enable() | void | Enables autocomplete. | 0.4.0 | -| RefreshDataAsync() | Task | Refresh the autocomplete data. | 0.4.0 | -| ResetAsync() | Task | Resets the autocomplete selection. | 0.4.0 | +| Disable() | void | Disables autocomplete. | 1.0.0 | +| Enable() | void | Enables autocomplete. | 1.0.0 | +| RefreshDataAsync() | Task | Refresh the autocomplete data. | 1.0.0 | +| ResetAsync() | Task | Resets the autocomplete selection. | 1.0.0 | ## Events | Name | Description | Added Version | |:--|:--|:--| -| OnChanged | This event fires immediately when the autocomplete selection changes by the user. | 0.4.0 | -| ValueChanged | This event fires on every user keystroke that changes the textbox value. | 0.4.0 | +| OnChanged | This event fires immediately when the autocomplete selection changes by the user. | 1.0.0 | +| ValueChanged | This event fires on every user keystroke that changes the textbox value. | 1.0.0 | ## Keyboard Navigation From 49acd7fb6d94c7009e0569a62e35dee01bfd2205 Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 31 Aug 2026 14:17:21 +0530 Subject: [PATCH 04/14] Add DefaultValue and remarks docs to input components Added [DefaultValue] attributes and detailed documentation to parameters in CheckboxInput, RadioInput, PasswordInput, RichTextEditor, TextAreaInput, and TextInput. Clarified default values and improved API docs for parameters like Label, Value, Name, MaxLength, Cols, Rows, AllowedImageDomains, AllowedImageFileTypes, AllowedLinkDomains, and ShowHidePasswordButtonCssClass. --- .../Form/CheckboxInput/CheckboxInput.razor.cs | 8 ++++++++ .../Form/PasswordInput/PasswordInput.razor.cs | 1 + .../Form/RadioInput/RadioInput.razor.cs | 12 ++++++++++++ .../Form/RichTextEditor/RichTextEditor.razor.cs | 12 ++++++++++++ .../Form/TextAreaInput/TextAreaInput.razor.cs | 16 ++++++++++++++++ .../Components/Form/TextInput/TextInput.razor.cs | 8 ++++++++ 6 files changed, 57 insertions(+) diff --git a/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs b/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs index fd12b60bc..82b04859e 100644 --- a/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs +++ b/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs @@ -76,7 +76,11 @@ private async Task OnChange(ChangeEventArgs e) /// /// Gets or sets the label. /// + /// + /// Default value is . + /// [AddedVersion("3.3.0")] + [DefaultValue(null)] [Description("Gets or sets the label.")] [Parameter] public string? Label { get; set; } @@ -84,7 +88,11 @@ private async Task OnChange(ChangeEventArgs e) /// /// Gets or sets the value. /// + /// + /// Default value is . + /// [AddedVersion("3.3.0")] + [DefaultValue(false)] [Description("Gets or sets the value.")] [Parameter] public bool Value { get; set; } diff --git a/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs b/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs index 32a542514..fead2430e 100644 --- a/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs +++ b/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs @@ -107,6 +107,7 @@ private async Task OnChange(ChangeEventArgs args) /// Default value is `btn btn-primary btn-sm`. /// [AddedVersion("3.3.0")] + [DefaultValue("btn border-top border-end border-bottom border border-start-0")] [Description("Gets or sets the show/hide password button CSS class.")] [Parameter] public string? ShowHidePasswordButtonCssClass { get; set; } = "btn border-top border-end border-bottom border border-start-0"; //""btn btn-light border"; diff --git a/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs index e13331541..31b72e142 100644 --- a/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs +++ b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs @@ -95,7 +95,11 @@ public async Task OnChangeJS(bool newValue) /// /// Gets or sets the label. /// + /// + /// Default value is . + /// [AddedVersion("3.3.0")] + [DefaultValue(null)] [Description("Gets or sets the label.")] [Parameter] public string? Label { get; set; } @@ -103,7 +107,11 @@ public async Task OnChangeJS(bool newValue) /// /// Gets or sets the name. /// + /// + /// Default value is . + /// [AddedVersion("3.3.0")] + [DefaultValue(null)] [Description("Gets or sets the name.")] [Parameter] public string? Name { get; set; } @@ -111,7 +119,11 @@ public async Task OnChangeJS(bool newValue) /// /// Gets or sets the value. /// + /// + /// Default value is . + /// [AddedVersion("3.3.0")] + [DefaultValue(false)] [Description("Gets or sets the value.")] [Parameter] public bool Value { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs index a5f0be983..cd87ae83c 100644 --- a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs +++ b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs @@ -455,19 +455,31 @@ private Task SetImageUploadInProgressAsync(bool value) private string Accept => string.Join(',', NormalizedAllowedImageFileTypes.Select(fileType => $".{fileType}")); /// Gets or sets the permitted HTTPS image domains. Subdomains are also permitted. + /// + /// Default value is . + /// [AddedVersion("4.0.0")] + [DefaultValue(null)] [Description("Gets or sets the permitted HTTPS image domains. Subdomains are also permitted.")] [Parameter] public IEnumerable? AllowedImageDomains { get; set; } /// Gets or sets the permitted image file extensions. + /// + /// Default value is . + /// [AddedVersion("4.0.0")] + [DefaultValue(null)] [Description("Gets or sets the permitted image file extensions.")] [Parameter] public IEnumerable? AllowedImageFileTypes { get; set; } /// Gets or sets the permitted HTTP(S) link domains. Subdomains are also permitted. + /// + /// Default value is . + /// [AddedVersion("4.0.0")] + [DefaultValue(null)] [Description("Gets or sets the permitted HTTP(S) link domains. Subdomains are also permitted.")] [Parameter] public IEnumerable? AllowedLinkDomains { get; set; } diff --git a/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs index 9a029be41..041e0e565 100644 --- a/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs +++ b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs @@ -72,7 +72,11 @@ private async Task OnChange(ChangeEventArgs e) /// /// Gets or sets the number of columns. /// + /// + /// Default value is . + /// [AddedVersion("3.3.0")] + [DefaultValue(null)] [Description("Gets or sets the number of columns.")] [Parameter] public int? Cols { get; set; } @@ -96,7 +100,11 @@ private async Task OnChange(ChangeEventArgs e) /// /// Gets or sets the maximum number of characters that can be entered. /// + /// + /// Default value is . + /// [AddedVersion("3.3.0")] + [DefaultValue(null)] [Description("Gets or sets the maximum number of characters that can be entered.")] [Parameter] public int? MaxLength { get; set; } @@ -116,7 +124,11 @@ private async Task OnChange(ChangeEventArgs e) /// /// Gets or sets the number of rows. /// + /// + /// Default value is . + /// [AddedVersion("3.3.0")] + [DefaultValue(null)] [Description("Gets or sets the number of rows.")] [Parameter] public int? Rows { get; set; } @@ -136,7 +148,11 @@ private async Task OnChange(ChangeEventArgs e) /// /// Gets or sets the value. /// + /// + /// Default value is . + /// [AddedVersion("3.3.0")] + [DefaultValue(null)] [Description("Gets or sets the value.")] [Parameter] public string Value { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs b/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs index fcba746ea..ffb73774f 100644 --- a/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs +++ b/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs @@ -88,7 +88,11 @@ private async Task OnChange(ChangeEventArgs e) /// /// Gets or sets the maximum number of characters that can be entered. /// + /// + /// Default value is . + /// [AddedVersion("3.3.0")] + [DefaultValue(null)] [Description("Gets or sets the maximum number of characters that can be entered.")] [Parameter] public int? MaxLength { get; set; } @@ -120,7 +124,11 @@ private async Task OnChange(ChangeEventArgs e) /// /// Gets or sets the value. /// + /// + /// Default value is . + /// [AddedVersion("3.3.0")] + [DefaultValue(null)] [Description("Gets or sets the value.")] [Parameter] public string Value { get; set; } = default!; From c0e28b709278634c84e5dfe3b8e67a53f2d4f62e Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 31 Aug 2026 14:27:46 +0530 Subject: [PATCH 05/14] Improve docs, consistency, and JS interop in Blazor components Enhanced [Description] attributes for clarity and completeness. Added or corrected [DefaultValue] attributes and default values for parameters. Applied [JSInvokable] to enable JavaScript interop on relevant methods and parameters. Reformatted private cascading parameters for consistency. These changes improve maintainability, API documentation, and JS interop support. --- .../Form/AutoComplete/AutoComplete.razor.cs | 14 +++--- .../Form/CurrencyInput/CurrencyInput.razor.cs | 46 ++++++++++--------- .../Form/DateInput/DateInput.razor.cs | 5 +- .../Form/EnumInput/EnumInput.razor.cs | 4 +- .../Form/NumberInput/NumberInput.razor.cs | 2 +- .../Form/RadioInput/RadioInput.razor.cs | 2 +- .../Form/RangeInput/RangeInput.razor.cs | 2 +- .../RichTextEditor/RichTextEditor.razor.cs | 2 +- .../Form/TimeInput/TimeInput.razor.cs | 4 +- 9 files changed, 42 insertions(+), 39 deletions(-) diff --git a/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs b/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs index f6dc37f30..e2feb5585 100644 --- a/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs +++ b/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs @@ -74,8 +74,8 @@ protected override async Task OnInitializedAsync() /// /// Handles the autocomplete dropdown hidden notification from JavaScript. /// - [Description("Handles the autocomplete dropdown hidden notification from JavaScript.")] [AddedVersion("1.0.0")] + [Description("Handles the autocomplete dropdown hidden notification from JavaScript.")] [JSInvokable] public void bsHiddenAutocomplete() { @@ -93,24 +93,24 @@ public void bsHiddenAutocomplete() /// /// Handles the autocomplete dropdown hide notification from JavaScript. /// - [Description("Handles the autocomplete dropdown hide notification from JavaScript.")] [AddedVersion("1.0.0")] + [Description("Handles the autocomplete dropdown hide notification from JavaScript.")] [JSInvokable] public void bsHideAutocomplete() { } /// /// Handles the autocomplete dropdown show notification from JavaScript. /// - [Description("Handles the autocomplete dropdown show notification from JavaScript.")] [AddedVersion("1.0.0")] + [Description("Handles the autocomplete dropdown show notification from JavaScript.")] [JSInvokable] public void bsShowAutocomplete() { } /// /// Handles the autocomplete dropdown shown notification from JavaScript. /// - [Description("Handles the autocomplete dropdown shown notification from JavaScript.")] [AddedVersion("1.0.0")] + [Description("Handles the autocomplete dropdown shown notification from JavaScript.")] [JSInvokable] public void bsShownAutocomplete() { } @@ -256,7 +256,7 @@ private async Task OnInputChangedAsync(ChangeEventArgs args) cancellationTokenSource = new CancellationTokenSource(); var token = cancellationTokenSource.Token; - await Task.Delay(300, token); // 300ms timeout for the debouncing + await Task.Delay(300, token); // 300ms timeout for the debouncing await FilterDataAsync(token); closeButton?.HideLoading(); @@ -358,7 +358,7 @@ private async Task ShowAsync() [Parameter] public bool Disabled { get; set; } - [CascadingParameter] + [CascadingParameter] private EditContext EditContext { get; set; } = default!; /// @@ -493,7 +493,7 @@ private async Task ShowAsync() [AddedVersion("1.0.0")] [DefaultValue(null)] [Description("Gets or sets the value expression.")] - [Parameter] + [Parameter] public Expression>? ValueExpression { get; set; } #endregion diff --git a/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs b/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs index 15bdf5e48..7db328183 100644 --- a/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs +++ b/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs @@ -95,14 +95,14 @@ protected override async Task OnParametersSetAsync() /// Disables currency input. /// [AddedVersion("1.0.0")] - [Description("Disables currency input.")] + [Description("Disables the currency input so users cannot change its value.")] public void Disable() => Disabled = true; /// /// Enables currency input. /// [AddedVersion("1.0.0")] - [Description("Enables currency input.")] + [Description("Enables the currency input so users can change its value.")] public void Enable() => Disabled = false; private string ExtractValue(object value, CultureInfo cultureInfo) @@ -412,7 +412,7 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.0.0")] [DefaultValue(false)] - [Description("If , allows negative numbers.")] + [Description("Gets or sets whether users can enter negative currency values. When false, negative input is rejected during parsing.")] [Parameter] public bool AllowNegativeNumbers { get; set; } @@ -426,7 +426,7 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.0.0")] [DefaultValue(false)] - [Description("If , CurrencyInput can complete the values automatically by the browser.")] + [Description("Gets or sets whether browser autocomplete is enabled. When true, the browser may offer saved values for the input.")] [Parameter] public bool AutoComplete { get; set; } @@ -438,7 +438,7 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.0.0")] [DefaultValue(CurrencySign.Standard)] - [Description("Gets or sets the currency sign.")] + [Description("Gets or sets how the currency sign is displayed when the value is formatted.")] [Parameter] public CurrencySign CurrencySign { get; set; } = CurrencySign.Standard; @@ -450,13 +450,13 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.0.0")] [DefaultValue(false)] - [Description("Gets or sets the disabled state.")] + [Description("Gets or sets whether the input is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } [AddedVersion("1.0.0")] - [DefaultValue(false)] [CascadingParameter] private EditContext EditContext { get; set; } = default!; + [DefaultValue(false)] /// /// Determines whether to restrict the user input to Min and Max range. @@ -465,21 +465,22 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// - [Description("Determines whether to restrict the user input to Min and Max range. If , restricts the user input between the Min and Max range. Else accepts the user input.")] + [AddedVersion("1.0.0")] + [Description("Gets or sets whether input is restricted to the configured minimum and maximum values. When true, values outside the range are rejected.")] [Parameter] public bool EnableMinMax { get; set; } private string fieldCssClasses => EditContext?.FieldCssClass(fieldIdentifier) ?? ""; /// - /// Determines whether to hide the currency symbol are not. + /// Gets or sets whether the currency symbol is hidden. /// /// /// Default value is false. /// [AddedVersion("1.0.0")] [DefaultValue(false)] - [Description("Determines whether to hide the currency symbol are not.")] + [Description("Gets or sets whether the currency symbol is hidden. When true, formatting omits the symbol while retaining the numeric value.")] [Parameter] public bool HideCurrencySymbol { get; set; } @@ -489,9 +490,10 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is 'en-US'. /// - [Parameter] - //[EditorRequired] [AddedVersion("1.0.0")] + [DefaultValue("en-US")] + [Description("Gets or sets the culture name used to format the currency value. It controls decimal separators, grouping, and currency conventions.")] + [Parameter] public string Locale { get; set; } = "en-US"; /// @@ -499,7 +501,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Max ignored if EnableMinMax="false". /// [AddedVersion("1.0.0")] - [Description("Gets or sets the max. Max ignored if EnableMinMax=\"false\".")] + [Description("Gets or sets the maximum permitted value. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Max { get; set; } = default!; @@ -511,7 +513,7 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.0.0")] [DefaultValue(null)] - [Description("The maximum number of fraction digits to use.")] + [Description("Gets or sets the maximum number of fraction digits used when formatting the value. Null uses the culture default.")] [Parameter] public byte? MaximumFractionDigits { get; set; } @@ -520,7 +522,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Min ignored if EnableMinMax="false". /// [AddedVersion("1.0.0")] - [Description("Gets or sets the min. Min ignored if EnableMinMax=\"false\".")] + [Description("Gets or sets the minimum permitted value. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Min { get; set; } = default!; @@ -532,7 +534,7 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.0.0")] [DefaultValue(null)] - [Description("The minimum number of fraction digits to use.")] + [Description("Gets or sets the minimum number of fraction digits used when formatting the value. Null uses the culture default.")] [Parameter] public byte? MinimumFractionDigits { get; set; } @@ -545,7 +547,7 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.0.0")] [DefaultValue(1)] - [Description("The minimum number of integer digits to use. A value with a smaller number of integer digits than this number will be left-padded with zeros (to the specified length) when formatted.")] + [Description("Gets or sets the minimum number of integer digits used when formatting. Values with fewer digits are left-padded with zeros.")] [Parameter] public byte MinimumIntegerDigits { get; set; } = 1; @@ -557,7 +559,7 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.0.0")] [DefaultValue(null)] - [Description("Gets or sets the placeholder.")] + [Description("Gets or sets placeholder text displayed when the input has no value.")] [Parameter] public string? Placeholder { get; set; } @@ -569,7 +571,7 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.0.0")] [DefaultValue(Alignment.None)] - [Description("Gets or sets the text alignment.")] + [Description("Gets or sets the horizontal alignment of the formatted input value.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.None; @@ -577,7 +579,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Gets or sets the value. /// [AddedVersion("1.0.0")] - [Description("Gets or sets the value.")] + [Description("Gets or sets the current currency value bound to the input.")] [Parameter] public TValue Value { get; set; } = default!; @@ -585,7 +587,7 @@ private bool TryParseValue(object value, out TValue newValue) /// This event fired on every user keystroke that changes the CurrencyInput value. /// [AddedVersion("1.0.0")] - [Description("This event fired on every user keystroke that changes the CurrencyInput value.")] + [Description("Fires whenever user input changes the currency value, including changes produced by typing.")] [Parameter] public EventCallback ValueChanged { get; set; } @@ -597,7 +599,7 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.0.0")] [DefaultValue(null)] - [Description("Gets or sets an expression that identifies the bound value.")] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs b/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs index ce773931f..d9c490011 100644 --- a/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs +++ b/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs @@ -316,7 +316,8 @@ private bool TryParseValue(object value, out TValue newValue) [AddedVersion("1.5.0")] [DefaultValue(false)] - [CascadingParameter] private EditContext EditContext { get; set; } = default!; + [CascadingParameter] + private EditContext EditContext { get; set; } = default!; /// /// Determines whether to restrict the user input to Min and Max range. @@ -383,8 +384,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is . /// - [DefaultValue(null)] [AddedVersion("1.5.0")] + [DefaultValue(null)] [Description("Gets or sets the expression.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs b/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs index 8ae1dcd94..97ae4fe3d 100644 --- a/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs +++ b/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs @@ -134,8 +134,8 @@ private void OnChange(ChangeEventArgs e) /// /// Default value is . /// - [DefaultValue(null)] [AddedVersion("3.5.0")] + [DefaultValue(null)] [Description("Gets or sets the expression.")] [Parameter] public Expression> TextExpression { get; set; } = default!; @@ -166,8 +166,8 @@ private void OnChange(ChangeEventArgs e) /// /// Default value is . /// - [DefaultValue(null)] [AddedVersion("3.5.0")] + [DefaultValue(null)] [Description("Gets or sets the expression.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs index 168b427c4..df3fd42ea 100644 --- a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs +++ b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs @@ -394,8 +394,8 @@ private bool TryParseValue(object value, out TValue newValue) public bool Disabled { get; set; } [AddedVersion("1.0.0")] - [DefaultValue(false)] [CascadingParameter] private EditContext EditContext { get; set; } = default!; + [DefaultValue(false)] /// /// Determines whether to restrict the user input to Min and Max range. diff --git a/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs index 31b72e142..e07895ef8 100644 --- a/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs +++ b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs @@ -37,8 +37,8 @@ protected override void OnInitialized() /// /// Updates the radio input value from JavaScript. /// - [Description("Updates the radio input value from JavaScript.")] [AddedVersion("3.3.0")] + [Description("Updates the radio input value from JavaScript.")] [JSInvokable] public async Task OnChangeJS(bool newValue) { diff --git a/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs b/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs index 687e7e5eb..f4092c90b 100644 --- a/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs +++ b/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs @@ -84,8 +84,8 @@ protected override async Task OnInitializedAsync() /// /// Updates the range input value from JavaScript. /// - [Description("Updates the range input value from JavaScript.")] [AddedVersion("1.10.6")] + [Description("Updates the range input value from JavaScript.")] [JSInvokable] public async Task bsOnInput(object? newValue) { diff --git a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs index cd87ae83c..fdb2a3177 100644 --- a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs +++ b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs @@ -597,8 +597,8 @@ private Task SetImageUploadInProgressAsync(bool value) /// /// Default value is . /// - [DefaultValue(null)] [AddedVersion("4.0.0")] + [DefaultValue(null)] [Description("Gets or sets the expression that identifies the bound value.")] [Parameter] public Expression>? ValueExpression { get; set; } diff --git a/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs b/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs index 0e8deb533..57474ad57 100644 --- a/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs +++ b/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs @@ -280,8 +280,8 @@ private bool TryParseValue(object value, out TValue newValue) public bool Disabled { get; set; } [AddedVersion("1.6.0")] - [DefaultValue(false)] [CascadingParameter] private EditContext EditContext { get; set; } = default!; + [DefaultValue(false)] /// /// Determines whether to restrict the user input to Min and Max range. @@ -348,8 +348,8 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is . /// - [DefaultValue(null)] [AddedVersion("1.6.0")] + [DefaultValue(null)] [Description("Gets or sets the expression.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; From edc21b223096e28e7f2c2ea3f8c22e168577f4fb Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 31 Aug 2026 15:23:16 +0530 Subject: [PATCH 06/14] Improve XML docs for Blazor input components Updated XML comments and Description attributes for DateInput, NumberInput, TextAreaInput, TextInput, and TimeInput. Enhanced clarity, consistency, and user focus in documentation. No changes to runtime behavior; improvements are limited to code documentation and API descriptions. --- .../Form/DateInput/DateInput.razor.cs | 52 +++++++-------- .../Form/NumberInput/NumberInput.razor.cs | 64 +++++++++---------- .../Form/TextAreaInput/TextAreaInput.razor.cs | 48 +++++++------- .../Form/TextInput/TextInput.razor.cs | 40 ++++++------ .../Form/TimeInput/TimeInput.razor.cs | 52 +++++++-------- 5 files changed, 128 insertions(+), 128 deletions(-) diff --git a/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs b/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs index d9c490011..10a250cc9 100644 --- a/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs +++ b/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap; +namespace BlazorBootstrap; [AddedVersion("1.5.0")] public partial class DateInput : BlazorBootstrapComponentBase @@ -117,17 +117,17 @@ protected override async Task OnParametersSetAsync() } /// - /// Disables currency input. + /// Disables the date input so users cannot change its value. /// [AddedVersion("1.5.0")] - [Description("Disables currency input.")] + [Description("Disables the date input so users cannot change its value.")] public void Disable() => Disabled = true; /// - /// Enables currency input. + /// Enables the date input so users can change its value. /// [AddedVersion("1.5.0")] - [Description("Enables currency input.")] + [Description("Enables the date input so users can change its value.")] public void Enable() => Disabled = false; private string GetFormattedValue(object value) @@ -291,26 +291,26 @@ private bool TryParseValue(object value, out TValue newValue) private string autoComplete => AutoComplete ? "true" : "false"; /// - /// If , DateInput can complete the values automatically by the browser. + /// Gets or sets whether browser autocomplete is enabled for the date input. /// /// /// Default value is false. /// [AddedVersion("1.5.0")] [DefaultValue(false)] - [Description("If , DateInput can complete the values automatically by the browser.")] + [Description("Gets or sets whether browser autocomplete is enabled. When true, the browser may offer saved dates for the input.")] [Parameter] public bool AutoComplete { get; set; } /// - /// Gets or sets the disabled state. + /// Gets or sets whether the date input is disabled. /// /// /// Default value is false. /// [AddedVersion("1.5.0")] [DefaultValue(false)] - [Description("Gets or sets the disabled state.")] + [Description("Gets or sets whether the date input is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } @@ -320,73 +320,73 @@ private bool TryParseValue(object value, out TValue newValue) private EditContext EditContext { get; set; } = default!; /// - /// Determines whether to restrict the user input to Min and Max range. - /// If , restricts the user input between the Min and Max range. Else accepts the user input. + /// Gets or sets whether input is restricted to the configured minimum and maximum dates. + /// /// /// /// Default value is false. /// - [Description("Determines whether to restrict the user input to Min and Max range. If , restricts the user input between the Min and Max range. Else accepts the user input.")] + [Description("Gets or sets whether input is restricted to the configured minimum and maximum dates. If , restricts the user input between the Min and Max range. Else accepts the user input.")] [Parameter] public bool EnableMinMax { get; set; } private string fieldCssClasses => EditContext?.FieldCssClass(fieldIdentifier) ?? ""; /// - /// Gets or sets the max. - /// Allowed format is yyyy-mm-dd. + /// Gets or sets the maximum permitted date. + /// /// [AddedVersion("1.5.0")] - [Description("Gets or sets the max. Allowed format is yyyy-mm-dd.")] + [Description("Gets or sets the maximum permitted date. ")] [Parameter] public TValue Max { get; set; } = default!; /// - /// Gets or sets the min. - /// Allowed format is yyyy-mm-dd. + /// Gets or sets the minimum permitted date. + /// /// [AddedVersion("1.5.0")] - [Description("Gets or sets the min. Allowed format is yyyy-mm-dd.")] + [Description("Gets or sets the minimum permitted date. ")] [Parameter] public TValue Min { get; set; } = default!; /// - /// Gets or sets the placeholder. + /// Gets or sets placeholder text displayed when the input has no value. /// /// /// Default value is null. /// [AddedVersion("1.5.0")] [DefaultValue(null)] - [Description("Gets or sets the placeholder.")] + [Description("Gets or sets placeholder text displayed when the input has no value.")] [Parameter] public string? Placeholder { get; set; } /// - /// Gets or sets the value. + /// Gets or sets the current date value bound to the input. /// [AddedVersion("1.5.0")] - [Description("Gets or sets the value.")] + [Description("Gets or sets the current date value bound to the input.")] [Parameter] public TValue Value { get; set; } = default!; /// - /// This event fired on every user keystroke that changes the DateInput value. + /// Occurs whenever user input changes the date value, including changes produced by typing. /// [AddedVersion("1.5.0")] - [Description("This event fired on every user keystroke that changes the DateInput value.")] + [Description("Fires whenever user input changes the date value, including changes produced by typing.")] [Parameter] public EventCallback ValueChanged { get; set; } /// - /// Gets or sets the expression. + /// Gets or sets the expression that identifies the bound value for validation and EditContext notifications. /// /// /// Default value is . /// [AddedVersion("1.5.0")] [DefaultValue(null)] - [Description("Gets or sets the expression.")] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs index df3fd42ea..dcec2c4be 100644 --- a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs +++ b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap; +namespace BlazorBootstrap; [AddedVersion("1.0.0")] public partial class NumberInput : BlazorBootstrapComponentBase @@ -79,17 +79,17 @@ protected override async Task OnInitializedAsync() } /// - /// Disables number input. + /// Disables the number input so users cannot change its value. /// [AddedVersion("1.0.0")] - [Description("Disables number input.")] + [Description("Disables the number input so users cannot change its value.")] public void Disable() => Disabled = true; /// - /// Enables number input. + /// Enables the number input so users can change its value. /// [AddedVersion("1.0.0")] - [Description("Enables number input.")] + [Description("Enables the number input so users can change its value.")] public void Enable() => Disabled = false; private string GetInvariantNumber(TValue value) @@ -363,33 +363,33 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.0.0")] [DefaultValue(false)] - [Description("If , allows negative numbers.")] + [Description("Gets or sets whether users can enter negative numbers. When false, negative input is rejected during parsing.")] [Parameter] public bool AllowNegativeNumbers { get; set; } private string autoComplete => AutoComplete ? "true" : "false"; /// - /// If , NumberInput can complete the values automatically by the browser. + /// Gets or sets whether browser autocomplete is enabled for the number input. /// /// /// Default value is false. /// [AddedVersion("1.0.0")] [DefaultValue(false)] - [Description("If , NumberInput can complete the values automatically by the browser.")] + [Description("Gets or sets whether browser autocomplete is enabled. When true, the browser may offer saved values for the input.")] [Parameter] public bool AutoComplete { get; set; } /// - /// Gets or sets the disabled state . + /// Gets or sets whether the input is disabled. /// /// /// Default value is false. /// [AddedVersion("1.0.0")] [DefaultValue(false)] - [Description("Gets or sets the disabled state .")] + [Description("Gets or sets whether the input is disabled.")] [Parameter] public bool Disabled { get; set; } @@ -398,20 +398,20 @@ private bool TryParseValue(object value, out TValue newValue) [DefaultValue(false)] /// - /// Determines whether to restrict the user input to Min and Max range. - /// If , restricts the user input between the Min and Max range. Else accepts the user input. + /// Gets or sets whether input is restricted to the configured minimum and maximum values. + /// /// /// /// Default value is false. /// - [Description("Determines whether to restrict the user input to Min and Max range. If , restricts the user input between the Min and Max range. Else accepts the user input.")] + [Description("Gets or sets whether input is restricted to the configured minimum and maximum values. If , restricts the user input between the Min and Max range. Else accepts the user input.")] [Parameter] public bool EnableMinMax { get; set; } private string fieldCssClasses => EditContext?.FieldCssClass(fieldIdentifier) ?? ""; /// - /// Gets or sets the locale. Default locale is 'en-US'. + /// Gets or sets the culture name used to parse and format the number. /// /// /// Default value is 'en-US'. @@ -422,84 +422,84 @@ private bool TryParseValue(object value, out TValue newValue) public string Locale { get; set; } = "en-US"; /// - /// Gets or sets the max. - /// Max ignored if EnableMinMax="false". + /// Gets or sets the maximum permitted value. + /// /// [AddedVersion("1.0.0")] - [Description("Gets or sets the max. Max ignored if EnableMinMax=\"false\".")] + [Description("Gets or sets the maximum permitted value. Max ignored if EnableMinMax=\"false\".")] [Parameter] public TValue Max { get; set; } = default!; /// - /// Gets or sets the min. - /// Min ignored if EnableMinMax="false". + /// Gets or sets the minimum permitted value. + /// /// [AddedVersion("1.0.0")] - [Description("Gets or sets the min. Min ignored if EnableMinMax=\"false\".")] + [Description("Gets or sets the minimum permitted value. Min ignored if EnableMinMax=\"false\".")] [Parameter] public TValue Min { get; set; } = default!; /// - /// Gets or sets the placeholder. + /// Gets or sets placeholder text displayed when the input has no value. /// /// /// Default value is null. /// [AddedVersion("1.0.0")] [DefaultValue(null)] - [Description("Gets or sets the placeholder.")] + [Description("Gets or sets placeholder text displayed when the input has no value.")] [Parameter] public string? Placeholder { get; set; } /// - /// Gets or sets the step. + /// Gets or sets the increment used by the browser's number input controls. /// /// /// Default value is null. /// [AddedVersion("1.0.0")] [DefaultValue(null)] - [Description("Gets or sets the step.")] + [Description("Gets or sets the increment used by the browser's number input controls.")] [Parameter] public double? Step { get; set; } /// - /// Gets or sets the text alignment. + /// Gets or sets the horizontal alignment of the input value. /// /// /// Default value is . /// [AddedVersion("1.0.0")] [DefaultValue(Alignment.None)] - [Description("Gets or sets the text alignment.")] + [Description("Gets or sets the horizontal alignment of the input value.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.None; /// - /// Gets or sets the value. + /// Gets or sets the current numeric value bound to the input. /// [AddedVersion("1.0.0")] - [Description("Gets or sets the value.")] + [Description("Gets or sets the current numeric value bound to the input.")] [Parameter] public TValue Value { get; set; } = default!; /// - /// This event fired on every user keystroke that changes the NumberInput value. + /// Occurs whenever user input changes the number value, including changes produced by typing. /// [AddedVersion("1.0.0")] - [Description("This event fired on every user keystroke that changes the NumberInput value.")] + [Description("Occurs whenever user input changes the number value, including changes produced by typing.")] [Parameter] public EventCallback ValueChanged { get; set; } /// - /// Gets or sets an expression that identifies the bound value. + /// Gets or sets the expression that identifies the bound value for validation and EditContext notifications. /// /// /// Default value is . /// [AddedVersion("1.0.0")] [DefaultValue(null)] - [Description("Gets or sets an expression that identifies the bound value.")] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs index 041e0e565..e75b0db65 100644 --- a/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs +++ b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap; +namespace BlazorBootstrap; [AddedVersion("3.3.0")] public partial class TextAreaInput : BlazorBootstrapComponentBase @@ -21,17 +21,17 @@ protected override void OnInitialized() } /// - /// Disables number input. + /// Disables the text area so users cannot change its value. /// [AddedVersion("3.3.0")] - [Description("Disables number input.")] + [Description("Disables the text area so users cannot change its value.")] public void Disable() => Disabled = true; /// - /// Enables number input. + /// Enables the text area so users can change its value. /// [AddedVersion("3.3.0")] - [Description("Enables number input.")] + [Description("Enables the text area so users can change its value.")] public void Enable() => Disabled = false; private async Task OnChange(ChangeEventArgs e) @@ -58,38 +58,38 @@ private async Task OnChange(ChangeEventArgs e) private string autoComplete => AutoComplete ? "true" : "false"; /// - /// If , NumberInput can complete the values automatically by the browser. + /// Gets or sets whether browser autocomplete is enabled for the text area. /// /// /// Default value is false. /// [AddedVersion("3.3.0")] [DefaultValue(false)] - [Description("If , NumberInput can complete the values automatically by the browser.")] + [Description("Gets or sets whether browser autocomplete is enabled. When true, the browser may offer saved values for the text area.")] [Parameter] public bool AutoComplete { get; set; } /// - /// Gets or sets the number of columns. + /// Gets or sets the visible width of the text area in columns. /// /// /// Default value is . /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets the number of columns.")] + [Description("Gets or sets the visible width of the text area in columns.")] [Parameter] public int? Cols { get; set; } /// - /// Gets or sets the disabled state. + /// Gets or sets whether the text area is disabled. /// /// /// Default value is false. /// [AddedVersion("3.3.0")] [DefaultValue(false)] - [Description("Gets or sets the disabled state.")] + [Description("Gets or sets whether the text area is disabled.")] [Parameter] public bool Disabled { get; set; } @@ -98,62 +98,62 @@ private async Task OnChange(ChangeEventArgs e) private string fieldCssClasses => EditContext?.FieldCssClass(fieldIdentifier) ?? ""; /// - /// Gets or sets the maximum number of characters that can be entered. + /// Gets or sets the maximum number of characters users can enter. /// /// /// Default value is . /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets the maximum number of characters that can be entered.")] + [Description("Gets or sets the maximum number of characters users can enter.")] [Parameter] public int? MaxLength { get; set; } /// - /// Gets or sets the placeholder text. + /// Gets or sets placeholder text displayed when the text area has no value. /// /// /// Default value is null. /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets the placeholder text.")] + [Description("Gets or sets placeholder text displayed when the text area has no value.")] [Parameter] public string? Placeholder { get; set; } /// - /// Gets or sets the number of rows. + /// Gets or sets the visible height of the text area in rows. /// /// /// Default value is . /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets the number of rows.")] + [Description("Gets or sets the visible height of the text area in rows.")] [Parameter] public int? Rows { get; set; } /// - /// Gets or sets the text alignment. + /// Gets or sets the horizontal alignment of the text area value. /// /// /// Default value is . /// [AddedVersion("3.3.0")] [DefaultValue(Alignment.None)] - [Description("Gets or sets the text alignment.")] + [Description("Gets or sets the horizontal alignment of the text area value.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.None; /// - /// Gets or sets the value. + /// Gets or sets the current text value bound to the text area. /// /// /// Default value is . /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets the value.")] + [Description("Gets or sets the current text value bound to the text area.")] [Parameter] public string Value { get; set; } = default!; @@ -161,19 +161,19 @@ private async Task OnChange(ChangeEventArgs e) /// This event fires when the value changes. /// [AddedVersion("3.3.0")] - [Description("This event fires when the value changes.")] + [Description("Fires whenever user input changes the text area value.")] [Parameter] public EventCallback ValueChanged { get; set; } /// - /// Gets or sets an expression that identifies the bound value. + /// Gets or sets the expression that identifies the bound value for validation and EditContext notifications. /// /// /// Default value is . /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets an expression that identifies the bound value.")] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs b/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs index ffb73774f..66a35659e 100644 --- a/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs +++ b/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap; +namespace BlazorBootstrap; [AddedVersion("3.3.0")] public partial class TextInput : BlazorBootstrapComponentBase @@ -21,17 +21,17 @@ protected override void OnInitialized() } /// - /// Disables number input. + /// Disables the text input so users cannot change its value. /// [AddedVersion("3.3.0")] - [Description("Disables number input.")] + [Description("Disables the text input so users cannot change its value.")] public void Disable() => Disabled = true; /// - /// Enables number input. + /// Enables the text input so users can change its value. /// [AddedVersion("3.3.0")] - [Description("Enables number input.")] + [Description("Enables the text input so users can change its value.")] public void Enable() => Disabled = false; private async Task OnChange(ChangeEventArgs e) @@ -58,26 +58,26 @@ private async Task OnChange(ChangeEventArgs e) private string autoComplete => AutoComplete ? "true" : "false"; /// - /// If , TextInput can complete the values automatically by the browser. + /// Gets or sets whether browser autocomplete is enabled for the text input. /// /// /// Default value is false. /// [AddedVersion("3.3.0")] [DefaultValue(false)] - [Description("If , TextInput can complete the values automatically by the browser.")] + [Description("Gets or sets whether browser autocomplete is enabled. When true, the browser may offer saved values for the input.")] [Parameter] public bool AutoComplete { get; set; } /// - /// Gets or sets the disabled state. + /// Gets or sets whether the input is disabled. /// /// /// Default value is false. /// [AddedVersion("3.3.0")] [DefaultValue(false)] - [Description("Gets or sets the disabled state.")] + [Description("Gets or sets whether the input is disabled.")] [Parameter] public bool Disabled { get; set; } @@ -86,50 +86,50 @@ private async Task OnChange(ChangeEventArgs e) private string fieldCssClasses => EditContext?.FieldCssClass(fieldIdentifier) ?? ""; /// - /// Gets or sets the maximum number of characters that can be entered. + /// Gets or sets the maximum number of characters users can enter. /// /// /// Default value is . /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets the maximum number of characters that can be entered.")] + [Description("Gets or sets the maximum number of characters users can enter.")] [Parameter] public int? MaxLength { get; set; } /// - /// Gets or sets the placeholder text. + /// Gets or sets placeholder text displayed when the input has no value. /// /// /// Default value is null. /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets the placeholder text.")] + [Description("Gets or sets placeholder text displayed when the input has no value.")] [Parameter] public string? Placeholder { get; set; } /// - /// Gets or sets the text alignment. + /// Gets or sets the horizontal alignment of the input value. /// /// /// Default value is . /// [AddedVersion("3.3.0")] [DefaultValue(Alignment.None)] - [Description("Gets or sets the text alignment.")] + [Description("Gets or sets the horizontal alignment of the input value.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.None; /// - /// Gets or sets the value. + /// Gets or sets the current text value bound to the input. /// /// /// Default value is . /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets the value.")] + [Description("Gets or sets the current text value bound to the input.")] [Parameter] public string Value { get; set; } = default!; @@ -137,19 +137,19 @@ private async Task OnChange(ChangeEventArgs e) /// This event fires when the value changes. /// [AddedVersion("3.3.0")] - [Description("This event fires when the value changes.")] + [Description("Fires whenever user input changes the text value.")] [Parameter] public EventCallback ValueChanged { get; set; } /// - /// Gets or sets an expression that identifies the bound value. + /// Gets or sets the expression that identifies the bound value for validation and EditContext notifications. /// /// /// Default value is . /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets an expression that identifies the bound value.")] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs b/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs index 57474ad57..b7acd3e4d 100644 --- a/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs +++ b/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap; +namespace BlazorBootstrap; [AddedVersion("1.6.0")] public partial class TimeInput : BlazorBootstrapComponentBase @@ -113,17 +113,17 @@ protected override async Task OnParametersSetAsync() } /// - /// Disables currency input. + /// Disables the time input so users cannot change its value. /// [AddedVersion("1.6.0")] - [Description("Disables currency input.")] + [Description("Disables the time input so users cannot change its value.")] public void Disable() => Disabled = true; /// - /// Enables currency input. + /// Enables the time input so users can change its value. /// [AddedVersion("1.6.0")] - [Description("Enables currency input.")] + [Description("Enables the time input so users can change its value.")] public void Enable() => Disabled = false; private string GetFormattedValue(object value) @@ -256,26 +256,26 @@ private bool TryParseValue(object value, out TValue newValue) private string autoComplete => AutoComplete ? "true" : "false"; /// - /// If , DateInput can complete the values automatically by the browser. + /// Gets or sets whether browser autocomplete is enabled for the time input. /// /// /// Default value is false. /// [AddedVersion("1.6.0")] [DefaultValue(false)] - [Description("If , DateInput can complete the values automatically by the browser.")] + [Description("Gets or sets whether browser autocomplete is enabled. When true, the browser may offer saved times for the input.")] [Parameter] public bool AutoComplete { get; set; } /// - /// Gets or sets the disabled state. + /// Gets or sets whether the time input is disabled. /// /// /// Default value is false. /// [AddedVersion("1.6.0")] [DefaultValue(false)] - [Description("Gets or sets the disabled state.")] + [Description("Gets or sets whether the time input is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } @@ -284,73 +284,73 @@ private bool TryParseValue(object value, out TValue newValue) [DefaultValue(false)] /// - /// Determines whether to restrict the user input to Min and Max range. - /// If , restricts the user input between the Min and Max range. Else accepts the user input. + /// Gets or sets whether input is restricted to the configured minimum and maximum times. + /// /// /// /// Default value is false. /// - [Description("Determines whether to restrict the user input to Min and Max range. If , restricts the user input between the Min and Max range. Else accepts the user input.")] + [Description("Gets or sets whether input is restricted to the configured minimum and maximum times. If , restricts the user input between the Min and Max range. Else accepts the user input.")] [Parameter] public bool EnableMinMax { get; set; } private string fieldCssClasses => EditContext?.FieldCssClass(fieldIdentifier) ?? ""; /// - /// Gets or sets the max. - /// Allowed format is hh:mm. + /// Gets or sets the maximum permitted time. + /// /// [AddedVersion("1.6.0")] - [Description("Gets or sets the max. Allowed format is hh:mm.")] + [Description("Gets or sets the maximum permitted time. ")] [Parameter] public TValue Max { get; set; } = default!; /// - /// Gets or sets the min. - /// Allowed format is hh:mm. + /// Gets or sets the minimum permitted time. + /// /// [AddedVersion("1.6.0")] - [Description("Gets or sets the min. Allowed format is hh:mm.")] + [Description("Gets or sets the minimum permitted time. ")] [Parameter] public TValue Min { get; set; } = default!; /// - /// Gets or sets the placeholder. + /// Gets or sets placeholder text displayed when the input has no value. /// /// /// Default value is null. /// [AddedVersion("1.6.0")] [DefaultValue(null)] - [Description("Gets or sets the placeholder.")] + [Description("Gets or sets placeholder text displayed when the input has no value.")] [Parameter] public string? Placeholder { get; set; } /// - /// Gets or sets the value. + /// Gets or sets the current time value bound to the input. /// [AddedVersion("1.6.0")] - [Description("Gets or sets the value.")] + [Description("Gets or sets the current time value bound to the input.")] [Parameter] public TValue Value { get; set; } = default!; /// - /// This event fired on every user keystroke that changes the TimeInput value. + /// Occurs whenever user input changes the time value, including changes produced by typing. /// [AddedVersion("1.6.0")] - [Description("This event fired on every user keystroke that changes the TimeInput value.")] + [Description("Fires whenever user input changes the time value, including changes produced by typing.")] [Parameter] public EventCallback ValueChanged { get; set; } /// - /// Gets or sets the expression. + /// Gets or sets the expression that identifies the bound value for validation and EditContext notifications. /// /// /// Default value is . /// [AddedVersion("1.6.0")] [DefaultValue(null)] - [Description("Gets or sets the expression.")] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; From 7cd7f7130e8fbefc8a039133180a0585105ee8cc Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 31 Aug 2026 15:30:24 +0530 Subject: [PATCH 07/14] Improve XML docs and descriptions for Blazor inputs Update and clarify XML documentation comments and [Description] attributes for Blazor input components. Enhance descriptions to specify component behavior, user interaction, and parameter effects. No functional changes; only documentation improved for API clarity. --- .../Form/AutoComplete/AutoComplete.razor.cs | 36 +++++++++--------- .../Form/CheckboxInput/CheckboxInput.razor.cs | 20 +++++----- .../Form/DateInput/DateInput.razor.cs | 8 ++-- .../DragAndDropFileInput.razor.cs | 4 +- .../Form/EnumInput/EnumInput.razor.cs | 20 +++++----- .../Form/FileInput/FileInput.razor.cs | 4 +- .../Form/FileInput/FileInputBase.cs | 24 ++++++------ .../Form/NumberInput/NumberInput.razor.cs | 10 ++--- .../Form/OTPInput/OTPInput.razor.cs | 12 +++--- .../Form/PasswordInput/PasswordInput.razor.cs | 20 +++++----- .../Form/RadioInput/RadioInput.razor.cs | 26 ++++++------- .../Form/RangeInput/RangeInput.razor.cs | 18 ++++----- .../RichTextEditor/RichTextEditor.razor.cs | 38 +++++++++---------- .../RichTextEditorToolbarButton.razor.cs | 6 +-- .../Components/Form/Switch/Switch.razor.cs | 22 +++++------ .../Form/TextAreaInput/TextAreaInput.razor.cs | 6 +-- .../Form/TextInput/TextInput.razor.cs | 6 +-- .../Form/TimeInput/TimeInput.razor.cs | 8 ++-- 18 files changed, 144 insertions(+), 144 deletions(-) diff --git a/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs b/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs index e2feb5585..91a0e45d0 100644 --- a/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs +++ b/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs @@ -118,14 +118,14 @@ public void bsShownAutocomplete() { } /// Disables autocomplete. /// [AddedVersion("1.0.0")] - [Description("Disables autocomplete.")] + [Description("Disables the autocomplete input so users cannot search or change its value.")] public void Disable() => Disabled = true; /// /// Enables autocomplete. /// [AddedVersion("1.0.0")] - [Description("Enables autocomplete.")] + [Description("Enables the autocomplete input so users can search and select a value.")] public void Enable() => Disabled = false; /// @@ -133,14 +133,14 @@ public void bsShownAutocomplete() { } /// /// Task [AddedVersion("1.0.0")] - [Description("Refresh the autocomplete data.")] + [Description("Refreshes the autocomplete results using the current input value and data provider.")] public async Task RefreshDataAsync() => await FilterDataAsync(); /// /// Resets the autocomplete selection. /// [AddedVersion("1.0.0")] - [Description("Resets the autocomplete selection.")] + [Description("Clears the input and selected item, then notifies bound values and the change callback.")] public async Task ResetAsync() => await ClearInputTextAsync(); /// @@ -329,7 +329,7 @@ private async Task ShowAsync() /// [AddedVersion("1.0.0")] [DefaultValue(null)] - [Description("Gets or sets the data provider.")] + [Description("Gets or sets the delegate used to retrieve autocomplete results for the current filter.")] [EditorRequired] [Parameter] public AutoCompleteDataProviderDelegate? DataProvider { get; set; } @@ -354,7 +354,7 @@ private async Task ShowAsync() /// [AddedVersion("1.0.0")] [DefaultValue(false)] - [Description("Gets or sets the disabled state.")] + [Description("Gets or sets whether the autocomplete input is disabled. When true, users cannot search or select a value.")] [Parameter] public bool Disabled { get; set; } @@ -369,7 +369,7 @@ private async Task ShowAsync() /// [AddedVersion("1.0.0")] [DefaultValue("No records found.")] - [Description("Gets or sets the empty text.")] + [Description("Gets or sets the message displayed when the data provider returns no matching results.")] [Parameter] public string EmptyText { get; set; } = "No records found."; @@ -383,7 +383,7 @@ private async Task ShowAsync() /// [AddedVersion("1.0.0")] [DefaultValue("Loading...")] - [Description("Gets or sets the loading text.")] + [Description("Gets or sets the message displayed while autocomplete results are loading.")] [Parameter] public string LoadingText { get; set; } = "Loading..."; @@ -391,7 +391,7 @@ private async Task ShowAsync() /// This event fires immediately when the autocomplete selection changes by the user. /// [AddedVersion("1.0.0")] - [Description("This event fires immediately when the autocomplete selection changes by the user.")] + [Description("Fires after a user selects an autocomplete item and supplies the selected item.")] [Parameter] public EventCallback OnChanged { get; set; } @@ -403,7 +403,7 @@ private async Task ShowAsync() /// [AddedVersion("1.0.0")] [DefaultValue(null)] - [Description("Gets or sets the placeholder.")] + [Description("Gets or sets placeholder text displayed when the autocomplete input has no value.")] [Parameter] public string? Placeholder { get; set; } @@ -415,7 +415,7 @@ private async Task ShowAsync() /// [AddedVersion("1.0.0")] [DefaultValue(null)] - [Description("Gets or sets the property name.")] + [Description("Gets or sets the TItem property whose text is shown and filtered in the autocomplete input.")] [EditorRequired] [Parameter] public string? PropertyName { get; set; } @@ -425,7 +425,7 @@ private async Task ShowAsync() /// [AddedVersion("1.0.0")] [DefaultValue(null)] - [Description("Gets selected item.")] + [Description("Gets the item most recently selected by the user, or null when no item is selected.")] public TItem? SelectedItem => selectedItem; /// @@ -436,7 +436,7 @@ private async Task ShowAsync() /// [AddedVersion("1.0.0")] [DefaultValue(AutoCompleteSize.Default)] - [Description("Gets or sets the autocomplete size.")] + [Description("Gets or sets the Bootstrap size of the autocomplete input.")] [Parameter] public AutoCompleteSize Size { get; set; } = AutoCompleteSize.Default; @@ -448,7 +448,7 @@ private async Task ShowAsync() /// [AddedVersion("1.0.0")] [DefaultValue(StringComparison.OrdinalIgnoreCase)] - [Description("Gets or sets the StringComparison.")] + [Description("Gets or sets the string-comparison rule used when filtering results.")] [Parameter] public StringComparison StringComparison { get; set; } = StringComparison.OrdinalIgnoreCase; @@ -460,7 +460,7 @@ private async Task ShowAsync() /// [AddedVersion("1.0.0")] [DefaultValue(StringFilterOperator.Contains)] - [Description("Gets or sets the string filter operator.")] + [Description("Gets or sets the operator used to match the input text against PropertyName.")] [Parameter] public StringFilterOperator StringFilterOperator { get; set; } = StringFilterOperator.Contains; @@ -472,7 +472,7 @@ private async Task ShowAsync() /// [AddedVersion("1.0.0")] [DefaultValue(null)] - [Description("Gets or sets the value.")] + [Description("Gets or sets the current text value bound to the autocomplete input.")] [Parameter] public string? Value { get; set; } @@ -480,7 +480,7 @@ private async Task ShowAsync() /// This is event fires on every user keystroke that changes the textbox value. /// [AddedVersion("1.0.0")] - [Description("This is event fires on every user keystroke that changes the textbox value.")] + [Description("Fires whenever user input changes the autocomplete text value, including changes produced by typing.")] [Parameter] public EventCallback ValueChanged { get; set; } @@ -492,7 +492,7 @@ private async Task ShowAsync() /// [AddedVersion("1.0.0")] [DefaultValue(null)] - [Description("Gets or sets the value expression.")] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression>? ValueExpression { get; set; } diff --git a/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs b/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs index 82b04859e..dd103654c 100644 --- a/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs +++ b/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs @@ -21,17 +21,17 @@ protected override void OnInitialized() } /// - /// Disables checkbox input. + /// Disables the checkbox so users cannot change its value. /// [AddedVersion("3.3.0")] - [Description("Disables checkbox input.")] + [Description("Disables the checkbox so users cannot change its value.")] public void Disable() => Disabled = true; /// - /// Enables checkbox input. + /// Enables the checkbox so users can change its value. /// [AddedVersion("3.3.0")] - [Description("Enables checkbox input.")] + [Description("Enables the checkbox so users can change its value.")] public void Enable() => Disabled = false; private async Task OnChange(ChangeEventArgs e) @@ -56,14 +56,14 @@ private async Task OnChange(ChangeEventArgs e) ); /// - /// Gets or sets the disabled state. + /// Gets or sets whether the checkbox is disabled. /// /// /// Default value is false. /// [AddedVersion("3.3.0")] [DefaultValue(false)] - [Description("Gets or sets the disabled state.")] + [Description("Gets or sets whether the checkbox is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } @@ -81,7 +81,7 @@ private async Task OnChange(ChangeEventArgs e) /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets the label.")] + [Description("Gets or sets the label displayed next to the checkbox.")] [Parameter] public string? Label { get; set; } @@ -93,7 +93,7 @@ private async Task OnChange(ChangeEventArgs e) /// [AddedVersion("3.3.0")] [DefaultValue(false)] - [Description("Gets or sets the value.")] + [Description("Gets or sets the current checked value bound to the checkbox.")] [Parameter] public bool Value { get; set; } @@ -101,7 +101,7 @@ private async Task OnChange(ChangeEventArgs e) /// This event fires when the value changes. /// [AddedVersion("3.3.0")] - [Description("This event fires when the value changes.")] + [Description("Fires whenever user interaction changes the checked value.")] [Parameter] public EventCallback ValueChanged { get; set; } @@ -113,7 +113,7 @@ private async Task OnChange(ChangeEventArgs e) /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets an expression that identifies the bound value.")] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs b/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs index 10a250cc9..8952d080b 100644 --- a/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs +++ b/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap; +namespace BlazorBootstrap; [AddedVersion("1.5.0")] public partial class DateInput : BlazorBootstrapComponentBase @@ -326,7 +326,7 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// - [Description("Gets or sets whether input is restricted to the configured minimum and maximum dates. If , restricts the user input between the Min and Max range. Else accepts the user input.")] + [Description("Gets or sets whether input is restricted to the configured minimum and maximum dates. When true, dates outside the range are rejected.")] [Parameter] public bool EnableMinMax { get; set; } @@ -337,7 +337,7 @@ private bool TryParseValue(object value, out TValue newValue) /// /// [AddedVersion("1.5.0")] - [Description("Gets or sets the maximum permitted date. ")] + [Description("Gets or sets the maximum permitted date. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Max { get; set; } = default!; @@ -346,7 +346,7 @@ private bool TryParseValue(object value, out TValue newValue) /// /// [AddedVersion("1.5.0")] - [Description("Gets or sets the minimum permitted date. ")] + [Description("Gets or sets the minimum permitted date. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Min { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/DragAndDropFileInput/DragAndDropFileInput.razor.cs b/blazorbootstrap/Components/Form/DragAndDropFileInput/DragAndDropFileInput.razor.cs index 1a4cc0f7a..5315d7173 100644 --- a/blazorbootstrap/Components/Form/DragAndDropFileInput/DragAndDropFileInput.razor.cs +++ b/blazorbootstrap/Components/Form/DragAndDropFileInput/DragAndDropFileInput.razor.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap; +namespace BlazorBootstrap; public partial class DragAndDropFileInput : FileInputBase { @@ -41,7 +41,7 @@ protected void OnDrop(DragEventArgs _) /// [AddedVersion("4.0.0")] [DefaultValue(BackgroundColor.None)] - [Description("Gets or sets the contextual background color of the drag-and-drop area.")] + [Description("Gets or sets the Bootstrap contextual background color of the drop area. The color is applied while the area is not using its default background.")] [Parameter] public BackgroundColor BackgroundColor { get; set; } = BackgroundColor.None; diff --git a/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs b/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs index 97ae4fe3d..940719a56 100644 --- a/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs +++ b/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs @@ -35,14 +35,14 @@ protected override void OnParametersSet() /// Disables the . /// [AddedVersion("3.5.0")] - [Description("Disables the .")] + [Description("Disables the enum input so users cannot change its selection.")] public void Disable() => Disabled = true; /// /// Enables the . /// [AddedVersion("3.5.0")] - [Description("Enables the .")] + [Description("Enables the enum input so users can change its selection.")] public void Enable() => Disabled = false; private void OnChange(ChangeEventArgs e) @@ -87,7 +87,7 @@ private void OnChange(ChangeEventArgs e) /// [AddedVersion("3.5.0")] [DefaultValue(false)] - [Description("Gets or sets the disabled state. Default value is false.")] + [Description("Gets or sets whether the enum input is disabled. When true, users cannot change its selection.")] [Parameter] public bool Disabled { get; set; } = false; @@ -104,7 +104,7 @@ private void OnChange(ChangeEventArgs e) /// [AddedVersion("3.5.0")] [DefaultValue(EnumInputSize.None)] - [Description("Gets or sets the size. Default value is .")] + [Description("Gets or sets the Bootstrap size of the enum select input.")] [Parameter] public EnumInputSize Size { get; set; } = EnumInputSize.None; @@ -116,7 +116,7 @@ private void OnChange(ChangeEventArgs e) /// [AddedVersion("3.5.0")] [DefaultValue(null)] - [Description("Gets or sets the text. Default value is .")] + [Description("Gets or sets the display text of the selected enum value.")] [Parameter] public string Text { get; set; } = default!; @@ -124,7 +124,7 @@ private void OnChange(ChangeEventArgs e) /// This event fires when the text changes. /// [AddedVersion("3.5.0")] - [Description("This event fires when the text changes.")] + [Description("Fires whenever selection changes the display text of the selected enum value.")] [Parameter] public EventCallback TextChanged { get; set; } @@ -136,7 +136,7 @@ private void OnChange(ChangeEventArgs e) /// [AddedVersion("3.5.0")] [DefaultValue(null)] - [Description("Gets or sets the expression.")] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression> TextExpression { get; set; } = default!; @@ -148,7 +148,7 @@ private void OnChange(ChangeEventArgs e) /// [AddedVersion("3.5.0")] [DefaultValue(0)] - [Description("Gets or sets the value. Default value is 0.")] + [Description("Gets or sets the numeric value of the selected enum member.")] [Parameter] public int Value { get; set; } @@ -156,7 +156,7 @@ private void OnChange(ChangeEventArgs e) /// This event fires when the value changes. /// [AddedVersion("3.5.0")] - [Description("This event fires when the value changes.")] + [Description("Fires whenever selection changes the numeric value of the selected enum member.")] [Parameter] public EventCallback ValueChanged { get; set; } @@ -168,7 +168,7 @@ private void OnChange(ChangeEventArgs e) /// [AddedVersion("3.5.0")] [DefaultValue(null)] - [Description("Gets or sets the expression.")] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/FileInput/FileInput.razor.cs b/blazorbootstrap/Components/Form/FileInput/FileInput.razor.cs index 6d0c1c891..2fffec072 100644 --- a/blazorbootstrap/Components/Form/FileInput/FileInput.razor.cs +++ b/blazorbootstrap/Components/Form/FileInput/FileInput.razor.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap; +namespace BlazorBootstrap; public partial class FileInput : FileInputBase { @@ -9,7 +9,7 @@ public partial class FileInput : FileInputBase /// [AddedVersion("4.0.0")] [DefaultValue(FileInputSize.Default)] - [Description("Gets or sets the component size.")] + [Description("Gets or sets the Bootstrap size used to render the file picker.")] [Parameter] public FileInputSize Size { get; set; } = FileInputSize.Default; diff --git a/blazorbootstrap/Components/Form/FileInput/FileInputBase.cs b/blazorbootstrap/Components/Form/FileInput/FileInputBase.cs index 149895cb0..5f8754316 100644 --- a/blazorbootstrap/Components/Form/FileInput/FileInputBase.cs +++ b/blazorbootstrap/Components/Form/FileInput/FileInputBase.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap; +namespace BlazorBootstrap; public abstract class FileInputBase : BlazorBootstrapComponentBase { @@ -122,7 +122,7 @@ private static string FormatValidationMessage(string template, params (string To /// [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the allowed file extensions.")] + [Description("Gets or sets the file extensions accepted by the picker. Null or an empty collection permits every extension.")] [Parameter] public IEnumerable? AllowedFileTypes { get; set; } @@ -139,7 +139,7 @@ private static string FormatValidationMessage(string template, params (string To /// This event fires when the selected files change. /// [AddedVersion("4.0.0")] - [Description("This event fires when the selected files change.")] + [Description("Fires after accepted files are added or removed and supplies the current read-only file list.")] [Parameter] public EventCallback> FilesChanged { get; set; } @@ -148,7 +148,7 @@ private static string FormatValidationMessage(string template, params (string To /// [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the hint text displayed below the component.")] + [Description("Gets or sets supplementary text displayed below the file selection area.")] [Parameter] public string? HintText { get; set; } @@ -158,7 +158,7 @@ private static string FormatValidationMessage(string template, params (string To /// [AddedVersion("4.0.0")] [DefaultValue(DefaultInvalidFileTypeErrorMessage)] - [Description("Gets or sets the invalid file type validation message template.")] + [Description("Gets or sets the message template used when a selected file extension is not allowed. Supports {FileName} and {AllowedFileTypes} tokens.")] [Parameter] public string InvalidFileTypeErrorMessage { get; set; } = DefaultInvalidFileTypeErrorMessage; @@ -167,7 +167,7 @@ private static string FormatValidationMessage(string template, params (string To /// [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the maximum number of selected files.")] + [Description("Gets or sets the maximum number of accepted files. Null does not impose a file-count limit.")] [Parameter] public int? MaxFileCount { get; set; } @@ -177,7 +177,7 @@ private static string FormatValidationMessage(string template, params (string To /// [AddedVersion("4.0.0")] [DefaultValue(DefaultMaxFileCountErrorMessage)] - [Description("Gets or sets the maximum file count validation message template.")] + [Description("Gets or sets the message template used when a file exceeds the configured file-count limit. Supports {FileName} and {MaxFileCount} tokens.")] [Parameter] public string MaxFileCountErrorMessage { get; set; } = DefaultMaxFileCountErrorMessage; @@ -186,7 +186,7 @@ private static string FormatValidationMessage(string template, params (string To /// [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the maximum allowed file size in bytes.")] + [Description("Gets or sets the maximum accepted file size in bytes. Null does not impose a size limit.")] [Parameter] public long? MaxFileSize { get; set; } @@ -196,7 +196,7 @@ private static string FormatValidationMessage(string template, params (string To /// [AddedVersion("4.0.0")] [DefaultValue(DefaultMaxFileSizeErrorMessage)] - [Description("Gets or sets the maximum file size validation message template.")] + [Description("Gets or sets the message template used when a file exceeds the configured size limit. Supports {FileName} and {MaxFileSize} tokens.")] [Parameter] public string MaxFileSizeErrorMessage { get; set; } = DefaultMaxFileSizeErrorMessage; @@ -205,14 +205,14 @@ private static string FormatValidationMessage(string template, params (string To /// [AddedVersion("4.0.0")] [DefaultValue(false)] - [Description("Gets or sets whether multiple files can be selected.")] + [Description("Gets or sets whether users can select multiple files. When false, selecting a file replaces the current selection.")] [Parameter] public bool Multiple { get; set; } /// /// Gets the currently selected files. /// - [Description("Gets the currently selected files.")] + [Description("Gets a read-only list of files currently accepted by the component.")] public IReadOnlyList SelectedFiles => files.AsReadOnly(); /// @@ -220,7 +220,7 @@ private static string FormatValidationMessage(string template, params (string To /// [AddedVersion("4.0.0")] [DefaultValue(DefaultSingleFileErrorMessage)] - [Description("Gets or sets the single-file selection validation message template.")] + [Description("Gets or sets the message shown when users select multiple files while Multiple is false.")] [Parameter] public string SingleFileErrorMessage { get; set; } = DefaultSingleFileErrorMessage; diff --git a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs index dcec2c4be..d4cd82f86 100644 --- a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs +++ b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap; +namespace BlazorBootstrap; [AddedVersion("1.0.0")] public partial class NumberInput : BlazorBootstrapComponentBase @@ -389,7 +389,7 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.0.0")] [DefaultValue(false)] - [Description("Gets or sets whether the input is disabled.")] + [Description("Gets or sets whether the input is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } @@ -404,7 +404,7 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// - [Description("Gets or sets whether input is restricted to the configured minimum and maximum values. If , restricts the user input between the Min and Max range. Else accepts the user input.")] + [Description("Gets or sets whether input is restricted to the configured minimum and maximum values. When true, values outside the range are rejected.")] [Parameter] public bool EnableMinMax { get; set; } @@ -426,7 +426,7 @@ private bool TryParseValue(object value, out TValue newValue) /// /// [AddedVersion("1.0.0")] - [Description("Gets or sets the maximum permitted value. Max ignored if EnableMinMax=\"false\".")] + [Description("Gets or sets the maximum permitted value. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Max { get; set; } = default!; @@ -435,7 +435,7 @@ private bool TryParseValue(object value, out TValue newValue) /// /// [AddedVersion("1.0.0")] - [Description("Gets or sets the minimum permitted value. Min ignored if EnableMinMax=\"false\".")] + [Description("Gets or sets the minimum permitted value. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Min { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/OTPInput/OTPInput.razor.cs b/blazorbootstrap/Components/Form/OTPInput/OTPInput.razor.cs index af0c38744..aa5bed813 100644 --- a/blazorbootstrap/Components/Form/OTPInput/OTPInput.razor.cs +++ b/blazorbootstrap/Components/Form/OTPInput/OTPInput.razor.cs @@ -26,7 +26,7 @@ protected override void OnParametersSet() /// Clears the OTP input fields. /// [AddedVersion("4.0.0")] - [Description("Clears the OTP input fields.")] + [Description("Clears every OTP digit, raises the change callback, and returns focus to the first field.")] public async Task ClearAsync() { otpValues = new string[Length]; @@ -174,7 +174,7 @@ private async Task OnKeyUp(KeyboardEventArgs e, int index) /// [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the CSS class for the container element.")] + [Description("Gets or sets CSS classes applied to the element that contains the OTP fields.")] [Parameter] public string? ContainerCssClass { get; set; } @@ -186,7 +186,7 @@ private async Task OnKeyUp(KeyboardEventArgs e, int index) /// [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the CSS style for the container element.")] + [Description("Gets or sets inline CSS styles applied to the element that contains the OTP fields.")] [Parameter] public string? ContainerCssStyle { get; set; } @@ -203,7 +203,7 @@ private async Task OnKeyUp(KeyboardEventArgs e, int index) /// [AddedVersion("4.0.0")] [DefaultValue(6)] - [Description("Gets or sets the OTP input length.")] + [Description("Gets or sets the number of digit fields rendered for the one-time password.")] [Parameter] public int Length { get; set; } = 6; @@ -211,7 +211,7 @@ private async Task OnKeyUp(KeyboardEventArgs e, int index) /// This event fires when the OTP input value changes. /// [AddedVersion("4.0.0")] - [Description("This event fires when the OTP input value changes.")] + [Description("Fires whenever an OTP digit changes and supplies the current combined value.")] [Parameter] public EventCallback OnOTPChanged { get; set; } @@ -222,7 +222,7 @@ private async Task OnKeyUp(KeyboardEventArgs e, int index) /// This event fires when the OTP input is completed. /// [AddedVersion("4.0.0")] - [Description("This event fires when the OTP input is completed.")] + [Description("Fires when every OTP field contains a digit and supplies the completed one-time password.")] [Parameter] public EventCallback OnOTPCompleted { get; set; } diff --git a/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs b/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs index fead2430e..94ec5cbbb 100644 --- a/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs +++ b/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs @@ -39,17 +39,17 @@ protected override async Task OnParametersSetAsync() } /// - /// Disables InputPassword. + /// Disables the password input so users cannot change its value. /// [AddedVersion("3.3.0")] - [Description("Disables InputPassword.")] + [Description("Disables the password input so users cannot change its value.")] public void Disable() => Disabled = true; /// - /// Enables InputPassword. + /// Enables the password input so users can change its value. /// [AddedVersion("3.3.0")] - [Description("Enables InputPassword.")] + [Description("Enables the password input so users can change its value.")] public void Enable() => Disabled = false; /// @@ -81,14 +81,14 @@ private async Task OnChange(ChangeEventArgs args) ); /// - /// Gets or sets the disabled state. + /// Gets or sets whether the password input is disabled. /// /// /// Default value is false. /// [AddedVersion("3.3.0")] [DefaultValue(false)] - [Description("Gets or sets the disabled state.")] + [Description("Gets or sets whether the password input is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } @@ -108,7 +108,7 @@ private async Task OnChange(ChangeEventArgs args) /// [AddedVersion("3.3.0")] [DefaultValue("btn border-top border-end border-bottom border border-start-0")] - [Description("Gets or sets the show/hide password button CSS class.")] + [Description("Gets or sets CSS classes applied to the button that reveals or hides the password.")] [Parameter] public string? ShowHidePasswordButtonCssClass { get; set; } = "btn border-top border-end border-bottom border border-start-0"; //""btn btn-light border"; @@ -122,7 +122,7 @@ private async Task OnChange(ChangeEventArgs args) /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets the value.")] + [Description("Gets or sets the current password value bound to the input.")] [Parameter] public string? Value { get; set; } @@ -130,7 +130,7 @@ private async Task OnChange(ChangeEventArgs args) /// This event is fired when the PasswordInput value changes. /// [AddedVersion("3.3.0")] - [Description("This event is fired when the PasswordInput value changes.")] + [Description("Fires whenever user input changes the password value.")] [Parameter] public EventCallback ValueChanged { get; set; } @@ -142,7 +142,7 @@ private async Task OnChange(ChangeEventArgs args) /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets an expression that identifies the bound value.")] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs index e07895ef8..467eecd9d 100644 --- a/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs +++ b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs @@ -35,10 +35,10 @@ protected override void OnInitialized() } /// - /// Updates the radio input value from JavaScript. + /// Updates the radio input value from the JavaScript change handler. /// [AddedVersion("3.3.0")] - [Description("Updates the radio input value from JavaScript.")] + [Description("Updates the radio input value from the JavaScript change handler.")] [JSInvokable] public async Task OnChangeJS(bool newValue) { @@ -50,17 +50,17 @@ public async Task OnChangeJS(bool newValue) } /// - /// Disables number input. + /// Disables the radio input so users cannot select it. /// [AddedVersion("3.3.0")] - [Description("Disables number input.")] + [Description("Disables the radio input so users cannot select it.")] public void Disable() => Disabled = true; /// - /// Enables number input. + /// Enables the radio input so users can select it. /// [AddedVersion("3.3.0")] - [Description("Enables number input.")] + [Description("Enables the radio input so users can select it.")] public void Enable() => Disabled = false; #endregion @@ -75,14 +75,14 @@ public async Task OnChangeJS(bool newValue) ); /// - /// Gets or sets the disabled state. + /// Gets or sets whether the radio input is disabled. /// /// /// Default value is false. /// [AddedVersion("3.3.0")] [DefaultValue(false)] - [Description("Gets or sets the disabled state.")] + [Description("Gets or sets whether the radio input is disabled. When true, users cannot select it.")] [Parameter] public bool Disabled { get; set; } @@ -100,7 +100,7 @@ public async Task OnChangeJS(bool newValue) /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets the label.")] + [Description("Gets or sets the label displayed next to the radio input.")] [Parameter] public string? Label { get; set; } @@ -112,7 +112,7 @@ public async Task OnChangeJS(bool newValue) /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets the name.")] + [Description("Gets or sets the HTML name used to group related radio inputs.")] [Parameter] public string? Name { get; set; } @@ -124,7 +124,7 @@ public async Task OnChangeJS(bool newValue) /// [AddedVersion("3.3.0")] [DefaultValue(false)] - [Description("Gets or sets the value.")] + [Description("Gets or sets the current value represented by this radio input.")] [Parameter] public bool Value { get; set; } = default!; @@ -132,7 +132,7 @@ public async Task OnChangeJS(bool newValue) /// This event fired on every user keystroke that changes the NumberInput value. /// [AddedVersion("3.3.0")] - [Description("This event fired on every user keystroke that changes the NumberInput value.")] + [Description("Fires whenever user interaction selects this radio input.")] [Parameter] public EventCallback ValueChanged { get; set; } @@ -144,7 +144,7 @@ public async Task OnChangeJS(bool newValue) /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets an expression that identifies the bound value.")] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs b/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs index f4092c90b..717b59fe3 100644 --- a/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs +++ b/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs @@ -85,7 +85,7 @@ protected override async Task OnInitializedAsync() /// Updates the range input value from JavaScript. /// [AddedVersion("1.10.6")] - [Description("Updates the range input value from JavaScript.")] + [Description("Updates the range input value from the JavaScript change handler.")] [JSInvokable] public async Task bsOnInput(object? newValue) { @@ -389,7 +389,7 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.10.6")] [DefaultValue(false)] - [Description("Gets or sets the disabled state.")] + [Description("Gets or sets whether the range input is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } @@ -401,7 +401,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Gets or sets the maximum value of the range input. /// [AddedVersion("1.10.6")] - [Description("Gets or sets the maximum value of the range input.")] + [Description("Gets or sets the maximum value selectable with the range input.")] [Parameter] public TValue Max { get; set; } = default!; @@ -409,7 +409,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Gets or sets the minimum value of the range input. /// [AddedVersion("1.10.6")] - [Description("Gets or sets the minimum value of the range input.")] + [Description("Gets or sets the minimum value selectable with the range input.")] [Parameter] public TValue Min { get; set; } = default!; @@ -423,7 +423,7 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.10.6")] [DefaultValue(1)] - [Description("Gets or sets the step value of the range input.")] + [Description("Gets or sets the increment between selectable range values.")] [Parameter] public double Step { get; set; } = 1; @@ -435,7 +435,7 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.10.6")] [DefaultValue(null)] - [Description("Gets or sets the tick marks.")] + [Description("Gets or sets tick marks displayed along the range input.")] [Parameter] public IEnumerable TickMarks { get; set; } = default!; @@ -443,7 +443,7 @@ private bool TryParseValue(object value, out TValue newValue) /// Gets or sets the value of the range input. /// [AddedVersion("1.10.6")] - [Description("Gets or sets the value of the range input.")] + [Description("Gets or sets the current value bound to the range input.")] [Parameter] public TValue Value { get; set; } = default!; @@ -451,7 +451,7 @@ private bool TryParseValue(object value, out TValue newValue) /// This event fires when the user specifies a numeric value. /// [AddedVersion("1.10.6")] - [Description("This event fires when the user specifies a numeric value.")] + [Description("Fires whenever user interaction changes the range value.")] [Parameter] public EventCallback ValueChanged { get; set; } @@ -463,7 +463,7 @@ private bool TryParseValue(object value, out TValue newValue) /// [AddedVersion("1.10.6")] [DefaultValue(null)] - [Description("Gets or sets an expression that identifies the bound value.")] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs index fdb2a3177..f5ead65c4 100644 --- a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs +++ b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap; +namespace BlazorBootstrap; /// /// Provides a dependency-free rich-text editing control with a grouped Bootstrap toolbar. @@ -108,14 +108,14 @@ protected override async Task OnParametersSetAsync() /// Clears the editor content. /// [AddedVersion("4.0.0")] - [Description("Clears the editor content.")] + [Description("Clears the editor HTML content through the editor module.")] public Task ClearAsync() => RichTextEditorJsInterop.ClearAsync(objRef!, Id!); /// /// Focuses the editable area. /// [AddedVersion("4.0.0")] - [Description("Focuses the editable area.")] + [Description("Moves keyboard focus to the editable area.")] public Task FocusAsync() => RichTextEditorJsInterop.FocusAsync(objRef!, Id!); /// @@ -460,7 +460,7 @@ private Task SetImageUploadInProgressAsync(bool value) /// [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the permitted HTTPS image domains. Subdomains are also permitted.")] + [Description("Gets or sets the HTTPS domains permitted for uploaded-image URLs. Subdomains of configured domains are also permitted.")] [Parameter] public IEnumerable? AllowedImageDomains { get; set; } @@ -470,7 +470,7 @@ private Task SetImageUploadInProgressAsync(bool value) /// [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the permitted image file extensions.")] + [Description("Gets or sets image file extensions accepted by the upload dialog. Null uses the built-in safe image types.")] [Parameter] public IEnumerable? AllowedImageFileTypes { get; set; } @@ -480,28 +480,28 @@ private Task SetImageUploadInProgressAsync(bool value) /// [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the permitted HTTP(S) link domains. Subdomains are also permitted.")] + [Description("Gets or sets the HTTP(S) domains permitted for inserted links. Subdomains of configured domains are also permitted.")] [Parameter] public IEnumerable? AllowedLinkDomains { get; set; } /// Gets or sets the accessible label for the editor. [AddedVersion("4.0.0")] [DefaultValue("Rich text editor")] - [Description("Gets or sets the accessible label for the editor.")] + [Description("Gets or sets the accessible name announced for the editor by assistive technologies.")] [Parameter] public string AriaLabel { get; set; } = "Rich text editor"; /// Gets or sets the delay, in milliseconds, before editor changes are raised. [AddedVersion("4.0.0")] [DefaultValue(300)] - [Description("Gets or sets the delay, in milliseconds, before editor changes are raised.")] + [Description("Gets or sets the debounce delay, in milliseconds, before editor content changes are raised to ValueChanged.")] [Parameter] public int DebounceInterval { get; set; } = 300; /// Gets or sets whether the editor is disabled. [AddedVersion("4.0.0")] [DefaultValue(false)] - [Description("Gets or sets whether the editor is disabled.")] + [Description("Gets or sets whether editing is disabled. When true, users cannot change content or invoke toolbar commands.")] [Parameter] public bool Disabled { get; set; } @@ -519,7 +519,7 @@ private Task SetImageUploadInProgressAsync(bool value) /// Gets or sets the image upload handler. [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the image upload handler.")] + [Description("Gets or sets the delegate that uploads a validated image and returns its HTTPS URL for insertion.")] [Parameter] public RichTextEditorImageUploadDelegate? ImageUploadHandler { get; set; } @@ -528,14 +528,14 @@ private Task SetImageUploadInProgressAsync(bool value) /// Gets or sets the maximum allowed image size in bytes. [AddedVersion("4.0.0")] [DefaultValue(5242880)] - [Description("Gets or sets the maximum allowed image size in bytes.")] + [Description("Gets or sets the maximum accepted image-upload size in bytes. Larger files are rejected before upload.")] [Parameter] public long MaxImageFileSize { get; set; } = 5 * 1024 * 1024; /// Gets or sets the maximum plain-text character count. [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the maximum plain-text character count.")] + [Description("Gets or sets the maximum plain-text character count. Null does not impose a character limit.")] [Parameter] public int? MaxLength { get; set; } @@ -548,7 +548,7 @@ private Task SetImageUploadInProgressAsync(bool value) /// Gets or sets the placeholder text. [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the placeholder text.")] + [Description("Gets or sets placeholder text displayed when the editor has no content.")] [Parameter] public string? Placeholder { get; set; } @@ -558,7 +558,7 @@ private Task SetImageUploadInProgressAsync(bool value) /// Gets or sets whether the editor footer is displayed. [AddedVersion("4.0.0")] [DefaultValue(true)] - [Description("Gets or sets whether the editor footer is displayed.")] + [Description("Gets or sets whether the footer displaying editor metrics is rendered.")] [Parameter] public bool ShowFooter { get; set; } = true; @@ -567,7 +567,7 @@ private Task SetImageUploadInProgressAsync(bool value) /// Fires for transient editor activity and error status. [AddedVersion("4.0.0")] - [Description("Fires for transient editor activity and error status.")] + [Description("Fires for transient editor activity and error status, such as image-upload progress or validation failures.")] [Parameter] public EventCallback StatusChanged { get; set; } @@ -576,20 +576,20 @@ private Task SetImageUploadInProgressAsync(bool value) /// /// Gets or sets the toolbar items. /// - [Description("Gets or sets the toolbar items.")] + [Description("Gets or sets the toolbar commands available to users. Null displays the complete built-in toolbar.")] [Parameter] public RichTextEditorToolbarItem[]? ToolbarItems { get; set; } /// Gets or sets the HTML value. [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the HTML value.")] + [Description("Gets or sets the editor HTML content bound to the component.")] [Parameter] public string Value { get; set; } = string.Empty; /// Fires after the editor commits a content change. [AddedVersion("4.0.0")] - [Description("Fires after the editor commits a content change.")] + [Description("Fires after debounced editor content changes and supplies HTML, normalized text, and character metrics.")] [Parameter] public EventCallback ValueChanged { get; set; } @@ -599,7 +599,7 @@ private Task SetImageUploadInProgressAsync(bool value) /// [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the expression that identifies the bound value.")] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression>? ValueExpression { get; set; } diff --git a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorToolbarButton.razor.cs b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorToolbarButton.razor.cs index f53568108..0fe0cd5b4 100644 --- a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorToolbarButton.razor.cs +++ b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorToolbarButton.razor.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap; +namespace BlazorBootstrap; public partial class RichTextEditorToolbarButton : BlazorBootstrapComponentBase { @@ -28,7 +28,7 @@ private async Task OnClickAsync() /// [AddedVersion("4.0.0")] [DefaultValue(false)] - [Description("Gets or sets a value indicating whether the button is disabled.")] + [Description("Gets or sets whether the toolbar button is disabled. When true, its command cannot be invoked.")] [Parameter] public bool Disabled { get; set; } @@ -40,7 +40,7 @@ private async Task OnClickAsync() /// [AddedVersion("4.0.0")] [DefaultValue(RichTextEditorToolbarItem.None)] - [Description("Gets or sets the toolbar item associated with the button.")] + [Description("Gets or sets the toolbar command represented by this button.")] [Parameter, EditorRequired] public RichTextEditorToolbarItem Item { get; set; } = RichTextEditorToolbarItem.None; diff --git a/blazorbootstrap/Components/Form/Switch/Switch.razor.cs b/blazorbootstrap/Components/Form/Switch/Switch.razor.cs index 77786c299..4038bd230 100644 --- a/blazorbootstrap/Components/Form/Switch/Switch.razor.cs +++ b/blazorbootstrap/Components/Form/Switch/Switch.razor.cs @@ -37,17 +37,17 @@ protected override async Task OnParametersSetAsync() } /// - /// Disables switch. + /// Disables the switch so users cannot change its value. /// [AddedVersion("1.3.0")] - [Description("Disables switch.")] + [Description("Disables the switch so users cannot change its value.")] public void Disable() => Disabled = true; /// - /// Enables switch. + /// Enables the switch so users can change its value. /// [AddedVersion("1.3.0")] - [Description("Enables switch.")] + [Description("Enables the switch so users can change its value.")] public void Enable() => Disabled = false; /// @@ -77,14 +77,14 @@ private async Task OnChange(ChangeEventArgs args) (BootstrapClass.FormCheckReverse, Reverse)); /// - /// Gets or sets the disabled state. + /// Gets or sets whether the switch is disabled. /// /// /// Default value is false. /// [AddedVersion("1.3.0")] [DefaultValue(false)] - [Description("Gets or sets the disabled state.")] + [Description("Gets or sets whether the switch is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } @@ -100,7 +100,7 @@ private async Task OnChange(ChangeEventArgs args) /// [AddedVersion("1.3.0")] [DefaultValue(null)] - [Description("Gets or sets the label.")] + [Description("Gets or sets the label displayed next to the switch.")] [Parameter] public string Label { get; set; } = default!; @@ -114,7 +114,7 @@ private async Task OnChange(ChangeEventArgs args) /// [AddedVersion("1.3.0")] [DefaultValue(false)] - [Description("Determines whether to put the switch on the opposite side.")] + [Description("Gets or sets whether the switch is displayed on the opposite side of its label.")] [Parameter] public bool Reverse { get; set; } @@ -126,7 +126,7 @@ private async Task OnChange(ChangeEventArgs args) /// [AddedVersion("1.3.0")] [DefaultValue(false)] - [Description("Gets or sets the value.")] + [Description("Gets or sets the current checked value bound to the switch.")] [Parameter] public bool Value { get; set; } @@ -134,7 +134,7 @@ private async Task OnChange(ChangeEventArgs args) /// This event is fired when the switch selection changes. /// [AddedVersion("1.3.0")] - [Description("This event is fired when the switch selection changes.")] + [Description("Fires whenever user interaction changes the switch value.")] [Parameter] public EventCallback ValueChanged { get; set; } = default!; @@ -146,7 +146,7 @@ private async Task OnChange(ChangeEventArgs args) /// [AddedVersion("1.3.0")] [DefaultValue(null)] - [Description("Gets or sets an expression that identifies the bound value.")] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs index e75b0db65..a65a001f2 100644 --- a/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs +++ b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap; +namespace BlazorBootstrap; [AddedVersion("3.3.0")] public partial class TextAreaInput : BlazorBootstrapComponentBase @@ -89,7 +89,7 @@ private async Task OnChange(ChangeEventArgs e) /// [AddedVersion("3.3.0")] [DefaultValue(false)] - [Description("Gets or sets whether the text area is disabled.")] + [Description("Gets or sets whether the text area is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } @@ -105,7 +105,7 @@ private async Task OnChange(ChangeEventArgs e) /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets the maximum number of characters users can enter.")] + [Description("Gets or sets the maximum number of characters users can enter. Additional input is prevented when the limit is reached.")] [Parameter] public int? MaxLength { get; set; } diff --git a/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs b/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs index 66a35659e..450bc8d5c 100644 --- a/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs +++ b/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap; +namespace BlazorBootstrap; [AddedVersion("3.3.0")] public partial class TextInput : BlazorBootstrapComponentBase @@ -77,7 +77,7 @@ private async Task OnChange(ChangeEventArgs e) /// [AddedVersion("3.3.0")] [DefaultValue(false)] - [Description("Gets or sets whether the input is disabled.")] + [Description("Gets or sets whether the input is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } @@ -93,7 +93,7 @@ private async Task OnChange(ChangeEventArgs e) /// [AddedVersion("3.3.0")] [DefaultValue(null)] - [Description("Gets or sets the maximum number of characters users can enter.")] + [Description("Gets or sets the maximum number of characters users can enter. Additional input is prevented when the limit is reached.")] [Parameter] public int? MaxLength { get; set; } diff --git a/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs b/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs index b7acd3e4d..1070467a0 100644 --- a/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs +++ b/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap; +namespace BlazorBootstrap; [AddedVersion("1.6.0")] public partial class TimeInput : BlazorBootstrapComponentBase @@ -290,7 +290,7 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// - [Description("Gets or sets whether input is restricted to the configured minimum and maximum times. If , restricts the user input between the Min and Max range. Else accepts the user input.")] + [Description("Gets or sets whether input is restricted to the configured minimum and maximum times. When true, times outside the range are rejected.")] [Parameter] public bool EnableMinMax { get; set; } @@ -301,7 +301,7 @@ private bool TryParseValue(object value, out TValue newValue) /// /// [AddedVersion("1.6.0")] - [Description("Gets or sets the maximum permitted time. ")] + [Description("Gets or sets the maximum permitted time. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Max { get; set; } = default!; @@ -310,7 +310,7 @@ private bool TryParseValue(object value, out TValue newValue) /// /// [AddedVersion("1.6.0")] - [Description("Gets or sets the minimum permitted time. ")] + [Description("Gets or sets the minimum permitted time. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Min { get; set; } = default!; From 0af1879ea394a7452b8317f4a0e14f7090f9c499 Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 31 Aug 2026 16:00:15 +0530 Subject: [PATCH 08/14] Expose SelectedFiles; improve RichTextEditor attributes Added SelectedFiles property to FileInputBase. Enhanced RichTextEditor ToolbarItems with version, default, and description attributes. Reordered attributes in RichTextEditorToolbarButton for consistency. --- blazorbootstrap/Components/Form/FileInput/FileInputBase.cs | 1 + .../Components/Form/RichTextEditor/RichTextEditor.razor.cs | 4 ++-- .../Form/RichTextEditor/RichTextEditorToolbarButton.razor.cs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/blazorbootstrap/Components/Form/FileInput/FileInputBase.cs b/blazorbootstrap/Components/Form/FileInput/FileInputBase.cs index 5f8754316..16e66e850 100644 --- a/blazorbootstrap/Components/Form/FileInput/FileInputBase.cs +++ b/blazorbootstrap/Components/Form/FileInput/FileInputBase.cs @@ -212,6 +212,7 @@ private static string FormatValidationMessage(string template, params (string To /// /// Gets the currently selected files. /// + [AddedVersion("4.0.0")] [Description("Gets a read-only list of files currently accepted by the component.")] public IReadOnlyList SelectedFiles => files.AsReadOnly(); diff --git a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs index f5ead65c4..aea7935c2 100644 --- a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs +++ b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs @@ -571,11 +571,11 @@ private Task SetImageUploadInProgressAsync(bool value) [Parameter] public EventCallback StatusChanged { get; set; } - [AddedVersion("4.0.0")] - [DefaultValue(null)] /// /// Gets or sets the toolbar items. /// + [AddedVersion("4.0.0")] + [DefaultValue(null)] [Description("Gets or sets the toolbar commands available to users. Null displays the complete built-in toolbar.")] [Parameter] public RichTextEditorToolbarItem[]? ToolbarItems { get; set; } diff --git a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorToolbarButton.razor.cs b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorToolbarButton.razor.cs index 0fe0cd5b4..300b7033f 100644 --- a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorToolbarButton.razor.cs +++ b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorToolbarButton.razor.cs @@ -41,7 +41,7 @@ private async Task OnClickAsync() [AddedVersion("4.0.0")] [DefaultValue(RichTextEditorToolbarItem.None)] [Description("Gets or sets the toolbar command represented by this button.")] - [Parameter, EditorRequired] + [EditorRequired, Parameter] public RichTextEditorToolbarItem Item { get; set; } = RichTextEditorToolbarItem.None; [CascadingParameter(Name = "RichTextEditor")] From 30cf1a7b30fc8632676da4dcd4d27eb7d65dffb8 Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 31 Aug 2026 17:08:22 +0530 Subject: [PATCH 09/14] Improve and expand XML docs for SplitView public API Enhanced and clarified XML documentation comments for all public members of the SplitView component. Added detailed summaries, parameter descriptions, default values, and usage notes for properties, events, and JS-invokable methods to improve API discoverability and developer experience. --- .../Components/SplitView/SplitView.razor.cs | 73 +++++++++++++------ 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/blazorbootstrap/Components/SplitView/SplitView.razor.cs b/blazorbootstrap/Components/SplitView/SplitView.razor.cs index 739d8c093..39c005d23 100644 --- a/blazorbootstrap/Components/SplitView/SplitView.razor.cs +++ b/blazorbootstrap/Components/SplitView/SplitView.razor.cs @@ -1,5 +1,9 @@ namespace BlazorBootstrap; +/// +/// Provides two resizable panes separated by a draggable divider. +/// +[AddedVersion("4.0.0")] public partial class SplitView : BlazorBootstrapComponentBase { #region Fields and Constants @@ -87,6 +91,13 @@ protected override Task OnParametersSetAsync() return base.OnParametersSetAsync(); } + /// + /// Handles the JavaScript notification that divider resizing has ended. + /// + /// The final primary-pane size as a percentage. + /// The final secondary-pane size as a percentage. + [AddedVersion("4.0.0")] + [Description("Handles the notification that divider resizing has ended, updates the current size, and raises OnResizeEnded.")] [JSInvokable] public async Task OnResizeEndedJS(double primaryPaneSize, double secondaryPaneSize) { @@ -98,6 +109,13 @@ public async Task OnResizeEndedJS(double primaryPaneSize, double secondaryPaneSi await OnResizeEnded.InvokeAsync(new SplitViewResizeEventArgs(primaryPaneSize, secondaryPaneSize, Orientation)); } + /// + /// Handles the JavaScript notification that divider resizing has started. + /// + /// The initial primary-pane size as a percentage. + /// The initial secondary-pane size as a percentage. + [AddedVersion("4.0.0")] + [Description("Handles the notification that divider resizing has started and raises OnResizeStarted.")] [JSInvokable] public async Task OnResizeStartedJS(double primaryPaneSize, double secondaryPaneSize) { @@ -108,6 +126,13 @@ public async Task OnResizeStartedJS(double primaryPaneSize, double secondaryPane await OnResizeStarted.InvokeAsync(new SplitViewResizeEventArgs(primaryPaneSize, secondaryPaneSize, Orientation)); } + /// + /// Handles the JavaScript notification that the divider size has changed. + /// + /// The current primary-pane size as a percentage. + /// The current secondary-pane size as a percentage. + [AddedVersion("4.0.0")] + [Description("Handles a divider-size change, updates the current primary-pane size, and raises the bound size and resize callbacks.")] [JSInvokable] public async Task OnResizedJS(double primaryPaneSize, double secondaryPaneSize) { @@ -164,19 +189,19 @@ private bool ParametersChanged() => private double EffectiveMinimumPaneSize => Math.Clamp(MinimumPaneSize, 0d, 50d); /// - /// Gets or sets the divider color. + /// Gets or sets the Bootstrap contextual color used for the divider. /// /// Default value is . /// /// [AddedVersion("4.0.0")] [DefaultValue(SplitViewColor.None)] - [Description("Gets or sets the divider color.")] + [Description("Gets or sets the Bootstrap contextual color used for the divider.")] [Parameter] public SplitViewColor Color { get; set; } /// - /// Gets or sets a custom divider color. + /// Gets or sets a custom CSS color used for the divider. /// /// Accepts any valid CSS color expression, including CSS variables. /// Default value is . @@ -184,113 +209,113 @@ private bool ParametersChanged() => /// [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets a custom divider color.")] + [Description("Gets or sets a custom CSS color used for the divider. When specified, it overrides the color supplied by Color.")] [Parameter] public string? CustomColor { get; set; } /// - /// Gets or sets a value indicating whether user interaction is disabled. + /// Gets or sets whether users can resize the panes. /// /// Default value is . /// /// [AddedVersion("4.0.0")] [DefaultValue(false)] - [Description("Gets or sets a value indicating whether user interaction is disabled.")] + [Description("Gets or sets whether users can resize the panes. When true, the divider is displayed but cannot be dragged.")] [Parameter] public bool IsDisabled { get; set; } /// - /// Gets or sets the minimum pane size as a percentage. + /// Gets or sets the minimum allowed size of each pane as a percentage. /// /// Default value is 0. /// /// [AddedVersion("4.0.0")] [DefaultValue(0d)] - [Description("Gets or sets the minimum pane size as a percentage.")] + [Description("Gets or sets the minimum allowed size of each pane as a percentage. Values are constrained to the range 0 through 50.")] [Parameter] public double MinimumPaneSize { get; set; } /// - /// Fired when resizing ends. + /// Occurs after the user releases the divider. /// [AddedVersion("4.0.0")] - [Description("Fired when resizing ends.")] + [Description("Fires after the user releases the divider and supplies the final size of both panes.")] [Parameter] public EventCallback OnResizeEnded { get; set; } /// - /// Fired while the divider is being dragged. + /// Occurs whenever dragging changes the divider position. /// [AddedVersion("4.0.0")] - [Description("Fired while the divider is being dragged.")] + [Description("Fires while the divider is dragged and supplies the current size of both panes.")] [Parameter] public EventCallback OnResized { get; set; } /// - /// Fired when resizing starts. + /// Occurs when the user starts dragging the divider. /// [AddedVersion("4.0.0")] - [Description("Fired when resizing starts.")] + [Description("Fires when the user starts dragging the divider and supplies the initial size of both panes.")] [Parameter] public EventCallback OnResizeStarted { get; set; } /// - /// Gets or sets the SplitView orientation. + /// Gets or sets whether panes are arranged side by side or stacked. /// /// Default value is . /// /// [AddedVersion("4.0.0")] [DefaultValue(SplitViewOrientation.Horizontal)] - [Description("Gets or sets the SplitView orientation.")] + [Description("Gets or sets whether panes are arranged side by side or stacked. The orientation also determines the divider drag direction.")] [Parameter] public SplitViewOrientation Orientation { get; set; } = SplitViewOrientation.Horizontal; /// - /// Gets or sets the first pane content. + /// Gets or sets the content rendered in the primary pane. /// /// Default value is . /// /// [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the first pane content.")] + [Description("Gets or sets the content rendered in the primary pane, before the divider.")] [EditorRequired] [Parameter] public RenderFragment? Pane1 { get; set; } /// - /// Gets or sets the second pane content. + /// Gets or sets the content rendered in the secondary pane. /// /// Default value is . /// /// [AddedVersion("4.0.0")] [DefaultValue(null)] - [Description("Gets or sets the second pane content.")] + [Description("Gets or sets the content rendered in the secondary pane, after the divider.")] [EditorRequired] [Parameter] public RenderFragment? Pane2 { get; set; } /// - /// Gets or sets the primary pane size as a percentage. + /// Gets or sets the primary-pane size as a percentage. /// /// Default value is 50. /// /// [AddedVersion("4.0.0")] [DefaultValue(50d)] - [Description("Gets or sets the primary pane size as a percentage.")] + [Description("Gets or sets the primary-pane size as a percentage. The value is constrained so both panes satisfy MinimumPaneSize.")] [Parameter] public double PrimaryPaneSize { get; set; } = 50d; /// - /// Fired when the primary pane size changes. + /// Occurs whenever the user changes the primary-pane size. /// [AddedVersion("4.0.0")] - [Description("Fired when the primary pane size changes.")] + [Description("Fires whenever dragging changes the primary-pane size and supports two-way binding with PrimaryPaneSize.")] [Parameter] public EventCallback PrimaryPaneSizeChanged { get; set; } From c563332a125798d0d6f6cd699f8d141ffe0dda0b Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 31 Aug 2026 21:42:17 +0530 Subject: [PATCH 10/14] Update links and add CarbonAd to rich-text-editor docs - Changed "Docs" link in EmptyLayout.razor to open in same tab - Updated blog URL in appsettings.json to absolute URL - Imported and rendered CarbonAd in rich-text-editor.mdx after heading --- BlazorBootstrap.Demo.RCL/Components/Layout/EmptyLayout.razor | 2 +- BlazorBootstrap.Demo.Server/appsettings.json | 2 +- BlazorBootstrap.Demo.WebAssembly/wwwroot/appsettings.json | 2 +- docs/docs/04-forms/rich-text-editor.mdx | 4 ++++ 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/BlazorBootstrap.Demo.RCL/Components/Layout/EmptyLayout.razor b/BlazorBootstrap.Demo.RCL/Components/Layout/EmptyLayout.razor index f643d9047..769a47ffd 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Layout/EmptyLayout.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Layout/EmptyLayout.razor @@ -31,7 +31,7 @@
diff --git a/BlazorBootstrap.Demo.Server/appsettings.json b/BlazorBootstrap.Demo.Server/appsettings.json index 7fb755b41..1c0f9ddcf 100644 --- a/BlazorBootstrap.Demo.Server/appsettings.json +++ b/BlazorBootstrap.Demo.Server/appsettings.json @@ -13,7 +13,7 @@ "urls": { "demos": "/demos/getting-started", "docs": "/docs/getting-started", - "blog": "/blog", + "blog": "https://docs.blazorbootstrap.com/blog", "github": "//github.com/vikramlearning/blazorbootstrap", "twitter": "//twitter.com/blazorbootstrap", "linkedin": "//www.linkedin.com/groups/14161025", diff --git a/BlazorBootstrap.Demo.WebAssembly/wwwroot/appsettings.json b/BlazorBootstrap.Demo.WebAssembly/wwwroot/appsettings.json index cc4a5819f..948bded28 100644 --- a/BlazorBootstrap.Demo.WebAssembly/wwwroot/appsettings.json +++ b/BlazorBootstrap.Demo.WebAssembly/wwwroot/appsettings.json @@ -6,7 +6,7 @@ "urls": { "demos": "/demos/getting-started", "docs": "/docs/getting-started", - "blog": "/blog", + "blog": "https://docs.blazorbootstrap.com/blog", "github": "//github.com/vikramlearning/blazorbootstrap", "twitter": "//twitter.com/blazorbootstrap", "linkedin": "//www.linkedin.com/groups/14161025", diff --git a/docs/docs/04-forms/rich-text-editor.mdx b/docs/docs/04-forms/rich-text-editor.mdx index 39fef19b1..c0841bf5e 100644 --- a/docs/docs/04-forms/rich-text-editor.mdx +++ b/docs/docs/04-forms/rich-text-editor.mdx @@ -5,10 +5,14 @@ sidebar_label: RichTextEditor sidebar_position: 13 --- +import CarbonAd from '/carbon-ad.mdx' + # Blazor RichTextEditor `RichTextEditor` is a dependency-free editor for HTML content. Its default toolbar includes document styles, font settings, text emphasis, colors, alignment, lists, links, images, tables, block content, fullscreen, printing, and history controls. + + ## Get started Add the component to a page, provide its initial HTML, and handle `ValueChanged` when the application needs the sanitized editor result. From aebbd72df53781907df5629c0406c8306a6db349 Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 31 Aug 2026 22:47:39 +0530 Subject: [PATCH 11/14] Add PNG assets for UI components and documentation Added drag-and-drop-file-input.png, file-input.png, otp-input.png, and rich-text-editor.png as image assets for UI illustrations or documentation screenshots. --- .../screenshots/drag-and-drop-file-input.png | Bin 0 -> 10548 bytes .../wwwroot/images/screenshots/file-input.png | Bin 0 -> 12936 bytes .../wwwroot/images/screenshots/otp-input.png | Bin 0 -> 2932 bytes .../images/screenshots/rich-text-editor.png | Bin 0 -> 82820 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/drag-and-drop-file-input.png create mode 100644 BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/file-input.png create mode 100644 BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/otp-input.png create mode 100644 BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/rich-text-editor.png diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/drag-and-drop-file-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/drag-and-drop-file-input.png new file mode 100644 index 0000000000000000000000000000000000000000..1e6c110b9824a90d15a22b315a8ad95807b36f37 GIT binary patch literal 10548 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

MU!oV~9K#n1CC0VW8NQ-;>Y5qd2`kw-R zQ7g#kY7POB*fnK6mJ$TjH;5Of2>|1Kw{fSwF9#-gwSBal-{|HiHRTfAufs#4NU}00 zFG^Z2s2efxv``d{{u-Pgh!&_SNI2)TY6KJHn+7~Dd9wSMu893Wqm~*%h>&q>nC_kJ zAXknyrHh`$)kqH)O3NcC5oK9tTPo;Nq*Rpl#Hi0_-68kg?7736H{-yy>Av1blrRzI%iI-q?7NUE;xN{F}SU)&!&2(D_Ec~@~T*K)hxXB1@{z>cGAQ- zVJSE2=YaCP23)!2AT)Vm25J9ySCJ5%oFc{{bBJ@eM@Q8(qc2I5MthF^3zUKH<>M2> zwu@dVM2v@AkXJf6gAVf(0Zm3u@QXYWw=5|a@59#A?So3puR-jW{v*O5mRq2gE$95# z{YQ>8eeYd24J#yKo;+546&s9loK8^rJ*8{sicg`|$YaWoM{Mv#Ao;|M;-M&_)=0S; z)@{+4C#Q=rZ-SU(%GNAD^s*ry=GYy_HRLd#z;H7rWq5A6vdWCCPVR!7w5VzgZZG%rVHL~4(K)a;=qsfliVfUf*4eR% zCQ+E$xK;;v=GOZ#1y@~E^ZS%M0R3Ekju>D#Tgv|Uqm{V?K;NntP6d4&Vo-=Da9K!PrSFDI_T%Rgwo4bR zOPr!^4o+#IV&*V+afC@D#nO!A&aK1zc@d!IeYunEA6U)zgqSGQ@RxKDCu43G!IIV_ zXh8GHEYBlxjf6L;uIA6{{n~OjGZZ@p!b|L9aIc)?=UX}=J@Lsz1tSQ|`GqB-6B-rT zeiAqZ=^8%H(+a1_$)pmd)Qw0vLmY#A=WzPCW-LL)@2}D|fbIRtN0OBYG?^GpmKl8H+|91`PM??|6Q|S^;zYGHAARB>eMW&RXI=g zI*k_CU4aIyvO$jK%xbJAimaz~q{j%=@I&$5 zXs%DE)u@-aT&_}R`zu>;Fcp1GyZH}TClANGz&{cuu%J{1L?==~O_YBc=xGH8A977a z3u0eol}Wc)0hyyq6Xg(ChRgnmdQ&pW9@7y^c~;*_ERp%GvjD#g_yO?%4PbW~69;rP z7Qv>i69M&0@m84+@9>=NQJMhX-)-KWOTDGs09_Em4tD_J+fugDF%fzBNklf28qc{H z+)_`H{i!J$uwF28r=wo}&{cj0*ePF-Mm&qQnBuYCR<|TrnsKVP5!wwu~Irs%5OVep6UCh zr!o#&YvOTwH~EngM~p$ILLDkY4#g*z&PVFKR_m0BA~a`S{vG3|G|a@nmU%7;`b$at z!#{HOg7}Z;BA+_5{1fvxa&NpT=yW`l`2R1!=R)@}r!FxZ_wzn}=X9XDs*XzW{U@*g E4@?~cssI20 literal 0 HcmV?d00001 From 7b9e144bb9d4638e418f4a890a74b35497352266 Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 31 Aug 2026 22:49:04 +0530 Subject: [PATCH 12/14] Add screenshots to docs for Blazor Bootstrap components Added illustrative screenshots to the documentation of DragAndDropFileInput, FileInput, RichTextEditor, and SplitView components. Screenshots are placed after the introduction and before parameters/usage, providing visual previews. No other content was changed. --- docs/docs/04-forms/drag-and-drop-file-input.mdx | 2 ++ docs/docs/04-forms/file-input.mdx | 2 ++ docs/docs/04-forms/rich-text-editor.mdx | 2 ++ docs/docs/05-components/split-view.mdx | 2 ++ 4 files changed, 8 insertions(+) diff --git a/docs/docs/04-forms/drag-and-drop-file-input.mdx b/docs/docs/04-forms/drag-and-drop-file-input.mdx index 00375118a..dcdf292c4 100644 --- a/docs/docs/04-forms/drag-and-drop-file-input.mdx +++ b/docs/docs/04-forms/drag-and-drop-file-input.mdx @@ -13,6 +13,8 @@ The Blazor Bootstrap `DragAndDropFileInput` component displays a file drop area. +Blazor Bootstrap DragAndDropFileInput component + ## Parameters | Name | Type | Default | Description | Added Version | diff --git a/docs/docs/04-forms/file-input.mdx b/docs/docs/04-forms/file-input.mdx index c2d7c1de2..b3a86d27b 100644 --- a/docs/docs/04-forms/file-input.mdx +++ b/docs/docs/04-forms/file-input.mdx @@ -13,6 +13,8 @@ The Blazor Bootstrap `FileInput` component follows the standard Bootstrap file-c +Blazor Bootstrap FileInput component + ## Parameters | Name | Type | Default | Description | Added Version | diff --git a/docs/docs/04-forms/rich-text-editor.mdx b/docs/docs/04-forms/rich-text-editor.mdx index c0841bf5e..375842758 100644 --- a/docs/docs/04-forms/rich-text-editor.mdx +++ b/docs/docs/04-forms/rich-text-editor.mdx @@ -13,6 +13,8 @@ import CarbonAd from '/carbon-ad.mdx' +Blazor Bootstrap RichTextEditor component + ## Get started Add the component to a page, provide its initial HTML, and handle `ValueChanged` when the application needs the sanitized editor result. diff --git a/docs/docs/05-components/split-view.mdx b/docs/docs/05-components/split-view.mdx index c53e7df0e..b02e0cb52 100644 --- a/docs/docs/05-components/split-view.mdx +++ b/docs/docs/05-components/split-view.mdx @@ -14,6 +14,8 @@ The Blazor Bootstrap **Split View** component arranges two panes with a draggabl +Blazor Bootstrap SplitView component + ## Parameters | Name | Type | Default | Required | Description | Added Version | From 153139c3a23ee0c2d381f734287f7d7dba59bba2 Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 31 Aug 2026 23:02:22 +0530 Subject: [PATCH 13/14] Add new components to docs and README with links & images Added DragAndDropFileInput, FileInput, OTPInput, RichTextEditor, and SplitView to the Blazor Bootstrap documentation and README. Each entry includes links to documentation, demos, and a screenshot section. --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 0d2da0782..70be7174b 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,9 @@ This is a breaking change for existing chart users: install `BlazorExpress.Chart | Currency Input | [Docs](https://docs.blazorbootstrap.com/forms/currency-input) | [Demos](https://demos.blazorbootstrap.com/form/currency-input) | | Date Input | [Docs](https://docs.blazorbootstrap.com/forms/date-input) | [Demos](https://demos.blazorbootstrap.com/form/date-input) | | Dropdown | [Docs](https://docs.blazorbootstrap.com/components/dropdown) | [Demos](https://demos.blazorbootstrap.com/dropdown) | +| DragAndDropFileInput | [Docs](https://docs.blazorbootstrap.com/forms/drag-and-drop-file-input) | [Demos](https://demos.blazorbootstrap.com/demos/form/drag-and-drop-file-input) | | Enum Input| [Docs](https://docs.blazorbootstrap.com/forms/enum-input) | [Demos](https://demos.blazorbootstrap.com//form/enum-input) | +| FileInput | [Docs](https://docs.blazorbootstrap.com/forms/file-input) | [Demos](https://demos.blazorbootstrap.com/demos/form/file-input) | | Google Map | [Docs](https://docs.blazorbootstrap.com/components/google-map) | [Demos](https://demos.blazorbootstrap.com/google-map) | | Grid | [Docs](https://docs.blazorbootstrap.com/components/grid) | [Demos](https://demos.blazorbootstrap.com/grid) | | Icons | [Docs](https://docs.blazorbootstrap.com/content/icons) | [Demos](https://demos.blazorbootstrap.com/icons) | @@ -83,6 +85,7 @@ This is a breaking change for existing chart users: install `BlazorExpress.Chart | Markdown | [Docs](https://docs.blazorbootstrap.com/content/markdown) | [Demos](https://demos.blazorbootstrap.com/markdown) | | Modals | [Docs](https://docs.blazorbootstrap.com/components/modal) | [Demos](https://demos.blazorbootstrap.com/modals) | | Number Input | [Docs](https://docs.blazorbootstrap.com/forms/number-input) | [Demos](https://demos.blazorbootstrap.com/form/number-input) | +| OTPInput | [Docs](https://docs.blazorbootstrap.com/forms/otp-input) | [Demos](https://demos.blazorbootstrap.com/demos/form/otp-input) | | Offcanvas | [Docs](https://docs.blazorbootstrap.com/components/offcanvas) | [Demos](https://demos.blazorbootstrap.com/offcanvas) | | Pagination | [Docs](https://docs.blazorbootstrap.com/components/pagination) | [Demos](https://demos.blazorbootstrap.com/pagination) | | Password Input | [Docs](https://docs.blazorbootstrap.com/forms/password-input) | [Demos](https://demos.blazorbootstrap.com/form/password-input) | @@ -92,10 +95,12 @@ This is a breaking change for existing chart users: install `BlazorExpress.Chart | Progress | [Docs](https://docs.blazorbootstrap.com/components/progress) | [Demos](https://demos.blazorbootstrap.com/progress) | | Radio Input | [Docs](https://docs.blazorbootstrap.com/forms/radio-input) | [Demos](https://demos.blazorbootstrap.com/form/radio-input) | | RangeInput | [Docs](https://docs.blazorbootstrap.com/forms/range-input) | [Demos](https://demos.blazorbootstrap.com/form/range-input) | +| RichTextEditor | [Docs](https://docs.blazorbootstrap.com/forms/rich-text-editor) | [Demos](https://demos.blazorbootstrap.com/demos/form/rich-text-editor) | | Ribbon | [Docs](https://docs.blazorbootstrap.com/components/ribbon) | [Demos](https://demos.blazorbootstrap.com/ribbon) | | Script Loader | [Docs](https://docs.blazorbootstrap.com/components/script-loader) | [Demos](https://demos.blazorbootstrap.com/script-loader) | | Sidebar | [Docs](https://docs.blazorbootstrap.com/components/sidebar) | [Demos](https://demos.blazorbootstrap.com/sidebar) | | Sidebar2 | [Docs](https://docs.blazorbootstrap.com/components/sidebar2) | [Demos](https://demos.blazorbootstrap.com/sidebar2) | +| SplitView | [Docs](https://docs.blazorbootstrap.com/components/split-view) | [Demos](https://demos.blazorbootstrap.com/demos/split-view) | | Sortable List | [Docs](https://docs.blazorbootstrap.com/components/sortable-list) | [Demos](https://demos.blazorbootstrap.com/sortable-list) | | Spinners | [Docs](https://docs.blazorbootstrap.com/components/spinners) | [Demos](https://demos.blazorbootstrap.com/spinners) | | Switch | [Docs](https://docs.blazorbootstrap.com/forms/switch) | [Demos](https://demos.blazorbootstrap.com/form/switch) | @@ -157,12 +162,18 @@ Blazor Bootstrap's documentation, which is included in this repository's root di ### Blazor Bootstrap - Date Input ![Blazor Bootstrap - Date Input](https://i.imgur.com/1mVjqQv.png "Blazor Bootstrap - Date Input") +### Blazor Bootstrap - DragAndDropFileInput +![Blazor Bootstrap - DragAndDropFileInput](https://demos.blazorbootstrap.com/_content/BlazorBootstrap.Demo.RCL/images/screenshots/drag-and-drop-file-input.png "Blazor Bootstrap - DragAndDropFileInput") + ### Blazor Bootstrap - Dropdown ![Blazor Bootstrap - Dropdown](https://i.imgur.com/beAr31J.png "Blazor Bootstrap - Dropdown") ### Blazor Bootstrap - Enum Input ![Blazor Bootstrap - Enum Input](https://private-user-images.githubusercontent.com/2337067/517874250-8a624590-1dfc-470a-8f9d-7636851d6c95.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NjM5MjAxNzEsIm5iZiI6MTc2MzkxOTg3MSwicGF0aCI6Ii8yMzM3MDY3LzUxNzg3NDI1MC04YTYyNDU5MC0xZGZjLTQ3MGEtOGY5ZC03NjM2ODUxZDZjOTUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MTEyMyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTExMjNUMTc0NDMxWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZmVlNDlmZDZkNGQ5ZWUxMjE5MGM3NmEzMzc2OTdhYzk0MjY4YTU3NTk5M2JmMGIxNDNkYjI0ZWYyM2UwMDA5YyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.hvU9-57w9n41vwE3eyy3ZcDPDYXbQ3p_JW1RmDmT-c8 "Blazor Bootstrap - Enum Input") +### Blazor Bootstrap - FileInput +![Blazor Bootstrap - FileInput](https://demos.blazorbootstrap.com/_content/BlazorBootstrap.Demo.RCL/images/screenshots/file-input.png "Blazor Bootstrap - FileInput") + ### Blazor Bootstrap - Google Map ![Blazor Bootstrap - Google Map](https://i.imgur.com/AbyDP51.png "Blazor Bootstrap - Google Map") @@ -184,6 +195,9 @@ Blazor Bootstrap's documentation, which is included in this repository's root di ### Blazor Bootstrap - Number Input ![Blazor Bootstrap - Number Input](https://i.imgur.com/iUNBkki.png "Blazor Bootstrap - Number Input") +### Blazor Bootstrap - OTPInput +![Blazor Bootstrap - OTPInput](https://demos.blazorbootstrap.com/_content/BlazorBootstrap.Demo.RCL/images/screenshots/otp-input.png "Blazor Bootstrap - OTPInput") + ### Blazor Bootstrap - Offcanvas ![Blazor Bootstrap - Offcanvas](https://i.imgur.com/1vNz5Ci.jpg "Blazor Bootstrap - Offcanvas") @@ -211,6 +225,9 @@ Blazor Bootstrap's documentation, which is included in this repository's root di ### Blazor Bootstrap - Range Input ![Blazor Bootstrap - Range Input](https://i.imgur.com/rWDDHaf.png "Blazor Bootstrap - Range Input") +### Blazor Bootstrap - RichTextEditor +![Blazor Bootstrap - RichTextEditor](https://demos.blazorbootstrap.com/_content/BlazorBootstrap.Demo.RCL/images/screenshots/rich-text-editor.png "Blazor Bootstrap - RichTextEditor") + ### Blazor Bootstrap - Ribbon ![Blazor Bootstrap - Ribbon](https://i.imgur.com/LpZVLbF.png "Blazor Bootstrap - Ribbon") @@ -223,6 +240,9 @@ Blazor Bootstrap's documentation, which is included in this repository's root di ### Blazor Bootstrap - Sidebar2 ![Blazor Bootstrap - Sidebar2](https://i.imgur.com/HUP7ydv.png "Blazor Bootstrap - Sidebar2") +### Blazor Bootstrap - SplitView +![Blazor Bootstrap - SplitView](https://demos.blazorbootstrap.com/_content/BlazorBootstrap.Demo.RCL/images/screenshots/split-view.png "Blazor Bootstrap - SplitView") + ### Blazor Bootstrap - Sortable List ![Blazor Bootstrap - Sortable List](https://i.imgur.com/bfzP8Yi.png "Blazor Bootstrap - Sortable List") From 161074cee3a75de8d8afe67188ed3d01115f7b86 Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 31 Aug 2026 23:06:30 +0530 Subject: [PATCH 14/14] Add enum-input.png image file Added a new PNG image file named enum-input.png to the project. No code changes were made. --- .../wwwroot/images/screenshots/enum-input.png | Bin 0 -> 4576 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/enum-input.png diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/enum-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/enum-input.png new file mode 100644 index 0000000000000000000000000000000000000000..c6695200b04115c0bb25661970dfb592020a92f4 GIT binary patch literal 4576 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 M%htwaMptkD7nrtZ;s5{u literal 0 HcmV?d00001