Skip to content
Open
175 changes: 175 additions & 0 deletions active/ThemingCornerRadii/CornerRadiusAPI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<!-- The purpose of this spec is to describe a new feature and
its APIs that make up a new feature in WinUI. -->

<!-- There are two audiences for the spec. The first are people
that want to evaluate and give feedback on the API, as part of
the submission process. When it's complete
it will be incorporated into the public documentation at
docs.microsoft.com (http://docs.microsoft.com/uwp/toolkits/winui/).
Hopefully we'll be able to copy it mostly verbatim.
So the second audience is everyone that reads there to learn how
and why to use this API. -->

# Background
<!-- Use this section to provide background context for the new API(s)
in this spec. -->

<!-- This section and the appendix are the only sections that likely
do not get copied to docs.microsoft.com; they're just an aid to reading this spec. -->

<!-- If you're modifying an existing API, included a link here to the
existing page(s) -->

<!-- For example, this section is a place to explain why you're adding this API rather than
modifying an existing API. -->

<!-- For example, this is a place to provide a brief explanation of some dependent
area, just explanation enough to understand this new API, rather than telling
the reader "go read 100 pages of background information posted at ...". -->

> See [proposal document](https://github.com/Microsoft/microsoft-ui-xaml/issues/684) for information on this feature's scope, and see the [parent proposal document](https://github.com/microsoft/microsoft-ui-xaml/issues/524) for information about design application of this feature.

# Description
<!-- Use this section to provide a brief description of the feature.-->
The ``CornerRadius`` property for controls and their templates can be easily customized/themed through the introduction of new [Lightweight styling](https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/xaml-styles#lightweight-styling) resources.

# Examples
The following example cover common use-case scenarios where an app-author would like to customize the corner radii of one or more controls.

## Setting the CornerRadii of controls
To make large changes globally and consistently to all controls within a scope, defining/overriding the ``ControlThemeCornerRadius`` and ``OverlayThemeCornerRadius`` resources from generic.xaml will affect all controls that benefit from rounded edges.

``` xml
<Application.Resources>
<Thickness x:Key="ControlThemeCornerRadius">10</Thickness>
<Thickness x:Key="OverlayThemeCornerRadius">10</Thickness>
</Application.Resources>
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth talking about alternatives and their pros/cons. For example, using a Style to target a control type, either directly:

<Button.Flyout>
  <Flyout>
    <Flyout.FlyoutPresenterStyle>
      <Style TargetType="FlyoutPresenter">
        <Setter Property="CornerRadius" Value="6"/>
      </Style>
    </Flyout.FlyoutPresenterStyle>
    <TextBlock Text="Hello World"/>
  </Flyout>
</Button.Flyout>

Or indirectly:

<Style TargetType="Button">
  <Setter Property="CornerRadius" Value="6"/>
</Style>

For some examples of setting CornerRadius, check out the CornerRadius test page

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chrisglein, are you suggesting that in addition to the lightweight styling approach, we'll need to update our documentation to also show examples of property setters? If so, I completely agree.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Property setters, explicit Style, and implicit Style. Basically, "Do you want to change CornerRadius? Here are your options. And let us tell you when to use one instead of another".

For example I was pretty easily* able to add rounded corners to an app by creating a bunch of implicit Styles in my App.xaml. We should explain the advantages/disadvantages of that approach.

*well, you'd have to do a style for every single control that accepts CornerRadius, so by "easy" I mean "not complicated, but verbose"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure the advantage/disadvantages of implicit vs explicit styles except the ability to scope that style to a single instance or not, and how is that better/worse than using a scope/global lightweight styling resource - can you elaborate?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we added the broad style values (control corner radius & overlay corner radius) do we still need the per-control resource keys? Is the ability to add an implicit style enough? How much developer choice is enough choice? (weighed against support cost and performance implications)

If we're following the pattern set before we'd add per-control resource keys. But resource key bloat is a real thing. If we decide that's the right pattern here as well then sure let's do it. But we should have clear reason why we make each of these tools available.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we added the broad style values (control corner radius & overlay corner radius) do we still need the per-control resource keys? Is the ability to add an implicit style enough? How much developer choice is enough choice? (weighed against support cost and performance implications)

If we're following the pattern set before we'd add per-control resource keys. But resource key bloat is a real thing. If we decide that's the right pattern here as well then sure let's do it. But we should have clear reason why we make each of these tools available.

I think the idea behind both is that you could use the "global" value to change all the controls to match each other in one go - but then you could override that value only on the control you want to not follow the rest of the UI.

I would imaging the local values by default would use the other global values as a Theme or StaticResource

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we added the broad style values (control corner radius & overlay corner radius) do we still need the per-control resource keys?

I think this is a great question. When we added lightweight styling for colors, the problem we solved was the need to retemplate a control to change, say, its hover color. But CornerRadius is already a property on most? all? controls. So maybe we need resources for corner radii of something like CalendarView, which might have multiple corners that can be adjusted, but we don't need a resource for Button because setting the property, either per instance or using an implicit style, is sufficient.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we added the broad style values (control corner radius & overlay corner radius) do we still need the per-control resource keys?

I think this is a great question. When we added lightweight styling for colors, the problem we solved was the need to retemplate a control to change, say, its hover color. But CornerRadius is already a property on most? all? controls. So maybe we need resources for corner radii of something like CalendarView, which might have multiple corners that can be adjusted, but we don't need a resource for Button because setting the property, either per instance or using an implicit style, is sufficient.

CornerRadius is a property on all FrameworkElements, I believe. So it exists for every control, however it just doesn't make sense to have one single one for many controls (like the CalendarView example you gave).

So we could introduce a bit of API inconsistency, by having a lot of cornerradius resources for some controls, and none for others, or we could introduce a resource for every control, and finer grain control can be done through the CornerRadius property directly, through the new Lightweight styling resource (which is cleaner when creating separate share-able themes), or though one of our style setter methods.

@chrisglein I agree it is resource bloat, but at this time we're not committed to better styling methodologies.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CornerRadius is a property on all FrameworkElements, I believe. So it exists for every control, however it just doesn't make sense to have one single one for many controls (like the CalendarView example you gave).

It's on Control. Which means it naturally makes its way to most things. That does mean, however, that we have to reconcile this single CornerRadius value with potentially multiple targets (Does it target the track or the handle for a Slider? Does it affect the box for a DatePicker or also the popup?). We have that API inconsistency regardless of whether we add lightweight styling knobs or not. Having resource keyed values for the different types of radii helps address the sub-components but we still have to clarify precedence between that and Control.CornerRadius.


## Defining the CornerRadius on specific control(s)
When more specific or localized changes to particular controls is desired, a [Lightweight styling](https://docs.microsoft.com/windows/uwp/design/controls-and-patterns/xaml-styles#lightweight-styling) approach is available to set the CornerRadii of controls.

``` xml
<Page.Resources>
<Thickness x:Key="ButtonThemeCornerRadius">5</Thickness>
<Thickness x:Key="ProgressBarThemeCornerRadius">3</Thickness>
</Page.Resources>
```

# Remarks
<!-- Explanation and guidance that doesn't fit into the Examples
section. For example, see the Remarks for the MediaPlayerElement
(https://docs.microsoft.com/uwp/api/Windows.UI.Xaml.Controls.MediaPlayerElement#remarks). -->
Much like the relationship between our [System Colors](https://docs.microsoft.com/en-us/windows/uwp/design/style/color) and our [Theme Brushes](https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/xaml-theme-resources#the-xaml-color-ramp-and-theme-dependent-brushes), there are two *system* [Lightweight styling](https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/xaml-styles#lightweight-styling) resources that control at a high-level the general corner roundness of controls (e.g. buttons and sliders) and overlays (e.g. flyouts and popups), and then there are control-specific Lightweight styling resources that allow customizing the corner radius on a per-control basis.

Depending on the granularity desired by the app-author, they can override either or both global and control-specific Lightweight resources depending, with the control-specific resources taking priority over the global ones when both specified.

```xml
<Page.Resources>
<Thickness x:Key="ControlThemeCornerRadius">2</Thickness>
<Thickness x:Key="ButtonThemeCornerRadius">10</Thickness>
</Page.Resources>

<Grid>
<StackPanel>
<ProgressBar Maximum="100" Value="30" Width="250" Height="10"/>
<ToggleSwitch ToolTipService.ToolTip="Toggle Switch"/>
<Button Content="My Button"/>
</StackPanel>
</Grid>
```

![Mixed resources cornerradius values](images/CornerRoundnessExample.png)

In this example, all controls' border radii have been set to two via the ``ControlThemeCornerRadius`` global resource, and the Button is honoring the control-specific reource ``ButtonThemeCornerRadius``.

# API Notes
<!-- Give a one or two line description of each API (type
and member), or at least the ones that aren't obvious
from their name. These descriptions are what show up
in IntelliSense. -->

|Global Lightweight resource| Default value |
|:-|:-:|
| ControlThemeCornerRadius | 2 |
| OverlayThemeCornerRadius | 4 |

## Affected controls
>Below is a list of control-specific [Lightweight styling](https://docs.microsoft.com/windows/uwp/design/controls-and-patterns/xaml-styles#lightweight-styling) resources that are getting updated and tied to the global Lightweight resources mentioned above.

This list also covers which part or parts of a certain control's template will get this new CornerRadius value applied, as some templates have multiple places where a CornerRadius attribute must be changed.

### ControlThemeCornerRadius
The following table details out the controls who's values corresponds to the global CornerRadius value for ``ControlThemeCornerRadius``.

|#| Control | Lightweight resource(s) | Affected template attribute/style |
|:-:|:-|:-|:-|
|1| Button | ButtonThemeCornerRadius | CornerRadius Property (Setter in Style) |
|2| Checkbox | CheckboxThemeCornerRadius | RootGrid (Grid), NormalRectangle (Checkbox Box Rectangle) |
|3| TextBox | TextBoxThemeCornerRadius | BorderElement (Border) |
|4| AutoSuggestBox | AutoSuggestBoxThemeCornerRadius | AutoSuggestBoxTextBoxStyle (CornerRadius Property definition) |
|5| Slider | SliderThemeCornerRadius | HorizontalTrackRect, HorizontalDecreaseRect, VerticalTrackRect, VerticalDecreaseRect (All Rectangles) |
|6| ComboBox | ComboBoxThemeCornerRadius, ComboBoxItemThemeCornerRadius | CornerRadius Property (Setter in Style) |
|7| DatePicker | DatePickerThemeCornerRadius | CornerRadius Property (Setter in Style) |
|8| TimePicker | TimePickerThemeCornerRadius | CornerRadius Property (Setter in Style) |
|9| CalendarDatePicker | CalendarDatePickerThemeCornerRadius | CornerRadius Property (Setter in Style) |
|10| ProgressBar | ProgressBarThemeCornerRadius | DeterminateRoot (Border) ProgressBarIndicator (Rectangle) |
|11| RichEditBox | RichEditBoxThemeCornerRadius | CornerRadius Property (Setter in Style) |
|12| ToggleButton | ToggleButtonThemeCornerRadius | CornerRadius Property (Setter in Style) |
|13| ToggleSwitch | ToggleSwitchThemeCornerRadius | OuterBorder (Rectangle), SwitchKnobBounds (Rectangle) |
|14| SplitButton | SplitButtonThemeCornerRadius | CornerRadius Property (Setter in Style) |
|15| DropDownButton | DropDownButtonThemeCornerRadius | CornerRadius Property (Setter in Style) |
|16| PasswordBox | PasswordBoxThemeCornerRadius | CornerRadius Property (Setter in Style) |
|17| RichEditBox | RichEditBoxThemeCornerRadius | CornerRadius Property (Setter in Style) |
|18| Tab Control | TabControlThemeCornerRadius | *tbd* |
|19| ToggleSplitButton | ToggleSplitButtonThemeCornerRadius | CornerRadius Property (Setter in Style) *Top,Bottom only on one side for each button "split"* |
|20| FlipView | FlipViewThemeCornerRadius | *tbd* |
|21| GridView | GridViewThemeCornerRadius | *tbd* |
|22| ListView | ListViewThemeCornerRadius | *tbd* |
|23| TreeView | TreeViewThemeCornerRadius | *tbd* |

#### Control "Bars"
The following controls receiving rounded corners don't back backplates that can round per-say, but instead have visual components (dubbed "bars") that indicate selection or state that will be getting rounded.

|#| Control | Lightweight resource(s) | Affected template attribute/style |
|:-:|:-|:-|:-|
|1| NavigationView | NavigationViewSelectorThemeCornerRadius | NavigationViewItemPresenter *(Top and Left style)* SelectionIndicator (Rectangle) |
|2| Pivot | PivotSelectorThemeCornerRadius | FocusFollower (Rectangle) |
|3| ScrollIndicator | ScrollIndicatorThemeCornerRadius | *tbd* |
|4| ColorPicker | ColorPickerThemeCornerRadius | *tbd* |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is a composite of all sorts of controls and its own thing. I've been trying to track the fine grain list of changes in the figma over in this WinUI issue.

Copy link
Author

@kikisaints kikisaints Jun 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Edit: If you're referring to ColorPicker - yes that one has many "moving parts" and needs a separate dev as well as design evaluation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe @chrisglein is talking about ColorPicker.

|5| MediaPlayerElement | MediaPlayerElementTrackThemeCornerRadius | *tbd* |

### OverlayThemeCornerRadius
The following table details out the controls who's values corresponds to the global CornerRadius value for ``OverlayThemeCornerRadius``.

|#| Control | Lightweight resource(s) | Affected template attribute/style |
|:-:|:-|:-|:-|
|1| ContentDialog | ContentDialogThemeCornerRadius | CornerRadius Property (Setter in Style) |
|2| Flyout | FlyoutThemeCornerRadius | CornerRadius Property (Setter in Style) |
|3| ComboBox Popup | ComboBoxPopupThemeCornerRadius | PopupBorder (Border) |
|4| DatePicker Flyout | DatePickerFlyoutThemeCornerRadius | DatePickerFlyoutPresenter (CornerRadius property) |
|5| TimePicker Flyout | TimePickerFlyoutThemeCornerRadius | TimePickerFlyoutPresenter (CornerRadius property) |
|6| MenuFlyout | MenuFlyoutThemeCornerRadius | MenuFlyoutPresenter (DefaultMenuFlyoutPresenterStyle CornerRadius propery) |
|7| CommandBar Overflow | CommandBarOverflowThemeCornerRadius | OverflowContentRoot (Grid) |
|8| Tooltip | ToolTipThemeCornerRadius| LayoutRoot (ContentPresenter CornerRadius property) |
|9| AutoSuggestBox Popup | AutoSuggestBoxSuggestionsThemeCornerRadius | SuggestionsContainer (Border) |
|10| ToggleSplitButton Dropdown | ToggleSplitButtonDropdownThemeCornerRadius | *tbd* |
|11| MenuBar Flyout | MenuBarFlyoutThemeCornerRadius | *tbd* |
|12| TeachingTip | TeachingTipThemeCornerRadius | *tbd* |
|13| CalendarDatePicker | CalendarDatePickerFlyoutThemeCornerRadius | FlyoutPresenter CornerRadius (Setter in AttachedFlyout Style) |

## CornerRadiusResources API (P2)
>This API follows a very similar model to that of the [ColorSchemeResources](https://docs.microsoft.com/en-us/windows/uwp/design/style/color#how-to-use-colorschemeresources).

``CornerRadiusResources`` is a class that has a property for every control-specific CornerRadius Lightweight styling resource that exists, and allows a condensed, easy-to-read-and-share styling format.

```xml
<Grid.Resources>
<CornerRadiusResources
MenuFlyout="2"
ComboBox="5"
ProgressBar="3"/>
</Grid.Resources>
```

# Open Questions
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.