Skip to content

Commit

Permalink
Define graph trace color tokens (#2194)
Browse files Browse the repository at this point in the history
# Pull Request

## 🀨 Rationale

Addresses #787 

## πŸ‘©β€πŸ’» Implementation

Added 8 color tokens for graph traces, e.g. `graphTrace1Color`.

Per the design, we cannot provide graph trace tokens that work generally
for monochromatic applications. If the use case only requires a single
trace, then it seems correct for that trace (`graphTrace1Color`) to be
white for the color theme. If there are more traces, then based on what
Rick wrote in his design, the client presumably has to override the
token values based on the background color. So defaulting all the traces
to white seems reasonable.

## πŸ§ͺ Testing

Token story

## βœ… Checklist

- [x] I have updated the project documentation to reflect my changes or
determined no changes are needed.

---------

Co-authored-by: Milan Raj <[email protected]>
  • Loading branch information
m-akinc and rajsite authored Jun 20, 2024
1 parent 51aef51 commit 0084f69
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Define graph trace color tokens",
"packageName": "@ni/nimble-components",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,14 @@ export const comments: { readonly [key in TokenName]: string } = {
elevation3BoxShadow:
'The box shadow for elevation 3. Used for components such as dialogs, overlays, and pop-ups.',
graphGridlineColor: 'Gridline color for graphs',
graphTrace1Color: 'Color for the first graph trace',
graphTrace2Color: 'Color for the second graph trace',
graphTrace3Color: 'Color for the third graph trace',
graphTrace4Color: 'Color for the fourth graph trace',
graphTrace5Color: 'Color for the fifth graph trace',
graphTrace6Color: 'Color for the sixth graph trace',
graphTrace7Color: 'Color for the seventh graph trace',
graphTrace8Color: 'Color for the eighth graph trace',
mentionFont: 'Font shorthand for mention views',
mentionFontColor: 'Font color for mention views',
mentionDisabledFontColor: 'Disabled font color for mention views',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,14 @@ export const tokenNames: { readonly [key in TokenName]: string } = {
elevation2BoxShadow: 'elevation-2-box-shadow',
elevation3BoxShadow: 'elevation-3-box-shadow',
graphGridlineColor: 'graph-gridline-color',
graphTrace1Color: 'graph-trace-1-color',
graphTrace2Color: 'graph-trace-2-color',
graphTrace3Color: 'graph-trace-3-color',
graphTrace4Color: 'graph-trace-4-color',
graphTrace5Color: 'graph-trace-5-color',
graphTrace6Color: 'graph-trace-6-color',
graphTrace7Color: 'graph-trace-7-color',
graphTrace8Color: 'graph-trace-8-color',
mentionFont: 'mention-font',
mentionFontColor: 'mention-font-color',
mentionDisabledFontColor: 'mention-disabled-font-color',
Expand Down
73 changes: 72 additions & 1 deletion packages/nimble-components/src/theme-provider/design-tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,21 @@ import {
GridHeaderFamily,
GridHeaderWeight,
GridHeaderSize,
DigitalGreenDark105
DigitalGreenDark105,
NiFern,
NiFernDark1,
NiHoneyLight,
NiIndigo,
NiIndigoDark2,
NiPlumDark1,
NiScarlet,
NiScarletDark1,
NiScarletDark3,
NiSea,
NiSeaLight,
NiSeaDark2,
NiSky,
NiTulip
} from '@ni/nimble-tokens/dist/styledictionary/js/tokens';
import {
modalBackdropColorThemeColorStatic,
Expand Down Expand Up @@ -204,6 +218,63 @@ export const graphGridlineColor = DesignToken.create<string>(
styleNameFromTokenName(tokenNames.graphGridlineColor)
).withDefault((element: HTMLElement) => hexToRgbaCssColor(getColorForTheme(element, Black91, Black15, White), 0.2));

export const graphTrace1Color = DesignToken.create<string>(
styleNameFromTokenName(tokenNames.graphTrace1Color)
).withDefault((element: HTMLElement) => getColorForTheme(element, NiIndigoDark2, NiSky, White));

export const graphTrace2Color = DesignToken.create<string>(
styleNameFromTokenName(tokenNames.graphTrace2Color)
).withDefault((element: HTMLElement) => getColorForTheme(
element,
NiScarletDark1,
NiScarlet,
hexToRgbaCssColor(White, 0.7)
));

export const graphTrace3Color = DesignToken.create<string>(
styleNameFromTokenName(tokenNames.graphTrace3Color)
).withDefault((element: HTMLElement) => getColorForTheme(
element,
NiFernDark1,
NiFern,
hexToRgbaCssColor(White, 0.4)
));

export const graphTrace4Color = DesignToken.create<string>(
styleNameFromTokenName(tokenNames.graphTrace4Color)
).withDefault((element: HTMLElement) => getColorForTheme(
element,
NiPlumDark1,
NiSeaLight,
hexToRgbaCssColor(White, 0.25)
));

export const graphTrace5Color = DesignToken.create<string>(
styleNameFromTokenName(tokenNames.graphTrace5Color)
).withDefault((element: HTMLElement) => getColorForTheme(element, NiSeaDark2, NiSea, hexToRgbaCssColor(White, 0.55)));

export const graphTrace6Color = DesignToken.create<string>(
styleNameFromTokenName(tokenNames.graphTrace6Color)
).withDefault((element: HTMLElement) => getColorForTheme(element, NiTulip, NiTulip, hexToRgbaCssColor(White, 0.85)));

export const graphTrace7Color = DesignToken.create<string>(
styleNameFromTokenName(tokenNames.graphTrace7Color)
).withDefault((element: HTMLElement) => getColorForTheme(
element,
NiScarletDark3,
NiHoneyLight,
hexToRgbaCssColor(White, 0.325)
));

export const graphTrace8Color = DesignToken.create<string>(
styleNameFromTokenName(tokenNames.graphTrace8Color)
).withDefault((element: HTMLElement) => getColorForTheme(
element,
NiIndigo,
NiIndigo,
hexToRgbaCssColor(White, 0.625)
));

export const tooltipBackgroundColor = DesignToken.create<string>(
styleNameFromTokenName(tokenNames.tooltipBackgroundColor)
).withDefault((element: HTMLElement) => getColorForTheme(element, Black15, Black85, ForestGreen));
Expand Down
26 changes: 26 additions & 0 deletions packages/storybook/src/nimble/graph/graph.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Canvas, Meta, Controls, Title } from '@storybook/blocks';
import * as graphStories from './graph.stories';
import * as tokenStories from '../theme-provider/tokens.stories';

<Meta of={graphStories} />
<Title of={graphStories} />

The Nimble Design System does not provide a graph component, but theme-aware
tokens are available for styling custom or third-party graph components to match
the Nimble Design System.

<Canvas of={tokenStories.graphTokens} />
<Controls of={tokenStories.graphTokens} />

## Usage

For monochromatic UIs using the Color theme, it is recommended to override the
default values of the graph trace tokens with colors that work with the specific
background color. Special care should be taken to ensure the colors pass
accessibility standards. Consult with a visual designer for help.

{/* ## Examples */}

{/* ## Accessibility */}

{/* ## Resources */}
13 changes: 13 additions & 0 deletions packages/storybook/src/nimble/graph/graph.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { html } from '@microsoft/fast-element';
import type { Meta, StoryObj } from '@storybook/html';
import { createUserSelectedThemeStory } from '../../utilities/storybook';
import { hiddenWrapper } from '../../utilities/hidden';

const metadata: Meta = {
title: 'Components/Graph',
render: createUserSelectedThemeStory(hiddenWrapper(html`<style></style>`))
};

export default metadata;

export const graph: StoryObj = {};
83 changes: 44 additions & 39 deletions packages/storybook/src/nimble/theme-provider/tokens.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { html, repeat, ViewTemplate, when } from '@microsoft/fast-element';
import { waitForUpdatesAsync } from '../../../../nimble-components/src/testing/async-helpers';
import { PropertyFormat } from '../../../../nimble-components/src/theme-provider/tests/types';
import {
tokenNames,
tokenNames as tokens,
cssPropertyFromTokenName,
scssPropertyFromTokenName,
TokenSuffix,
Expand All @@ -20,27 +20,17 @@ import {
} from '../../../../nimble-components/src/theme-provider/design-tokens';
import { createUserSelectedThemeStory } from '../../utilities/storybook';

type TokenName = keyof typeof tokenNames;
const tokenNameKeys = Object.keys(tokenNames) as TokenName[];
tokenNameKeys.sort((a, b) => a.localeCompare(b));
type TokenName = keyof typeof tokens;
const tokenNames = Object.keys(tokens) as TokenName[];
tokenNames.sort((a, b) => a.localeCompare(b));
const graphTokenNames = tokenNames.filter(x => x.startsWith('graph'));

interface TokenArgs {
metaTitle: string;
tokenNames: TokenName[];
propertyFormat: PropertyFormat;
}

const metadata: Meta = {
title: 'Tokens/Theme-aware Tokens',
parameters: {
docs: {
source: {
code: null
}
}
}
};

export default metadata;

const computedCSSValueFromTokenName = (tokenName: string): string => {
return getComputedStyle(document.documentElement).getPropertyValue(
cssPropertyFromTokenName(tokenName)
Expand All @@ -49,41 +39,41 @@ const computedCSSValueFromTokenName = (tokenName: string): string => {

const colorTemplate = html<TokenName>`
<div
title="${x => computedCSSValueFromTokenName(tokenNames[x])}"
title="${x => computedCSSValueFromTokenName(tokens[x])}"
style="
display: inline-block;
height: 24px;
width: 24px;
border: 1px solid black;
background-color: var(${x => cssPropertyFromTokenName(tokenNames[x])});
background-color: var(${x => cssPropertyFromTokenName(tokens[x])});
"
></div>
`;

const rgbColorTemplate = html<TokenName>`
<div
title="${x => computedCSSValueFromTokenName(tokenNames[x])}"
title="${x => computedCSSValueFromTokenName(tokens[x])}"
style="
display: inline-block;
height: 24px;
width: 24px;
border: 1px solid black;
background-color: rgba(var(${x => cssPropertyFromTokenName(tokenNames[x])}), 1.0);
background-color: rgba(var(${x => cssPropertyFromTokenName(tokens[x])}), 1.0);
"
></div>
`;

const stringValueTemplate = html<TokenName>`
<div style="display: inline-block;">
${x => computedCSSValueFromTokenName(tokenNames[x])}
${x => computedCSSValueFromTokenName(tokens[x])}
</div>
`;

const fontTemplate = html<TokenName>`
<div
style="
display: inline-block;
font: var(${x => cssPropertyFromTokenName(tokenNames[x])});
font: var(${x => cssPropertyFromTokenName(tokens[x])});
"
>
Nimble
Expand Down Expand Up @@ -127,8 +117,14 @@ const templateForTokenName = (
};

// prettier-ignore
export const themeAwareTokens: StoryObj<TokenArgs> = {
const metadata: Meta<TokenArgs> = {
title: 'Tokens/Theme-aware Tokens',
parameters: {
docs: {
source: {
code: null
}
},
controls: { hideNoControlsWarning: true }
},
args: {
Expand All @@ -139,9 +135,12 @@ export const themeAwareTokens: StoryObj<TokenArgs> = {
options: Object.values(PropertyFormat),
control: { type: 'radio' },
name: 'Property Format'
},
tokenNames: {
table: { disable: true }
}
},
render: createUserSelectedThemeStory(html<TokenArgs>`
render: createUserSelectedThemeStory(html`
<style>
table {
font: var(${bodyFont.cssCustomProperty});
Expand All @@ -166,14 +165,14 @@ export const themeAwareTokens: StoryObj<TokenArgs> = {
</tr>
</thead>
<tbody>
${repeat(() => tokenNameKeys, html<TokenName, TokenArgs>`
${repeat(x => x.tokenNames, html<TokenName, TokenArgs>`
<tr>
<td>
${when((_, c) => (c.parent as TokenArgs).propertyFormat === PropertyFormat.css, html<TokenName>`
${x => cssPropertyFromTokenName(tokenNames[x])}
${x => cssPropertyFromTokenName(tokens[x])}
`)}
${when((_, c) => (c.parent as TokenArgs).propertyFormat === PropertyFormat.scss, html<TokenName>`
${x => scssPropertyFromTokenName(tokenNames[x])}
${x => scssPropertyFromTokenName(tokens[x])}
`)}
</td>
<td>${x => templateForTokenName(x)}</td>
Expand All @@ -182,17 +181,23 @@ export const themeAwareTokens: StoryObj<TokenArgs> = {
`)}
</tbody>
</table>
`)
`),
// Setting token default values is done as part of the FAST render queue so it needs to be cleared before reading them
// https://github.com/microsoft/fast/blob/bbf4e532cf9263727ef1bd8afbc30d79d1104c03/packages/web-components/fast-foundation/src/design-token/custom-property-manager.ts#LL154C3-L154C3
// This uses Storybook's "loaders" feature to await the queue. https://storybook.js.org/docs/html/writing-stories/loaders
loaders: [
async (): Promise<void> => {
await waitForUpdatesAsync();
}
]
};

themeAwareTokens.name = 'Theme-aware Tokens';
export default metadata;

// Setting token default values is done as part of the FAST render queue so it needs to be cleared before reading them
// https://github.com/microsoft/fast/blob/bbf4e532cf9263727ef1bd8afbc30d79d1104c03/packages/web-components/fast-foundation/src/design-token/custom-property-manager.ts#LL154C3-L154C3
// This uses Storybook's "loaders" feature to await the queue. https://storybook.js.org/docs/html/writing-stories/loaders
themeAwareTokens.loaders = [
async () => {
await waitForUpdatesAsync();
return {};
}
];
export const themeAwareTokens: StoryObj<TokenArgs> = {
args: { tokenNames }
};

export const graphTokens: StoryObj<TokenArgs> = {
args: { tokenNames: graphTokenNames }
};

0 comments on commit 0084f69

Please sign in to comment.