fluentui-blazor icon indicating copy to clipboard operation
fluentui-blazor copied to clipboard

[FluentPersona] Add support for icons

Open hksalessio opened this issue 1 year ago • 11 comments

Pull Request

📖 Description

The FluentPersona component only supports displaying images and initials in its circular avatar area. This pull request adds additional support for icons to be displayed. Images will always be preferred over icons, which themselves will always be preferred over initials.

This pull request further fixes the RTL margin for the FluentPersona component.

✅ Checklist

General

  • [ ] I have added tests for my changes.
  • [x] I have tested my changes.
  • [x] I have updated the project documentation to reflect my changes.
  • [x] I have read the CONTRIBUTING documentation and followed the standards for this project.

Component-specific

  • [ ] I have added a new component
  • [ ] I have added Unit Tests for my new compontent
  • [x] I have modified an existing component
  • [ ] I have validate Unit Tests for an existing component

hksalessio avatar Feb 20 '24 12:02 hksalessio

It might be a good idea to allow icon content (SVG) in this image part of the component. But I'm a bit scared by the complexity of the available properties: Image vs Icon and ImageSize vs IconSize. We'll need to explain the "priority" of the properties (Icon then Image) and also how to specify sizes.

It would be more "logical" to allow an icon (SVG) to be included in the Image property.

dvoituron avatar Feb 20 '24 13:02 dvoituron

It would be more "logical" to allow an icon (SVG) to be included in the Image property.

Funnily, that's the first thing I tried today, when I needed an icon avatar 😄

So, you say no new properties should be added but instead it should be checked whether Image contains an SVG (i.e. Image.StartsWith("<svg>")? At least, I wouldn't know how else this could be implemented)?

hksalessio avatar Feb 20 '24 13:02 hksalessio

We could convert an Icon to an img src (used in FluentPersona), adding this part of code in Icon.cs file

public virtual string ToDataUri(string? size = null, string? color = null)
{
    var svg = ToMarkup(size, color).Value;

    // Attribute xmlns="http://www.w3.org/2000/svg" is required for SVG data URI.
    svg = svg.Contains("http://www.w3.org/2000/svg") ? svg : svg.Replace("<svg ", "<svg xmlns=\"http://www.w3.org/2000/svg\" ");

    var base64Svg = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(svg));
    return $"data:image/svg+xml;base64,{base64Svg}";
}

So, the usage will be

<FluentPersona Name="Bill Gates"
               Status="PresenceStatus.Available"
               StatusSize="PresenceBadgeSize.Small"
               StatusTitle="He is available"
               Image="@(new Icons.Regular.Size48.Person().ToDataUri(color: "white"))"
               ImageSize="50px">
</FluentPersona>

Can you update your PR? Or I can create a new one if you prefer.

dvoituron avatar Feb 20 '24 14:02 dvoituron

I can update my PR, but I just tested this and it does neither seem to work with custom sizes nor with variable colors (e.g. var(--fill-color)) :/

hksalessio avatar Feb 20 '24 14:02 hksalessio

We could convert an Icon to an img src (used in FluentPersona), adding this part of code in Icon.cs file

public virtual string ToDataUri(string? size = null, string? color = null)
{
    var svg = ToMarkup(size, color).Value;

    // Attribute xmlns="http://www.w3.org/2000/svg" is required for SVG data URI.
    svg = svg.Contains("http://www.w3.org/2000/svg") ? svg : svg.Replace("<svg ", "<svg xmlns=\"http://www.w3.org/2000/svg\" ");

    var base64Svg = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(svg));
    return $"data:image/svg+xml;base64,{base64Svg}";
}

So, the usage will be

<FluentPersona Name="Bill Gates"
               Status="PresenceStatus.Available"
               StatusSize="PresenceBadgeSize.Small"
               StatusTitle="He is available"
               Image="@(new Icons.Regular.Size48.Person().ToDataUri(color: "white"))"
               ImageSize="50px">
</FluentPersona>

Can you update your PR? Or I can create a new one if you prefer.

What if, in addition to your suggested changes, a RenderFragment named "ImageContent" (or something similar) is provided. This would allow customization of the image without adding any new parameters (except the RenderFragment) or worrying about explaining the priority of parameters.

hksalessio avatar Feb 26 '24 11:02 hksalessio

With a RenderFragment we can't control and/or check if an actual image is being supplied. I rather add some parameters and be 'in control'.

vnbaaij avatar Feb 26 '24 11:02 vnbaaij

With a RenderFragment we can't control and/or check if an actual image is being supplied. I rather add some parameters and be 'in control'.

So, how should we proceed with this? I guess this feature would be of great use, but I would like to get it done right (and conforming to your library).

hksalessio avatar Feb 27 '24 07:02 hksalessio

I'd say we go with the solution @dvoituron provided (and make it work)

vnbaaij avatar Feb 27 '24 08:02 vnbaaij

Yes, I think this solution does not (yet) cover all cases, but it does cover a large proportion. The advantage is that it can also be used for other types of problem. We can always think later about additional options to manage the "system" color.

dvoituron avatar Feb 27 '24 09:02 dvoituron

Alright, I've update the code to use @dvoituron's solution. I also tinkered around with how to support custom sizes for icons. The only problem left is that images smaller than the specified ImageSize do not fill up the full image area. Maybe you can come up with a solution to this problem?

hksalessio avatar Feb 28 '24 13:02 hksalessio

@hksalessio can you check the Unit Tests. Some are failing and because of that the pipline that build the code won't run.

vnbaaij avatar Feb 28 '24 13:02 vnbaaij

We are merging this as-is and then do some checks ourselves on the dev branch

vnbaaij avatar Mar 05 '24 14:03 vnbaaij