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

UI: Add bottom navigation on mobile #24228

Merged
merged 31 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e917749
Bring back mobile drawers
cdedreuille Sep 18, 2023
6302b90
Add menu icon
cdedreuille Sep 18, 2023
246fbe4
Merge branch 'charles-sb-mobile' into charles-mobile-menu-drawers
cdedreuille Sep 18, 2023
3fbb783
Improve icons in mobile navigation
cdedreuille Sep 18, 2023
216c208
Merge branch 'charles-sb-mobile' into charles-mobile-menu-drawers
cdedreuille Sep 18, 2023
ca9c691
Merge branch 'charles-mobile-1' into charles-mobile-2
cdedreuille Sep 19, 2023
294b1b5
Merge branch 'new-layout' into charles-mobile-2
cdedreuille Sep 19, 2023
b8f57dc
Merge branch 'new-layout' into charles-mobile-2
cdedreuille Sep 19, 2023
5e9e94c
Add the About for mobile
cdedreuille Sep 19, 2023
471dd5c
About is now working
cdedreuille Sep 20, 2023
86fd48c
Replace mobile components
cdedreuille Sep 20, 2023
cab08c5
Fix dark mode on mobile
cdedreuille Sep 20, 2023
3f5c5fb
Improved upgradeBlock
cdedreuille Sep 20, 2023
07f423c
Update About page to take the new upgrade block
cdedreuille Sep 20, 2023
faa5fb1
Update MobileAbout.tsx
cdedreuille Sep 20, 2023
56feda8
Fix issue when clicking on search
cdedreuille Sep 20, 2023
7a105d2
Fix CI errors
cdedreuille Sep 20, 2023
5218bab
Update Panel.tsx
cdedreuille Sep 20, 2023
d41bc20
Move sidebar and panel outside of each components
cdedreuille Sep 20, 2023
82a98d8
use context for layout states
JReinhold Sep 20, 2023
65127d9
improve closing about page
JReinhold Sep 20, 2023
568215d
add mobile stories
JReinhold Sep 20, 2023
d599393
cleanup
JReinhold Sep 20, 2023
1eec03b
disable mobile panel button in docs mode
JReinhold Sep 20, 2023
efa3aed
improve mobile stories
JReinhold Sep 20, 2023
1fd83dd
viewport in mobile about
JReinhold Sep 20, 2023
da1fbd5
fix types
JReinhold Sep 20, 2023
c950a98
fix drag handles when existing mobile
JReinhold Sep 20, 2023
ff336a1
fix about stories
JReinhold Sep 20, 2023
7bb3e8b
Merge branch 'new-layout' of github.com:storybookjs/storybook into ch…
JReinhold Sep 20, 2023
3ab7738
remove fullscreen button in mobile view
JReinhold Sep 20, 2023
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
2 changes: 1 addition & 1 deletion code/builders/builder-manager/templates/template.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="utf-8" />

<title><%= typeof title !== 'undefined'? title : 'Storybook'%></title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />

<% if (favicon.endsWith('.svg')) {%>
<link rel="icon" type="image/svg+xml" href="./<%= favicon %>" />
Expand Down
2 changes: 2 additions & 0 deletions code/ui/manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"@storybook/theming": "workspace:*",
"@storybook/types": "workspace:*",
"@testing-library/react": "^11.2.2",
"@types/react-transition-group": "^4",
"@types/semver": "^7.3.4",
"browser-dtector": "^3.4.0",
"copy-to-clipboard": "^3.3.1",
Expand All @@ -80,6 +81,7 @@
"react-draggable": "^4.4.3",
"react-helmet-async": "^1.0.7",
"react-resize-detector": "^7.1.2",
"react-transition-group": "^4.4.5",
"resolve-from": "^5.0.0",
"semver": "^7.3.7",
"store2": "^2.14.2",
Expand Down
5 changes: 5 additions & 0 deletions code/ui/manager/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Route } from '@storybook/router';
import { Global, createGlobal } from '@storybook/theming';
import { Symbols } from '@storybook/components';
import type { Addon_PageType } from '@storybook/types';
import { useStorybookApi } from '@storybook/manager-api';
import Sidebar from './container/Sidebar';
import Preview from './container/Preview';
import Panel from './container/Panel';
Expand All @@ -19,6 +20,9 @@ type Props = {
};

export const App = ({ managerLayoutState, setManagerLayoutState, pages }: Props) => {
const api = useStorybookApi();
const storyTitle = api.getCurrentStoryData()?.title;

return (
<>
<Global styles={createGlobal} />
Expand All @@ -36,6 +40,7 @@ export const App = ({ managerLayoutState, setManagerLayoutState, pages }: Props)
slotPages={pages.map(({ id, render: Content }) => (
<Content key={id} />
))}
storyTitle={storyTitle}
/>
</>
);
Expand Down
12 changes: 9 additions & 3 deletions code/ui/manager/src/components/layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { styled } from '@storybook/theming';
import type { API_Layout, API_ViewMode } from '@storybook/types';
import { useDragging } from './useDragging';
import { useMediaQuery } from '../hooks/useMedia';
import { MobileNavigation } from '../mobile-navigation/MobileNavigation';
import { MobileNavigation } from '../mobile/navigation/MobileNavigation';
import { BREAKPOINT_MIN_600 } from '../../constants';

interface InternalLayoutState {
Expand All @@ -24,6 +24,7 @@ interface Props {
slotSidebar?: React.ReactNode;
slotPanel?: React.ReactNode;
slotPages?: React.ReactNode;
storyTitle?: string | null | undefined;
}
const MINIMUM_CONTENT_WIDTH_PX = 100;

Expand Down Expand Up @@ -112,7 +113,12 @@ const useLayoutSyncingState = (
};
};

export const Layout = ({ managerLayoutState, setManagerLayoutState, ...slots }: Props) => {
export const Layout = ({
managerLayoutState,
setManagerLayoutState,
storyTitle,
...slots
}: Props) => {
const isDesktop = useMediaQuery(BREAKPOINT_MIN_600);
const isMobile = !isDesktop;

Expand Down Expand Up @@ -157,7 +163,7 @@ export const Layout = ({ managerLayoutState, setManagerLayoutState, ...slots }:
)}
</>
)}
{isMobile && <MobileNavigation />}
{isMobile && <MobileNavigation storyTitle={storyTitle} />}
</LayoutContainer>
);
};
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { Meta, StoryObj } from '@storybook/react';
import { ManagerContext } from '@storybook/manager-api';
import React from 'react';
import { MobileAbout } from './MobileAbout';

const meta = {
component: MobileAbout,
title: 'MobileAbout',
decorators: [
(storyFn) => (
<ManagerContext.Provider
value={
{
api: {
getCurrentVersion: () => ({
version: '7.2.2-alpha.0',
}),
},
} as any
}
>
{storyFn()}
</ManagerContext.Provider>
),
],
} satisfies Meta<typeof MobileAbout>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
isAboutOpen: true,
},
};
JReinhold marked this conversation as resolved.
Show resolved Hide resolved
140 changes: 140 additions & 0 deletions code/ui/manager/src/components/mobile/about/MobileAbout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import type { FC } from 'react';
import React, { useRef } from 'react';
import { Transition, type TransitionStatus } from 'react-transition-group';
import { styled } from '@storybook/theming';
import { Icons, Link } from '@storybook/components';
import { UpgradeBlock } from '../../upgrade/UpgradeBlock';
import { MOBILE_TRANSITION_DURATION } from '../../../constants';

interface MobileAboutProps {
isAboutOpen: boolean;
setAboutOpen: (open: boolean) => void;
}

export const MobileAbout: FC<MobileAboutProps> = ({ isAboutOpen, setAboutOpen }) => {
const aboutRef = useRef(null);

return (
<Transition
nodeRef={aboutRef}
in={isAboutOpen}
timeout={MOBILE_TRANSITION_DURATION}
appear
mountOnEnter
unmountOnExit
>
{(state) => (
<Container ref={aboutRef} state={state} transitionDuration={MOBILE_TRANSITION_DURATION}>
<Button onClick={() => setAboutOpen(false)}>
<Icons icon="arrowleftalt" />
Back
</Button>
<LinkContainer>
<LinkLine href="https://github.com/storybookjs/storybook" target="_blank">
<LinkLeft>
<Icons icon="github" />
<span>Github</span>
</LinkLeft>
<Icons icon="sharealt" width={12} />
</LinkLine>
<LinkLine
href="https://storybook.js.org/docs/react/get-started/install/"
target="_blank"
>
<LinkLeft>
<Icons icon="storybook" />
<span>Documentation</span>
</LinkLeft>
<Icons icon="sharealt" width={12} />
</LinkLine>
</LinkContainer>
<UpgradeBlock />
<BottomText>
Open source software maintained by{' '}
<Link href="https://chromatic.com" target="_blank">
Chromatic
</Link>{' '}
and the{' '}
<Link href="https://github.com/storybookjs/storybook/graphs/contributors">
Storybook Community
</Link>
</BottomText>
</Container>
)}
</Transition>
);
};

const Container = styled.div<{ state: TransitionStatus; transitionDuration: number }>(
({ theme, state, transitionDuration }) => ({
position: 'absolute',
width: '100%',
height: '100%',
top: 0,
left: 0,
zIndex: 11,
JReinhold marked this conversation as resolved.
Show resolved Hide resolved
transition: `all ${transitionDuration}ms ease-in-out`,
overflow: 'scroll',
padding: '20px',
color: theme.color.defaultText,
background: theme.background.content,
opacity: `${(() => {
if (state === 'entering') return 1;
if (state === 'entered') return 1;
if (state === 'exiting') return 0;
if (state === 'exited') return 0;
return 0;
})()}`,
transform: `${(() => {
if (state === 'entering') return 'translateX(0)';
if (state === 'entered') return 'translateX(0)';
if (state === 'exiting') return 'translateX(20px)';
if (state === 'exited') return 'translateX(20px)';
return 'translateX(0)';
})()}`,
})
);

const LinkContainer = styled.div({
marginTop: 20,
marginBottom: 20,
});

const LinkLine = styled.a(({ theme }) => ({
all: 'unset',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
fontSize: theme.typography.size.s2 - 1,
height: 52,
borderBottom: `1px solid ${theme.appBorderColor}`,
cursor: 'pointer',
padding: '0 10px',

'&:last-child': {
borderBottom: 'none',
},
}));

const LinkLeft = styled.div(({ theme }) => ({
display: 'flex',
alignItems: 'center',
fontSize: theme.typography.size.s2 - 1,
height: 40,
gap: 5,
}));

const BottomText = styled.div(({ theme }) => ({
fontSize: theme.typography.size.s2 - 1,
marginTop: 30,
}));

const Button = styled.button(({ theme }) => ({
all: 'unset',
display: 'flex',
alignItems: 'center',
gap: 10,
color: 'currentColor',
fontSize: theme.typography.size.s2 - 1,
padding: '0 10px',
}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { FC, ReactNode } from 'react';
import React, { useRef } from 'react';
import { styled } from '@storybook/theming';
import { Transition } from 'react-transition-group';
import type { TransitionStatus } from 'react-transition-group/Transition';

interface MobileAddonsDrawerProps {
children: ReactNode;
isAddonsOpen: boolean;
}

const duration = 200;

const Container = styled.div<{ state: TransitionStatus }>(({ theme, state }) => ({
position: 'fixed',
boxSizing: 'border-box',
width: '100%',
background: theme.background.content,
height: '50%',
bottom: 0,
left: 0,
zIndex: 11,
transition: `all ${duration}ms ease-in-out`,
overflow: 'hidden',
borderTop: `1px solid ${theme.appBorderColor}`,
transform: `${(() => {
if (state === 'entering') return 'translateY(0)';
if (state === 'entered') return 'translateY(0)';
if (state === 'exiting') return 'translateY(100%)';
if (state === 'exited') return 'translateY(100%)';
return 'translateY(0)';
})()}`,
}));

export const MobileAddonsDrawer: FC<MobileAddonsDrawerProps> = ({ children, isAddonsOpen }) => {
const containerRef = useRef(null);

return (
<Transition
nodeRef={containerRef}
in={isAddonsOpen}
timeout={duration}
mountOnEnter
unmountOnExit
>
{(state) => (
<Container ref={containerRef} state={state}>
{children}
</Container>
)}
</Transition>
);
};
Loading