Skip to content

Commit

Permalink
Merge pull request #16042 from storybookjs/interactions-rewind
Browse files Browse the repository at this point in the history
feat: add rewind button to interactions subnav
  • Loading branch information
darleendenno authored Sep 15, 2021
2 parents 7546777 + 8b4b56d commit 1fb8e08
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 40 deletions.
1 change: 1 addition & 0 deletions addons/interactions/src/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ export const Panel: React.FC<PanelProps> = (props) => {
onPrevious={prev}
onNext={next}
onReplay={replay}
goToStart={start}
goToEnd={stop}
hasPrevious={hasPrevious}
hasNext={hasNext}
Expand Down
31 changes: 28 additions & 3 deletions addons/interactions/src/Tool.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,38 @@
import React from 'react';
import React, { useState } from 'react';
import { useChannel } from '@storybook/api';
import { Icons, IconButton } from '@storybook/components';
import { styled } from '@storybook/theming';
import { ButtonProps } from '@storybook/components/dist/ts3.9/Button/Button';
import { EVENTS, TOOL_ID } from './constants';

interface AnimatedButtonProps extends ButtonProps {
animating?: boolean;
}
const StyledAnimatedIconButton = styled(IconButton)<AnimatedButtonProps>(
({ theme, animating }) => ({
svg: {
animation: animating && `${theme.animation.rotate360} 1000ms ease-out`,
},
})
);

export const Tool = () => {
const emit = useChannel({});
const [isAnimating, setIsAnimating] = useState(false);
const animateAndReplay = () => {
setIsAnimating(true);
emit(EVENTS.RELOAD);
};

return (
<IconButton key={TOOL_ID} title="Rerun story" onClick={() => emit(EVENTS.RELOAD)}>
<StyledAnimatedIconButton
key={TOOL_ID}
title="Rerun interactions"
onClick={animateAndReplay}
onAnimationEnd={() => setIsAnimating(false)}
animating={isAnimating}
>
<Icons icon="sync" />
</IconButton>
</StyledAnimatedIconButton>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default {
onPrevious: () => {},
onNext: () => {},
onReplay: () => {},
goToStart: () => {},
goToEnd: () => {},
storyFileName: 'Subnav.stories.tsx',
hasNext: true,
Expand Down
58 changes: 21 additions & 37 deletions addons/interactions/src/components/Subnav/Subnav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React, { useState } from 'react';
import { Button, Icons, Separator, P } from '@storybook/components';
import { styled } from '@storybook/theming';
import { transparentize } from 'polished';
import { ButtonProps } from '@storybook/components/dist/ts3.9/Button/Button';
import { CallState, CallStates } from '../../types';
import { StatusBadge } from '../StatusBadge/StatusBadge';

Expand All @@ -24,6 +23,7 @@ export interface SubnavProps {
onPrevious: () => void;
onNext: () => void;
onReplay: () => void;
goToStart: () => void;
goToEnd: () => void;
storyFileName?: string;
hasPrevious: boolean;
Expand All @@ -34,30 +34,23 @@ const StyledButton = styled(Button)(({ theme }) => ({
borderRadius: 4,
padding: 6,
color: theme.color.dark,
'&:hover,&:focus-visible': {
color: theme.color.secondary,
'&:not(:disabled)': {
'&:hover,&:focus-visible': {
color: theme.color.secondary,
},
},
}));

const StyledIconButton = styled(StyledButton)(({ theme }) => ({
export const StyledIconButton = styled(StyledButton)(({ theme }) => ({
color: theme.color.mediumdark,
margin: '0 3px',
'&:hover,&:focus-visible': {
background: transparentize(0.9, theme.color.secondary),
'&:not(:disabled)': {
'&:hover,&:focus-visible': {
background: transparentize(0.9, theme.color.secondary),
},
},
}));

interface AnimatedButtonProps extends ButtonProps {
animating?: boolean;
}
const StyledAnimatedIconButton = styled(StyledIconButton)<AnimatedButtonProps>(
({ theme, animating }) => ({
svg: {
animation: animating && `${theme.animation.rotate360} 1000ms ease-out`,
},
})
);

const StyledSeparator = styled(Separator)({
marginTop: 0,
});
Expand All @@ -75,7 +68,7 @@ const Group = styled.div({
alignItems: 'center',
});

const PlaybackButton = styled(StyledIconButton)({
const RewindButton = styled(StyledIconButton)({
marginLeft: 9,
});

Expand All @@ -88,18 +81,13 @@ export const Subnav: React.FC<SubnavProps> = ({
status,
onPrevious,
onNext,
onReplay,
goToStart,
goToEnd,
storyFileName,
hasNext,
hasPrevious,
}) => {
const buttonText = status === CallStates.ERROR ? 'Jump to error' : 'Jump to end';
const [isAnimating, setIsAnimating] = useState(false);
const animateAndReplay = () => {
setIsAnimating(true);
onReplay();
};
const buttonText = status === CallStates.ERROR ? 'Scroll to error' : 'Scroll to end';

return (
<StyledSubnav>
Expand All @@ -112,27 +100,23 @@ export const Subnav: React.FC<SubnavProps> = ({

<StyledSeparator />

<PlaybackButton
<RewindButton containsIcon title="Rewind" onClick={goToStart} disabled={!hasPrevious}>
<Icons icon="rewind" />
</RewindButton>
<StyledIconButton
containsIcon
title="Previous step"
onClick={onPrevious}
disabled={!hasPrevious}
>
<Icons icon="playback" />
</PlaybackButton>
</StyledIconButton>
<StyledIconButton containsIcon title="Next step" onClick={onNext} disabled={!hasNext}>
<Icons icon="playnext" />
</StyledIconButton>
<StyledAnimatedIconButton
containsIcon
title="Replay interactions"
onClick={animateAndReplay}
onAnimationEnd={() => setIsAnimating(false)}
animating={isAnimating}
data-test-id="button--replay"
>
<Icons icon="sync" />
</StyledAnimatedIconButton>
<StyledIconButton containsIcon title="Last step" onClick={goToEnd} disabled={!hasNext}>
<Icons icon="fastforward" />
</StyledIconButton>
</Group>
{storyFileName && (
<Group>
Expand Down
4 changes: 4 additions & 0 deletions lib/components/src/icon/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ export const icons = {
'M1024 512A512 512 0 100 512a512 512 0 001024 0zM215 809a418 418 0 010-594 418 418 0 01594 0 418 418 0 010 594 418 418 0 01-594 0zm471-78H338c-25 0-45-20-45-45V338c0-25 20-45 45-45h348c25 0 45 20 45 45v348c0 25-20 45-45 45z',
stopalt:
'M894 85H130c-25 0-45 20-45 45v764c0 25 20 45 45 45h764c25 0 45-20 45-45V130c0-25-20-45-45-45z',
rewind:
'm631.8 642.6 345 245.4c7.7 5.4 15 8 21.4 8 15.9 0 26.8-15.5 26.8-42.3V170.3c0-26.8-11-42.3-26.8-42.3-6.4 0-13.7 2.6-21.4 8l-345 245.4v-211c0-26.9-10.9-42.4-26.8-42.4-6.4 0-13.7 2.6-21.4 8L129 459.4V192a64 64 0 0 0-128 0v640a64 64 0 0 0 128 0V564.6L583.6 888c7.7 5.4 15 8 21.4 8 15.9 0 26.8-15.5 26.8-42.3v-211Z',
fastforward:
'M398.2 386.4 53.2 141c-7.7-5.4-15-8-21.4-8C15.9 133 5 148.5 5 175.3v683.4C5 885.5 16 901 31.8 901c6.4 0 13.7-2.6 21.4-8l345-245.4v211c0 26.9 11 42.4 26.8 42.4 6.4 0 13.7-2.6 21.4-8L901 569.6V837a64 64 0 0 0 128 0V197a64 64 0 0 0-128 0v267.4L446.4 141c-7.7-5.4-15-8-21.4-8-15.9 0-26.8 15.5-26.8 42.3v211Z',
email:
'M960.032 268.004c0.748-10.040-2.246-20.364-9.226-28.684-5.984-7.132-13.938-11.62-22.394-13.394-0.13-0.026-0.268-0.066-0.396-0.092-1.082-0.22-2.172-0.376-3.272-0.5-0.25-0.032-0.492-0.080-0.742-0.102-1.028-0.096-2.052-0.136-3.090-0.156-0.292-0.002-0.582-0.042-0.876-0.042h-816.008c-21.416 0-38.848 16.844-39.898 38-0.034 0.628-0.092 1.256-0.096 1.89 0 0.034-0.006 0.074-0.006 0.114 0 0.050 0.008 0.102 0.008 0.152v495.692c0 0.054-0.008 0.106-0.008 0.156 0 22.090 17.91 40 40 40h816.004c13.808 0 25.98-6.996 33.17-17.636 0.1-0.148 0.182-0.312 0.28-0.458 0.606-0.93 1.196-1.868 1.722-2.84 0.046-0.082 0.080-0.172 0.124-0.258 2.992-5.604 4.704-12.008 4.704-18.804v0 0-493.038zM144.032 350.156l339.946 281.188c6.568 6.434 14.918 10.168 23.564 11.122 0.16 0.024 0.32 0.050 0.48 0.066 0.838 0.082 1.676 0.114 2.518 0.14 0.496 0.020 0.994 0.058 1.492 0.058s0.996-0.042 1.492-0.058c0.842-0.028 1.68-0.058 2.518-0.14 0.16-0.016 0.32-0.042 0.48-0.066 8.646-0.958 16.996-4.688 23.564-11.122l339.946-281.206v370.894h-736v-370.876zM215.066 305.030h593.91l-296.946 245.422-296.964-245.422z',

Expand Down

0 comments on commit 1fb8e08

Please sign in to comment.