Skip to content
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

[Feature] Add a Reimagined Color Picker #3363

Closed
robloo opened this issue Jun 24, 2020 · 65 comments · Fixed by #3379
Closed

[Feature] Add a Reimagined Color Picker #3363

robloo opened this issue Jun 24, 2020 · 65 comments · Fixed by #3379

Comments

@robloo
Copy link
Contributor

robloo commented Jun 24, 2020

The current WinUI ColorPicker has some deficiencies:

  1. #1637 It is a big control without an adaptive layout. There is no way to switch between horizontal or vertical mode based on available space.
  2. #2309 It does not follow the 'Picker' convention by having a preview button that can be pressed to open an editing flyout
  3. #1659 There is no way to select from a pre-existing list of swatches.
  4. The existing ColorPicker doesn't use NumberBox

Describe the solution

A brand new ColorSwatchPicker control (deriving from ColorPicker) with a totally redesigned layout:

  • Spectrum | to visually select a color on the color spectrum
  • Swatches/Palette | to select a pre-defined color from a palette. This could be from a system colors list, a recent colors list, or a custom-developer supplied list of colors. A configuration will be added so the swatches can be a circle or square.
  • Channels | to create a color using numerical component values. Sliders will be added for each component along with NumberBoxes.

The ColorSwatchPicker will appear as a drop-down button previewing the selected color with a totally redesigned picker within the flyout to edit it.

A custom color pallete (list of swatches) is now supported as well using three properties (and their associated DPs):

        /// <summary>
        /// Gets the list of custom palette colors.
        /// </summary>
        public ObservableCollection<Windows.UI.Color> CustomPaletteColors { get; }

        /// <summary>
        /// Gets or sets the number of colors in each section of the custom color palette.
        /// A section is the number of columns within an entire row in the palette.
        /// Within a standard palette, rows are shades and columns are unique colors.
        /// </summary>
        public int CustomPaletteSectionCount { get; set; }

        /// <summary>
        /// Gets or sets a custom IPalette.
        /// This will automatically set <see cref="CustomPaletteColors"/> and <see cref="CustomPaletteSectionCount"/> 
        /// overwriting any existing values.
        /// </summary>
        public IColorPalette CustomPalette { get; set; }

This requires the implementation of a new interface which I feel is useful enough to be general purpose.

    /// <summary>
    /// Interface to define a color palette.
    /// </summary>
    public interface IColorPalette
    {
        /// <summary>
        /// Gets the total number of colors in this palette.
        /// A color is not necessarily a single value and may be composed of several shades.
        /// </summary>
        int ColorCount { get; }

        /// <summary>
        /// Gets the total number of shades for each color in this palette.
        /// Shades are usually a variation of the color lightening or darkening it.
        /// </summary>
        int ShadeCount { get; }

        /// <summary>
        /// Gets a color in the palette by index.
        /// </summary>
        /// <param name="colorIndex">The index of the color in the palette.
        /// The index must be between zero and <see cref="ColorCount"/>.</param>
        /// <param name="shadeIndex">The index of the color shade in the palette.
        /// The index must be between zero and <see cref="ShadeCount"/>.</param>
        /// <returns>The color at the specified index or an exception.</returns>
        Color GetColor(int colorIndex, int shadeIndex);
    }

Describe alternatives you've considered

The alternative is to modify ColorPicker directly but these changes are too far reaching for existing users of the ColorPicker. Its better to implement this as a brand new control.

Additional context & Screenshots

Below is the implementation of ColorSwatchPicker. Functionally, it is complete as proposed. With styling further work is needed around the sliders to dynamically change the background colors (if possible without too much complexity).

example1

Spectrum Palette Channels
Spectrum Palette Channels1
Channels2
@robloo robloo added the feature request 📬 A request for new changes to improve functionality label Jun 24, 2020
@ghost
Copy link

ghost commented Jun 24, 2020

Hello, 'robloo! Thanks for submitting a new feature request. I've automatically added a vote 👍 reaction to help get things started. Other community members can vote to help us prioritize this feature in the future!

@robloo
Copy link
Contributor Author

robloo commented Jun 24, 2020

I should add, I intend to implement this control myself. I'm looking for more feedback before coding starts though.

@Kyaa-dost
Copy link
Contributor

@robloo seems like an interesting feature. Let's see what our devs think about this and then you can proceed with the PR 🚀

@niels9001
Copy link

niels9001 commented Jun 24, 2020

Great idea!

Having a 'compact' mode (where the selected color is shown) would be great. As you mentioned in the OT, a DropDown button could work for that. This is how we implemented this in PowerToys:

FZColors

And this is a UX proposal for a Windows color picker tool: a redesigned colorpicker would be useful there as well (more info on this in microsoft/PowerToys#864):

Colorpicker_Twitter

@robloo
Copy link
Contributor Author

robloo commented Jun 24, 2020

@niels9001

I will definitely implement the drop down / preview functionality. I already have a control for this implementing it in one of my apps. It also has a checkered background for transparency. Bottom line, one of the main drivers of this is to get a more usable color picker to put in apps as soon as possible. We need to close the feature gap with user expectation.

The second idea is very interesting. It previews a bunch of different tints and shades which is useful. I'll have to think if that can be worked into the existing ideas. Once I have a prototype (which might be some weeks) I would like your feedback on ideas like this.

@niels9001
Copy link

@niels9001

I will definitely implement the drop down / preview functionality. I already have a control for this implementing it in one of my apps. It also has a checkered background for transparency. Bottom line, one of the main drivers of this is to get a more usable color picker to put in apps as soon as possible. We need to close the feature gap with user expectation.

The second idea is very interesting. It previews a bunch of different tints and shades which is useful. I'll have to think if that can be worked into the existing ideas. Once I have a prototype (which might be some weeks) I would like your feedback on ideas like this.

That would actually be a pretty neat addition: having a palette based on the selected color or swatch.

If you want me to help to do some UX mocks, let me know.

@robloo
Copy link
Contributor Author

robloo commented Jun 24, 2020

Yes, I definitely see the value. Actually, this (small palette) preview could probably be added as a preview method in ALL tabs. Instead of previewing only the selected color, the additional shades would also be shown. That would allow quickly increasing/decreasing shade or tint in a visual way.

For calculating the tints and shades what algorithm did you use? I don't want to just randomly mix in some white and black and wonder if there are usability studies on different thresholds?

UX is kind of a joy for me too. Personally, I find it's best to R&D this stuff in controls directly though. I would like to put my ideas down first before getting wider feedback. Your help refining them (or even changing them) at that point would be invaluable.

@niels9001
Copy link

Yes, I definitely see the value. Actually, this (small palette) preview could probably be added as a preview method in ALL tabs. Instead of previewing only the selected color, the additional shades would also be shown. That would allow quickly increasing/decreasing shade or tint in a visual way.

For calculating the tints and shades what algorithm did you use? I don't want to just randomly mix in some white and black and wonder if there are usability studies on different thresholds?

UX is kind of a joy for me too. Personally, I find it's best to R&D this stuff in controls directly though. I would like to put my ideas down first before getting wider feedback. Your help refining them (or even changing them) at that point would be invaluable.

I translated the Windows.UI.Color into a HSV value, and just played around with the V value. There are much better ways to do it, this was a 5 min hack to get the concept right :)

@mdtauk
Copy link

mdtauk commented Jun 24, 2020

You could perhaps employ the same colour maths that is used to generate the light and dark shades of an accent colour.

@robloo
Copy link
Contributor Author

robloo commented Jun 24, 2020

I decided, for now, to start implementing these ideas into an existing app's custom color picker. That will speed up prototyping a lot and it allows for quickly adding these features to my own app without waiting for Microsoft. But it also means I'll have images to start getting feedback on quite a bit faster. When we have direction from Microsoft I can pull the code into the toolkit.

I also want to add an IPalette interface that defines a 'grid' or 'chart' of colors.

int ColorCount;
int ShadeCount;
Color GetColor(int colorIndex, int shadeIndex);

What will this do? It will make it easy to define, use and share color palettes like material design, flat UI, etc. You will be able to set the Palette of the color picker all at once instead of having to provide a list of Colors with no knowledge of how to arrange them. This might not make it outside my apps but I think it would be useful to prototype and get feedback on. It might also be useful in the framework someday as a higher level structure for a chart of colors.

@robloo
Copy link
Contributor Author

robloo commented Jun 25, 2020

Here is what I have in mind for the Components tab. This is non-functional but it's real XAML and represents what I'm planning. Please let me know any comments. @mdtauk I used some of your previous mock-ups as well.

image

It would also be good to have the background of the sliders dynamically change. Each slider would show a gradient. I haven't decided whether to implement that in this version. I'll probably get to more of this during the weekend.

Note that the default NumberBox and ComboBox heights are different too which I find strange.

Edit: Also note that the preview color along with +/-2 shades will be at the bottom which is not pictured.

@michael-hawker
Copy link
Member

Hey all, love the enthusiasm here. I know we do have some Color value helpers in the toolkit for some of these different HSV scenarios.

As for the re-implementing ColorPicker, especially with the existing proposals for WinUI, I really think improving the platform based control would be the best option still here.

@robloo I'm assuming you're more comfortable with C# vs. C++ and thus choosing to propose this to the Toolkit based on that? If so, I do know WinUI still does some prototyping in C#, so there could still be an opportunity to work with them to build out the vision and then work towards improving the existing controls.

It could maybe make sense to add the picker dropdown here in the meantime. However we'd still want to rely on the inbox ColorPicker vs. the WinUI one (as we don't have a dependency in our main package on WinUI).

I did a quick experiment here that looks promising:

        <DropDownButton AutomationProperties.Name="Color" CornerRadius="2">
            <DropDownButton.Content>
                <Border Width="20" Height="20" Margin="-6,-4,0,-4" CornerRadius="2">
                    <Border.Background>
                        <SolidColorBrush Color="{Binding Color, ElementName=ColorPicker}" />
                    </Border.Background>
                </Border>
            </DropDownButton.Content>
            <DropDownButton.Flyout>
                <Flyout Placement="BottomEdgeAlignedLeft">
                    <ColorPicker x:Name="ColorPicker"/>
                </Flyout>
            </DropDownButton.Flyout>
        </DropDownButton>

I could see us inheriting from ColorPicker and exposing the Flyout Placement value in a simple templated control.

FYI @ranjeshj @stmoy @chingucoding

@robloo
Copy link
Contributor Author

robloo commented Jun 25, 2020

Hi @michael-hawker Thanks for the feedback.

I definitely agree that improving the platform control directly in WinUI is the end goal. However:

  1. I need this ASAP for apps -- especially the color-picker in a flyout drop-down button concept. Why not share it as others need it too?
  2. Prototype and implementing a first version here is a lot faster than in WinUI. You know Microsoft is a big ship, when/if Microsoft gets around to this in WinUI 3.0 is an open-ended question.
  3. My existing apps are not only in C#, but C# is a lot quicker to get things done in. It makes sense to prototype here first from that aspect as well.
  4. @ranjeshj actually requested this be done here origininally Proposal: Add a ColorPickerButton Control microsoft/microsoft-ui-xaml#2309 (comment)

Here is my plan:

  1. Get the go-ahead from you
  2. Work on all changes in the Windows Community Toolkit repo
  3. A few rounds of community feedback and bugfixes to stabilize the new control
  4. Create a very clear WinUI proposal based on everything learned in the toolkit -- get it accepted
  5. Port the control over to WinUI

This is very similar to what has been done in past control. What is new here is that it is kind-of a mix between a new control (ColorSwatchPicker) and a re-imagining of an existing one. I understand a community re-imagining of an existing Microsoft control at first causes some concerns. Hopefully my plan and reasoning above helps with that.

@robloo
Copy link
Contributor Author

robloo commented Jun 26, 2020

Could I entice anyone with this?

example1

I had some extra time this evening and probably got 60% finished. I'm open for feedback now!

@robloo
Copy link
Contributor Author

robloo commented Jun 26, 2020

The color palette is also fully customizable. Assign a list of colors to CustomPaletteColors and then set the CustomPaletteSectionCount and you can do this:

example3

image

@niels9001
Copy link

niels9001 commented Jun 26, 2020

Awesome job @robloo I like it overall :)!

  • Is there a branch somewhere to play with?
  • I think an Alpha slider in the Spectrum page is important to have (albeit optional). Maybe having that to the right of the component could work?
  • Maybe, next to the compact mode (using the dropdown button) having the color 'gradient' as a standalone mode would be nice as well? Clicking on a color would trigger an event with the selected color and could open the entire control?

I think there are some (minor) margins/paddings that would need to be fixed, but let's leave that for now until we have the functionality right!

@robloo
Copy link
Contributor Author

robloo commented Jun 26, 2020

@niels9001

Is there a branch somewhere to play with?

Not yet, this is being built first on an app with proprietary code just to make things faster. I don't have to worry about setting up the whole infrastructure of the toolkit and using my own nugets -- actually, I'm trying to avoid that altogether.

I think an Alpha slider in the Spectrum page is important to have (albeit optional). Maybe having that to the right of the component could work?

I was going to do the same! :) To not mess up the symmetry it should go above/below but that just isn't working layout-wise so it will probably have to go to the right as you thought as well. Visibility of all alpha sliders will be wired to the existing IsAlphaSliderVisible property.

Maybe, next to the compact mode (using the dropdown button) having the color 'gradient' as a standalone mode would be nice as well? Clicking on a color would trigger an event with the selected color and could open the entire control?

So you are saying that with the flyout collapsed, the selected color would be visible along with the +/- 2 shades which would be independently clickable? That would be similar to your second concept as I understand it. I'm not sure the added complexity would quite justify the usefulness of that feature. It would technically be prohibitive requiring more template parts which I'm always trying to avoid. It would also be confusing for the end user to see anything other than the single, selected color when the flyout is closed. I wouldn't want to adopt this for usability concerns.

Actually, if you have a good idea on how to wire-up pressing a border to change the selected color let me know. I don't really want to make those +/- 2 shade borders template parts and then hook-up to events in code-behind. However, that's all I can think of doing right now.

I think there are some (minor) margins/paddings that would need to be fixed, but let's leave that for now until we have the functionality right!

Oh yes, I notice many of these myself! The screen shots are by no means of a finished control. Actually, it's probably only about 40% complete if I think about it more. But the arrangement of components and functionality is there now. I want to be sure there are no major objections to the overall control design.

I'm also leaning towards dropping the suggested changes to the ColorPicker itself. I will just focus on the new ColorSwatchPicker control (I don't plan on it being a compact mode of the existing control).

@robloo
Copy link
Contributor Author

robloo commented Jun 27, 2020

This is functionally complete now. I would like your feedback if I should proceed adding it to the toolkit. @niels9001 Thanks for all the comments and ideas so far.

example3

@niels9001
Copy link

@robloo Awesome!

Do you have a test project you could create and share publically? I think it's more productive if I have access to the actual XAML instead of just a gif to provide feedback on.

Top of mind as far as I can see:

  • We need to align margins
  • The alpha slider should show the color gradient. This is how the current colorpicker does it (and is basically a industry standard).
  • Should there be a focus rectangle on the middle color of the gradient? Not sure if that makes sense if it never changes - maybe we should have another visual cue to indicate that this color is the selected one.

@robloo
Copy link
Contributor Author

robloo commented Jun 27, 2020

Do you have a test project you could create and share publically? I think it's more productive if I have access to the actual XAML instead of just a gif to provide feedback on.

I'll zip up a file and share hopefully this weekend. There are a few things I'm planning to wrap up as well:

  1. Update the color on a specific time period < 50ms (will remove lag from continuous color updates)
  2. Implement more visual states
  3. Work-around a fun binding issue that wouldn't be an issue in WPF. I can't Bind to UniformGrid Columns inside a GridView ItemsPanelTemplate -- makes sense. But the standard work-around for this used to be relative source with an ancestor of a certain type. Now I'm going to have to manually walk the tree in code-behind after the control is loaded.
<GridView.ItemsPanel>
  <ItemsPanelTemplate>
    <!-- Would be nice if RelativeSource could find an ancestor of type CustomControl... like WPF -->
      <toolkit:UniformGrid Columns="{TemplateBinding CustomPaletteSectionCount}" />
    </ItemsPanelTemplate>
</GridView.ItemsPanel>

We need to align margins

Several have already been made uniform. I'm matching the padding of the standard Flyout. I think only the Components page has significant differences right now. (spacing between channel input controls is an open question).

The alpha slider should show the color gradient.

Only the alpha slider? ;) All sliders will get a custom-rendered background along with a totally new style. Hopefully I will have a chance to complete that this weekend. Right now only the color previews are rendering their own checkered backgrounds.

Should there be a focus rectangle on the middle color of the gradient?

I think there should be something in the preview mini palette to indicate what the actual selected color is. Adding a selection border around the selected color was in Microsoft's UWP UI guidelines as well (which I can't seem to find at the moment). What may need to change is the border color. For simplicity it just automatically switches between black/white based on perceptual color brightness. Another option instead of a border though is something like this:

image

@niels9001
Copy link

niels9001 commented Jun 27, 2020

A .zip would be great!

Mini-palette: I was imagining something like that as well :)! It's nice how the 'active' color is larger and in the middle. This makes it clearer that these are a range of colors IMO!

Margins: Mostly the sliders page - but maybe we also need to widen the gap between the palette and the active controls with the double amount? This way the items would stand out a bit more.

Circle color picker: The colorpicker has a circle mode as well. I'm guessing this will still be used?

Pivot items: In my opinion, the labels are pretty big in this scenario. Also, to make the actual content stand out more we can maybe add an acrylic brush in the background as well?
The Tab control does this by default, and in a Flyout - that would look similar to this:
image

@robloo
Copy link
Contributor Author

robloo commented Jun 27, 2020

Mini-palette: I was imagining something like that as well :)! It's nice how the 'active' color is larger and in the middle. This makes it clearer that these are a range of colors IMO!

Yea its for sure an interesting idea to test out. Not sure how much better it will look until we try it. I am a little concerned that the different sizes of swatches won't look quite right. Also, since WinUI/UWP doesn't support non-rectangular clipping I'm going to be rendering 3 checkered backgrounds instead of 1. There will be performance hit -- however small -- doing that and aligning the checkered patterns.... not easy. There might be significant technical hurdles doing this.

Margins: Mostly the sliders page - but maybe we also need to widen the gap between the palette and the active controls with the double amount? This way the items would stand out a bit more.

Could be done -- I'm more of a compact spacing fan myself. Right now it's supposed to match with the Flyout padding. I'll let you play around with this when I zip up the code.

Circle color picker: The colorpicker has a circle mode as well. I'm guessing this will still be used?

Yes, I still have to connect back some of the visual states but circle spectrum shape should be supported.

Pivot items: In my opinion, the labels are pretty big in this scenario. Also, to make the actual content stand out more we can maybe add an acrylic brush in the background as well?

It's a default pivot header style with default FontIcons at this point. I do like the tab style with acrylic brush a bit more. Will take a look!!

@robloo
Copy link
Contributor Author

robloo commented Jun 27, 2020

@niels9001

One thing we need to figure out if we are going to use the mini-palette: How to calculated the shades? I just used your HSV hack in my code so far but that obviously doesn't work in all cases. It might take a lot of time to figure out how to calculate this so I would like some help. So far I've found:

I've also taken a look at the images here: https://docs.microsoft.com/en-us/windows/uwp/design/style/color

image

Using the above table and a rough approximation in HSV representation of the percentage change from base color for each shade results in what is below. There is clearly a perceptual adjustment being applied that isn't captured by a percentage algorithm without weighting per channel. Based on some standard models of how the eye perceives color I could adjust -- but I really want to match Windows here.

example1

@robloo
Copy link
Contributor Author

robloo commented Jun 27, 2020

Sizing the selected color larger in the mini-palette is better. There is also a possibility of animating the transitions in this palette so it looks like a carousel flipping through.

image

@marcelwgn
Copy link
Contributor

How about adding a light shadow to the selected color?

@robloo
Copy link
Contributor Author

robloo commented Jul 1, 2020

DropDownColorPicker would probably be the most correct considering existing control names. ColorSwatchPicker was shorter and more differentiated -- had a nice sound to it. ColorPickerButton is what I call it in my own apps at the moment. I haven't dismissed anything this is just one of those controls that's tricky to get the name right.

Edit: Part of the problem here too is the WinUI/Windows ColorPicker seems incorrectly named. This control should be the 'real' ColorPicker as it matches with the picker convention in other controls.

@marcelwgn
Copy link
Contributor

Yes it's problematic that the obvious choice ColorPicker is already taken. DropDownColorPicker sounds good as it is even more accurate. Though ColorPickerButton I think describes a bit more what this is: It's a ColorPicker opened by a button. But still ColorPicker would have been the best name for this.

@mdtauk
Copy link

mdtauk commented Jul 2, 2020

ColorPickerFlyout would bring it in line with the Menu Flyouts. But ColorPickerDropDownButton could also work, if a little verbose.

@robloo robloo mentioned this issue Jul 5, 2020
52 tasks
@ghost ghost added the In-PR 🚀 label Jul 5, 2020
@robloo
Copy link
Contributor Author

robloo commented Jul 5, 2020

I decided to go with the original name I'm using in my apps 'ColorPickerButton' and what was suggested by @chingucoding . It's similar to 'DropDownButton' but instead specifies that a ColorPicker is provided. I decided against longer names that were slightly more descriptive that included the terms 'DropDown.' The names just became too long. After all, I blame Microsoft for misnaming the ColorPicker currently provided by WinUI :)

Also note that several other names were also considered in microsoft/microsoft-ui-xaml#2309.

I created the draft PR #3379 for this control. There is still a long todo list but please try out the code and provide feedback.

@mdtauk
Copy link

mdtauk commented Jul 7, 2020

These thought occurred to me in another github repo issue, but there were perhaps out of scope, but may be useful here...

ColourPalettes.Analagous
              .Monochromatic
              .Complimentary
              .SplitTriad

etc

You could include a tab for generated Palettes using colour math and colour theory, similar to Adobe Color.

@robloo
Copy link
Contributor Author

robloo commented Jul 7, 2020

@mdtauk I had a similar thought and it's why I designed the IColorPalette interface to be what it is. Any class can implement this interface to provide a color palette for the control and have it visually represented correctly in the color picker. There is no reason the implementing class couldn't generate colors dynamically as well!

In my own apps I've already added several different color palettes. I'm only providing the Windows Color palette for this PR though: https://github.com/windows-toolkit/WindowsCommunityToolkit/blob/2de382f3f31d90fe1f6953b9c15dce201ad21baa/Microsoft.Toolkit.Uwp.UI.Controls/ColorPickerButton/WindowsColorPalette.cs

image

I've taken some liberties with windows color ordering that I describe in detail in the linked file. You might be interested in looking into it and I would value your feedback.

Also note that the new properties for this picker are purposely name 'CustomPalette...' instead of 'Palette...' as multiple palettes may be supported in the future (windows colors, recent colors, custom palette all in different sections/expanders visible at the same time). So hopefully this is future-proofed.

@robloo
Copy link
Contributor Author

robloo commented Jul 8, 2020

@niels9001 Have you had a chance to look at this recently? There is a PR for it you can download and build as well. I know you are working with your ColorPickerUX which looks awesome. However, your feedback and lesson's learned are quite useful wrapping up the first version of this control.

@niels9001
Copy link

@robloo Sorry for the late reply. I did some tweaks:

  • Acrylic backdrop behind the pivot tabs - this separates the tabs slightly more from the content of the pivot items.
  • Added CornerRadius 4 to a lot of elements, so it's inline with WinUI's new style.
  • Tweaked the Slider2 thumb so it's round.
  • Updated a lot of spacing related stuff: using margins that are multipliers of 12. (the slider page still needs some tweaking tbh).
  • Changed Bold labels to SemiBold
  • Added a 2px gap between in the colors gridview (so it's inline with the color picker that is in the W10 Settings app).

Let me know what you think!

ColorSlidersButton

ColorSwatchPicker.zip

@robloo
Copy link
Contributor Author

robloo commented Jul 12, 2020

Thanks a lot for the feedback!

Acrylic backdrop behind the pivot tabs - this separates the tabs slightly more from the content of the pivot items.

I like the pivot header background being a different color. Acrylic was a good thought to add here.

Added CornerRadius 4 to a lot of elements, so it's inline with WinUI's new style.

The CornerRadius of 4 is only for overlays. Controls use 2. I realize 4 looks nice but this seems to violate the design convention. Any thoughts on this? Additionally, I was keeping all color swatches 'square' which seems to be the windows convention. I agree that the rounded corners in the palette and mini-preview look nicer but doesn't this violate the windows styling?

Tweaked the Slider2 thumb so it's round.

This was already done in the PR. As I mentioned to @mdtauk, I also had the thought originally to make it round fully inside the track. However, I was trying to avoid the iOS style and use the style of the existing color picker. The existing color picker has a bar that extends outside of the track. This was also done so that the thumb is visible no matter what the color of the track is. To solve this problem of color visibility/contrast, I have the thumb dynamically change color between black/white just like the color spectrum. This required adding a new converter which you can see in the PR code -- I will make 1 additional improvement with that converter as well (remove the need for code-behind to handle transparency).

Updated a lot of spacing related stuff: using margins that are multipliers of 12. (the slider page still needs some tweaking tbh).

I think we have a different eye for spacing and I prefer compact themes. I'm not a big fan of the difference in spacing at the top of a pivot item vs the bottom. What is the reasoning behind it? The slider spacing also looks better to me evenly distributed.

Changed Bold labels to SemiBold

I'm glad you noticed this. I was going back/forth on whether these should be bold at all. They still seemed slightly off to me but semi-bold looks great.

Added a 2px gap between in the colors gridview (so it's inline with the color picker that is in the W10 Settings app).

The reason I didn't add spacing between swatches was because some palettes have a lot more than 16 colors in them. The default palette is now the Windows Color Palette as well. If you try to add that spacing to a flat UI palette it's not going to work. So I dropped the spacing. This could theoretically be made configurable with another converter and a maximum count of colors before spacing is removed -- seems like too much complexity though. Other color pickers also do not have this gap. Separately note that the selected item template is going to be matched with the settings app (check mark, on selected color).

Finally, a LOT of additional changes were made to the PR #3379 compared to the .zip file I sent. The RGB/HSV selection is now togglebuttons as well. For my own sanity can we all use that code from now on? I'll pull over the changes you've made here that we agree on later today into the production code.

Edit: I also don't think it's a good idea to make the spectrum smaller although I agree for the ring it looks better. In my opinion it should always be the maximum size possible. When the spectrum is a box it's going to look strange not aligned with the sliders height. There are also some spectrum sizing bugs that I have to work around.

@niels9001
Copy link

Thanks a lot for the feedback!

Acrylic backdrop behind the pivot tabs - this separates the tabs slightly more from the content of the pivot items.

I like the pivot header background being a different color. Acrylic was a good thought to add here.

Added CornerRadius 4 to a lot of elements, so it's inline with WinUI's new style.

The CornerRadius of 4 is only for overlays. Controls use 2. I realize 4 looks nice but this seems to violate the design convention. Any thoughts on this? Additionally, I was keeping all color swatches 'square' which seems to be the windows convention. I agree that the rounded corners in the palette and mini-preview look nicer but doesn't this violate the windows styling?

Tweaked the Slider2 thumb so it's round.

This was already done in the PR. As I mentioned to @mdtauk, I also had the thought originally to make it round fully inside the track. However, I was trying to avoid the iOS style and use the style of the existing color picker. The existing color picker has a bar that extends outside of the track. This was also done so that the thumb is visible no matter what the color of the track is. To solve this problem of color visibility/contrast, I have the thumb dynamically change color between black/white just like the color spectrum. This required adding a new converter which you can see in the PR code -- I will make 1 additional improvement with that converter as well (remove the need for code-behind to handle transparency).

Updated a lot of spacing related stuff: using margins that are multipliers of 12. (the slider page still needs some tweaking tbh).

I think we have a different eye for spacing and I prefer compact themes. I'm not a big fan of the difference in spacing at the top of a pivot item vs the bottom. What is the reasoning behind it? The slider spacing also looks better to me evenly distributed.

Changed Bold labels to SemiBold

I'm glad you noticed this. I was going back/forth on whether these should be bold at all. They still seemed slightly off to me but semi-bold looks great.

Added a 2px gap between in the colors gridview (so it's inline with the color picker that is in the W10 Settings app).

The reason I didn't add spacing between swatches was because some palettes have a lot more than 16 colors in them. The default palette is now the Windows Color Palette as well. If you try to add that spacing to a flat UI palette it's not going to work. So I dropped the spacing. This could theoretically be made configurable with another converter and a maximum count of colors before spacing is removed -- seems like too much complexity though. Other color pickers also do not have this gap. Separately note that the selected item template is going to be matched with the settings app (check mark, on selected color).

Finally, a LOT of additional changes were made to the PR #3379 compared to the .zip file I sent. The RGB/HSV selection is now togglebuttons as well. For my own sanity can we all use that code from now on? I'll pull over the changes you've made here that we agree on later today into the production code.

Edit: I also don't think it's a good idea to make the spectrum smaller although I agree for the ring it looks better. In my opinion it should always be the maximum size possible. When the spectrum is a box it's going to look strange not aligned with the sliders height. There are also some spectrum sizing bugs that I have to work around.

Good catch. Agree on 2 vs. 4, I picked the wrong number there. Since WCT didn't move towards WinUI at all we may want to skip it for now. Everything is square so having a control with rounded everything is maybe not really consistent.

Spacing on GridView makes sense. Making this configurable would be nice though.

As I mentioned, the spacing was a bit all over the place. I defaulted to 12px now, and skipping to 24 in between chunks of information. This seems to work out for the first two pivots. The slider page needs some more work. I would however opt for more spacing between the first row and the chunk of sliders, since they belong together.

Another question I had: I wasn't able to check out the PR just yet - but I could imagine the Pivot control goes away entirely when I'd only want to see the colorpicker, and not the other two items. Correct?

@robloo
Copy link
Contributor Author

robloo commented Jul 12, 2020

Good catch. Agree on 2 vs. 4, I picked the wrong number there. Since WCT didn't move towards WinUI at all we may want to skip it for now. Everything is square so having a control with rounded everything is maybe not really consistent.

Ok, if we have the thought perhaps we can revisit this in 6-9 months once WinUI 3.0 is out and everyone has moved over to its standardized styling.

As I mentioned, the spacing was a bit all over the place. I defaulted to 12px now, and skipping to 24 in between chunks of information.

Generally, I like grouping related information by additional spacing as well. In this case 12px across the board seems to look better for me though (expect for the slider page). I thought I was pretty consistent with that 12px -- perhaps the code you have is just too old compared to the PR or I'm missing something. Let's start talking about specific spacing and margins so we can resolve this.

The slider page needs some more work. I would however opt for more spacing between the first row and the chunk of sliders, since they belong together.

Agree on that, I'll see how it looks to keep 24px above and below the sliders (as a group) only.

Another question I had: I wasn't able to check out the PR just yet - but I could imagine the Pivot control goes away entirely when I'd only want to see the colorpicker, and not the other two items. Correct?

This isn't implemented yet but yes, tabs should disappear when they aren't needed and go away entirely if only one tab is needed. That said, Pivot has a bug where settings the visibility of a PivotItem to collapsed does not remove it from the pivot. This could be an issue to implement anything here and I haven't figured out what I'm going to do about it yet. Edit: I'm also going to have to add an IsPaletteVisible property I think.

@robloo
Copy link
Contributor Author

robloo commented Jul 12, 2020

@niels9001

I update the styling in the PR:

  • Acrylic backdrop behind the pivot tabs - this separates the tabs slightly more from the content of the pivot items.
  • Added CornerRadius 2 to the mini-preview (it does look better)
  • Changed Bold labels to SemiBold

The code was changed to optimize things here and there.

@Sergio0694
Copy link
Member

Was reading a blog post about the new WinUI-powered Syncfusion controls, and noticed they have a new DropDownColorPicker control as well, which conceptually seems very very similar to this one, so I figured I'd mention it.
The link to the blog post is here, and here's a screenshot of that control in particular:

image

NOTE: just sharing this here as I thought it might be interesting/relevant to the conversation. I'm not actually suggesting any particular action due to this announcement and this message is not meant to be a "there's that, so let's just drop this proposal".

@robloo
Copy link
Contributor Author

robloo commented Sep 17, 2020

Its always good to see what others are doing! I think the ColorPickerButton has some key design differences that address additional issues (like overall size, separation of functionality, palette, etc.) that makes it a more valuable control at this point. Of course I'm biased 😀

@ghost ghost closed this as completed in #3379 Nov 9, 2020
ghost pushed a commit that referenced this issue Nov 9, 2020
# Add ColorPickerButton to the Toolkit

Closes #3363 

## PR Type
What kind of change does this PR introduce?

Feature
Documentation content changes
Sample app changes

## What is the current behavior?

The toolkit, and WinUI/UWP, has no flyout ColorPicker. The color picker that currently exists is a large canvas-type control (that is incorrectly named). This existing control has lots of usability concerns discussed in #3363 and the WinUI repository.

## What is the new behavior?

A brand-new control is added to allow selecting and editing a color within a flyout. The selected color is always visible in the content area of a drop-down button as a preview. 

![example1](https://user-images.githubusercontent.com/17993847/87890618-4933cc00-ca05-11ea-8dca-0889f4d9f3c2.gif)

The new properties for this picker are below. Note that these are purposely name 'CustomPalette...' instead of 'Palette...' as multiple palettes may be supported in the future (windows colors, recent colors, custom palette all in different sections visible at the same time).

```csharp
/// <summary>
/// Gets the list of custom palette colors.
/// </summary>
public ObservableCollection<Windows.UI.Color> CustomPaletteColors { get; }

/// <summary>
/// Gets or sets the number of colors in each row (section) of the custom color palette.
/// A section is the number of columns within an entire row in the palette.
/// Within a standard palette, rows are shades and columns are unique colors.
/// </summary>
public int CustomPaletteColumns { get; set; }

/// <summary>
/// Gets or sets a custom IColorPalette .
/// This will automatically set <see cref="CustomPaletteColors"/> and <see cref="CustomPaletteSectionCount"/> 
/// overwriting any existing values.
/// </summary>
public IColorPalette CustomPalette { get; set; }

/// <summary>
/// Gets or sets a value indicating whether the color palette is visible.
/// </summary>
public bool IsColorPaletteVisible { get; set; }
```

Making all of this easier is a new IColorPalette interface. Any class can implement this interface to provide a custom color palette such as windows colors (the default), RYB colors, Flat UI colors, etc. Colors could also be algorithmically generated.

```csharp
/// <summary>
/// Interface to define a color palette.
/// </summary>
public interface IColorPalette
{
    /// <summary>
    /// Gets the total number of colors in this palette.
    /// A color is not necessarily a single value and may be composed of several shades.
    /// </summary>
    int ColorCount { get; }

    /// <summary>
    /// Gets the total number of shades for each color in this palette.
    /// Shades are usually a variation of the color lightening or darkening it.
    /// </summary>
    int ShadeCount { get; }

    /// <summary>
    /// Gets a color in the palette by index.
    /// </summary>
    /// <param name="colorIndex">The index of the color in the palette.
    /// The index must be between zero and <see cref="ColorCount"/>.</param>
    /// <param name="shadeIndex">The index of the color shade in the palette.
    /// The index must be between zero and <see cref="ShadeCount"/>.</param>
    /// <returns>The color at the specified index or an exception.</returns>
    Color GetColor(int colorIndex, int shadeIndex);
}
```

## PR Checklist

Please check if your PR fulfills the following requirements:

- [x] Tested code with current [supported SDKs](../readme.md#supported)
- [ ] Pull Request has been submitted to the documentation repository [instructions](..\contributing.md#docs). Link: <!-- docs PR link -->
- [x] Sample in sample app has been added / updated (for bug fixes / features)
    - [x] Icon has been created (if new sample) following the [Thumbnail Style Guide and templates](https://github.com/windows-toolkit/WindowsCommunityToolkit-design-assets)
- [ ] Tests for the changes have been added (for bug fixes / features) (if applicable)
- [x] Header has been added to all new source files (run *build/UpdateHeaders.bat*)
- [x] Contains **NO** breaking changes

## Other information

**Control**

 * [x] Ensure the name ColorPickerButton is accepted
 * [x] Rename ColorPickerSlider to ColorPickerButtonSlider. ColorPickerSlider is already used by WinUI.
 * [x] Implement all accessibility functionality. Check tab ordering.
 * [x] This control originally used NumberBoxes for channel numerical input. Complete porting this functionality over to TextBoxes as the Toolkit does not have a dependency on WinUI.
 * [x] Support all visual state groups in the original ColorPicker. Connect all functionality
 * [x] Test changing all ColorPicker properties. Determine which ones make sense to ignore
 * [x] Trim displayed hex if alpha is not enabled
 * [x] ~~Switch to radio buttons to switch between RGB/HSV representation. A ComboBox within a Flyout is generally bad practice and is also limited by some bugs in UWP (#1467).~~
 * [x] Switch to ToggleButton instead of RadioButton for RGB/HSV representation. Radio buttons don't work in flyouts and controls well due to UWP bugs. ToggleButtons may also visually look better. The design follows a 'segmented control' concept discussed here: microsoft/microsoft-ui-xaml#2310
 * [x] Switch the default color palette to be the windows colors (if possible)
 * [x] Align formatting to the toolkit conventions
 * [x] Handle CornerRadius in the template. Conditional XAML? Check how other controls do this.
 * [x] Rename 'CustomPaletteSectionCount' to ~~'CustomPaletteWrapCount'~~ or 'CustomPaletteColumns' like UniformGrid
 * [x] Update selected palette color data template to provide correct contrast of the border with the selected color ~~to match with windows settings app (check mark overlay)~~ The check mark is not included as the size of swatches in the palette could be smaller than the check mark itself.
 * [x] Rename 'CustomPaletteColumns' to 'CustomPaletteColumnCount' 
 * [ ] Treat negative/zero numbers in CustomPaletteColumnCount as 'auto' and automatically calculate a good column count to keep rows/columns even. Set the default of this property to 0 'auto'.
 * [x] Improve spacing above/below channel sliders -- try 24px (2 x 12px)
 * [ ] Move localizable strings into resources
 * [x] ~Do not show the color (set the preview border visibility to collapsed) while the control is initializing. This prevents the default color from briefly appearing during initial load. Instead, the background will just show through.~
 * [x] Do not change the saturation and value in the hue slider background. Keep SV at maximum. This allows the hue to always be clear to the user and is in line with other implementations (like in Inkscape).
 * [x] Rename `WindowsColorPalette` to `FluentColorPalette`
 * [x] Show palette color display name in a tooltip
 * [x] Use the WinUI algorithm for light/dark color switching
 * [x] Each tab should have independent visibility using IsColorPaletteVisible (new), IsColorSpectrumVisible (existing) and IsColorChannelTextInputVisible (repurposed to mean the entire tab). The tabs still visible should take up available space remaining. With only one tab visible the tab header should disappear.

**Code Review**
 1. [x] The mini-palette and color preview will be all one color when the selected color is black or white. The calculated accent colors will not change and pressing them will not change the selected color. 
       * Requires feedback from Microsoft on how the accent colors are calculated in Windows
       * It is possible to specially handle when the color is as max/min value (black or white) at least the two accent colors to the left/right could be different shades of gray.
 1. [x] The mini-palette accent colors are destructive. Pressing back and forward by 1 will not restore the original color. 
       * Again, requires feedback from Microsoft on how the accent colors are calculated in Windows.
       * Due to perceptual adjustments it's likely this will always be destructive.
 1. [x] The third dimension slider in the spectrum tab will vary the other dimensions in the spectrum. This results in the spectrum cursor jumping around as the slider value changes. This might be related to HSV/RGB conversion but needs to be investigated.
 1. [x] Adjust the design of the sample app page to move the ColorPickerButton closer to the description.
 1. [x] Check if a ColorToDisplayName converter already exists. Consider adding control specific converters to their own sub-namespace.
 1. [x] The ColorPickerButton will derive from DropDownButton and have a ColorPicker property. Dependent on #3440 
 1. [x] The ColorPicker will have the same new style as the ColorPickerButton flyout. While it's a new concept to have tabs in a panel-type control, this is considered acceptable.
 1. [x] Merge @michael-hawker branch into this one when given the thumb's up. Both controls will be in the same directory.
 1. [x] Remove conditional XAML for corner radius after WinUI 3.0. Conditional XAML doesn't work correctly in resource dictionaries and with setters. See microsoft/microsoft-ui-xaml#2556, fixed with #3440
 1. [ ] All slider rendering will be broken out and put into a new ColorPickerSlider. This should simplify code-behind and the default template.
 1. [x] The Pivot tab width and show/hide of tabs will be controlled in code-behind. use of the pivot itself is somewhat dependent on issues with touch. The pivot, or switching to a new control, will not hold the release.
 1. [ ] Sliders should vary only 1-channel and keep the other channels at maximum. This ensures the gradient always makes sense and never becomes fully black/white/transparent. This could also be made a configuration of the ColorPickerSlider control. Edit: This does need to be configurable as it's only required in HSV mode.
 1. [ ] Add color history palette to the sample app

**Other**
 * [x] Complete integration with the sample app. Add XAML to dynamically change the control.
 * [ ] Complete documentation of the control

**Future**

These changes should be considered for future versions of the control. They are recorded here for lack of a better location.

 * [ ] The mini selected color palette may follow the Windows accent color lighter/darker shades algorithm. However, the implementation of this algorithm is currently unknown. This algorithm may be in the XAML fluent theme editor: https://github.com/microsoft/fluent-xaml-theme-editor
 * [ ] Switch back to NumberBox for all color channel numerical input. This will require WinUI 3.0 and the corresponding release of the toolkit. When microsoft/microsoft-ui-xaml#2757 is implemented, also use NumberBox for hex color input.
 * [ ] ~Remove the custom 'ColorPickerButtonSlider' after switch to WinUI 3.0. This assumes there is no additional control-specific code at that point. (It currently exists just to work-around UWP bugs).~ This should be turned into it's own full primitive control.
 * [ ] Update ColorSpectrum_GotFocus event handler (instructions are within code) after/if ColorSpectrum bugs are fixed (likely after WinUI 3.0
 * [ ] Use Color.IsEmpty if microsoft/microsoft-ui-xaml#2826 is implemented
 * [ ] ~Ensure PivotItems are properly removed once/if microsoft/microsoft-ui-xaml#2952 is closed.~
@ghost ghost added Completed 🔥 and removed In-PR 🚀 labels Nov 9, 2020
@michael-hawker michael-hawker added this to the 7.0 milestone Jan 6, 2021
@Kyaa-dost Kyaa-dost mentioned this issue Jan 6, 2021
70 tasks
@ghost ghost locked as resolved and limited conversation to collaborators Mar 8, 2021
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants