Repository: terminal
Issue: Add comprehensive XAML "theming" functionality
Labels: Area-Settings,Product-Terminal,Issue-Scenario,Area-Theming

As I mentioned in https://github.com/microsoft/terminal/issues/3322#issuecomment-546391285, we've been dancing around the idea of "XAML theming" for a while in a bunch of issues, but never had one place to track all the requested functionality. This will serve as the master thread for those requests.

> It looks to me like we've danced around the idea in #1963, #1337, #3061/#3062, #2994, but never had a comprehensive answer.

Ideally, these are something that's more powerful than just setting the "color scheme". This would control sizing, coloration of UI elements of the app itself, not just the colors of the terminal _contents_. Consider things like themes in VsCode, Sublime Text, where there are _schemes_ that can control the colorization of the buffer, and **themes** that can change the appearance of the app itself.

UI elements to be able to control:
* [ ] #3061 Pane Border colors (both the background, and the "focused" color)
* [ ] #3063 Pane border width
* [x] #702 👀 Tab Background color 
  - also: #1337
  - also: #2994
* [x] #13684
* [x] #3774 👀 Tab row BG color
  - [x] #1963 👀 users should be able to set it to the system accent color
  - Users want the tab row to match the BG color of the focused pane/terminal. This is the inverse of #702
* [x] #3335 👀 Feature Request: Setting to hide/remove close ("x") button from tabs
* [x] #4862 👀 Support using different colors in the titlebar for focused/unfocused windows
* [ ] #5911 Support for `compact`, `default`, and `touch` friendly tab row sizes 
* [ ] #7213 
  - Also used for setting the corner radius
  - Also tracking "get rid of the bottom, outwards corner radius"
* [ ] #16114

Other ideas:
* [ ] #5155 Tab row height
* [ ] Tab row font size, font face
* [ ] Margin between tabs?
* [ ] Padding within the tab?
* [ ] Control colors for light vs dark vs high-contrast modes
* [ ] Enable/disable a shadow underneath the tab row, between tabs and content 
  - **more relevant after #12916** which added the shadow to the whole row
* [ ] Enable/disable a shadow cast by terminals on pane borders or a shadow cast by pane borders on Terminal panes
* [ ] Similarly to the tabs, styling the Status Bar (#3459)
  - Maybe enable it to have the same color as the active TermControl, causing the same "seamless" effect (https://github.com/microsoft/terminal/issues/3459#issuecomment-550501577)
  - Change font size, face, colors
  - Control the borders on the status bar - no top border would give the impression it's "seamless"
* [ ] Enable hiding the tab icon altogether (#8157)
* [ ] Enable forcing tab icons to monochrome
* [ ] Force a colorscheme? This seems weird, and probably not what people want.
* [ ] Allow color fields to refer back to the active color scheme (like `cursorColor = yellow`) (#7522)
* [ ] Please provide a new setting: verticalScrollBarWidth #9218
* [ ] Light mode in settings UI only #9231
* [ ] #13991 
* [ ] #12632

Currently we don't have all that many UI elements, but in a hypothetical world with a command palette (#2046) and a search box (#605), there'll be even more UI elements to be able to control.

I know @cinnamon-msft had some mockups of "themes".

I imagine that these would be something that would be easier to control with XAML resources somehow, though I'm not sure how technically possible it would be to have the user specify a XAML file and have us load it into our resources at runtime. But that might be an option to pursue as an alternative to adding tons of new settings that will need to be parsed and applied manually at runtime.



Potential solution design:
<details>

This is a real showerthought of a design, which needs real spec'ing, but here's what I came up with this (06 Dec 2019) morning

```json
{
    "applicationTheme": "My Boxy Theme",
    "themes": [
        {
            "name": "My Boxy Theme",
            "requestedTheme": "dark",
            "tab.radius": 0,
            "tab.padding": 5,
            "tab.background": "terminalBackground",
            "tab.textColor": "key:SystemAccentColorLight3",
            "tab.icon": "monochrome",
            "tab.closeButton": "hidden",
            "tabRow.background": "accent",
            "tabRow.shadows": false
        },
        {
            "name": "My small light theme",
            "tabBackground": "#80ff0000",
            "tabRowBackground": "#ffffffff",
            "tabHeight": 16,
            "requestedTheme": "light",
            "colorSheme": "Solarized Light",
            "tabIcon": "hidden",
            "tabCloseButton": "hover"
        }
    ]
}
```

I've given both a `tab.<property>` and a `tab<Property>` style here, for comparison. Unsure of which is better.

Colors can be one of:
* an `#aarrggbb` color
* `accent` for the accent color
* `terminalBackground` to use the default background color of the focused terminal
* `terminalForeground` to use the default foreground color of the focused terminal
  - does anyone want this?
* `key:SomeXamlKey` to try and look `SomeXamlKey` up from our resources as a `Color`, and use that color for the value.
  - Does anyone want this?
  - is `accent` just `key:SystemAccentColor`?

Then we have a bunch of UI settings.

We'll use these settings to set XAML resource values, like the `TabViewBackground`. Then, when they change, the UI should just respond to these values changing right?


### Open Questions:
* For hot-reloading settings - does updating resources in xaml auto-relayout things?

* For `"tabBackground": "terminalBackground"`, does changing the default background color from within the terminal automatically update this color for UI elements? (hopefully).

* This design doesn't really have both light and dark variants, instead just sets a system theme it wants. What if the theme specifies `system`? could it support light and dark versions somehow?

#### Tab Color Picker

With the tab color picker that sets tab colors, how does that interact with this? We probably don't actually want the color to apply to the whole tab itself, we probably just want an overline. If we have an overline, people probably what to be able to set it. Manually setting the color with the menu should just be an override - "tabColorOverride", so that a settings reload doesn't blow it away. Presumably, there's a way to set the background color of a tab manually to override that of the theme - thet's probably how that PR works today.

How would we make sure that `"tab.background": "terminalBackground"` works with manually overriding the tab color?


</details>


Terminal should be able to look [beautiful](https://github.com/microsoft/terminal/issues/3327#issuecomment-765493313), and also like this:
![image](https://user-images.githubusercontent.com/18356694/151258949-bcca7275-4be7-48a4-ab60-f60e917e0e62.png)



#### Followup flow chart:

```mermaid
flowchart TD
    subgraph Theming
        id_b[tabRow.background]
        id_c[ themeColor:accent ]
        id_d[ themeColor:terminalBackground ]

        %% id1[Theming #12992]
    end

    id2[tab.background<br>#702<br>PR #13178]
    id3[tabRow.inactiveBackground<br>#4862<br>PR 13049]
    id4(tab.inactiveBackground<br>#4862)
    tabclose[tab.closeButton<br>#3335<br>PR #13348]

    id15{{Terminal v1.16}}

    %% Initial theming support
    %% id_a-->id1
    %% id_b-->id1
    %% id_c-->id1
    %% id_d-->id1
    
    %% 1.16 features
    Theming --> id3
    Theming --> id2
    id2 --> id4
    id3 --> id15
    id4 --> id15
    id2 --> tabclose  --> id15
    Theming --> id_transparent(Transparent titlebars<br>window.useMica<br>#10509)
    Theming --> id_acrylic_tabRow(Acrylic titlebar) --> id15


    %% Etc features
    subgraph Pane
        direction TB
        pane.borderColor(pane.borderColor<br>#3061)
        pane.inactiveBorderColor(pane.inactiveBorderColor)
        pane.borderWidth(pane.borderWidth<br>#3063)
        pane.borderColor --> pane.inactiveBorderColor
    end
    subgraph Tab
        direction TB
        tabcorners(tab.corners<br>#7213)
    end
    subgraph Window
        direction TB
        window.background(window.background<br>#16114)
        window.frameColor(window.frameColor) --> rainbow(themeColor:rainbow<br>#12950)
    end

    id15 --> Pane
    id15 --> Tab
    id15 --> Window
    id15 --> lightDark(OS-theme sensitive theming)
    click id4 "http://www.github.com/microsoft/terminal/issues/4862"
```