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

feat(website): show text color token pairings #3034

Merged
merged 9 commits into from Mar 2, 2023
6 changes: 6 additions & 0 deletions .changeset/sixty-chefs-cover.md
@@ -0,0 +1,6 @@
---
'@twilio-paste/design-tokens': patch
'@twilio-paste/core': patch
---

[Design Tokens]: correct color contrast token pair naming for decorative background 10
8 changes: 4 additions & 4 deletions packages/paste-design-tokens/tokens/global/text-color.yml
Expand Up @@ -483,28 +483,28 @@ props:
text_contrast_pairing:
- color-background
- color-background-body
- color-background-decorative-10
- color-background-decorative-10-weakest
color-text-decorative-20:
value: "{!palette-blue-80}"
comment: Text color with no semantic meaning, used for decorative purposes only. Should generally be used with matching decorative background and/or border tokens.
text_contrast_pairing:
- color-background
- color-background-body
- color-background-decorative-20
- color-background-decorative-20-weakest
color-text-decorative-30:
value: "{!palette-green-70}"
comment: Text color with no semantic meaning, used for decorative purposes only. Should generally be used with matching decorative background and/or border tokens.
text_contrast_pairing:
- color-background
- color-background-body
- color-background-decorative-30
- color-background-decorative-30-weakest
color-text-decorative-40:
value: "{!palette-purple-60}"
comment: Text color with no semantic meaning, used for decorative purposes only. Should generally be used with matching decorative background and/or border tokens.
text_contrast_pairing:
- color-background
- color-background-body
- color-background-decorative-40
- color-background-decorative-40-weakest
Copy link
Contributor Author

Choose a reason for hiding this comment

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

incorrect annotations here. These tokens don't exist.


# user
color-text-user:
Expand Down
@@ -1,8 +1,8 @@
imports:
- ../../../aliases/box-shadow.yml
- ../../../aliases/offset.yml
Copy link
Contributor Author

Choose a reason for hiding this comment

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

offset file was empty, might as well inherit the base

- ./color-palette.yml
- ./color.yml
- ./offset.yml
aliases:
shadow-elevation-0: "none"
shadow-elevation-10: "{!offset-0} {!offset-10} {!offset-20} {!offset-0} {!black-transparent-40}"
Expand Down

This file was deleted.

Expand Up @@ -155,31 +155,15 @@ props:
color-text-decorative-10:
value: "{!palette-gray-20}"
comment: Text color with no semantic meaning, used for decorative purposes only. Should generally be used with matching decorative background and/or border tokens.
text_contrast_pairing:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

No need to declare the pairings at the theme level. The pairings are set at the system level, so every theme should meet the same token pair requirements as they are used in the same places across the theme.

- color-background
- color-background-body
- color-background-decorative-10
color-text-decorative-20:
value: "{!palette-blue-20}"
comment: Text color with no semantic meaning, used for decorative purposes only. Should generally be used with matching decorative background and/or border tokens.
text_contrast_pairing:
- color-background
- color-background-body
- color-background-decorative-20
color-text-decorative-30:
value: "{!palette-green-30}"
comment: Text color with no semantic meaning, used for decorative purposes only. Should generally be used with matching decorative background and/or border tokens.
text_contrast_pairing:
- color-background
- color-background-body
- color-background-decorative-30
color-text-decorative-40:
value: "{!palette-purple-20}"
comment: Text color with no semantic meaning, used for decorative purposes only. Should generally be used with matching decorative background and/or border tokens.
text_contrast_pairing:
- color-background
- color-background-body
- color-background-decorative-40

# user
color-text-user:
Expand Down
@@ -1,8 +1,8 @@
imports:
- ../../../aliases/box-shadow.yml
- ../../../aliases/offset.yml
- ./color-palette.yml
- ./color.yml
- ./offset.yml
Copy link
Contributor Author

Choose a reason for hiding this comment

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

copy pasta from the other theme that didn't need the empty file

aliases:
shadow-elevation-0: "none"
shadow-elevation-10: "{!offset-0} {!offset-10} {!offset-20} {!offset-0} {!black-transparent-40}"
Expand Down

This file was deleted.

Expand Up @@ -132,28 +132,12 @@ props:
color-text-decorative-10:
value: "#696F8C"
comment: Text color with no semantic meaning, used for decorative purposes only. Should generally be used with matching decorative background and/or border tokens.
text_contrast_pairing:
- color-background
- color-background-body
- color-background-decorative-10
color-text-decorative-20:
value: "#2952CC"
comment: Text color with no semantic meaning, used for decorative purposes only. Should generally be used with matching decorative background and/or border tokens.
text_contrast_pairing:
- color-background
- color-background-body
- color-background-decorative-20
color-text-decorative-30:
value: "#317159"
comment: Text color with no semantic meaning, used for decorative purposes only. Should generally be used with matching decorative background and/or border tokens.
text_contrast_pairing:
- color-background
- color-background-body
- color-background-decorative-30
color-text-decorative-40:
value: "#6E62B6"
comment: Text color with no semantic meaning, used for decorative purposes only. Should generally be used with matching decorative background and/or border tokens.
text_contrast_pairing:
- color-background
- color-background-body
- color-background-decorative-40
Expand Up @@ -28,10 +28,6 @@ props:
color-text-decorative-40:
value: "{!palette-purple-30}"
comment: Text color with no semantic meaning, used for decorative purposes only. Should generally be used with matching decorative background and/or border tokens.
text_contrast_pairing:
- color-background
- color-background-body
- color-background-decorative-40

# user
color-text-user:
Expand Down

This file was deleted.

Expand Up @@ -3,7 +3,6 @@ global:
category: box-shadow
imports:
- ../../../global/box-shadow.yml
- ../aliases/box-shadow.yml
Copy link
Contributor Author

Choose a reason for hiding this comment

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

redundant file

props:
shadow-focus:
value: "{!offset-0} {!offset-0} {!offset-0} {!offset-10} {!palette-gray-0}, {!offset-0} {!offset-0} {!offset-0} 3px {!palette-blue-55}, {!offset-0} {!offset-0} {!offset-0} 5px {!palette-blue-20}"
Expand Down
Expand Up @@ -49,10 +49,6 @@ props:
color-text-decorative-30:
value: "{!palette-green-80}"
comment: Text color with no semantic meaning, used for decorative purposes only. Should generally be used with matching decorative background and/or border tokens.
text_contrast_pairing:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

More copy pasta

- color-background
- color-background-body
- color-background-decorative-30

# user
color-text-user:
Expand Down
78 changes: 78 additions & 0 deletions packages/paste-website/src/__tests__/tokenAccessiblePairs.test.tsx
@@ -0,0 +1,78 @@
import {getTokenContrastPairs} from '../components/tokens-list/helpers';

describe('Color token pairing display', () => {
describe('getTokenContrastPairs', () => {
it('should only return an object of tokens with their accessbile pairings', () => {
const mockTokens = {
tokens: {
'background-colors': [
{
type: 'color',
value: 'rgb(244, 244, 246)',
comment: 'Default background color for any container.',
name: 'color-background',
altValue: '#F4F4F6',
category: 'background-color',
},
{
type: 'color',
value: 'rgb(20, 176, 83)',
comment: 'Background color used to represent an entity or person as "available".',
name: 'color-background-available',
altValue: '#14B053',
category: 'background-color',
},
],
'text-colors': [
{
type: 'color',
value: 'rgb(96, 107, 133)',
comment: 'Weak body text for visual hierarchy.',
text_contrast_pairing: [
'color-background',
'color-background-body',
'color-background-neutral-weakest',
'color-background-warning-weakest',
'color-background-error-weakest',
'color-background-row-striped',
'color-background-primary-weakest',
'color-background-destructive-weakest',
],
name: 'color-text-weak',
altValue: '#606B85',
category: 'text-color',
},
{
type: 'color',
value: 'rgb(96, 107, 133)',
name: 'color-text',
altValue: '#606B85',
category: 'text-color',
},
{
type: 'color',
value: 'rgb(96, 107, 133)',
text_contrast_pairing: ['color-background', 'color-background-body'],
name: 'color-text-strong',
altValue: '#606B85',
category: 'text-color',
},
],
},
};
expect(getTokenContrastPairs(mockTokens)).toEqual({
'color-text-weak': [
'color-background',
'color-background-body',
'color-background-neutral-weakest',
'color-background-warning-weakest',
'color-background-error-weakest',
'color-background-row-striped',
'color-background-primary-weakest',
'color-background-destructive-weakest',
],
'color-text-strong': ['color-background', 'color-background-body'],
});
});
});
});
6 changes: 6 additions & 0 deletions packages/paste-website/src/__tests__/tokenCard.test.tsx
Expand Up @@ -33,6 +33,7 @@ describe('TokenCard', () => {
textColor={testExampleTextColor}
textColorInverse={testExampleTextColorInverse}
useCamelCase={useCamelCase}
selectedTheme="default"
/>
</Theme.Provider>
);
Expand Down Expand Up @@ -66,6 +67,7 @@ describe('TokenCard', () => {
value="70.5rem"
altValue="1128px"
comment="Generic sizing token scale for UI components."
selectedTheme="default"
/>
</Theme.Provider>
);
Expand All @@ -86,6 +88,7 @@ describe('TokenCard', () => {
backgroundColorInverse={testExampleBackgroundInverse}
textColor={testExampleTextColor}
textColorInverse={testExampleTextColorInverse}
selectedTheme="default"
/>
</Theme.Provider>
);
Expand All @@ -105,6 +108,7 @@ describe('TokenCard', () => {
comment="Light inverse background color for any container. Must be used on color-background-body-inverse."
backgroundColor={testExampleBackground}
backgroundColorInverse={testExampleBackgroundInverse}
selectedTheme="default"
/>
</Theme.Provider>
);
Expand All @@ -127,6 +131,7 @@ describe('TokenCard', () => {
backgroundColorInverse={testExampleBackgroundInverse}
textColor={testExampleTextColor}
textColorInverse={testExampleTextColorInverse}
selectedTheme="default"
/>
</Theme.Provider>
);
Expand All @@ -149,6 +154,7 @@ describe('TokenCard', () => {
highlightColor={testExampleHighlightColor}
textColor={testExampleTextColor}
textColorInverse={testExampleTextColorInverse}
selectedTheme="default"
/>
</Theme.Provider>
);
Expand Down
18 changes: 17 additions & 1 deletion packages/paste-website/src/components/tokens-list/helpers.tsx
@@ -1,7 +1,7 @@
import type {Properties} from 'csstype';
import debounce from 'lodash/debounce';

import type {Token, Tokens, TokenExampleColors} from './types';
import type {Token, Tokens, TokenExampleColors, TokensShape} from './types';
import {event} from '../../lib/gtag';

export const trackTokenFilterString = debounce((filter: string): void => {
Expand Down Expand Up @@ -63,3 +63,19 @@ export const getTokenExampleColors = (tokens: Tokens): TokenExampleColors => {
?.value as Properties['color'],
};
};

export const getTokenContrastPairs = (Tokens: TokensShape): Record<string, string[]> => {
const {tokens} = Tokens;
const tokensWithPairs: Record<string, string[]> = {};
const tokenCategories = tokens ? (Object.keys(tokens) as [keyof typeof tokens]) : [];
tokenCategories.forEach((tokenCatgory) => {
if (tokens) {
tokens[tokenCatgory].forEach((token) => {
if (token.text_contrast_pairing) {
tokensWithPairs[token.name] = token.text_contrast_pairing;
}
});
}
});
return tokensWithPairs;
};
13 changes: 9 additions & 4 deletions packages/paste-website/src/components/tokens-list/index.tsx
Expand Up @@ -7,7 +7,7 @@ import {useClipboard} from '@twilio-paste/clipboard-copy-library';
import kebabCase from 'lodash/kebabCase';

import {AnchoredHeading} from '../Heading';
import {trackTokenFilterString, filterTokenList, getTokenExampleColors} from './helpers';
import {trackTokenFilterString, filterTokenList, getTokenExampleColors, getTokenContrastPairs} from './helpers';
import type {Tokens, TokenExampleColors} from './types';
import {PageAside} from '../shortcodes/PageAside';
import {NoTokensFound} from './NoTokensFound';
Expand Down Expand Up @@ -46,19 +46,22 @@ export const TokensList = (): JSX.Element => {

// State related to select and filter controls
const [filterString, setFilterString] = React.useState('');
const [selectedTheme, setSelectedTheme] = React.useState(defaultTheme);
const [selectedTheme, setSelectedTheme] = React.useState<'default' | 'dark'>(defaultTheme);
const [selectedFormat, setSelectedFormat] = React.useState(defaultFormat);
const [useJavascriptNames, setUseJavascriptNames] = React.useState(false);

// State related to the clipboard
const [lastCopiedValue, setLastCopiedValue] = React.useState('');

// Get a static list of tokens and color contrast pairs
const tokenContrastPairs = getTokenContrastPairs(DefaultThemeTokens);

/*
* This runs on hydration, grabs any settings from the client's localStorage,
* and populates the token list.
*/
React.useEffect(() => {
const userTheme = SimpleStorage.get('themeControl') || defaultTheme;
const userTheme = (SimpleStorage.get('themeControl') as 'dark' | 'default') || defaultTheme;
const userFormat = SimpleStorage.get('formatControl') || defaultFormat;
let tokenList: Tokens = DefaultThemeTokens.tokens;

Expand Down Expand Up @@ -98,7 +101,7 @@ export const TokensList = (): JSX.Element => {
const newTokens = value === 'dark' ? DarkThemeTokens.tokens : DefaultThemeTokens.tokens;

SimpleStorage.set('themeControl', value);
setSelectedTheme(value);
setSelectedTheme(value as 'default' | 'dark');
setTokens(newTokens);
setExampleColors(getTokenExampleColors(newTokens));
};
Expand Down Expand Up @@ -210,6 +213,8 @@ export const TokensList = (): JSX.Element => {
useCamelCase={useJavascriptNames}
onCopyText={handleCopyName}
isCopied={clipboard.copied && lastCopiedValue === name}
text_contrast_pairing={tokenContrastPairs[name]}
selectedTheme={selectedTheme}
/>
))
) : (
Expand Down