diff --git a/lib/ui/src/components/preview/FramesRenderer.tsx b/lib/ui/src/components/preview/FramesRenderer.tsx index f441a74bd8c3..701dae709928 100644 --- a/lib/ui/src/components/preview/FramesRenderer.tsx +++ b/lib/ui/src/components/preview/FramesRenderer.tsx @@ -1,5 +1,7 @@ import React, { Fragment, FunctionComponent, useMemo, useEffect, useState } from 'react'; -import { Global, CSSObject } from '@storybook/theming'; +import { Consumer, Combo } from '@storybook/api'; +import { Button } from '@storybook/components'; +import { Global, CSSObject, styled } from '@storybook/theming'; import { IFrame } from './iframe'; import { FramesRendererProps } from './utils/types'; import { stringifyQueryParams } from './utils/stringifyQueryParams'; @@ -12,6 +14,29 @@ const getActive = (refId: FramesRendererProps['refId']) => { return 'storybook-preview-iframe'; }; +const SkipToSidebarLink = styled(Button)(({ theme }) => ({ + display: 'none', + '@media (min-width: 600px)': { + display: 'block', + position: 'absolute', + top: 10, + right: 15, + padding: '10px 15px', + fontSize: theme.typography.size.s1, + transform: 'translateY(-100px)', + '&:focus': { + transform: 'translateY(0)', + zIndex: 1, + }, + }, +})); + +const whenSidebarIsVisible = ({ state }: Combo) => ({ + isFullscreen: state.layout.isFullscreen, + showNav: state.layout.showNav, + selectedStoryId: state.storyId, +}); + export const FramesRenderer: FunctionComponent = ({ refs, story, @@ -72,6 +97,18 @@ export const FramesRenderer: FunctionComponent = ({ return ( + + {({ isFullscreen, showNav, selectedStoryId }) => { + if (!isFullscreen && !!showNav && selectedStoryId) { + return ( + + Skip to sidebar + + ); + } + return null; + }} + {Object.entries(frames).map(([id, src]) => (