Skip to content

Commit e01265c

Browse files
2 parents 0bd23c0 + 2ff2228 commit e01265c

File tree

38 files changed

+1182
-53
lines changed

38 files changed

+1182
-53
lines changed

.github/workflows/ci-build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ jobs:
2626
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
2727

2828
- name: Cache SonarCloud packages
29-
uses: actions/[email protected].2
29+
uses: actions/[email protected].3
3030
with:
3131
path: ~\sonar\cache
3232
key: ${{ runner.os }}-sonar
3333
restore-keys: ${{ runner.os }}-sonar
3434

3535
- name: Cache SonarCloud scanner
3636
id: cache-sonar-scanner
37-
uses: actions/[email protected].2
37+
uses: actions/[email protected].3
3838
with:
3939
path: .\.sonar\scanner
4040
key: ${{ runner.os }}-sonar-scanner

README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# AspNetCore Bootstrap5 Tag Helpers ![](https://img.shields.io/github/license/iowacomputergurus/aspnetcore.utilities.bootstrap5taghelpers.svg)
22

3-
A collection of TagHelpers for ASP.NET Core that make utilizing the Bootstrap 4.x library easier to use for developers. Designed to reduce code effort substantially
3+
A collection of TagHelpers for ASP.NET Core that make utilizing the Bootstrap 5.x library easier to use for developers. Designed to reduce code effort substantially
44

55
![Build Status](https://github.com/IowaComputerGurus/aspnetcore.utilities.bootstrap5taghelpers/actions/workflows/ci-build.yml/badge.svg)
66

@@ -23,14 +23,14 @@ These tag helpers are only for markup display, your web project must properly in
2323
You must modify your `_viewimports.cshtml` file by adding
2424

2525
``` html+razor
26-
@addTagHelper *, ICG.AspNetCore.Utilities.bootstrap5taghelpers
26+
@addTagHelper *, ICG.AspNetCore.Utilities.Bootstrap5TagHelpers
2727
```
2828

2929
## Usage
3030

31-
The goal of these tag helpers is to reduce the redundant coding, and compliance with various features of not only the Bootstrap library but form patterns. Within the "Samples" folder there are examples of all included tag helpers. However, the below shows a quick example of the power of these helps.
31+
The goal of these tag helpers is to reduce the redundant coding, and compliance with various features of not only the Bootstrap library but form patterns. Within the "Sample" project you will find examples of all tag helper usage. However, the below shows a quick example of the power of these tag helpers.
3232

33-
### Before Usage
33+
### Before Bootstrap 5 Tag Helper
3434

3535
The following markup is how you would output a model-bound field for a password field, including a note on complexity and validation.
3636

@@ -45,7 +45,7 @@ The following markup is how you would output a model-bound field for a password
4545

4646
This is a total of *306* characters with spaces or *268* without. Granted we get some help with auto-complete etc.
4747

48-
### After Using
48+
### After Using Bootstrap 5 Tag Helper
4949

5050
You can take the entire above example and simplify it to the following
5151

@@ -64,11 +64,15 @@ At this time tag helpers have been implemented for the following elements.
6464

6565
| Element | Description of Implementation |
6666
| --- | --- |
67+
| Accordion | Full support for implementation of accordion, including stay-open modes |
6768
| Alerts | Full support for implementation of alerts, including dismissible alerts |
6869
| Badges | Full support for implementation of badges of all Bootstrap color variations |
6970
| Buttons | Full support for implementation of buttons of all Bootstrap color variations, including outlines |
7071
| Cards | Support for Card, Card Header, Card Header Actions, and Card body elements |
7172
| Environment Alert | An extension of the `<environment>` tag helper to render as an alert style |
7273
| Input | Support for Form input controls for anything tied to the `<input>` tag including ASP.NET Code Model Binding & Validation |
7374
| Modals | Support for modal dialogs, including Modal Body, header, footer, dismiss, and toggles |
75+
| Offcanvas | Full support for implementation of offcanvas display, including sizing/placement |
7476
| TextArea | Support for Form input controls tied to the `<textarea>` tag including ASP.NET Core Model Binding & Validation |
77+
78+
If you find that we are missing a particular tag helper, we welcome contributions!

src/AspNetCore.Utilities.Bootstrap5TagHelpers.Sample/Views/Home/Index.cshtml

Lines changed: 151 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -324,50 +324,50 @@
324324

325325
<table class="table table-striped table-hover">
326326
<thead>
327-
<tr>
328-
<th>Example</th>
329-
<th>Code</th>
330-
</tr>
327+
<tr>
328+
<th>Example</th>
329+
<th>Code</th>
330+
</tr>
331331
</thead>
332332
<tbody>
333-
<tr>
334-
<td>
335-
<modal-toggle Target="testing">
336-
Launch Demo
337-
</modal-toggle>
333+
<tr>
334+
<td>
335+
<modal-toggle Target="testing">
336+
Launch Demo
337+
</modal-toggle>
338338

339-
<modal id="testing" class="im-weird" vertically-centered="true" >
340-
<modal-header Title="Testing Modal Header">
341-
<modal-header-dismiss></modal-header-dismiss>
342-
</modal-header>
343-
<modal-body>
344-
<form-input asp-for="FirstName"></form-input>
345-
</modal-body>
346-
<modal-footer>
347-
<bs-button bs-color="Secondary" dismisses="modal">Close</bs-button>
348-
</modal-footer>
349-
</modal>
350-
</td>
351-
<td>
352-
<code>
353-
&lt;modal-toggle Target=&quot;testing&quot;&gt;
354-
Launch Demo
355-
&lt;/modal-toggle&gt;
339+
<modal id="testing" class="im-weird" vertically-centered="true" >
340+
<modal-header Title="Testing Modal Header">
341+
<modal-header-dismiss></modal-header-dismiss>
342+
</modal-header>
343+
<modal-body>
344+
<form-input asp-for="FirstName"></form-input>
345+
</modal-body>
346+
<modal-footer>
347+
<bs-button bs-color="Secondary" dismisses="modal">Close</bs-button>
348+
</modal-footer>
349+
</modal>
350+
</td>
351+
<td>
352+
<code>
353+
&lt;modal-toggle Target=&quot;testing&quot;&gt;
354+
Launch Demo
355+
&lt;/modal-toggle&gt;
356356

357-
&lt;modal id=&quot;testing&quot;&gt;
358-
&lt;modal-header Title=&quot;Testing Modal Header&quot;&gt;
359-
&lt;modal-header-dismiss&gt;&lt;/modal-header-dismiss&gt;
360-
&lt;/modal-header&gt;
361-
&lt;modal-body&gt;
362-
&lt;form-input asp-for=&quot;FirstName&quot;&gt;&lt;/form-input&gt;
363-
&lt;/modal-body&gt;
364-
&lt;modal-footer&gt;
365-
&lt;button type=&quot;button&quot; class=&quot;btn btn-secondary&quot; data-dismiss=&quot;modal&quot;&gt;Close&lt;/button&gt;
366-
&lt;/modal-footer&gt;
367-
&lt;/modal&gt;
368-
</code>
369-
</td>
370-
</tr>
357+
&lt;modal id=&quot;testing&quot;&gt;
358+
&lt;modal-header Title=&quot;Testing Modal Header&quot;&gt;
359+
&lt;modal-header-dismiss&gt;&lt;/modal-header-dismiss&gt;
360+
&lt;/modal-header&gt;
361+
&lt;modal-body&gt;
362+
&lt;form-input asp-for=&quot;FirstName&quot;&gt;&lt;/form-input&gt;
363+
&lt;/modal-body&gt;
364+
&lt;modal-footer&gt;
365+
&lt;button type=&quot;button&quot; class=&quot;btn btn-secondary&quot; data-dismiss=&quot;modal&quot;&gt;Close&lt;/button&gt;
366+
&lt;/modal-footer&gt;
367+
&lt;/modal&gt;
368+
</code>
369+
</td>
370+
</tr>
371371
<tr>
372372
<td>
373373
<modal-toggle Target="testing-secondary">
@@ -409,6 +409,117 @@
409409
</tbody>
410410
</table>
411411

412+
<h2>Progress</h2>
413+
<table class="table table-striped table-hover">
414+
<thead>
415+
<tr>
416+
<th>Description</th>
417+
<th>Display</th>
418+
</tr>
419+
</thead>
420+
<tbody>
421+
<tr>
422+
<th>Simple Progress</th>
423+
<th><progress progress-value="75" ></progress></th>
424+
</tr>
425+
<tr>
426+
<th>With Background</th>
427+
<th><progress progress-value="75" background-color="BootstrapColor.Danger"></progress></th>
428+
</tr>
429+
<tr>
430+
<th>With Background, Striped</th>
431+
<th><progress progress-value="75" background-color="BootstrapColor.Danger" is-striped="true"></progress></th>
432+
</tr>
433+
<tr>
434+
<th>With Background, Striped, Animated</th>
435+
<th><progress progress-value="75" background-color="BootstrapColor.Danger" is-striped="true" is-animated="true"></progress></th>
436+
</tr>
437+
<tr>
438+
<th>With Background, Striped, Animated, Label</th>
439+
<th><progress progress-value="75" background-color="BootstrapColor.Danger" is-striped="true" is-animated="true" progress-display-label="75%"></progress></th>
440+
</tr>
441+
</tbody>
442+
</table>
443+
444+
<h2>OffCanvas</h2>
445+
<table class="table table-striped table-hover">
446+
<thead>
447+
<tr>
448+
<th>Description</th>
449+
<th>Display</th>
450+
</tr>
451+
</thead>
452+
<tbody>
453+
<tr>
454+
<td>Simple Setup</td>
455+
<td>
456+
<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasExample" aria-controls="offcanvasExample">
457+
Show Demo
458+
</button>
459+
<offcanvas id="offcanvasExample">
460+
<offcanvas-header title="Example 1">
461+
<offcanvas-dismiss></offcanvas-dismiss>
462+
</offcanvas-header>
463+
<offcanvas-body>
464+
<h3>Magic Content</h3>
465+
<p>Goes here!</p>
466+
</offcanvas-body>
467+
</offcanvas>
468+
</td>
469+
</tr>
470+
<tr>
471+
<td>Static Backdrop</td>
472+
<td>
473+
<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasExample2" aria-controls="offcanvasExample2">
474+
Show Example
475+
</button>
476+
<offcanvas id="offcanvasExample2" static-backdrop="true">
477+
<offcanvas-header title="Example 2">
478+
<offcanvas-dismiss></offcanvas-dismiss>
479+
</offcanvas-header>
480+
<offcanvas-body>
481+
<h3>Magic Content</h3>
482+
<p>Goes here!</p>
483+
</offcanvas-body>
484+
</offcanvas>
485+
</td>
486+
</tr>
487+
<tr>
488+
<td>Body Scroll Backdrop</td>
489+
<td>
490+
<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasExample3" aria-controls="offcanvasExample3">
491+
Show Example
492+
</button>
493+
<offcanvas id="offcanvasExample3" enable-body-scrolling="true">
494+
<offcanvas-header title="Example 3">
495+
<offcanvas-dismiss></offcanvas-dismiss>
496+
</offcanvas-header>
497+
<offcanvas-body>
498+
<h3>Magic Content</h3>
499+
<p>Goes here!</p>
500+
</offcanvas-body>
501+
</offcanvas>
502+
</td>
503+
</tr>
504+
<tr>
505+
<td>Placement</td>
506+
<td>
507+
<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasExample4" aria-controls="offcanvasExample4">
508+
Show Example
509+
</button>
510+
<offcanvas id="offcanvasExample4" placement="End">
511+
<offcanvas-header title="Example 4">
512+
<offcanvas-dismiss></offcanvas-dismiss>
513+
</offcanvas-header>
514+
<offcanvas-body>
515+
<h3>Magic Content</h3>
516+
<p>Goes here!</p>
517+
</offcanvas-body>
518+
</offcanvas>
519+
</td>
520+
</tr>
521+
</tbody>
522+
</table>
412523
<style>
413524
code {
414525
white-space: pre;

src/AspNetCore.Utilities.Bootstrap5TagHelpers.Tests/ButtonTagHelperTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ public async Task Sets_Button_Size_If_Not_Normal(ButtonSize size, string expecte
105105
public async Task Throws_Error_If_Invalid_ButtonSize()
106106
{
107107
var error = await Assert.ThrowsAsync<ArgumentOutOfRangeException>(async () => await (new ButtonTagHelper { Size = (ButtonSize)Int16.MaxValue }).Render());
108-
109108
}
110109

111110
[Fact]

src/AspNetCore.Utilities.Bootstrap5TagHelpers.Tests/Modal/ModalTagHelperTests.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using ICG.AspNetCore.Utilities.Bootstrap5TagHelpers.Contexts;
22
using ICG.AspNetCore.Utilities.Bootstrap5TagHelpers.Modal;
33
using Microsoft.AspNetCore.Razor.TagHelpers;
4+
using System.Drawing;
45

56
namespace ICG.AspNetCore.Utilities.Bootstrap5TagHelpers.Tests.Modal;
67

@@ -186,4 +187,47 @@ public async Task Should_Render_Scrollable_Class_When_Flagged()
186187
//Assert
187188
Assert.Equal(expectedContent, output.Content.GetContent());
188189
}
190+
191+
[Theory]
192+
[InlineData(ModalSize.Small, "modal-dialog modal-sm")]
193+
[InlineData(ModalSize.Default, "modal-dialog")]
194+
[InlineData(ModalSize.Large, "modal-dialog modal-lg")]
195+
[InlineData(ModalSize.ExtraLarge, "modal-dialog modal-xl")]
196+
public async Task Should_Render_ProperModalDialogClass_ForSize(ModalSize size, string expectedClass)
197+
{
198+
//Arrange
199+
TagHelperContext context = MakeTagHelperContext();
200+
TagHelperOutput output = MakeTagHelperOutput(" ");
201+
var expectedContent = $"<div class=\"{expectedClass}\"><div class=\"modal-content\"></div></div>";
202+
203+
//Act
204+
var helper = new ModalTagHelper { Size = size};
205+
await helper.ProcessAsync(context, output);
206+
207+
//Assert
208+
Assert.Equal(expectedContent, output.Content.GetContent());
209+
}
210+
211+
[Theory]
212+
[InlineData(ModalFullscreenMode.Never, "modal-dialog")]
213+
[InlineData(ModalFullscreenMode.Always, "modal-dialog modal-fullscreen")]
214+
[InlineData(ModalFullscreenMode.BelowSmall, "modal-dialog modal-fullscreen-sm-down")]
215+
[InlineData(ModalFullscreenMode.BelowMedium, "modal-dialog modal-fullscreen-md-down")]
216+
[InlineData(ModalFullscreenMode.BelowLarge, "modal-dialog modal-fullscreen-lg-down")]
217+
[InlineData(ModalFullscreenMode.BelowXLarge, "modal-dialog modal-fullscreen-xl-down")]
218+
[InlineData(ModalFullscreenMode.BelowXXLarge, "modal-dialog modal-fullscreen-xxl-down")]
219+
public async Task Should_Render_ProperModalDialogClass_ForFullscreen(ModalFullscreenMode mode, string expectedClass)
220+
{
221+
//Arrange
222+
TagHelperContext context = MakeTagHelperContext();
223+
TagHelperOutput output = MakeTagHelperOutput(" ");
224+
var expectedContent = $"<div class=\"{expectedClass}\"><div class=\"modal-content\"></div></div>";
225+
226+
//Act
227+
var helper = new ModalTagHelper { FullscreenMode = mode};
228+
await helper.ProcessAsync(context, output);
229+
230+
//Assert
231+
Assert.Equal(expectedContent, output.Content.GetContent());
232+
}
189233
}

0 commit comments

Comments
 (0)