Skip to content

Commit

Permalink
feat(components): introduce Tabs component (#159)
Browse files Browse the repository at this point in the history
* feat(motion): add reference to LumexMotion

* chore: update .editorconfig

* feat(components): add baseline implementation of `LumexTabs` component

* feat(tabs): add `Size` parameter

* feat(tabs): add `Radius` parameter

* feat(tabs): add `FullWidth` parameter

* feat(tabs): add `Disabled` parameter

* feat(tabs): add `Colors` parameter and compound styles

* feat(motion): update package contents

* feat: add `Id` param for the tab component

* refactor: set defaults for the `Variant`, `Color`, `Size` and `Radius`

* feat: add `Disabled` and `DisabledItems` parameters

* fix: multiple Tabs share the same layoutId causing conflicts

* fix: tabs are getting removed on active tab change

* chore: .editorconfig

* fix: correct outlined variant styles

* feat: render tab as link if `href` is provided; automatically set as active if matches route

* feat: add 2-way data binding

* feat: add slots support

* chore(motion): nits

* chore(motion): update package contents

* refactor(docs): stop treating RZ2012 warning as error

* test: add tests

* chore(motion): exclude from code coverage (will be tested in its own solution)

* feat: respect predefined `SelectedId` set on the owner

* chore: add summaries

* fix: typo

* fix: 2-way binding logic

* feat(docs): introduce Tabs page

* refactor: make relative path and href matching less permissive

* refactor: make relative path and href matching less permissive

* refactor: make relative path and href matching less permissive

* test: fix
  • Loading branch information
desmondinho authored Jan 30, 2025
1 parent bb5fead commit acb86a1
Show file tree
Hide file tree
Showing 59 changed files with 2,159 additions and 47 deletions.
40 changes: 20 additions & 20 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
root = true

# C# files
[*.{cs,razor}]
[*.cs]

#### Core EditorConfig Options ####

Expand Down Expand Up @@ -93,14 +93,14 @@ csharp_style_var_for_built_in_types = true:warning
csharp_style_var_when_type_is_apparent = true:warning

# Expression-bodied members
csharp_style_expression_bodied_accessors = when_on_single_line
csharp_style_expression_bodied_accessors = false
csharp_style_expression_bodied_constructors = false:warning
csharp_style_expression_bodied_indexers = when_on_single_line
csharp_style_expression_bodied_lambdas = when_on_single_line
csharp_style_expression_bodied_local_functions = when_on_single_line
csharp_style_expression_bodied_methods = when_on_single_line
csharp_style_expression_bodied_operators = when_on_single_line
csharp_style_expression_bodied_properties = when_on_single_line
csharp_style_expression_bodied_indexers = false
csharp_style_expression_bodied_lambdas = false
csharp_style_expression_bodied_local_functions = false
csharp_style_expression_bodied_methods = false
csharp_style_expression_bodied_operators = false
csharp_style_expression_bodied_properties = false

# Pattern matching preferences
csharp_style_pattern_matching_over_as_with_null_check = true:warning
Expand Down Expand Up @@ -135,21 +135,21 @@ csharp_style_deconstructed_variable_declaration = false
csharp_style_implicit_object_creation_when_type_is_apparent = true
csharp_style_inlined_variable_declaration = true:warning
csharp_style_prefer_index_operator = true
csharp_style_prefer_local_over_anonymous_function = true:warning
csharp_style_prefer_local_over_anonymous_function = false:silent
csharp_style_prefer_null_check_over_type_check = true
csharp_style_prefer_range_operator = true
csharp_style_prefer_tuple_swap = true
csharp_style_prefer_utf8_string_literals = true
csharp_style_throw_expression = true:warning
csharp_style_unused_value_assignment_preference = discard_variable
csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion
csharp_style_unused_value_assignment_preference = discard_variable:silent
csharp_style_unused_value_expression_statement_preference = discard_variable

# 'using' directive preferences
csharp_using_directive_placement = outside_namespace:error

# New line preferences
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false:warning
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = false:warning
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = false
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false:warning
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false:warning
csharp_style_allow_embedded_statements_on_same_line_experimental = true
Expand Down Expand Up @@ -194,7 +194,7 @@ csharp_space_between_method_call_parameter_list_parentheses = true
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = true
csharp_space_between_parentheses = control_flow_statements
csharp_space_between_parentheses = expressions,control_flow_statements
csharp_space_between_square_brackets = false

# Wrapping preferences
Expand All @@ -217,9 +217,9 @@ dotnet_naming_rule.property_should_be_pascal_case.severity = warning
dotnet_naming_rule.property_should_be_pascal_case.symbols = property
dotnet_naming_rule.property_should_be_pascal_case.style = pascal_case

dotnet_naming_rule.field_should_be_camel_case_prefixed_with__.severity = warning
dotnet_naming_rule.field_should_be_camel_case_prefixed_with__.symbols = field
dotnet_naming_rule.field_should_be_camel_case_prefixed_with__.style = camel_case_prefixed_with__
dotnet_naming_rule.private_or_internal_field_should_be_camel_case_prefixed_with__.severity = warning
dotnet_naming_rule.private_or_internal_field_should_be_camel_case_prefixed_with__.symbols = private_or_internal_field
dotnet_naming_rule.private_or_internal_field_should_be_camel_case_prefixed_with__.style = camel_case_prefixed_with__

# Symbol specifications

Expand All @@ -231,14 +231,14 @@ dotnet_naming_symbols.property.applicable_kinds = property
dotnet_naming_symbols.property.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.property.required_modifiers =

dotnet_naming_symbols.private_or_internal_field.applicable_kinds = field
dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities = internal, private, private_protected
dotnet_naming_symbols.private_or_internal_field.required_modifiers =

dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =

dotnet_naming_symbols.field.applicable_kinds = field
dotnet_naming_symbols.field.applicable_accessibilities = private
dotnet_naming_symbols.field.required_modifiers = readonly, static

# Naming styles

dotnet_naming_style.pascal_case.required_prefix =
Expand Down
7 changes: 7 additions & 0 deletions LumexUI.sln
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LumexUI.Docs", "docs\LumexU
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LumexUI.Docs.Client", "docs\LumexUI.Docs.Client\LumexUI.Docs.Client.csproj", "{6CE81AB3-399F-44CB-9DBE-9A8D62B07C8A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LumexUI.Motion", "src\LumexUI.Motion\LumexUI.Motion.csproj", "{52657DBF-5D90-4829-9AE9-713E0C39E5CA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -58,6 +60,10 @@ Global
{6CE81AB3-399F-44CB-9DBE-9A8D62B07C8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6CE81AB3-399F-44CB-9DBE-9A8D62B07C8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6CE81AB3-399F-44CB-9DBE-9A8D62B07C8A}.Release|Any CPU.Build.0 = Release|Any CPU
{52657DBF-5D90-4829-9AE9-713E0C39E5CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{52657DBF-5D90-4829-9AE9-713E0C39E5CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{52657DBF-5D90-4829-9AE9-713E0C39E5CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{52657DBF-5D90-4829-9AE9-713E0C39E5CA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -69,6 +75,7 @@ Global
{06E849E9-A8EA-410B-83BC-0366524C4953} = {898610F1-A6C1-422C-84C9-C1E386957F31}
{2A341376-2409-422C-A7A9-1AE6E86F91D9} = {3F4DE3FA-2636-440C-ACCC-137BAD95BAC4}
{6CE81AB3-399F-44CB-9DBE-9A8D62B07C8A} = {3F4DE3FA-2636-440C-ACCC-137BAD95BAC4}
{52657DBF-5D90-4829-9AE9-713E0C39E5CA} = {5DBC44B8-5B92-4504-8B8F-91A1672251E6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1B8CD55B-BEF0-42D1-936A-BC1FB5D02CE2}
Expand Down
5 changes: 3 additions & 2 deletions docs/LumexUI.Docs.Client/Common/Navigation/NavigationStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,18 @@ public class NavigationStore
.Add( new( nameof( LumexCheckbox ) ) )
.Add( new( nameof( LumexCheckboxGroup ) ) )
.Add( new( nameof( LumexCollapse ) ) )
.Add( new( nameof( LumexDataGrid<T> ), ComponentStatus.Preview ) )
.Add( new( nameof( LumexDataGrid<T> ) ) )
.Add( new( nameof( LumexDivider ) ) )
.Add( new( nameof( LumexIcon ) ) )
.Add( new( nameof( LumexLink ) ) )
.Add( new( nameof( LumexListbox<T> ), ComponentStatus.New ) )
.Add( new( nameof( LumexNavbar ) ) )
.Add( new( nameof( LumexNumbox<T> ) ) )
.Add( new( nameof( LumexPopover ) ) )
.Add( new( nameof( LumexRadioGroup<T>), ComponentStatus.New ) )
.Add( new( nameof( LumexRadioGroup<T> ), ComponentStatus.New ) )
.Add( new( nameof( LumexSelect<T> ), ComponentStatus.New ) )
.Add( new( nameof( LumexSwitch ) ) )
.Add( new( nameof( LumexTabs ), ComponentStatus.New ) )
.Add( new( nameof( LumexTextbox ) ) );

private static NavigationCategory ComponentsApiCategory =>
Expand Down
1 change: 0 additions & 1 deletion docs/LumexUI.Docs.Client/Components/DocsApiSection.razor
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
@namespace LumexUI.Docs.Client.Components
@inject NavigationManager NavigationManager

<LumexDivider />
<DocsSection Title="API">
<p>
See the API references below for a complete guide to all the
Expand Down
4 changes: 0 additions & 4 deletions docs/LumexUI.Docs.Client/LumexUI.Docs.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@
<StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
</PropertyGroup>

<PropertyGroup>
<WarningsAsErrors>RZ2012</WarningsAsErrors>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentValidation" Version="11.10.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.11" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<div class="flex flex-wrap gap-4">
@foreach (var color in Enum.GetValues<ThemeColor>()[1..])
{
<LumexTabs Color="@color">
<LumexTab Id="@("photos")" Title="Photos" />
<LumexTab Id="@("music")" Title="Music" />
<LumexTab Id="@("videos")" Title="Videos" />
</LumexTabs>
}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<div class="w-full flex flex-col">
<LumexTabs Variant="@TabVariant.Underlined"
Color="@ThemeColor.Primary"
Classes="@_classes">
<LumexTab Id="@("photos")">
<TitleContent>
<div class="flex items-center space-x-2">
<LumexIcon Icon="@Icons.Rounded.PhotoLibrary" />
<span>Photos</span>
@_chip(12)
</div>
</TitleContent>
</LumexTab>
<LumexTab Id="@("music")">
<TitleContent>
<div class="flex items-center space-x-2">
<LumexIcon Icon="@Icons.Rounded.LibraryMusic" />
<span>Music</span>
@_chip(2)
</div>
</TitleContent>
</LumexTab>
<LumexTab Id="@("videos")">
<TitleContent>
<div class="flex items-center space-x-2">
<LumexIcon Icon="@Icons.Rounded.VideoLibrary" />
<span>Videos</span>
@_chip(7)
</div>
</TitleContent>
</LumexTab>
</LumexTabs>
</div>

@code {
private RenderFragment<int> _chip = content =>
@<div class="size-5 inline-flex items-center justify-center border-2 border-default-200 bg-default-100 text-default-foreground rounded-full">
<span class="text-tiny">@content</span>
</div>;

private TabsSlots _classes = new()
{
TabList = "gap-6 w-full rounded-none p-0 border-b border-divider",
Tab = "max-w-fit px-0 h-12",
TabContent = "group-data-[selected=true]:text-secondary",
Cursor = "w-full bg-secondary"
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<div class="w-full flex flex-col">
<LumexTabs Disabled="@true">
<LumexTab Id="@("photos")" Title="Photos">
<LumexCard>
<LumexCardBody>
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.
</LumexCardBody>
</LumexCard>
</LumexTab>
<LumexTab Id="@("music")" Title="Music">
<LumexCard>
<LumexCardBody>
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.
</LumexCardBody>
</LumexCard>
</LumexTab>
<LumexTab Id="@("videos")" Title="Videos">
<LumexCard>
<LumexCardBody>
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</LumexCardBody>
</LumexCard>
</LumexTab>
</LumexTabs>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<div class="w-full flex flex-col">
<LumexTabs DisabledItems="@(["music"])">
<LumexTab Id="@("photos")" Title="Photos">
<LumexCard>
<LumexCardBody>
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.
</LumexCardBody>
</LumexCard>
</LumexTab>
<LumexTab Id="@("music")" Title="Music">
<LumexCard>
<LumexCardBody>
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.
</LumexCardBody>
</LumexCard>
</LumexTab>
<LumexTab Id="@("videos")" Title="Videos">
<LumexCard>
<LumexCardBody>
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</LumexCardBody>
</LumexCard>
</LumexTab>
</LumexTabs>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<div class="w-full flex flex-col">
<LumexTabs>
<LumexTab Id="@("photos")" Title="Photos" href="/photos">
<LumexCard>
<LumexCardBody>
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.
</LumexCardBody>
</LumexCard>
</LumexTab>
<LumexTab Id="@("music")" Title="Music" href="/music">
<LumexCard>
<LumexCardBody>
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.
</LumexCardBody>
</LumexCard>
</LumexTab>
<LumexTab Id="@("videos")" Title="Videos" href="/videos">
<LumexCard>
<LumexCardBody>
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</LumexCardBody>
</LumexCard>
</LumexTab>
</LumexTabs>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<div class="flex flex-wrap gap-4">
@foreach (var size in Enum.GetValues<Size>())
{
<LumexTabs Size="@size">
<LumexTab Id="@("photos")" Title="Photos" />
<LumexTab Id="@("music")" Title="Music" />
<LumexTab Id="@("videos")" Title="Videos" />
</LumexTabs>
}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<div class="w-full flex flex-col">
<LumexTabs Color="@ThemeColor.Primary">
<LumexTab Id="@("photos")">
<TitleContent>
<div class="flex items-center space-x-2">
<LumexIcon Icon="@Icons.Rounded.PhotoLibrary" />
<span>Photos</span>
</div>
</TitleContent>
</LumexTab>
<LumexTab Id="@("music")">
<TitleContent>
<div class="flex items-center space-x-2">
<LumexIcon Icon="@Icons.Rounded.LibraryMusic" />
<span>Music</span>
</div>
</TitleContent>
</LumexTab>
<LumexTab Id="@("videos")">
<TitleContent>
<div class="flex items-center space-x-2">
<LumexIcon Icon="@Icons.Rounded.VideoLibrary" />
<span>Videos</span>
</div>
</TitleContent>
</LumexTab>
</LumexTabs>
</div>
Loading

0 comments on commit acb86a1

Please sign in to comment.