chore: type src of addons/a11y

This commit is contained in:
Gaëtan Maisse 2019-02-24 17:37:16 +01:00
parent 76029c9400
commit d7ad26e90e
11 changed files with 132 additions and 138 deletions

View File

@ -16,7 +16,7 @@ const ColorIcon = styled.span(
height: '1rem',
width: '1rem',
},
({ filter }: any) => ({
({ filter }: { filter: string | null }) => ({
filter: filter === 'mono' ? 'grayscale(100%)' : `url('#${filter}')`,
}),
({ theme }) => ({
@ -24,13 +24,21 @@ const ColorIcon = styled.span(
})
);
class ColorBlindness extends Component {
state = {
// tslint:disable-next-line:no-empty-interface
interface ColorBlindnessProps {}
interface ColorBlindnessState {
expanded: boolean;
filter: string | null;
}
class ColorBlindness extends Component<ColorBlindnessProps, ColorBlindnessState> {
state: ColorBlindnessState = {
expanded: false,
filter: null,
};
setFilter = (filter: any) => {
setFilter = (filter: string | null) => {
const iframe = getIframe();
if (iframe) {
@ -69,11 +77,13 @@ class ColorBlindness extends Component {
if (filter !== null) {
colorList = [
{
id: 'reset',
title: 'Reset color filter',
onClick: () => {
this.setFilter(null);
},
} as any,
right: undefined,
},
...colorList,
];
}
@ -83,7 +93,7 @@ class ColorBlindness extends Component {
placement="top"
trigger="click"
tooltipShown={expanded}
onVisibilityChange={(s: any) => this.setState({ expanded: s })}
onVisibilityChange={(s: boolean) => this.setState({ expanded: s })}
tooltip={<TooltipLinkList links={colorList} />}
closeOnClick
>

View File

@ -1,5 +1,4 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { styled } from '@storybook/theming';
@ -11,6 +10,7 @@ import EVENTS from '../constants';
import Tabs from './Tabs';
import Report from './Report';
import { AxeResults, Result } from 'axe-core';
const Icon = styled(Icons)(
{
@ -34,20 +34,26 @@ const Violations = styled.span(({ theme }) => ({
color: theme.color.negative,
}));
class A11YPanel extends Component<any, any> {
static propTypes = {
active: PropTypes.bool.isRequired,
api: PropTypes.shape({
on: PropTypes.func,
emit: PropTypes.func,
off: PropTypes.func,
}).isRequired,
};
interface A11YPanelState {
status: string;
passes: Result[];
violations: Result[];
}
state = {
interface A11YPanelProps {
active: boolean;
api: {
on(event: string, callback: (data: any) => void): void;
off(event: string, callback: (data: any) => void): void;
emit(event: string): void;
};
}
class A11YPanel extends Component<A11YPanelProps, A11YPanelState> {
state: A11YPanelState = {
status: 'ready',
passes: [] as any[],
violations: [] as any[],
passes: [],
violations: [],
};
componentDidMount() {
@ -57,7 +63,7 @@ class A11YPanel extends Component<any, any> {
api.on(EVENTS.RESULT, this.onUpdate);
}
componentDidUpdate(prevProps: any) {
componentDidUpdate(prevProps: A11YPanelProps) {
// TODO: might be able to remove this
const { active } = this.props;
@ -73,7 +79,7 @@ class A11YPanel extends Component<any, any> {
api.off(EVENTS.RESULT, this.onUpdate);
}
onUpdate = ({ passes, violations }: any) => {
onUpdate = ({ passes, violations }: AxeResults) => {
this.setState(
{
status: 'ran',

View File

@ -1,9 +1,9 @@
import React from 'react';
import PropTypes from 'prop-types';
import React, { FunctionComponent } from 'react';
import { styled } from '@storybook/theming';
import Rules from './Rules';
import { NodeResult } from 'axe-core';
const Item = styled.li({
fontWeight: 600,
@ -16,7 +16,12 @@ const ItemTitle = styled.span({
marginBottom: '4px',
});
function Element({ element, passes }: any) {
interface ElementProps {
element: NodeResult;
passes: boolean;
}
const Element: FunctionComponent<ElementProps> = ({ element, passes }) => {
const { any, all, none } = element;
const rules = [...any, ...all, ...none];
@ -27,34 +32,19 @@ function Element({ element, passes }: any) {
<Rules rules={rules} passes={passes} />
</Item>
);
}
Element.propTypes = {
element: PropTypes.shape({
any: PropTypes.array.isRequired,
all: PropTypes.array.isRequired,
none: PropTypes.array.isRequired,
}).isRequired,
passes: PropTypes.bool.isRequired,
};
/* eslint-disable react/no-array-index-key */
const Elements = ({ elements, passes }: any) => (
interface ElementsProps {
elements: NodeResult[];
passes: boolean;
}
const Elements: FunctionComponent<ElementsProps> = ({ elements, passes }) => (
<ol>
{elements.map((element: any, index: any) => (
{elements.map((element, index) => (
<Element passes={passes} element={element} key={index} />
))}
</ol>
);
Elements.propTypes = {
elements: PropTypes.arrayOf(
PropTypes.shape({
any: PropTypes.array.isRequired,
all: PropTypes.array.isRequired,
none: PropTypes.array.isRequired,
})
).isRequired,
passes: PropTypes.bool.isRequired,
};
export default Elements;

View File

@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import React, { FunctionComponent } from 'react';
import { styled } from '@storybook/theming';
import { Result } from 'axe-core';
const Wrapper = styled.div(({ theme }) => ({
backgroundColor: theme.background.bar,
@ -18,7 +18,11 @@ const Link = styled.a({
display: 'block',
});
function Info({ item }: any) {
interface InfoProps {
item: Result;
}
const Info: FunctionComponent<InfoProps> = ({ item }) => {
return (
<Wrapper>
<Help>{item.help}</Help>
@ -27,13 +31,6 @@ function Info({ item }: any) {
</Link>
</Wrapper>
);
}
Info.propTypes = {
item: PropTypes.shape({
help: PropTypes.node,
helpUrl: PropTypes.string,
}).isRequired,
};
export default Info;

View File

@ -1,5 +1,4 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { styled } from '@storybook/theming';
import { Icons } from '@storybook/components';
@ -7,6 +6,7 @@ import { Icons } from '@storybook/components';
import Info from './Info';
import Tags from './Tags';
import Elements from './Elements';
import { Result } from 'axe-core';
const Wrapper = styled.div();
@ -37,22 +37,22 @@ const HeaderBar = styled.button(({ theme }) => ({
},
}));
class Item extends Component<any, any> {
static propTypes = {
item: PropTypes.shape({
description: PropTypes.string,
nodes: PropTypes.array,
tags: PropTypes.array,
}).isRequired,
passes: PropTypes.bool.isRequired,
};
interface ItemProps {
item: Result;
passes: boolean;
}
interface ItemState {
open: boolean;
}
class Item extends Component<ItemProps, ItemState> {
state = {
open: false,
};
onToggle = () =>
this.setState((prevState: any) => ({
this.setState(prevState => ({
open: !prevState.open,
}));

View File

@ -1,8 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import React, { FunctionComponent } from 'react';
import { styled } from '@storybook/theming';
import { Icons } from '@storybook/components';
import { CheckResult } from 'axe-core';
const impactColors = {
minor: '#f1c40f',
@ -29,7 +29,7 @@ const Message = styled.div({
paddingLeft: '6px',
});
const Status = styled.div(({ passes, impact }: any) => ({
const Status = styled.div(({ passes, impact }: { passes: boolean; impact: string }) => ({
height: '16px',
width: '16px',
borderRadius: '8px',
@ -42,7 +42,12 @@ const Status = styled.div(({ passes, impact }: any) => ({
color: passes ? impactColors.success : (impactColors as any)[impact],
}));
const Rule = ({ rule, passes }: any) => (
interface RuleProps {
rule: CheckResult;
passes: boolean;
}
const Rule: FunctionComponent<RuleProps> = ({ rule, passes }) => (
<Item>
<Status passes={passes || undefined} impact={rule.impact}>
{passes ? <Icons icon="check" /> : <Icons icon="cross" />}
@ -51,30 +56,19 @@ const Rule = ({ rule, passes }: any) => (
</Item>
);
Rule.propTypes = {
rule: PropTypes.shape({
message: PropTypes.node,
}).isRequired,
passes: PropTypes.bool.isRequired,
};
interface RulesProps {
rules: CheckResult[];
passes: boolean;
}
/* eslint-disable react/no-array-index-key */
function Rules({ rules, passes }: any) {
const Rules: FunctionComponent<RulesProps> = ({ rules, passes }) => {
return (
<List>
{rules.map((rule: any, index: any) => (
{rules.map((rule, index) => (
<Rule passes={passes} rule={rule} key={index} />
))}
</List>
);
}
Rules.propTypes = {
rules: PropTypes.arrayOf(
PropTypes.shape({
message: PropTypes.node,
})
).isRequired,
passes: PropTypes.bool.isRequired,
};
export default Rules;

View File

@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import React, { FunctionComponent } from 'react';
import { styled } from '@storybook/theming';
import { TagValue } from 'axe-core';
const Wrapper = styled.div({
display: 'flex',
@ -16,17 +16,18 @@ const Item = styled.div(({ theme }) => ({
borderRadius: theme.appBorderRadius,
}));
function Tags({ tags }: any) {
interface TagsProps {
tags: TagValue[];
}
const Tags: FunctionComponent<TagsProps> = ({ tags }) => {
return (
<Wrapper>
{tags.map((tag: any) => (
{tags.map(tag => (
<Item key={tag}>{tag}</Item>
))}
</Wrapper>
);
}
Tags.propTypes = {
tags: PropTypes.arrayOf(PropTypes.node).isRequired,
};
export default Tags;

View File

@ -1,29 +1,23 @@
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import React, { Fragment, FunctionComponent } from 'react';
import { Placeholder } from '@storybook/components';
import Item from './Item';
import { Result } from 'axe-core';
const Report = ({ items, empty, passes }: any) => (
export interface ReportProps {
items: Result[];
empty: string;
passes: boolean;
}
const Report: FunctionComponent<ReportProps> = ({ items, empty, passes }) => (
<Fragment>
{items.length ? (
items.map((item: any) => <Item passes={passes} item={item} key={item.id} />)
items.map((item) => <Item passes={passes} item={item} key={item.id} />)
) : (
<Placeholder key="placeholder">{empty}</Placeholder>
)}
</Fragment>
);
Report.propTypes = {
items: PropTypes.arrayOf(
PropTypes.shape({
description: PropTypes.string,
nodes: PropTypes.array,
tags: PropTypes.array,
})
).isRequired,
empty: PropTypes.string.isRequired,
passes: PropTypes.bool.isRequired,
};
export default Report;

View File

@ -1,5 +1,4 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { styled } from '@storybook/theming';
// TODO: reuse the Tabs component from @storybook/theming instead
@ -46,25 +45,36 @@ const Item = styled.button(
: {}
);
class Tabs extends Component<any, any> {
state = {
interface TabsProps {
tabs: Array<{
label: JSX.Element;
panel: JSX.Element;
}>;
}
interface TabsState {
active: number;
}
class Tabs extends Component<TabsProps, TabsState> {
state: TabsState = {
active: 0,
};
onToggle = (index: any) => {
onToggle = (index: number) => {
this.setState({
active: index,
});
};
render() {
const { tabs } = this.props as any;
const { tabs } = this.props;
const { active } = this.state;
return (
<Container>
<List>
{tabs.map((tab: any, index: any) => (
{tabs.map((tab, index) => (
<Item
// eslint-disable-next-line react/no-array-index-key
key={index}
@ -81,13 +91,4 @@ class Tabs extends Component<any, any> {
}
}
(Tabs as any).propTypes = {
tabs: PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.node,
panel: PropTypes.node,
})
).isRequired,
};
export default Tabs;

View File

@ -1,15 +1,15 @@
import { document } from 'global';
import axe, { RunOptions, Spec } from 'axe-core';
import axe, { AxeResults, RunOptions, Spec } from 'axe-core';
import deprecate from 'util-deprecate';
import { stripIndents } from 'common-tags';
import addons, { StoryGetter, StoryWrapper } from '@storybook/addons';
import addons, { StoryWrapper } from '@storybook/addons';
import { STORY_RENDERED } from '@storybook/core-events';
import EVENTS, { PARAM_KEY } from './constants';
const channel = addons.getChannel();
let progress = Promise.resolve();
let setup: any = {};
let setup: { config: Spec; options: RunOptions } = { config: {}, options: {} };
const getElement = () => {
const storyRoot = document.getElementById('story-root');
@ -20,7 +20,7 @@ const getElement = () => {
return document.getElementById('root');
};
const report = (input: any) => {
const report = (input: AxeResults) => {
channel.emit(EVENTS.RESULT, input);
};

View File

@ -1,4 +1,4 @@
import React, { Fragment } from 'react';
import React, { Fragment, FunctionComponent } from 'react';
import addons, { types } from '@storybook/addons';
import { styled } from '@storybook/theming';
@ -11,7 +11,7 @@ const Hidden = styled.div(() => ({
display: 'none',
}));
const PreviewWrapper = (p: any) => (
const PreviewWrapper: FunctionComponent<{}> = p => (
<Fragment>
{p.children}
<Hidden>
@ -81,20 +81,21 @@ const PreviewWrapper = (p: any) => (
addons.register(ADDON_ID, api => {
addons.add(PANEL_ID, {
title: '',
type: types.TOOL,
match: ({ viewMode }: any) => viewMode === 'story',
match: ({ viewMode }) => viewMode === 'story',
render: () => <ColorBlindness />,
} as any);
});
addons.add(PANEL_ID, {
type: types.PANEL,
title: 'Accessibility',
// eslint-disable-next-line react/prop-types
type: types.PANEL,
render: ({ active, key }) => <Panel key={key} api={api} active={active} />,
});
addons.add(PANEL_ID, {
title: '',
type: types.PREVIEW,
render: PreviewWrapper,
} as any);
render: PreviewWrapper as any,
});
});