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

Use TS strict mode in a11y addon sources #9180

Merged
merged 12 commits into from
Jan 11, 2020
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
10 changes: 6 additions & 4 deletions addons/a11y/src/components/A11YPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Component, Fragment } from 'react';
import React, { Component, Fragment, ComponentProps } from 'react';

import { styled } from '@storybook/theming';

Expand All @@ -20,13 +20,15 @@ export enum RuleType {
INCOMPLETION,
}

const Icon = styled(Icons)(
type IconProps = ComponentProps<typeof Icons> & { status?: string; inline?: boolean };

const Icon = styled(Icons)<IconProps>(
{
height: 12,
width: 12,
marginRight: 4,
},
({ status, theme }: any) =>
({ status, theme }) =>
status === 'running'
? {
animation: `${theme.animation.rotate360} 1s linear infinite;`,
Expand Down Expand Up @@ -177,7 +179,7 @@ export class A11YPanel extends Component<A11YPanelProps, A11YPanelState> {

const { passes, violations, incomplete, status } = this.state;

let actionTitle;
let actionTitle: string | JSX.Element = 'Rerun tests';
if (status === 'ready') {
actionTitle = 'Rerun tests';
} else if (status === 'running') {
Expand Down
6 changes: 3 additions & 3 deletions addons/a11y/src/components/ColorBlindness.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ const getFilter = (filter: string | null) => {
return `url('#${filter}')`;
};

const ColorIcon = styled.span(
const ColorIcon = styled.span<{ filter: string | null }>(
{
background: 'linear-gradient(to right, #F44336, #FF9800, #FFEB3B, #8BC34A, #2196F3, #9C27B0)',
borderRadius: '1rem',
display: 'block',
height: '1rem',
width: '1rem',
},
({ filter }: { filter: string | null }) => ({
({ filter }) => ({
filter: getFilter(filter),
}),
({ theme }) => ({
Expand Down Expand Up @@ -80,7 +80,7 @@ const getColorList = (active: string | null, set: (i: string | null) => void): L
];

export const ColorBlindness: FunctionComponent = () => {
const [active, setActiveState] = useState(null);
const [active, setActiveState] = useState<string | null>(null);

const setActive = (activeState: string | null): void => {
const iframe = getIframe();
Expand Down
29 changes: 14 additions & 15 deletions addons/a11y/src/components/Report/HighlightToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@ import { styled, themes, convert } from '@storybook/theming';
import memoize from 'memoizerific';

import { NodeResult } from 'axe-core';
import { Dispatch } from 'redux';
import { RuleType } from '../A11YPanel';
import { addElement } from '../../redux-config';
import { IFRAME } from '../../constants';

export class HighlightedElementData {
export interface HighlightedElementData {
originalOutline: string;

isHighlighted: boolean;
}

interface ToggleProps {
elementsToHighlight: NodeResult[];
type: RuleType;
addElement?: (data: any) => void;
highlightedElementsMap?: Map<HTMLElement, HighlightedElementData>;
addElement: (data: any) => void;
highlightedElementsMap: Map<HTMLElement, HighlightedElementData>;
isToggledOn?: boolean;
toggleId?: string;
indeterminate?: boolean;
indeterminate: boolean;
}

enum CheckBoxStates {
Expand All @@ -48,7 +48,7 @@ function getElementBySelectorPath(elementPath: string): HTMLElement {
if (iframe && iframe.contentDocument && elementPath) {
return iframe.contentDocument.querySelector(elementPath);
}
return null;
return (null as unknown) as HTMLElement;
}

function setElementOutlineStyle(targetElement: HTMLElement, outlineStyle: string): void {
Expand All @@ -64,7 +64,7 @@ function areAllRequiredElementsHighlighted(
const targetElement = getElementBySelectorPath(item.target[0]);
return (
highlightedElementsMap.has(targetElement) &&
highlightedElementsMap.get(targetElement).isHighlighted
(highlightedElementsMap.get(targetElement) as HighlightedElementData).isHighlighted
);
}).length;

Expand All @@ -76,7 +76,7 @@ function areAllRequiredElementsHighlighted(
: CheckBoxStates.INDETERMINATE;
}

function mapDispatchToProps(dispatch: any) {
function mapDispatchToProps(dispatch: Dispatch) {
return {
addElement: (data: { element: HTMLElement; data: HighlightedElementData }) =>
dispatch(addElement(data)),
Expand Down Expand Up @@ -112,7 +112,7 @@ class HighlightToggle extends Component<ToggleProps> {
});
}

componentDidUpdate(prevProps: Readonly<ToggleProps>): void {
componentDidUpdate(): void {
const { indeterminate } = this.props;
if (this.checkBoxRef.current) {
this.checkBoxRef.current.indeterminate = indeterminate;
Expand All @@ -126,8 +126,9 @@ class HighlightToggle extends Component<ToggleProps> {
if (!highlightedElementsMap.has(targetElement)) {
return;
}
const { originalOutline } = highlightedElementsMap.get(targetElement);
const { isHighlighted } = highlightedElementsMap.get(targetElement);
const { originalOutline, isHighlighted } = highlightedElementsMap.get(
targetElement
) as HighlightedElementData;
const { isToggledOn } = this.props;
if ((isToggledOn && isHighlighted) || (!isToggledOn && !isHighlighted)) {
const addHighlight = !isToggledOn && !isHighlighted;
Expand All @@ -151,7 +152,7 @@ class HighlightToggle extends Component<ToggleProps> {
if (highlightedElementsMap.has(targetElement)) {
setElementOutlineStyle(
targetElement,
highlightedElementsMap.get(targetElement).originalOutline
highlightedElementsMap.get(targetElement)!.originalOutline
);
}
}
Expand All @@ -162,9 +163,7 @@ class HighlightToggle extends Component<ToggleProps> {
originalOutline: string
): void {
const { addElement: localAddElement } = this.props;
const data: HighlightedElementData = new HighlightedElementData();
data.isHighlighted = isHighlighted;
data.originalOutline = originalOutline;
const data: HighlightedElementData = { isHighlighted, originalOutline };
const payload = { element: targetElement, highlightedElementData: data };
localAddElement(payload);
}
Expand Down
30 changes: 5 additions & 25 deletions addons/a11y/src/components/Report/Rules.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
import React, { FunctionComponent } from 'react';
import { styled } from '@storybook/theming';
import { Badge, Icons } from '@storybook/components';
import { Badge } from '@storybook/components';
import { CheckResult } from 'axe-core';
import { SizeMe } from 'react-sizeme';
import { RuleType } from '../A11YPanel';

const impactColors = {
minor: '#f1c40f',
moderate: '#e67e22',
serious: '#e74c3c',
critical: '#c0392b',
success: '#2ecc71',
};

const List = styled.div({
display: 'flex',
Expand All @@ -22,7 +13,7 @@ const List = styled.div({
fontWeight: '400',
} as any);

const Item = styled.div(({ elementWidth }: { elementWidth: number }) => {
const Item = styled.div<{ elementWidth: number }>(({ elementWidth }) => {
const maxWidthBeforeBreak = 407;
return {
flexDirection: elementWidth > maxWidthBeforeBreak ? 'row' : 'inherit',
Expand All @@ -31,31 +22,20 @@ const Item = styled.div(({ elementWidth }: { elementWidth: number }) => {
};
});

const StyledBadge = styled(Badge)(({ status }: { status: string }) => ({
const StyledBadge = styled(Badge)({
padding: '2px 8px',
marginBottom: 3,
minWidth: 65,
maxWidth: 'fit-content',
width: '100%',
textAlign: 'center',
}));
});

const Message = styled.div({
paddingLeft: 6,
paddingRight: 23,
});

const Status = styled.div(({ passes, impact }: { passes: boolean; impact: string }) => ({
display: 'inline-flex',
justifyContent: 'center',
alignItems: 'center',
color: passes ? impactColors.success : (impactColors as any)[impact],
'& > svg': {
height: 16,
width: 16,
},
}));

export enum ImpactValue {
MINOR = 'minor',
MODERATE = 'moderate',
Expand Down Expand Up @@ -94,7 +74,7 @@ const Rule: FunctionComponent<RuleProps> = ({ rule }) => {
}
return (
<SizeMe refreshMode="debounce">
{({ size }: { size: any }) => (
{({ size }: { size: { width: number; height: number } }) => (
<Item elementWidth={size.width}>
<StyledBadge status={badgeType}>{formatSeverityText(rule.impact)}</StyledBadge>
<Message>{rule.message}</Message>
Expand Down
12 changes: 6 additions & 6 deletions addons/a11y/src/components/Tabs.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Component, SyntheticEvent } from 'react';

import { styled, themes } from '@storybook/theming';
import { styled } from '@storybook/theming';
import { NodeResult, Result } from 'axe-core';
import { SizeMe } from 'react-sizeme';
import store, { clearElements } from '../redux-config';
Expand All @@ -23,7 +23,7 @@ const HighlightToggleLabel = styled.label<{}>(({ theme }) => ({
color: theme.color.dark,
}));

const GlobalToggle = styled.div(({ elementWidth }: { elementWidth: number }) => {
const GlobalToggle = styled.div<{ elementWidth: number }>(({ elementWidth }) => {
const maxWidthBeforeBreak = 450;
return {
cursor: 'pointer',
Expand All @@ -47,7 +47,7 @@ const GlobalToggle = styled.div(({ elementWidth }: { elementWidth: number }) =>
};
});

const Item = styled.button(
const Item = styled.button<{ active?: boolean }>(
({ theme }) => ({
textDecoration: 'none',
padding: '10px 15px',
Expand All @@ -66,7 +66,7 @@ const Item = styled.button(
borderBottom: `3px solid ${theme.color.secondary}`,
},
}),
({ active, theme }: any) =>
({ active, theme }) =>
active
? {
opacity: 1,
Expand Down Expand Up @@ -99,7 +99,7 @@ interface TabsState {
}

function retrieveAllNodesFromResults(items: Result[]): NodeResult[] {
return items.reduce((acc, item) => acc.concat(item.nodes), []);
return items.reduce((acc, item) => acc.concat(item.nodes), [] as NodeResult[]);
}

export class Tabs extends Component<TabsProps, TabsState> {
Expand All @@ -109,7 +109,7 @@ export class Tabs extends Component<TabsProps, TabsState> {

onToggle = (event: SyntheticEvent) => {
this.setState({
active: parseInt(event.currentTarget.getAttribute('data-index'), 10),
active: parseInt(event.currentTarget.getAttribute('data-index') || '', 10),
});
// removes all elements from the redux map in store from the previous panel
store.dispatch(clearElements());
Expand Down
6 changes: 4 additions & 2 deletions addons/a11y/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface Setup {
config: Spec;
options: RunOptions;
}
let setup: Setup = { element: null, config: {}, options: {} };
let setup: Setup = { element: undefined, config: {}, options: {} };

const getElement = () => {
const storyRoot = document.getElementById('story-root');
Expand Down Expand Up @@ -63,7 +63,9 @@ export const withA11y = makeDecorator({
Object.assign(setup, storedDefaultSetup);
storedDefaultSetup = null;
}
addons.getChannel().on(EVENTS.REQUEST, () => run(setup.element, setup.config, setup.options));
addons
.getChannel()
.on(EVENTS.REQUEST, () => run(setup.element as ElementContext, setup.config, setup.options));

return getStory(context);
},
Expand Down
8 changes: 7 additions & 1 deletion addons/a11y/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"types": ["webpack-env"]
"types": ["webpack-env"],
"forceConsistentCasingInFileNames": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"include": [
"src/**/*"
Expand Down