Skip to content

Commit

Permalink
Anchor tabs Blazor support (#989)
Browse files Browse the repository at this point in the history
## 🤨 Rationale

Blazor support for anchor tabs component

## 👩‍💻 Implementation

- Adds components NimbleAnchorTabs and NimbleAnchorTab
- A few tests
- Add to example app
- Update README

## 🧪 Testing

Ran tests and exercised example app.

## ✅ Checklist

- [x] I have updated the project documentation to reflect my changes or
determined no changes are needed.
  • Loading branch information
m-akinc authored Jan 25, 2023
1 parent d41d875 commit 0671e34
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 5 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ NOTE: To update the component status:
| Accordion | | [Issue](https://github.com/ni/nimble/issues/533) | :o: | :o: | :o: |
| Anchor | [XD](https://xd.adobe.com/view/33ffad4a-eb2c-4241-b8c5-ebfff1faf6f6-66ac/screen/bfadf499-caf5-4ca0-9814-e777fbae0d46/) | [Issue](https://github.com/ni/nimble/issues/324) | [:white_check_mark: - SB](https://ni.github.io/nimble/storybook/?path=/docs/anchor--text-anchor) | :white_check_mark: | :white_check_mark: |
| Anchor Button | | [Issue](https://github.com/ni/nimble/issues/324) | [:white_check_mark: - SB](https://ni.github.io/nimble/storybook/?path=/docs/anchor-button--outline-anchor-button) | :white_check_mark: | :white_check_mark: |
| Anchor Tabs | [XD](https://xd.adobe.com/view/33ffad4a-eb2c-4241-b8c5-ebfff1faf6f6-66ac/screen/b2aa2c0c-03b7-4571-8e0d-de88baf0814b) | [Issue](https://github.com/ni/nimble/issues/479) | [:white_check_mark: - SB](https://nimble.ni.dev/storybook/?path=/docs/anchor-tabs--tabs) | :white_check_mark: | :o: |
| Anchor Tabs | [XD](https://xd.adobe.com/view/33ffad4a-eb2c-4241-b8c5-ebfff1faf6f6-66ac/screen/b2aa2c0c-03b7-4571-8e0d-de88baf0814b) | [Issue](https://github.com/ni/nimble/issues/479) | [:white_check_mark: - SB](https://nimble.ni.dev/storybook/?path=/docs/anchor-tabs--tabs) | :white_check_mark: | :white_check_mark: |
| Banners | [XD](https://xd.adobe.com/view/33ffad4a-eb2c-4241-b8c5-ebfff1faf6f6-66ac/screen/29c405f7-08ea-48b6-973f-546970b9dbab) | [Issue](https://github.com/ni/nimble/issues/305) | :o: | :o: | :o: |
| Breadcrumb | [XD](https://xd.adobe.com/view/33ffad4a-eb2c-4241-b8c5-ebfff1faf6f6-66ac/screen/7b53bb3e-439b-4f13-9d5f-55adc7da8a2e) | | [:white_check_mark: - SB](https://ni.github.io/nimble/storybook/?path=/docs/breadcrumb--standard-breadcrumb) | :white_check_mark: | :white_check_mark: |
| Card | | [Issue](https://github.com/ni/nimble/issues/296) | :o: | :o: | :o: |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Support for anchor tabs",
"packageName": "@ni/nimble-blazor",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,9 @@
<div class="sub-container">
<div class="container-label">Tabs</div>
<NimbleTabs @bind-ActiveId="@ActiveTabId">
<NimbleTab>Tab 1</NimbleTab>
<NimbleTab>Tab 2</NimbleTab>
<NimbleTab Disabled="true">Tab 3 (Disabled)</NimbleTab>
<NimbleTab id="tab-1">Tab 1</NimbleTab>
<NimbleTab id="tab-2">Tab 2</NimbleTab>
<NimbleTab id="tab-3" Disabled="true">Tab 3 (Disabled)</NimbleTab>
<NimbleTabsToolbar>
<NimbleButton>Toolbar Button</NimbleButton>
</NimbleTabsToolbar>
Expand All @@ -222,12 +222,34 @@
<div class="container-label">Tab 3 content</div>
</NimbleTabPanel>
</NimbleTabs>
<NimbleSelect @bind-Value="@ActiveTabId">
<label id="activeTab">
Active tab:
</label>
<NimbleSelect @bind-Value="@ActiveTabId" aria-labelledby="activeTab">
<NimbleListOption Value="tab-1">Tab 1</NimbleListOption>
<NimbleListOption Value="tab-2">Tab 2</NimbleListOption>
<NimbleListOption Value="tab-3">Tab 3</NimbleListOption>
</NimbleSelect>
</div>
<div class="sub-container">
<div class="container-label">Tabs - Anchor</div>
<NimbleAnchorTabs ActiveId="@ActiveAnchorTabId">
<NimbleAnchorTab id="a-tab-1" href="https://nimble.ni.dev">Tab 1</NimbleAnchorTab>
<NimbleAnchorTab id="a-tab-2" href="https://ni.com">Tab 2</NimbleAnchorTab>
<NimbleAnchorTab id="a-tab-3" Disabled="true">Tab 3 (Disabled)</NimbleAnchorTab>
<NimbleTabsToolbar>
<NimbleButton>Toolbar Button</NimbleButton>
</NimbleTabsToolbar>
</NimbleAnchorTabs>
<label id="activeAnchorTab">
Active tab:
</label>
<NimbleSelect @bind-Value="@ActiveAnchorTabId" aria-labelledby="activeAnchorTab">
<NimbleListOption Value="a-tab-1">Tab 1</NimbleListOption>
<NimbleListOption Value="a-tab-2">Tab 2</NimbleListOption>
<NimbleListOption Value="a-tab-3">Tab 3</NimbleListOption>
</NimbleSelect>
</div>
<div class="sub-container">
<div class="container-label">Text Area</div>
<NimbleTextArea Placeholder="Text Area" Cols="50" Rows="5" TextAreaResize="TextAreaResize.Horizontal" Value="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.">Text Area Label</NimbleTextArea>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public partial class ComponentsDemo
{
private DrawerLocation _drawerLocation = DrawerLocation.Right;
private string? ActiveTabId { get; set; }
private string? ActiveAnchorTabId { get; set; } = "a-tab-1";
private NimbleDialog<DialogResult>? _dialog;
private string? DialogClosedReason { get; set; }
private NimbleDrawer<DialogResult>? _drawer;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@namespace NimbleBlazor
<nimble-anchor-tab
disabled="@Disabled"
@attributes="AdditionalAttributes">
@ChildContent
</nimble-anchor-tab>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Components;

namespace NimbleBlazor;

/// <summary>
/// A link styled as a tab
/// </summary>
public partial class NimbleAnchorTab : ComponentBase
{
/// <summary>
/// The child content of the element.
/// </summary>
[Parameter]
public RenderFragment? ChildContent { get; set; }

/// <summary>
/// Whether the tab is disabled (not selectable)
/// </summary>
[Parameter]
public bool? Disabled { get; set; }

/// <summary>
/// Any additional attributes that did not match known properties.
/// </summary>
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object>? AdditionalAttributes { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@namespace NimbleBlazor
<nimble-anchor-tabs
activeid="@BindConverter.FormatValue(ActiveId)"
@attributes="AdditionalAttributes">
@ChildContent
</nimble-anchor-tabs>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Components;

namespace NimbleBlazor;

/// <summary>
/// A sequence of links styled as tabs.
/// </summary>
public partial class NimbleAnchorTabs : ComponentBase
{
/// <summary>
/// The child content of the element.
/// </summary>
[Parameter]
public RenderFragment? ChildContent { get; set; }

/// <summary>
/// The id of the contained NimbleAnchorTab that is marked as active.
/// </summary>
[Parameter]
public string? ActiveId { get; set; }

/// <summary>
/// Any additional attributes that did not match known properties.
/// </summary>
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object>? AdditionalAttributes { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System.Linq;
using AngleSharp.Dom;
using Bunit;
using Xunit;

namespace NimbleBlazor.Tests.Unit.Components;

/// <summary>
/// Tests for <see cref="NimbleAnchorTabs"/>
/// </summary>
public class NimbleAnchorTabsTests
{
[Fact]
public void NimbleAnchorTabsRendered_HasTabsMarkup()
{
var context = new TestContext();
context.JSInterop.Mode = JSRuntimeMode.Loose;
var expectedMarkup = "nimble-anchor-tabs";
var tabs = context.RenderComponent<NimbleAnchorTabs>();

Assert.Contains(expectedMarkup, tabs.Markup);
}

[Fact]
public void NimbleAnchorTabsWithChildContent_HasChildMarkup()
{
var tabs = RenderTabsWithContent();
var expectedChildrenNames = new[] { "nimble-anchor-tab", "nimble-anchor-tab", "nimble-tabs-toolbar" };

var actualChildNodeNames = tabs.Nodes.First().ChildNodes.OfType<IElement>().Select(node => node.LocalName).ToArray();
Assert.Equal(expectedChildrenNames, actualChildNodeNames);
}

[Fact]
public void NimbleAnchorTabsWithChildContent_HasActiveIdMarkup()
{
var tabs = RenderTabsWithContent();

Assert.Contains("activeid", tabs.Markup);
}

[Fact]
public void NimbleAnchorTabsWithChildContent_HasDisabledMarkup()
{
var tabs = RenderTabsWithContent();

Assert.Contains("disabled", tabs.Markup);
}

private IRenderedComponent<NimbleAnchorTabs> RenderTabsWithContent()
{
var context = new TestContext();
context.JSInterop.Mode = JSRuntimeMode.Loose;
return context.RenderComponent<NimbleAnchorTabs>(AddChildContentToTabs);
}

private void AddChildContentToTabs(ComponentParameterCollectionBuilder<NimbleAnchorTabs> parameters)
{
parameters.Add(x => x.ActiveId, "tab1");
parameters.AddChildContent<NimbleAnchorTab>();
parameters.AddChildContent<NimbleAnchorTab>(SetTabDisabled);
parameters.AddChildContent<NimbleTabsToolbar>();
}

private void SetTabDisabled(ComponentParameterCollectionBuilder<NimbleAnchorTab> parameters)
{
parameters.Add(x => x.Disabled, true);
}
}

0 comments on commit 0671e34

Please sign in to comment.