-
-
Notifications
You must be signed in to change notification settings - Fork 26
feat(components): add User component #252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
292a0cd
f11693d
53a9ab2
b4e0ccd
c318301
161867e
bce89d8
1e8aec9
7e8dc81
1bdbc4c
7bb72fa
d4ef66e
bc1f488
d852201
7379d6e
4b009ea
e14bdd0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,22 @@ | ||
| @namespace LumexUI | ||
| @inherits LumexComponentBase | ||
|
|
||
| @using S = UserSlots; | ||
|
|
||
| <LumexComponent As="@As" | ||
| Class="@GetStyles( nameof(S.Base) )" | ||
| Style="@RootStyle" | ||
| data-slot="base" | ||
| data-focus="" | ||
| data-focus-visible="" | ||
| @attributes="AdditionalAttributes"> | ||
| <LumexAvatar /> | ||
| <div class="@GetStyles( nameof( S.Wrapper ) )"> | ||
| <span class="@GetStyles( nameof( S.Name ) )"> | ||
| @Name | ||
| </span> | ||
| <span class="@GetStyles( nameof( S.Description ))"> | ||
| @Description | ||
| </span> | ||
| </div> | ||
| </LumexComponent> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,12 +2,58 @@ | |
| // LumexUI licenses this file to you under the MIT license | ||
| // See the license here https://github.com/LumexUI/lumexui/blob/main/LICENSE | ||
|
|
||
| using System.Diagnostics.CodeAnalysis; | ||
|
|
||
| using LumexUI.Common; | ||
| using LumexUI.Utilities; | ||
|
|
||
| using Microsoft.AspNetCore.Components; | ||
|
|
||
| namespace LumexUI; | ||
|
|
||
| /// <summary> | ||
| /// A component that represents user information, such as an avatar, name, and email. | ||
| /// </summary> | ||
| public partial class LumexUser : LumexComponentBase | ||
| public partial class LumexUser : LumexComponentBase, ISlotComponent<UserSlots> | ||
| { | ||
| [Parameter] public string? Name { get; set; } | ||
|
|
||
| [Parameter] public string? Description { get; set; } | ||
|
|
||
| [Parameter] public bool IsFocusable { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the CSS class names for the user slots. | ||
| /// </summary> | ||
| [Parameter] public UserSlots? Classes { get; set; } | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here is a missing property for the 'Avatar Props', but I'm unsure how to handle the class. Should I use a dedicated class? Or there are already some examples in the codebase?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I need to think about that...
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is actually sad :D I see a couple of options:
I think that the last option is the best here. I have plans to move to the following structure in the future: , where each slot is a separate component that can be styled and arranged independently.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, I just realized that LumexChip already does that (
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But don't wrap
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Oh fantastic! I love this approach 🚀 Ok, so for now I add this 'AvatarContent' as RenderFragment
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it cool for you, if after this component is reviewed I make a branch to try and convert all the components with old styling method to the new? Just to have the project prepared for the architectural shift. I'd like to help, but I don't want to be too overwhelming 😁
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, I’m totally fine with it! I really appreciate your input. I will do my best to make the process as smooth as possible for you. I have to let you know that the utility for the new styling method is far from ideal, so we’ll most likely need to update it a bit. |
||
|
|
||
| private Dictionary<string, ComponentSlot> _slots = []; | ||
|
|
||
| /// <inheritdoc/> | ||
| protected override void OnParametersSet() | ||
| { | ||
| var user = Styles.User.Style( TwMerge ); | ||
| _slots = user( new() | ||
| { | ||
|
|
||
| } ); | ||
| } | ||
|
|
||
| [ExcludeFromCodeCoverage] | ||
| private string? GetStyles( string slot ) | ||
| { | ||
| if( !_slots.TryGetValue( slot, out var styles ) ) | ||
| { | ||
| throw new NotImplementedException(); | ||
| } | ||
|
|
||
| return slot switch | ||
| { | ||
| nameof( UserSlots.Base ) => styles( Classes?.Base, Class ), | ||
| nameof( UserSlots.Wrapper ) => styles( Classes?.Wrapper ), | ||
| nameof( UserSlots.Name ) => styles( Classes?.Name ), | ||
| nameof( UserSlots.Description ) => styles( Classes?.Description ), | ||
| _ => throw new NotImplementedException() | ||
| }; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| // Copyright (c) LumexUI 2024 | ||
| // LumexUI licenses this file to you under the MIT license | ||
| // See the license here https://github.com/LumexUI/lumexui/blob/main/LICENSE | ||
|
|
||
| using LumexUI.Common; | ||
|
|
||
| namespace LumexUI; | ||
|
|
||
| /// <summary> | ||
| /// Represents the set of customizable slots for the <see cref="LumexUser"/> component. | ||
| /// </summary> | ||
| public class UserSlots : SlotBase | ||
| { | ||
| /// <summary> | ||
| /// Gets or sets the CSS class for the wrapper slot. | ||
| /// </summary> | ||
| public string? Wrapper { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the CSS class for the name slot. | ||
| /// </summary> | ||
| public string? Name { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the CSS class for the description slot. | ||
| /// </summary> | ||
| public string? Description { get; set; } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| // Copyright (c) LumexUI 2024 | ||
| // LumexUI licenses this file to you under the MIT license | ||
| // See the license here https://github.com/LumexUI/lumexui/blob/main/LICENSE | ||
|
|
||
| using System.Diagnostics.CodeAnalysis; | ||
|
|
||
| using LumexUI.Components.User; | ||
| using LumexUI.Utilities; | ||
|
|
||
| using TailwindMerge; | ||
|
|
||
| namespace LumexUI.Styles; | ||
|
|
||
| [ExcludeFromCodeCoverage] | ||
| internal static class User | ||
| { | ||
| private static ComponentVariant? _variant; | ||
|
|
||
| public static ComponentVariant Style( TwMerge twMerge ) | ||
| { | ||
| var twVariants = new TwVariants( twMerge ); | ||
|
|
||
| return _variant ?? twVariants.Create( new VariantConfig() | ||
| { | ||
| Base = new ElementClass() | ||
| .Add( "inline-flex" ) | ||
| .Add( "items-center" ) | ||
| .Add( "justify-center" ) | ||
| .Add( "gap-2" ) | ||
| .Add( "rounded-small" ) | ||
| .Add( "outline-solid" ) | ||
| .Add( "outline-transparent" ) | ||
| .Add( "outline-solid" ) | ||
| .Add( "outline-transparent" ) | ||
| .ToString(), | ||
|
|
||
| Slots = new SlotCollection | ||
| { | ||
| [nameof(UserSlots.Wrapper)] = "inline-flex flex-col items-start", | ||
|
|
||
| [nameof(UserSlots.Name)] = "text-small text-inherit", | ||
|
|
||
| [nameof(UserSlots.Description)] = "text-tiny text-foreground-400", | ||
| } | ||
| } ); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see on the HeroUI docs that this two attributes are set, I don't know if they can be useful to this library
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are setting interaction states programmatically. We don't do this.
These should be covered by
Styles.Utils.FocusVisiblein the styles. Search for theFocusVisibleusages.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect, I was already using that, I was only wandering if this was the right path. So the IsFocusable property, can be used to toggle this behavior or should I remove it directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I haven't noticed this prop before. According to HeroUI isFocusable means: "Whether the user is focusable. This is useful when using Dropdown or similar components."
I think it's better to keep it to toggle this behaviour.