Skip to content

Commit

Permalink
Merge pull request #23357 from storybookjs/kasper/about-page
Browse files Browse the repository at this point in the history
Settings: New about page design
  • Loading branch information
kasperpeulen authored Jul 10, 2023
2 parents d827944 + d04b161 commit a13ac8a
Show file tree
Hide file tree
Showing 11 changed files with 273 additions and 130 deletions.
1 change: 1 addition & 0 deletions code/ui/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const config: StorybookConfig = {
'@storybook/addon-essentials',
'@storybook/addon-interactions',
'@storybook/addon-storysource',
'@storybook/addon-designs',
],
framework: {
name: '@storybook/react-vite',
Expand Down
27 changes: 27 additions & 0 deletions code/ui/components/src/clipboard/ClipboardCode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import { color, styled, typography } from '@storybook/theming';

const Code = styled.pre`
line-height: 18px;
padding: 11px 1rem;
white-space: pre-wrap;
background: rgba(0, 0, 0, 0.05);
color: ${color.darkest};
border-radius: 3px;
margin: 1rem 0;
width: 100%;
display: block;
overflow: hidden;
font-family: ${typography.fonts.mono};
font-size: ${typography.size.s2 - 1}px;
`;

interface ClipboardCodeProps {
code: string;
}

export const ClipboardCode = ({ code, ...props }: ClipboardCodeProps) => (
<Code id="clipboard-code" {...props}>
{code}
</Code>
);
3 changes: 2 additions & 1 deletion code/ui/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export { Span } from './typography/elements/Span';
export { Table } from './typography/elements/Table';
export { TT } from './typography/elements/TT';
export { UL } from './typography/elements/UL';

export { Badge } from './Badge/Badge';

// Typography
Expand Down Expand Up @@ -85,6 +84,8 @@ export * from './typography/ResetWrapper';

export { withReset, codeCommon } from './typography/lib/common';

export { ClipboardCode } from './clipboard/ClipboardCode';

// eslint-disable-next-line prefer-destructuring
export const components = typography.components;

Expand Down
1 change: 1 addition & 0 deletions code/ui/manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
},
"devDependencies": {
"@fal-works/esbuild-plugin-global-externals": "^2.1.2",
"@storybook/addon-designs": "^7.0.0",
"@storybook/addons": "7.1.0-beta.2",
"@storybook/api": "7.1.0-beta.2",
"@storybook/channel-postmessage": "7.1.0-beta.2",
Expand Down
1 change: 1 addition & 0 deletions code/ui/manager/src/globals/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export default {
'Bar',
'Blockquote',
'Button',
'ClipboardCode',
'Code',
'DL',
'Div',
Expand Down
44 changes: 0 additions & 44 deletions code/ui/manager/src/settings/about.stories.jsx

This file was deleted.

39 changes: 39 additions & 0 deletions code/ui/manager/src/settings/about.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { Meta, StoryObj } from '@storybook/react';
import React from 'react';
import { AboutScreen } from './about';

const meta = {
component: AboutScreen,
title: 'Settings/AboutScreen',
decorators: [
(Story) => (
<div
style={{
position: 'relative',
height: '100vh',
width: '100vw',
}}
>
<Story />
</div>
),
],
} satisfies Meta<typeof AboutScreen>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
current: {
version: '7.0.1',
},
},
parameters: {
design: {
type: 'figma',
url: 'https://www.figma.com/file/ur4kydUbRqdDyfoZWzdiIw/Storybook-app?type=design&node-id=9564-120444&mode=design&t=0TPINZFpwgFQFQeX-4',
},
},
};
203 changes: 124 additions & 79 deletions code/ui/manager/src/settings/about.tsx
Original file line number Diff line number Diff line change
@@ -1,114 +1,159 @@
/* eslint-disable no-nested-ternary */
import type { FC } from 'react';
import React from 'react';
import semver from 'semver';
import React, { useState } from 'react';
import { styled } from '@storybook/theming';
import type { State } from '@storybook/manager-api';

import { StorybookIcon, SyntaxHighlighter, DocumentWrapper } from '@storybook/components';

import SettingsFooter from './SettingsFooter';
import { Button as BaseButton, Icons, Link, StorybookIcon } from '@storybook/components';

const Header = styled.header(({ theme }) => ({
marginBottom: 20,
fontSize: theme.typography.size.m3,
marginBottom: 32,
fontSize: theme.typography.size.l2,
color: theme.base === 'light' ? theme.color.darkest : theme.color.lightest,
fontWeight: theme.typography.weight.bold,
alignItems: 'center',
display: 'flex',

'> svg': {
height: 32,
height: 48,
width: 'auto',
marginRight: 8,
},
}));

const UpdateMessage = styled.div<{ status: 'positive' | 'negative' | string }>(
({ status, theme }) => {
if (status === 'positive') {
return { background: theme.background.positive, color: theme.color.positiveText };
}
if (status === 'negative') {
return { background: theme.background.negative, color: theme.color.negativeText };
}
return {
background: theme.base === 'light' ? '#EAF3FC' : theme.color.darkest,
color: theme.base === 'light' ? theme.color.darkest : theme.defaultText,
};
},
const Container = styled.div({
display: `flex`,
alignItems: 'center',
justifyContent: 'center',
height: 'calc(100% - 40px)',
flexDirection: 'column',
});

({ theme }) => ({
fontWeight: theme.typography.weight.bold,
const UpgradeBlock = styled.div(({ theme }) => {
return {
border: '1px solid',
borderRadius: 5,
padding: 20,
margin: 20,
maxWidth: 400,
borderColor: theme.appBorderColor,
fontSize: theme.typography.size.s2,
padding: '10px 20px',
marginBottom: 24,
borderRadius: theme.appBorderRadius,
border: `1px solid ${theme.appBorderColor}`,
textAlign: 'center',
})
);
};
});

const Upgrade = styled.div(({ theme }) => ({
marginTop: 20,
borderTop: `1px solid ${theme.appBorderColor}`,
const Code = styled.pre(({ theme }) => ({
background: theme.base === 'light' ? 'rgba(0, 0, 0, 0.05)' : theme.appBorderColor,
fontSize: theme.typography.size.s2 - 1,
margin: '4px 0 16px',
}));

const Container = styled.div({
padding: `3rem 20px`,
maxWidth: 600,
margin: '0 auto',
});
const Footer = styled.div(({ theme }) => ({
marginBottom: 24,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
color: theme.base === 'light' ? theme.color.dark : theme.color.lightest,
fontWeight: theme.typography.weight.regular,
fontSize: theme.typography.size.s2,
}));

const AboutScreen: FC<{
latest: State['versions']['latest'];
current: State['versions']['current'];
}> = ({ latest = null, current }) => {
const canUpdate = latest && semver.gt(latest.version, current.version);
const SquareButton = styled(BaseButton)(({ theme }) => ({
'&&': {
borderRadius: 4,
fontSize: '13px',
lineHeight: '14px',
color: theme.base === 'light' ? theme.color.darker : theme.color.lightest,
padding: '9px 12px',
svg: {
marginRight: 6,
},
},
}));

const TabButton = styled(BaseButton)<{ active: boolean }>(({ theme, active }) => ({
'&&': {
padding: 2,
paddingRight: 8,
margin: 0,
color: active
? theme.color.secondary
: theme.base === 'light'
? theme.color.dark
: theme.color.lightest,
},
}));

let updateMessage;
if (latest) {
if (canUpdate) {
updateMessage = (
<UpdateMessage status="positive">
Storybook {latest.version} is available. Upgrade from {current.version} now.
</UpdateMessage>
);
} else {
updateMessage = (
<UpdateMessage status="neutral">Looking good! You're up to date.</UpdateMessage>
);
}
} else {
updateMessage = (
<UpdateMessage status="negative">
Oops! The latest version of Storybook couldn't be fetched.
</UpdateMessage>
);
}
const StyledLink = styled(Link as any)(({ theme }) => ({
'&&': {
fontWeight: theme.typography.weight.bold,
color: theme.base === 'light' ? theme.color.dark : theme.color.light,
},
'&:hover': {
color: theme.base === 'light' ? theme.color.darkest : theme.color.lightest,
},
}));

const AboutScreen: FC<{
current: State['versions']['current'];
onNavigateToWhatsNew?: () => void;
}> = ({ current, onNavigateToWhatsNew }) => {
const [activeTab, setActiveTab] = useState<'npm' | 'pnpm'>('npm');
return (
<Container>
<div style={{ flex: '1' }} />
<Header>
<StorybookIcon />
Storybook {current.version}
<StorybookIcon /> Storybook
</Header>
<UpgradeBlock>
<strong>You are on Storybook {current.version}</strong>
<p>Run the following script to check for updates and upgrade to the latest version.</p>
<div>
<TabButton active={activeTab === 'npm'} onClick={() => setActiveTab('npm')}>
npm
</TabButton>
<TabButton active={activeTab === 'pnpm'} onClick={() => setActiveTab('pnpm')}>
pnpm
</TabButton>
</div>

{updateMessage}
<Code>
{activeTab === 'npm'
? 'npx storybook@latest upgrade'
: 'pnpm dlx storybook@latest upgrade'}
</Code>
{onNavigateToWhatsNew && (
// eslint-disable-next-line jsx-a11y/anchor-is-valid
<Link onClick={onNavigateToWhatsNew}>See what's new in Storybook</Link>
)}
</UpgradeBlock>

{canUpdate && (
<Upgrade>
<DocumentWrapper>
<p>
<b>Upgrade all Storybook packages to latest:</b>
</p>
<SyntaxHighlighter language="bash" copyable padded bordered>
npx storybook@latest upgrade
</SyntaxHighlighter>
</DocumentWrapper>
</Upgrade>
)}
<div style={{ flex: '1.2' }} />
<Footer>
<div style={{ marginBottom: 12 }}>
<SquareButton
isLink
outline
small
href="https://github.com/storybookjs/storybook"
style={{ marginRight: 12 }}
>
<Icons icon="github" style={{ display: 'inline', marginRight: 5 }} />
GitHub
</SquareButton>

<SettingsFooter />
<SquareButton isLink outline small href="https://storybook.js.org/docs">
<Icons icon="document" style={{ display: 'inline', marginRight: 5 }} />
Documentation
</SquareButton>
</div>
<div>
Open source software maintained by{' '}
<StyledLink href="https://www.chromatic.com/">Chromatic</StyledLink> and the{' '}
<StyledLink href="https://github.com/storybookjs/storybook/graphs/contributors">
Storybook Community
</StyledLink>
</div>
</Footer>
</Container>
);
};
Expand Down
Loading

0 comments on commit a13ac8a

Please sign in to comment.