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
5 changes: 3 additions & 2 deletions BitBlazor.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 18
VisualStudioVersion = 18.0.11123.170
# Visual Studio Version 17
VisualStudioVersion = 17.12.35527.113 d17.12
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
EndProject
Expand Down Expand Up @@ -36,6 +36,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "components", "components",
docs\components\alert.md = docs\components\alert.md
docs\components\avatar.md = docs\components\avatar.md
docs\components\badge.md = docs\components\badge.md
docs\components\breadcrumb.md = docs\components\breadcrumb.md
docs\components\button-badge.md = docs\components\button-badge.md
docs\components\button.md = docs\components\button.md
docs\components\card.md = docs\components\card.md
Expand Down
5 changes: 5 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ Small and adaptable labels for adding information.
- Support for rounded shapes
- Various colors available

#### [Breadcrumb](components/breadcrumb.md)
Breadcrumb navigation component to display the current location within a hierarchy.
- Support for the customization of items and the separator
- Accessibility support

#### [Button](components/button.md)
Interactive buttons with support for icons and different styles.
- Solid and outline variants
Expand Down
153 changes: 153 additions & 0 deletions docs/components/breadcrumb.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# BitBreadcrumb

The `BitBreadcrumb` component renders a [breadcrumb navigation](https://getbootstrap.com/docs/5.3/components/breadcrumb/) to display the user's current location within a hierarchy, supporting customization of items, separators, and accessibility features.

## Namespace

```csharp
BitBlazor.Components
```

## Description

The Breadcrumb component provides a navigational aid that helps users understand and navigate the hierarchy of a website or application. It displays the current page's location within a navigational hierarchy and allows users to quickly move to previous levels.

## Parameters

| Name | Type | Required | Default | Description |
|-----------|--------------------------------------|----------|---------|-----------------------------------------------------------------------------|
| `Label` | `string?` | ✗ | `null` | The ARIA label for the breadcrumb component, improving accessibility. |
| `Items` | `IReadOnlyList<BitBreadcrumbItem>` | ✓ | empty list | The collection of breadcrumb items to display. |
| `Separator` | `string?` | ✗ | `"/"` | The separator string shown between breadcrumb items. |
| `Dark` | `bool` | ✗ | `false` | Indicates if the breadcrumb is rendered on a dark background. |

## BitBreadcrumbItem

Each breadcrumb item is represented by a `BitBreadcrumbItem` object. Typically, this includes properties such as:

| Property | Type | Description |
|------------|----------|---------------------------------------------|
| `Text` | `string` | The display text for the breadcrumb item. (Default empty string) |
| `Href` | `string` | The URL to navigate to when the item is clicked. (Default `"#"`, optional for the last item) |
| `Icon` | `string?` | The icon to show before the item (Optional) |

> **Note:** The last item in the `Items` list is considered the current page and is not rendered as a link.

## Usage Examples

### Basic breadcrumb

C#:
```csharp
List<BitBreadcrumbItem> items =
[
new BitBreadcrumbItem { Text = "Home", Link = "#" },
new BitBreadcrumbItem { Text = "Category", Link = "#" },
new BitBreadcrumbItem { Text = "Subcategory", Link = "#" },
new BitBreadcrumbItem { Text = "Item" }
];
```

Razor:
```razor
<BitBreadcrumb Items="@items" />
```

### Breadcrumb with custom separator

C#:
```csharp
List<BitBreadcrumbItem> items =
[
new BitBreadcrumbItem { Text = "Home", Link = "#" },
new BitBreadcrumbItem { Text = "Category", Link = "#" },
new BitBreadcrumbItem { Text = "Subcategory", Link = "#" },
new BitBreadcrumbItem { Text = "Item" }
];
```

Razor:
```razor
<BitBreadcrumb Items="@items" Separator=">" />
```

### Breadcrumb with icons

C#:
```csharp
List<BitBreadcrumbItem> items =
[
new BitBreadcrumbItem { Text = "Home", Link = "#", Icon= BitBlazor.Utilities.Icons.ItLink },
new BitBreadcrumbItem { Text = "Category", Link = "#", Icon= BitBlazor.Utilities.Icons.ItLink },
new BitBreadcrumbItem { Text = "Subcategory", Link = "#", Icon= BitBlazor.Utilities.Icons.ItLink },
new BitBreadcrumbItem { Text = "Item", Icon= BitBlazor.Utilities.Icons.ItLink }
];
```

Razor:
```razor
<BitBreadcrumb Items="@items" />
```

### Breadcrumb with dark background

C#
```csharp
List<BitBreadcrumbItem> items =
[
new BitBreadcrumbItem { Text = "Home", Link = "#" },
new BitBreadcrumbItem { Text = "Category", Link = "#" },
new BitBreadcrumbItem { Text = "Subcategory", Link = "#" },
new BitBreadcrumbItem { Text = "Item" }
];
```

Razor:
```razor
<BitBreadcrumb Items="@items" Dark="true" />
```


## Accessibility

- The `Label` parameter sets the `aria-label` attribute for the breadcrumb navigation, enhancing accessibility for assistive technologies.

## Generated CSS Classes

The component generates the following CSS classes based on parameters:

- `breadcrumb`: Base class for the breadcrumb container.
- `dark`: Added when `Dark` is `true`.
- `px-3`: Added when `Dark` is `true` for horizontal padding.

## Generated HTML Structure

```html
<nav class="breadcrumb-container">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="#">Home</a>
<span class="separator">/</span>
</li>
<li class="breadcrumb-item">
<a href="#">Category</a>
<span class="separator">/</span>
</li>
<li class="breadcrumb-item">
<a href="#">Subcategory</a>
<span class="separator">/</span>
</li>
<li class="breadcrumb-item active" aria-current="page">
Item
</li>
</ol>
</nav>
```


## Notes

- The `Separator` parameter allows customization of the character or string used between breadcrumb items.
- When `Dark` is set to `true`, additional CSS classes are applied for better contrast on dark backgrounds.
- The last item in the `Items` list is rendered as plain text to indicate the current page.
- If `Items` is `null` or empty, the component renders nothing.
52 changes: 52 additions & 0 deletions src/BitBlazor/Components/Breadcrumb/BitBreadcrumb.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
@namespace BitBlazor.Components

@inherits BitComponentBase

<!-- BitBreadcrumb renders a breadcrumb navigation component to display the current location within a hierarchy.
The component supports customization of items, separators, and accessibility features. -->

<nav class="breadcrumb-container" aria-label="@Label">
<ol class="@ComputeCssClasses()">
@foreach (var item in Items)
{
@if (IsLeaf(item))
{
<li class="breadcrumb-item active" aria-current="page">
@BreadcrumbIconFragment(item)
@item.Text
</li>
}
else
{
<li class="breadcrumb-item">
@BreadcrumbIconFragment(item)
<a href="@(string.IsNullOrWhiteSpace(item.Link) ? "#" : item.Link)">@item.Text</a>
<span class="separator">@Separator</span>
</li>
}
}
</ol>
</nav>


@code {

/// <summary>
/// Gets the item icon fragment, if specified.
/// </summary>
private RenderFragment BreadcrumbIconFragment(BitBreadcrumbItem item) => __builder =>
{
@if (item.HasIcon())
{
if (!Dark)
{
<BitIcon IconName="@item.Icon" Size="IconSize.ExtraSmall" aria-hidden="true" />
}
else
{
<BitIcon IconName="@item.Icon" Size="IconSize.ExtraSmall" Color="IconColor.White" aria-hidden="true" />
}
}
};

}
53 changes: 53 additions & 0 deletions src/BitBlazor/Components/Breadcrumb/BitBreadcrumb.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using BitBlazor.Core;
using Microsoft.AspNetCore.Components;

namespace BitBlazor.Components;

/// <summary>
/// BitBreadcrumb renders a breadcrumb navigation component to display the current location within a hierarchy.
/// The component supports customization of items, separators, and accessibility features.
/// </summary>
public partial class BitBreadcrumb : BitComponentBase
{
/// <summary>
/// Gets or sets the ARIA label for the breadcrumb component.
/// </summary>
[Parameter]
public string? Label { get; set; }

/// <summary>
/// Gets or sets the items shown on the breadcrumb.
/// </summary>
[Parameter]
public IReadOnlyList<BitBreadcrumbItem> Items { get; set; } = Enumerable.Empty<BitBreadcrumbItem>().ToList();

/// <summary>
/// Gets or sets the separator to show between breadcrumb components.
/// </summary>
[Parameter]
public string? Separator { get; set; } = "/";

/// <summary>
/// Gets or sets a value indicating whether the component is rendered on a dark background, or not.
/// </summary>
[Parameter]
public bool Dark { get; set; } = false;

private string ComputeCssClasses()
{
var builder = new CssClassBuilder("breadcrumb");

if (Dark)
{
builder.AddRange(new[] { "dark", "px-3" });
}

return builder.Build();
}

private bool IsLeaf(BitBreadcrumbItem? item)
{
return item is not null && Items?.LastOrDefault() == item;
}
}

28 changes: 28 additions & 0 deletions src/BitBlazor/Components/Breadcrumb/BitBreadcrumbItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace BitBlazor.Components;

/// <summary>
/// Represents an item in a <see cref="BitBreadcrumb"/> navigation component.
/// </summary>
public class BitBreadcrumbItem
{
/// <summary>
/// Gets or sets the text to display for the item.
/// </summary>
public string Text { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the icon name to display before the item.
/// </summary>
public string? Icon { get; set; }

/// <summary>
/// Gets or sets the URL to link to the item.
/// </summary>
public string? Link { get; set; }

/// <summary>
/// Gets a value indicating whether the item has an icon.
/// </summary>
/// <returns><code>true</code> if the item has an icon specified, <code>false</code> otherwise</returns>
public bool HasIcon() => !string.IsNullOrEmpty(Icon);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
@attribute [Stories("Components/BitBreadcrumb")]

<Stories TComponent="BitBreadcrumb">
<ArgType For="_ => _.Dark" DefaultValue="false" />
<ArgType For="_ => _.Separator" DefaultValue="@("/")" />

<Story Name="Default">
<Arguments>
<Arg For="_ => _.Dark" Value="false" />
</Arguments>
<Template>
<div class="px-2 py-2 d-flex align-items-center justify-content-around flex-wrap flex-sm-nowrap">
<BitBreadcrumb @attributes="context.Args" Items="@_items" />
</div>
</Template>
</Story>

<Story Name="Breadcrumb with custom separator">
<Arguments>
<Arg For="_ => _.Dark" Value="false" />
</Arguments>
<Template>
<div class="px-2 py-2 d-flex align-items-center justify-content-around flex-wrap flex-sm-nowrap">
<BitBreadcrumb @attributes="context.Args" Items="@_items" Separator=">" />
</div>
</Template>
</Story>

<Story Name="Breadcrumb with icons">
<Arguments>
<Arg For="_ => _.Dark" Value="false" />
<ArgType For="_ => _.Separator" DefaultValue="@("/")" />
</Arguments>
<Template>
<div class="px-2 py-2 d-flex align-items-center justify-content-around flex-wrap flex-sm-nowrap">
<BitBreadcrumb @attributes="context.Args" Items="@_itemsWithIcons" />
</div>
<div class="px-2 py-2 d-flex align-items-center justify-content-around flex-wrap flex-sm-nowrap">
<BitBreadcrumb @attributes="context.Args" Items="@_itemsWithIcons" Separator="@(">")" />
</div>
</Template>
</Story>

<Story Name="Breadcrumb with dark background">
<Arguments>
<Arg For="_ => _.Dark" Value="true" />
<ArgType For="_ => _.Separator" DefaultValue="@("/")" />
</Arguments>
<Template>
<div class="px-2 py-2 d-flex align-items-center justify-content-around flex-wrap flex-sm-nowrap">
<BitBreadcrumb @attributes="context.Args" Items="@_itemsWithIcons" Dark="true" />
</div>
<div class="px-2 py-2 d-flex align-items-center justify-content-around flex-wrap flex-sm-nowrap">
<BitBreadcrumb @attributes="context.Args" Items="@_itemsWithIcons" Separator="@(">")" Dark="true" />
</div>
</Template>
</Story>
</Stories>

@code
{
private List<BitBreadcrumbItem> _items = new()
{
new BitBreadcrumbItem { Text = "Home", Link = "#" },
new BitBreadcrumbItem { Text = "Category", Link = "#" },
new BitBreadcrumbItem { Text = "Subcategory", Link = "#" },
new BitBreadcrumbItem { Text = "Item"}
};

private List<BitBreadcrumbItem> _itemsWithIcons = new()
{
new BitBreadcrumbItem { Text = "Home", Link = "#", Icon= BitBlazor.Utilities.Icons.ItLink },
new BitBreadcrumbItem { Text = "Category", Link = "#", Icon= BitBlazor.Utilities.Icons.ItLink },
new BitBreadcrumbItem { Text = "Subcategory", Link = "#", Icon= BitBlazor.Utilities.Icons.ItLink },
new BitBreadcrumbItem { Text = "Item", Icon= BitBlazor.Utilities.Icons.ItLink }
};
}
Loading
Loading