Skip to content

Commit

Permalink
feat(website): Add text color token accessibility rating to the token…
Browse files Browse the repository at this point in the history
… page (#28)

* feat(website): add accessibility rating for text color tokens

* feat(website): fix up the color rating test

* fix(website): color combos test prettier

* feat(screen-reader-only): create a SRO component

* fix: update the component category in package.json

* fix: \correct the tokens that are being displayed

* fix: remove importants and update license field

* fix: eslint of jest test promises
  • Loading branch information
SiTaggart committed Aug 13, 2019
1 parent 3fbd4d0 commit 74f12d1
Show file tree
Hide file tree
Showing 21 changed files with 3,405 additions and 59 deletions.
41 changes: 41 additions & 0 deletions packages/paste-core/utilities/screen-reader-only/package.json
@@ -0,0 +1,41 @@
{
"name": "@twilio-paste/screen-reader-only",
"version": "0.0.0",
"category": "typography",
"status": "alpha",
"description": "",
"author": "Twilio Inc.",
"license": "MIT",
"main:dev": "src/index.tsx",
"main": "dist/index.js",
"module": "dist/index.es.js",
"types": "dist/index.d.ts",
"sideEffects": false,
"files": [
"dist"
],
"scripts": {
"build": "yarn clean && yarn compile",
"build:dev": "yarn clean && yarn compile:dev",
"clean": "rm -rf ./dist && rm -rf tsconfig.build.tsbuildinfo && rm -rf .rpt2_cache",
"compile": "rollup -c --environment NODE_ENV:production",
"compile:dev": "rollup -c --environment NODE_ENV:development",
"prepublishOnly": "yarn build",
"type-check": "tsc --noEmit"
},
"peerDependencies": {
"@emotion/styled": "^10.0.10",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"styled-system": "^4.1.0"
},
"devDependencies": {
"rollup": "^1.16.2",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-commonjs": "^10.0.1",
"rollup-plugin-node-resolve": "^5.1.0",
"rollup-plugin-terser": "^5.0.0",
"rollup-plugin-typescript2": "^0.21.2",
"typescript": "^3.5.2"
}
}
34 changes: 34 additions & 0 deletions packages/paste-core/utilities/screen-reader-only/rollup.config.js
@@ -0,0 +1,34 @@
import typescript from 'rollup-plugin-typescript2';
import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import {terser} from 'rollup-plugin-terser';
import pkg from './package.json';

export default {
input: pkg['main:dev'],
output: [
{
file: pkg.main,
format: 'cjs',
},
{
file: pkg.module,
format: 'es',
},
],
external: [...Object.keys(pkg.peerDependencies || {})],
plugins: [
resolve(),
commonjs(),
typescript({
clean: true,
typescript: require('typescript'),
tsconfig: './tsconfig.build.json',
}),
babel({
exclude: 'node_modules/**',
}),
process.env.NODE_ENV === 'production' ? terser() : null,
],
};
14 changes: 14 additions & 0 deletions packages/paste-core/utilities/screen-reader-only/src/index.tsx
@@ -0,0 +1,14 @@
import styled from '@emotion/styled';

export const ScreenReaderOnly = styled.span<{}>`
position: absolute;
margin: -1px;
border: 0;
padding: 0;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0 0 0 0);
text-transform: none;
white-space: nowrap;
`;
@@ -0,0 +1,15 @@
import * as React from 'react';
import {storiesOf} from '@storybook/react';
import {withKnobs} from '@storybook/addon-knobs';
import {Text} from '@twilio-paste/text';
import {ScreenReaderOnly} from '../src';

storiesOf('Utilities|Screen reader only', module)
.addDecorator(withKnobs)
.add('Default', () => {
return (
<Text>
Some visible text <ScreenReaderOnly>some not visible text</ScreenReaderOnly>
</Text>
);
});
@@ -0,0 +1,15 @@
{
"extends": "../../../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": [
"src/**/*"
],
"references": [
{
"path": "../../../paste-theme-tokens"
}
]
}
@@ -0,0 +1,4 @@
{
"extends": "../../../../tsconfig.json",
"include": ["src/**/*"]
}
Expand Up @@ -4,8 +4,8 @@ import {dTSTokenFormat} from '../d.ts';
theo.registerFormat('d.ts', dTSTokenFormat);

describe('dTSFormatter', () => {
test('should return typescript definitions formatted tokens', () => {
theo
it('should return typescript definitions formatted tokens', () => {
return theo
.convert({
transform: {
type: 'web',
Expand Down
4 changes: 2 additions & 2 deletions packages/paste-design-tokens/formatters/__tests__/es6.spec.ts
Expand Up @@ -4,8 +4,8 @@ import {es6TokenFormat} from '../es6';
theo.registerFormat('es6.js', es6TokenFormat);

describe('es6Formatter', () => {
test('should return es6 formatted tokens', () => {
theo
it('should return es6 formatted tokens', () => {
return theo
.convert({
transform: {
type: 'web',
Expand Down
Expand Up @@ -4,8 +4,8 @@ import {sketchpaletteTokenFormat} from '../sketchpalette';
theo.registerFormat('sketchpalette', sketchpaletteTokenFormat);

describe('sketchPaletteTokenFormatter', () => {
test('should return sketch palette color formatted tokens', () => {
theo
it('should return sketch palette color formatted tokens', () => {
return theo
.convert({
transform: {
type: 'web',
Expand Down
1 change: 0 additions & 1 deletion packages/paste-design-tokens/types/index.ds.ts
@@ -1,3 +1,2 @@
declare module 'gulp-theo';
declare module 'gulp-restart';
declare module 'color';
8 changes: 6 additions & 2 deletions packages/paste-website/gatsby-config.js
Expand Up @@ -65,8 +65,12 @@ module.exports = {
return 'PasteUtility';
}

if (node.relativePath.endsWith('gatsby.json')) {
return 'PasteToken';
if (node.relativePath.endsWith('dist/tokens.gatsby.json')) {
return 'PasteTokenDefault';
}

if (node.relativePath.endsWith('dist/themes/sendgrid/tokens.gatsby.json')) {
return 'PasteTokenSendGrid';
}

return 'DefaultJson';
Expand Down
5 changes: 4 additions & 1 deletion packages/paste-website/src/components/table/index.tsx
Expand Up @@ -44,7 +44,10 @@ export const Td = styled.td(props => ({
},
}));

export const Th = styled(Td)(props => ({
interface ThProps {
width?: string;
}
export const Th = styled<ThProps>(Td)(props => ({
textAlign: 'left',
fontWeight: themeGet('fontWeights.fontWeightSemibold')(props),
})).withComponent('th');
50 changes: 37 additions & 13 deletions packages/paste-website/src/components/token-example/index.tsx
Expand Up @@ -2,8 +2,12 @@ import * as React from 'react';
import * as lodash from 'lodash';
import {ThemeShape} from '@twilio-paste/theme-tokens';
import {Absolute, AbsoluteProps} from '@twilio-paste/absolute';
import {useTheme} from '@twilio-paste/theme';
import {Box, BoxProps} from '@twilio-paste/box';
import {Text, TextProps} from '@twilio-paste/text';
import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only';
import ColorCombos, {ColorCombinationAccessibility} from '../../utils/color-combos';
import colorRating from '../../utils/color-rating';

// Traditional import as the color package isn't exported and typed correctly
const Color = require('color');
Expand All @@ -20,13 +24,34 @@ export const BorderBox: React.FC<BorderBoxProps> = ({borderColor, borderWidth})
);
};

type TextBoxProp = Pick<TextProps, 'fontFamily' | 'fontSize' | 'fontWeight' | 'textColor'>;
interface TextBoxProps extends TextBoxProp {
color?: string;
type TextBoxProp = Pick<TextProps, 'fontFamily' | 'fontSize' | 'fontWeight'>;
export const TextBox: React.FC<TextBoxProp> = ({fontFamily, fontSize, fontWeight}) => {
return (
<Text fontFamily={fontFamily} fontSize={fontSize || 'fontSize60'} fontWeight={fontWeight} lineHeight="lineHeight60">
Ag
</Text>
);
};

type TextColorBoxProp = Pick<TextProps, 'textColor'>;
interface TextColorBoxProps extends TextColorBoxProp {
color: string;
}
export const TextBox: React.FC<TextBoxProps> = ({color, fontFamily, fontSize, fontWeight, textColor}) => {
export const TextColorBox: React.FC<TextColorBoxProps> = ({color, textColor}) => {
const theme = useTheme();
const colorFn = Color(color);
const isInverse = colorFn.isLight();
const backgroundColorValue = isInverse
? theme.backgroundColors.colorBackgroundBrand
: theme.backgroundColors.colorBackgroundBody;
const colorCombos = ColorCombos([color, backgroundColorValue]);
const {accessibility} = colorCombos[1].combinations[0];

const getContrastRating = (acc: ColorCombinationAccessibility): string => {
const rating = colorRating(acc);
return rating.small;
};

return (
<Absolute
backgroundColor={isInverse ? 'colorBackgroundBrand' : 'colorBackgroundBody'}
Expand All @@ -35,16 +60,15 @@ export const TextBox: React.FC<TextBoxProps> = ({color, fontFamily, fontSize, fo
css={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
}}
>
<Text
fontFamily={fontFamily}
fontSize={fontSize || 'fontSize60'}
fontWeight={fontWeight}
lineHeight="lineHeight60"
textColor={textColor}
>
Ag
<Text as="span" fontSize="fontSize60" lineHeight="lineHeight60" textColor={textColor}>
<ScreenReaderOnly>Example text: </ScreenReaderOnly>Ag
</Text>
<Text as="span" fontSize="fontSize40" lineHeight="lineHeight30" textColor={textColor}>
<ScreenReaderOnly>Accessibility rating: </ScreenReaderOnly>
{getContrastRating(accessibility)}
</Text>
</Absolute>
);
Expand Down Expand Up @@ -107,7 +131,7 @@ export const TokenExample: React.FC<TokenExampleProps> = ({token}) => {
case 'spacing':
return <SpacingBox padding={tokenName as keyof ThemeShape['space']} />;
case 'text-color':
return <TextBox color={token.value} textColor={tokenName as keyof ThemeShape['textColors']} />;
return <TextColorBox color={token.value} textColor={tokenName as keyof ThemeShape['textColors']} />;
default:
return <Box>{token.value}</Box>;
}
Expand Down
24 changes: 12 additions & 12 deletions packages/paste-website/src/components/tokens-list/index.tsx
Expand Up @@ -29,31 +29,32 @@ interface TokenCategory {
tokens: Token[];
}

interface DataShape {
interface TokensShape {
node: {
tokens: TokenCategory[];
};
}

interface TokensListProps {
children?: React.ReactElement;
data: DataShape[];
default: TokensShape[];
sendgrid: TokensShape[];
}

const setInitialState = (data: DataShape[]): TokenCategory[] | null => {
const setInitialState = (data: TokensShape[]): TokenCategory[] | null => {
if (data != null) {
// eslint-disable-next-line prefer-destructuring
return data[0].node.tokens;
const {tokens} = data[0].node;
return tokens;
}
return null;
};

export const TokensList: React.FC<TokensListProps> = props => {
const [tokens, setTokens] = React.useState(setInitialState(props.data));
const [tokens, setTokens] = React.useState(setInitialState(props.sendgrid));

const filterTokenList = (filter: string): void => {
setTokens(() => {
const newTokenCategories = props.data[0].node.tokens.map(
const newTokenCategories = props.sendgrid[0].node.tokens.map(
(category): TokenCategory => {
const newTokens = category.tokens.filter(token => {
return token.name.includes(filter) || token.value.includes(filter);
Expand Down Expand Up @@ -105,22 +106,21 @@ export const TokensList: React.FC<TokensListProps> = props => {
<thead>
<Tr>
<Th>Token</Th>
<Th>Value</Th>
<Th>Description</Th>
<Th>Example</Th>
<Th width="250px">Value</Th>
<Th width="250px">Example</Th>
</Tr>
</thead>
<Tbody>
{cat.tokens.map((token: Token) => {
return (
<Tr key={`token${token.name}`}>
<Td>
<Text fontSize="fontSize30">
<Text fontSize="fontSize30" mb="space30">
<code>${token.name}</code>
</Text>
<Text textColor="colorTextWeak">{token.comment}</Text>
</Td>
<Td>{token.value}</Td>
<Td>{token.comment}</Td>
<Td
css={{
position: 'relative',
Expand Down
28 changes: 23 additions & 5 deletions packages/paste-website/src/pages/tokens/index.mdx
Expand Up @@ -13,9 +13,9 @@ import {TokensList} from '../../components/tokens-list';

Laboris Lorem veniam nostrud enim do esse mollit adipisicing dolore proident labore elit et. Adipisicing sint incididunt ipsum nisi ut mollit et id est consequat qui cillum magna enim. Occaecat voluptate aute nisi aute magna enim minim quis. Irure minim nisi culpa ipsum nisi duis enim laboris officia occaecat laborum est. Duis reprehenderit magna eu laboris. Enim ad id nulla esse do excepteur.

<Box backgroundColor="colorBackground" borderRadius="borderRadius20" padding="space60" my="space100" maxWidth="size40">
<Text as="p" marginBottom="space40">
Working on Sketch? Download it from here. No access?
<Box backgroundColor="colorBackground" borderRadius="borderRadius20" padding="space80" my="space100" maxWidth="size40">
<Text as="p" lineHeight="lineHeight30" marginBottom="space40">
Working on Sketch? Download it from here. No access?{' '}
<Anchor href="#">
Send us a request
</Anchor>.
Expand All @@ -28,11 +28,29 @@ Laboris Lorem veniam nostrud enim do esse mollit adipisicing dolore proident lab
</Text>
</Box>

<TokensList data={props.data.allPasteToken.edges} />
<TokensList default={props.data.allPasteTokenDefault.edges} sendgrid={props.data.allPasteTokenSendGrid.edges} />

export const pageQuery = graphql`
{
allPasteToken {
allPasteTokenDefault {
edges {
node {
id
tokens {
categoryName
tokens {
category
comment
name
originalValue
type
value
}
}
}
}
},
allPasteTokenSendGrid {
edges {
node {
id
Expand Down

0 comments on commit 74f12d1

Please sign in to comment.