Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions examples/Demo/Shared/Pages/Design/DesignTokensPage.razor
Original file line number Diff line number Diff line change
@@ -1,11 +1,34 @@
@page "/DesignTokens"
@using FluentUI.Demo.Shared.Pages.Design.Examples

<PageTitle>@App.PageTitle("Design Tokens")</PageTitle>

<h1>Design Tokens</h1>

<MarkdownSection FromAsset="./_content/FluentUI.Demo.Shared/docs/DesignTokens.md" OnContentConverted="RefreshTableOfContents" />

<DemoSection Component="@typeof(DesignTokensDefault)" Title="Example of working with DesignTokens programmatically">
<Description>
<p>Use the first button go swith bewteen dark and light mode. Click the second button to toggle the accent and neutral colors. The third button has a custom font, and the last one has a custom border width and corner radius.</p>
<p>
As can be seen in the code tab (with the `ref4.Element`), it is possible to apply multiple tokens to the same component.
</p>

<p>
For Design Tokens that work with a color value, you must call the <code>ToSwatch()</code> extension method* on a string value or use one of the Swatch constructors. This
makes sure the color is using a format that Design Tokens can handle. A Swatch has a lot of commonality with the <code>System.Drawing.Color</code> struct. Instead of
the values of the components being between 0 and 255, in a Swatch the components are expressed as a value between 0 and 1
</p>
<p><em>* except for the AccentBaseColor and NeutralBaseColor. These just take a hex value as a string for the color.</em></p>
</Description>
</DemoSection>

<h3>Colors for integration with specific Microsoft products</h3>
<p>
If you are configuring the components for integration into a specific Microsoft product, the following table provides `AccentBaseColor` values you can use.
<strong>The specific accent colors for many Office applications are offered in the `OfficeColor` enumeration.</strong>
</p>

@if (refreshCount > 0)
{
<OfficeColorTable />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
@using Microsoft.FluentUI.AspNetCore.Components.DesignTokens

<FluentButton @ref="ref1" @onclick="OnClickFirst">Dark/Light</FluentButton>
<FluentButton @ref="ref2" @onclick="OnClickSecond" Appearance ="Appearance.Accent">Accent button</FluentButton>
<FluentButton @ref="ref3">And one more</FluentButton>
<FluentButton @ref="ref4" @onclick=OnClickLast>Last button</FluentButton>


@code {
[Inject]
private BaseLayerLuminance BaseLayerLuminance { get; set; } = default!;

[Inject]
private AccentBaseColor AccentBaseColor { get; set; } = default!;

[Inject]
private NeutralBaseColor NeutralBaseColor { get; set; } = default!;

[Inject]
private BodyFont BodyFont { get; set; } = default!;

[Inject]
private StrokeWidth StrokeWidth { get; set; } = default!;

[Inject]
private ControlCornerRadius ControlCornerRadius { get; set; } = default!;

private FluentButton? ref1;
private FluentButton? ref2;
private FluentButton? ref3;
private FluentButton? ref4;

protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
//Set to dark mode
//await BaseLayerLuminance.SetValueFor(ref1!.Element, (float)0.15);

//Set the font
await BodyFont.SetValueFor(ref3!.Element, "Comic Sans MS");

//Set 'border' width for ref4
await StrokeWidth.SetValueFor(ref4!.Element, 7);
//And change conrner radius as well
await ControlCornerRadius.SetValueFor(ref4!.Element, 15);

StateHasChanged();
}
}

public async Task OnClickFirst()
{
float? value = await BaseLayerLuminance.GetValueFor(ref1!.Element);
//Set to light mode
await BaseLayerLuminance.WithDefault(value == 0.15f ? (float)1.0 : (float)0.15);
}

public async Task OnClickSecond()
{
Swatch accent = await AccentBaseColor.GetValueFor(ref2!.Element);
Swatch neutral = await NeutralBaseColor.GetValueFor(ref2!.Element);

await AccentBaseColor.WithDefault(accent.B == (float)0.274509817 ? "#0078D4" : "#217346");
await NeutralBaseColor.WithDefault(neutral.B == (float)0.3372549 ? "#808080" : "#c75656");
}

public async Task OnClickLast()
{
//Remove the wide border
await StrokeWidth.DeleteValueFor(ref4!.Element);
}

}
69 changes: 68 additions & 1 deletion examples/Demo/Shared/Pages/Lab/IssueTester.razor
Original file line number Diff line number Diff line change
@@ -1 +1,68 @@

@using Microsoft.FluentUI.AspNetCore.Components.DesignTokens

<FluentButton @ref="ref1" @onclick=OnClickFirst>Dark/Light</FluentButton>
<FluentButton @ref="ref2" Appearance="Appearance.Accent">Accent button</FluentButton>
<FluentButton @ref="ref3">And one more</FluentButton>
<FluentButton @ref="ref4" @onclick=OnClickLast>Last button</FluentButton>


@code {
[Inject]
private BaseLayerLuminance BaseLayerLuminance { get; set; } = default!;

[Inject]
private AccentBaseColor AccentBaseColor { get; set; } = default!;

[Inject]
private NeutralBaseColor NeutralBaseColor { get; set; } = default!;

[Inject]
private BodyFont BodyFont { get; set; } = default!;

[Inject]
private StrokeWidth StrokeWidth { get; set; } = default!;

[Inject]
private ControlCornerRadius ControlCornerRadius { get; set; } = default!;

private FluentButton? ref1;
private FluentButton? ref2;
private FluentButton? ref3;
private FluentButton? ref4;

protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
//Set to dark mode
//await BaseLayerLuminance.SetValueFor(ref1!.Element, (float)0.15);

//Set the font
await BodyFont.SetValueFor(ref3!.Element, "Comic Sans MS");

//Set 'border' width for ref4
await StrokeWidth.SetValueFor(ref4!.Element, 7);
//And change conrner radius as well
await ControlCornerRadius.SetValueFor(ref4!.Element, 15);

await AccentBaseColor.WithDefault("#217346");
await NeutralBaseColor.WithDefault("#c75656");

StateHasChanged();
}
}

public async Task OnClickFirst()
{
float? value = await BaseLayerLuminance.GetValueFor(ref1!.Element);
//Set to light mode
await BaseLayerLuminance.WithDefault(value == 0.15f ? (float)1.0 : (float)0.15);
}

public async Task OnClickLast()
{
//Remove the wide border
await StrokeWidth.DeleteValueFor(ref4!.Element);
}

}
74 changes: 0 additions & 74 deletions examples/Demo/Shared/wwwroot/docs/DesignTokens.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,78 +237,7 @@ There are a couple of methods available **per design token** to get or set its v
- `{DesignTokenName}.WithDefault(T value)` - Sets the default value for the whole design system use.
- `{DesignTokenName}.GetValueFor(ElementReference element)` - Gets the value for the given element.- `

#### Example
Given the following `.razor` page fragment:

```cshtml
<FluentButton @ref="ref1">A button</FluentButton>
<FluentButton @ref="ref2" Appearance="Appearance.Accent">Another button</FluentButton>
<FluentButton @ref="ref3">And one more</FluentButton>
<FluentButton @ref="ref4" @onclick=OnClick>Last button</FluentButton>
```

You can use Design Tokens to manipulate the styles from C# code as follows:

```csharp
@using Microsoft.FluentUI.AspNetCore.Components.DesignTokens

[Inject]
private BaseLayerLuminance BaseLayerLuminance { get; set; } = default!;

[Inject]
private AccentBaseColor AccentBaseColor { get; set; } = default!;

[Inject]
private BodyFont BodyFont { get; set; } = default!;

[Inject]
private StrokeWidth StrokeWidth { get; set; } = default!;

[Inject]
private ControlCornerRadius ControlCornerRadius { get; set; } = default!;

private FluentButton? ref1;
private FluentButton? ref2;
private FluentButton? ref3;
private FluentButton? ref4;

protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
//Set to dark mode
await BaseLayerLuminance.SetValueFor(ref1!.Element, (float)0.15);

//Set to Excel color
await AccentBaseColor.SetValueFor(ref2!.Element, "#217346".ToSwatch());

//Set the font
await BodyFont.SetValueFor(ref3!.Element, "Comic Sans MS");

//Set 'border' width for ref4
await StrokeWidth.SetValueFor(ref4!.Element, 7);
//And change conrner radius as well
await ControlCornerRadius.SetValueFor(ref4!.Element, 15);

// If you would like to change the BaseLayerLuminance value for the whole site, you can use the WithDefault method
await BaseLayerLuminance.WithDefault((float)0.15);

StateHasChanged();
}
}

public async Task OnClick()
{
//Remove the wide border
await StrokeWidth.DeleteValueFor(ref4!.Element);
}
```

As can be seen in the code above (with the `ref4.Element`), it is possible to apply multiple tokens to the same component.

For Design Tokens that work with a color value, you must call the `ToSwatch()` extension method on a string value or use one of the Swatch constructors. This
makes sure the color is using a format that Design Tokens can handle. A Swatch has a lot of commonality with the `System.Drawing.Color` struct. Instead of
the values of the components being between 0 and 255, in a Swatch the components are expressed as a value between 0 and 1.

### Using Design Tokens as components
The Design Tokens can also be used as components in a `.razor` page directely. It looks like this:
Expand All @@ -334,6 +263,3 @@ To make this work, a link needs to be created between the Design Token component
> Only one Design Token component at a time can be used this way. If you need to set more tokens, use the code approach as described in Option 1 above.


## Colors for integration with specific Microsoft products
If you are configuring the components for integration into a specific Microsoft product, the following table provides `AccentBaseColor` values you can use.
*The specific accent colors for many Office applications are offered in the `OfficeColor` enumeration.*
59 changes: 0 additions & 59 deletions src/Core.Assets/src/Design/ColorsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,6 @@ class ColorsUtils {
return (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches);
}

/**
* See https://github.com/microsoft/fast -> packages/utilities/fast-colors/src/parse-color.ts
*/
public static parseColorHexRGB(raw: string | null): ColorRGB | null {
// Matches #RGB and #RRGGBB, where R, G, and B are [0-9] or [A-F]
const hexRGBRegex: RegExp = /^#((?:[0-9a-f]{6}|[0-9a-f]{3}))$/i;
const result: string[] | null = hexRGBRegex.exec(raw ?? ColorsUtils.DEFAULT_COLOR);

if (result === null) {
return null;
}

let digits: string = result[1];

if (digits.length === 3) {
const r: string = digits.charAt(0);
const g: string = digits.charAt(1);
const b: string = digits.charAt(2);

digits = r.concat(r, g, g, b, b);
}

const rawInt: number = parseInt(digits, 16);

if (isNaN(rawInt)) {
return null;
}

return new ColorRGB(
this.normalized((rawInt & 0xff0000) >>> 16, 0, 255),
this.normalized((rawInt & 0x00ff00) >>> 8, 0, 255),
this.normalized(rawInt & 0x0000ff, 0, 255),
);
}

/**
* Scales an input to a number between 0 and 1
*/
public static normalized(i: number, min: number, max: number): number {
if (isNaN(i) || i <= min) {
return 0.0;
} else if (i >= max) {
return 1.0;
}
return i / (max - min);
}

/**
* Convert to named color to an equivalent Hex color
* @param name Office color name
Expand Down Expand Up @@ -94,16 +47,4 @@ class ColorsUtils {
];
}

class ColorRGB {
constructor(red: number, green: number, blue: number) {
this.r = red;
this.g = green;
this.b = blue;
}

public readonly r: number;
public readonly g: number;
public readonly b: number;
}

export { ColorsUtils };
9 changes: 5 additions & 4 deletions src/Core.Assets/src/DesignTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// ********************

import { ColorsUtils } from "./Design/ColorsUtils";
import { parseColorHexRGB } from '@microsoft/fast-colors'
import {
baseLayerLuminance,
StandardLuminance,
Expand Down Expand Up @@ -81,8 +82,8 @@ class DesignTheme extends HTMLElement {

/**
* Gets the current color or office name attribute value.
* Access, Booking, Exchange, Excel, GroupMe, Office, OneDrive, OneNote, Outlook,
* Planner, PowerApps, PowerBI, PowerPoint, Project, Publisher, SharePoint, Skype,
* Access, Booking, Exchange, Excel, GroupMe, Office, OneDrive, OneNote, Outlook,
* Planner, PowerApps, PowerBI, PowerPoint, Project, Publisher, SharePoint, Skype,
* Stream, Sway, Teams, Visio, Windows, Word, Yammer
*/
get primaryColor(): string | null {
Expand All @@ -101,7 +102,7 @@ class DesignTheme extends HTMLElement {
: value;

// Apply the color
const rgb = ColorsUtils.parseColorHexRGB(color);
const rgb = parseColorHexRGB(color);
if (rgb != null) {
const swatch = SwatchRGB.from(rgb);
accentBaseColor.withDefault(swatch);
Expand Down Expand Up @@ -250,7 +251,7 @@ class DesignTheme extends HTMLElement {
// If not, the dev already "forced" the mode to "dark" or "light"
if (currentMode == null) {

// console.log(` ** colorSchemeListener = "${currentMode}"`)
// console.log(` ** colorSchemeListener = "${currentMode}"`)

// Dark
if (e.matches) {
Expand Down
Loading
Loading