Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions BlazorBootstrap.Demo.RCL/BlazorBootstrap.Demo.RCL.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
</ItemGroup>

<ItemGroup>
<Folder Include="Pages\Spinner\" />
<Folder Include="Pages\ScriptLoader\" />
</ItemGroup>

Expand Down
5 changes: 5 additions & 0 deletions BlazorBootstrap.Demo.RCL/Pages/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.LayoutSidebarInset" class="me-2" /> Sidebar</h4>
</a>
</div>
<div class="col-sm-4 mb-2">
<a class="d-block pe-lg-4 text-decoration-none lh-sm" href="/spinner">
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.ArrowRepeat" class="me-2" /> Spinner <Badge Color="BadgeColor.Danger">New</Badge></h4>
</a>
</div>
<div class="col-sm-4 mb-2">
<a class="d-block pe-lg-4 text-decoration-none lh-sm" href="/form/switch">
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.ToggleOn" class="me-2" /> Switch</h4>
Expand Down
64 changes: 64 additions & 0 deletions BlazorBootstrap.Demo.RCL/Pages/Spinner/SpinnerDocumentation.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
@page "/spinner"

<PageTitle>@title</PageTitle>

<MetaTags PageUrl="@pageUrl" Title="@title" Description="@description" ImageUrl="@imageUrl" />

<h1>Blazor Spinner</h1>
<div class="lead mb-3">
Visualize the loading state of a component or page using the Blazor Bootstrap Spinner component.
</div>

@* <CarbonAds /> *@

<SectionHeading Size="HeadingSize.H2" Text="Border spinner" PageUrl="@pageUrl" HashTagName="border-spinner" />
<div class="mb-3">Use the border spinners for a lightweight loading indicator.</div>
<Demo Type="typeof(Spinner_Demo_01_Border_Spinner)" />

<SectionHeading Size="HeadingSize.H2" Text="Colors" PageUrl="@pageUrl" HashTagName="colors" />
<div class="mb-3">
The border spinner's border color inherits the element's color (<code>currentColor</code>). This means you can easily customize the spinner's color by changing the <code>Color</code> parameter on the standard spinner.
</div>
<Demo Type="typeof(Spinner_Demo_02_Colors)" />

<SectionHeading Size="HeadingSize.H2" Text="Grow spinner" PageUrl="@pageUrl" HashTagName="grow-spinner" />
<div class="mb-3">
If you don't fancy a border spinner, switch to the grow spinner, while it doesn't technically spin, it does repeatedly grow!
</div>
<Demo Type="typeof(Spinner_Demo_03_Grow_spinner_A)" />
<Demo Type="typeof(Spinner_Demo_03_Grow_spinner_B)" />

<SectionHeading Size="HeadingSize.H2" Text="Loading dots spinner" PageUrl="@pageUrl" HashTagName="loading-dots-spinner" />
<div class="mb-3">The loading dots are a special indicator for a lightweight loading indicator.</div>
<Demo Type="typeof(Spinner_Demo_04_Loading_dots_spinner_A)" />
<Demo Type="typeof(Spinner_Demo_04_Loading_dots_spinner_B)" />

<SectionHeading Size="HeadingSize.H2" Text="Alignment" PageUrl="@pageUrl" HashTagName="alignment" />
<SectionHeading Size="HeadingSize.H2" Text="Margin" PageUrl="@pageUrl" HashTagName="margin" />
<Demo Type="typeof(Spinner_Demo_05_Alignment_A_Margin)" />

<SectionHeading Size="HeadingSize.H2" Text="Placement" PageUrl="@pageUrl" HashTagName="placement" />
<SectionHeading Size="HeadingSize.H2" Text="Flex" PageUrl="@pageUrl" HashTagName="flex" />
<Demo Type="typeof(Spinner_Demo_05_Alignment_B_Palcement_Flex_01)" />
<Demo Type="typeof(Spinner_Demo_05_Alignment_B_Palcement_Flex_02)" />

<SectionHeading Size="HeadingSize.H2" Text="Floats" PageUrl="@pageUrl" HashTagName="floats" />
<Demo Type="typeof(Spinner_Demo_05_Alignment_C_Palcement_Floats)" />

<SectionHeading Size="HeadingSize.H2" Text="Text align" PageUrl="@pageUrl" HashTagName="text-align" />
<Demo Type="typeof(Spinner_Demo_05_Alignment_D_Palcement_Text_align)" />

<SectionHeading Size="HeadingSize.H2" Text="Size" PageUrl="@pageUrl" HashTagName="size" />
<Demo Type="typeof(Spinner_Demo_06_Size_A_Border)" />
<Demo Type="typeof(Spinner_Demo_06_Size_B_Grow)" />
<Demo Type="typeof(Spinner_Demo_06_Size_C_Dots)" />

<SectionHeading Size="HeadingSize.H2" Text="Visible" PageUrl="@pageUrl" HashTagName="visible" />
<Demo Type="typeof(Spinner_Demo_07_Visible)" />

@code{
private string pageUrl = "/spinner";
private string title = "Blazor Spinner Component";
private string description = "Visualize the loading state of a component or page using the Blazor Bootstrap Spinner component.";
private string imageUrl = "https://i.imgur.com/273TamX.png"; // TODO: update this
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<Spinner />
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Spinner Color="SpinnerColor.Primary" />
<Spinner Color="SpinnerColor.Secondary" />
<Spinner Color="SpinnerColor.Success" />
<Spinner Color="SpinnerColor.Danger" />
<Spinner Color="SpinnerColor.Warning" />
<Spinner Color="SpinnerColor.Info" />
<Spinner Color="SpinnerColor.Light" />
<Spinner Color="SpinnerColor.Dark" />
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<Spinner Type="SpinnerType.Grow" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Spinner Type="SpinnerType.Grow" Color="SpinnerColor.Primary" />
<Spinner Type="SpinnerType.Grow" Color="SpinnerColor.Secondary" />
<Spinner Type="SpinnerType.Grow" Color="SpinnerColor.Success" />
<Spinner Type="SpinnerType.Grow" Color="SpinnerColor.Danger" />
<Spinner Type="SpinnerType.Grow" Color="SpinnerColor.Warning" />
<Spinner Type="SpinnerType.Grow" Color="SpinnerColor.Info" />
<Spinner Type="SpinnerType.Grow" Color="SpinnerColor.Light" />
<Spinner Type="SpinnerType.Grow" Color="SpinnerColor.Dark" />
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<Spinner Type="SpinnerType.Dots" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Spinner Type="SpinnerType.Dots" Class="me-3" Color="SpinnerColor.Primary" />
<Spinner Type="SpinnerType.Dots" Class="me-3" Color="SpinnerColor.Secondary" />
<Spinner Type="SpinnerType.Dots" Class="me-3" Color="SpinnerColor.Success" />
<Spinner Type="SpinnerType.Dots" Class="me-3" Color="SpinnerColor.Danger" />
<Spinner Type="SpinnerType.Dots" Class="me-3" Color="SpinnerColor.Warning" />
<Spinner Type="SpinnerType.Dots" Class="me-3" Color="SpinnerColor.Info" />
<Spinner Type="SpinnerType.Dots" Class="me-3" Color="SpinnerColor.Light" />
<Spinner Type="SpinnerType.Dots" Class="me-3" Color="SpinnerColor.Dark" />
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<Spinner Type="SpinnerType.Border" Class="m-5" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="d-flex justify-content-center">
<Spinner Type="SpinnerType.Border" />
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<div class="d-flex justify-content-center">
<strong role="status">Loading...</strong>
<Spinner Type="SpinnerType.Border" Class="ms-auto" />
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="clearfix">
<Spinner Type="SpinnerType.Border" Class="float-end" />
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="text-center">
<Spinner Type="SpinnerType.Border" />
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<Spinner Type="SpinnerType.Border" Size="SpinnerSize.Small" />
<Spinner Type="SpinnerType.Border" />
<Spinner Type="SpinnerType.Border" Size="SpinnerSize.Large" />
<Spinner Type="SpinnerType.Border" Size="SpinnerSize.ExtraLarge" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<Spinner Type="SpinnerType.Grow" Size="SpinnerSize.Small" />
<Spinner Type="SpinnerType.Grow" />
<Spinner Type="SpinnerType.Grow" Size="SpinnerSize.Large" />
<Spinner Type="SpinnerType.Grow" Size="SpinnerSize.ExtraLarge" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<Spinner Class="me-3" Type="SpinnerType.Dots" Color="SpinnerColor.Primary" Size="SpinnerSize.Small" />
<Spinner Class="me-3" Type="SpinnerType.Dots" Color="SpinnerColor.Secondary" />
<Spinner Class="me-3" Type="SpinnerType.Dots" Color="SpinnerColor.Success" Size="SpinnerSize.Large" />
<Spinner Class="me-3" Type="SpinnerType.Dots" Color="SpinnerColor.Danger" Size="SpinnerSize.ExtraLarge" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Spinner Class="me-3" Type="SpinnerType.Dots" Color="SpinnerColor.Primary" Visible="@visible" />

<div class="b-block mt-3">
<Button Type="ButtonType.Button" Color="ButtonColor.Primary" Size="Size.Small" @onclick="Hide">Hide</Button>
<Button Type="ButtonType.Button" Color="ButtonColor.Primary" Size="Size.Small" @onclick="Show">Show</Button>
</div>

@code {
private bool visible = true;

private void Hide() => visible = false;

private void Show() => visible = true;
}
7 changes: 4 additions & 3 deletions BlazorBootstrap.Demo.RCL/Shared/MainLayout.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,10 @@ private IEnumerable<NavItem> GetNavItems()
new (){ Id = "518", Text = "Progress", Href = "/progress", IconName = IconName.UsbC, ParentId = "5" },
new (){ Id = "519", Text = "Script Loader", Href = "/script-loader", IconName = IconName.CodeSlash, ParentId = "5" },
new (){ Id = "520", Text = "Sidebar", Href = "/sidebar", IconName = IconName.LayoutSidebar, ParentId = "5" },
new (){ Id = "521", Text = "Tabs", Href = "/tabs", IconName = IconName.WindowPlus, ParentId = "5" },
new (){ Id = "522", Text = "Toasts", Href = "/toasts", IconName = IconName.ExclamationTriangleFill, ParentId = "5" },
new (){ Id = "523", Text = "Tooltips", Href = "/tooltips", IconName = IconName.ChatSquareDotsFill, ParentId = "5" },
new (){ Id = "521", Text = "Spinner", Href = "/spinner", IconName = IconName.ArrowRepeat, ParentId = "5" },
new (){ Id = "522", Text = "Tabs", Href = "/tabs", IconName = IconName.WindowPlus, ParentId = "5" },
new (){ Id = "523", Text = "Toasts", Href = "/toasts", IconName = IconName.ExclamationTriangleFill, ParentId = "5" },
new (){ Id = "524", Text = "Tooltips", Href = "/tooltips", IconName = IconName.ChatSquareDotsFill, ParentId = "5" },

new (){ Id = "6", Text = "Data Visualization", IconName = IconName.BarChartFill, IconColor = IconColor.Warning },
new (){ Id = "600", Text = "Bar Chart", Href = "/charts/bar-chart", IconName = IconName.BarChartFill, ParentId = "6", Match = NavLinkMatch.All },
Expand Down
24 changes: 24 additions & 0 deletions blazorbootstrap/Components/Spinner/Spinner.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@namespace BlazorBootstrap
@inherits BlazorBootstrapComponentBase

@if (Visible)
{
@if (Type == SpinnerType.Dots)
{
<svg id="@ElementId" class="@ClassNames" style="@StyleNames" @attributes="@Attributes" width="@SpinnerSvg.Width" height="@SpinnerSvg.Height" role="status" xmlns="http://www.w3.org/2000/svg">
@if (!string.IsNullOrWhiteSpace(Title))
{
<title>@Title</title>
}
<circle cx="@SpinnerSvg.Circles[0].Cx" cy="@SpinnerSvg.Circles[0].Cy" r="@SpinnerSvg.Circles[0].Radius"/>
<circle cx="@SpinnerSvg.Circles[1].Cx" cy="@SpinnerSvg.Circles[1].Cy" r="@SpinnerSvg.Circles[1].Radius"/>
<circle cx="@SpinnerSvg.Circles[2].Cx" cy="@SpinnerSvg.Circles[2].Cy" r="@SpinnerSvg.Circles[2].Radius"/>
</svg>
}
else
{
<div id="@ElementId" class="@ClassNames" style="@StyleNames" @attributes="@Attributes" role="status">
<span class="visually-hidden">@VisuallyHiddenText</span>
</div>
}
}
138 changes: 138 additions & 0 deletions blazorbootstrap/Components/Spinner/Spinner.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
namespace BlazorBootstrap;

public partial class Spinner : BlazorBootstrapComponentBase
{
#region Fields and Constants

private SpinnerColor color = SpinnerColor.None;

private SpinnerType type = SpinnerType.Border;

#endregion

#region Methods

/// <inheritdoc />
protected override void BuildClasses(CssClassBuilder builder)
{
builder.Append(BootstrapClassProvider.Spinner(Type));
builder.Append(BootstrapClassProvider.Spinner(Color));
builder.Append(BootstrapClassProvider.Spinner(Type, Size), Type is (SpinnerType.Border or SpinnerType.Grow));

base.BuildClasses(builder);
}

protected override void OnInitialized()
{
Attributes ??= new Dictionary<string, object>();

if (Type != SpinnerType.Dots)
{
if (string.IsNullOrWhiteSpace(Title))
Attributes.Remove("title");
else if (!Attributes.TryGetValue("title", out _))
Attributes.Add("title", Title);
else if (Attributes.TryGetValue("title", out _))
Attributes["title"] = Title;
}

base.OnInitialized();
}

/// <summary>
/// Calculates width, height, and circles information for the spinner SVG.
/// </summary>
/// <returns>A tuple containing width, height, and a list of spinner circles.</returns>
private (int Width, int Height, List<SpinnerCircle> Circles) GetSpinnerSvgInfo()
{
// Calculate radius based on Size
var radius = 4; // default: SpinnerSize.Medium

if (Size == SpinnerSize.Small)
radius = 2;
else if (Size == SpinnerSize.Large)
radius = 6;
else if (Size == SpinnerSize.ExtraLarge)
radius = 8;

var defaultSpace = 4;

// Calculate other dimensions based on radius
var diameter = 2 * radius;

var circle1 = new SpinnerCircle(radius, radius, diameter);
var circle2 = new SpinnerCircle(radius, circle1.Cx + diameter + defaultSpace, diameter);
var circle3 = new SpinnerCircle(radius, circle2.Cx + diameter + defaultSpace, diameter);

var width = defaultSpace + diameter * 3 + defaultSpace;
var height = defaultSpace + diameter + defaultSpace;

return (width, height, new List<SpinnerCircle> { circle1, circle2, circle3 });
}

#endregion

#region Properties, Indexers

/// <inheritdoc />
protected override bool ShouldAutoGenerateId => true;

/// <summary>
/// Gets or sets the color of the spinner.
/// </summary>
[Parameter]
public SpinnerColor Color
{
get => color;
set
{
color = value;
DirtyClasses();
}
}

/// <summary>
/// Gets or sets the size of the spinner.
/// </summary>
[Parameter]
public SpinnerSize Size { get; set; } = SpinnerSize.Medium;

/// <summary>
/// Gets the width, height, and circles information for the spinner SVG.
/// </summary>
private (int Width, int Height, List<SpinnerCircle> Circles) SpinnerSvg => GetSpinnerSvgInfo();

/// <summary>
/// Gets or sets the title text used as an accessibility attribute.
/// </summary>
[Parameter]
public string? Title { get; set; }

/// <summary>
/// Gets or sets the type of the spinner.
/// </summary>
[Parameter]
public SpinnerType Type
{
get => type;
set
{
type = value;
DirtyClasses();
}
}

/// <summary>
/// Gets or sets whether the spinner is visible or not.
/// </summary>
[Parameter]
public bool Visible { get; set; } = true;

/// <summary>
/// Gets or sets the visually hidden text.
/// </summary>
[Parameter]
public string? VisuallyHiddenText { get; set; } = "Loading...";

#endregion
}
Loading