From 4db854238245f40d56ab5ce67e4277613b28e394 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Fri, 7 Jul 2023 14:43:15 +0200 Subject: [PATCH] Implement new about page design --- code/ui/.storybook/main.ts | 1 + .../src/clipboard/ClipboardCode.tsx | 27 +++ code/ui/components/src/index.ts | 3 +- code/ui/manager/package.json | 1 + .../ui/manager/src/settings/about.stories.jsx | 44 ---- .../ui/manager/src/settings/about.stories.tsx | 39 +++ code/ui/manager/src/settings/about.tsx | 222 +++++++++++------- code/ui/manager/src/settings/about_page.tsx | 15 +- code/yarn.lock | 67 +++++- 9 files changed, 287 insertions(+), 132 deletions(-) create mode 100644 code/ui/components/src/clipboard/ClipboardCode.tsx delete mode 100644 code/ui/manager/src/settings/about.stories.jsx create mode 100644 code/ui/manager/src/settings/about.stories.tsx diff --git a/code/ui/.storybook/main.ts b/code/ui/.storybook/main.ts index 23a70dc16661..541b0f2c69e1 100644 --- a/code/ui/.storybook/main.ts +++ b/code/ui/.storybook/main.ts @@ -50,6 +50,7 @@ const config: StorybookConfig = { '@storybook/addon-essentials', '@storybook/addon-interactions', '@storybook/addon-storysource', + '@storybook/addon-designs', ], framework: { name: '@storybook/react-vite', diff --git a/code/ui/components/src/clipboard/ClipboardCode.tsx b/code/ui/components/src/clipboard/ClipboardCode.tsx new file mode 100644 index 000000000000..577a6674f5d4 --- /dev/null +++ b/code/ui/components/src/clipboard/ClipboardCode.tsx @@ -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} + +); diff --git a/code/ui/components/src/index.ts b/code/ui/components/src/index.ts index c654094f1b61..292a9c7067dd 100644 --- a/code/ui/components/src/index.ts +++ b/code/ui/components/src/index.ts @@ -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 @@ -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; diff --git a/code/ui/manager/package.json b/code/ui/manager/package.json index 1b4dd1152305..cb86ca81fd9f 100644 --- a/code/ui/manager/package.json +++ b/code/ui/manager/package.json @@ -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.1", "@storybook/api": "7.1.0-beta.1", "@storybook/channel-postmessage": "7.1.0-beta.1", diff --git a/code/ui/manager/src/settings/about.stories.jsx b/code/ui/manager/src/settings/about.stories.jsx deleted file mode 100644 index 7bb06a45ad0b..000000000000 --- a/code/ui/manager/src/settings/about.stories.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; -import { actions as createActions } from '@storybook/addon-actions'; - -import { AboutScreen } from './about'; - -const info = { - plain: `- upgrade webpack & babel to latest\n- new addParameters and third argument to .add to pass data to addons\n- added the ability to theme storybook\n- improved ui for mobile devices\n- improved performance of addon-knobs`, -}; - -export default { - component: AboutScreen, - title: 'Settings/AboutScreen', - decorators: [ - (storyFn) => ( -
- {storyFn()} -
- ), - ], -}; - -const actions = createActions('onClose'); - -export const UpToDate = () => ( - -); - -export const OldVersionRaceCondition = () => ( - -); - -export const NewVersionRequired = () => ( - -); - -export const FailedToFetchNewVersion = () => ( - -); diff --git a/code/ui/manager/src/settings/about.stories.tsx b/code/ui/manager/src/settings/about.stories.tsx new file mode 100644 index 000000000000..67fcabcf6667 --- /dev/null +++ b/code/ui/manager/src/settings/about.stories.tsx @@ -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) => ( +
+ +
+ ), + ], +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +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', + }, + }, +}; diff --git a/code/ui/manager/src/settings/about.tsx b/code/ui/manager/src/settings/about.tsx index fccd4ee15111..c6f3552d6117 100644 --- a/code/ui/manager/src/settings/about.tsx +++ b/code/ui/manager/src/settings/about.tsx @@ -1,114 +1,172 @@ +/* eslint-disable no-nested-ternary */ import type { FC } from 'react'; -import React from 'react'; -import semver from 'semver'; -import { styled } from '@storybook/theming'; +import React, { useState } from 'react'; +import { styled, typography } 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, 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', +}); + +export const UpgradeBlock = styled.div(({ theme }) => { + return { + border: '1px solid', + borderRadius: 5, + padding: 20, + margin: 20, + maxWidth: 400, + borderColor: theme.color.border, + fontSize: theme.typography.size.s2, + }; +}); + +const Code = styled.pre` + background: rgba(0, 0, 0, 0.05); + font-size: ${typography.size.s2 - 1}px; + margin: 4px 0 16px; +`; + +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, +})); + +export const Button = 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 Tab = styled(Button)<{ active: boolean }>(({ theme, active }) => ({ + '&&': { + padding: 2, + paddingRight: 8, + margin: 0, + color: active + ? theme.color.secondary + : theme.base === 'light' + ? theme.color.dark + : theme.color.lightest, }, +})); - ({ theme }) => ({ - fontWeight: theme.typography.weight.bold, +const BlueLinkButton = styled(Button)(({ theme }) => ({ + '&&': { + padding: 0, + paddingRight: 8, + margin: 0, + color: theme.color.secondary, 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}`, + fontWeight: theme.typography.weight.regular, + }, })); -const Container = styled.div({ - padding: `3rem 20px`, - maxWidth: 600, - margin: '0 auto', -}); +export const StyledA = styled.a(({ theme }) => ({ + '&&': { + textDecoration: 'none', + 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<{ - latest: State['versions']['latest']; current: State['versions']['current']; -}> = ({ latest = null, current }) => { - const canUpdate = latest && semver.gt(latest.version, current.version); - - let updateMessage; - if (latest) { - if (canUpdate) { - updateMessage = ( - - Storybook {latest.version} is available. Upgrade from {current.version} now. - - ); - } else { - updateMessage = ( - Looking good! You're up to date. - ); - } - } else { - updateMessage = ( - - Oops! The latest version of Storybook couldn't be fetched. - - ); - } - + onNavigateToWhatsNew?: () => void; +}> = ({ current, onNavigateToWhatsNew }) => { + const [activeTab, setActiveTab] = useState<'npm' | 'pnpm'>('npm'); return ( +
- - Storybook {current.version} + Storybook
+ + You are on Storybook {current.version} +

Run the following script to check for updates and upgrade to the latest version.

+
+ setActiveTab('npm')}> + npm + + setActiveTab('pnpm')}> + pnpm + +
+ + + {activeTab === 'npm' + ? 'npx storybook@latest upgrade' + : 'pnpm dlx storybook@latest upgrade'} + + {onNavigateToWhatsNew && ( + + See what's new in Storybook + + )} +
+ +
+
+
+ - {updateMessage} - - {canUpdate && ( - - -

- Upgrade all Storybook packages to latest: -

- - npx storybook@latest upgrade - -
-
- )} - - + +
+
+ Open source software maintained by{' '} + Chromatic and the{' '} + + Storybook Community + +
+
); }; diff --git a/code/ui/manager/src/settings/about_page.tsx b/code/ui/manager/src/settings/about_page.tsx index 34640957ad18..e20d89d5362a 100644 --- a/code/ui/manager/src/settings/about_page.tsx +++ b/code/ui/manager/src/settings/about_page.tsx @@ -1,7 +1,7 @@ import type { FC } from 'react'; -import React, { Component } from 'react'; +import React, { Component, useCallback } from 'react'; -import { type API, useStorybookApi } from '@storybook/manager-api'; +import { type API, useStorybookApi, useStorybookState } from '@storybook/manager-api'; import { AboutScreen } from './about'; @@ -20,10 +20,19 @@ class NotificationClearer extends Component<{ api: API; notificationId: string } const AboutPage: FC = () => { const api = useStorybookApi(); + const state = useStorybookState(); + const onNavigateToWhatsNew = useCallback(() => { + api.changeSettingsTab('whats-new'); + }, [api]); return ( - + ); }; diff --git a/code/yarn.lock b/code/yarn.lock index 7a0c69c10d4e..5662351e9b41 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -2922,6 +2922,27 @@ __metadata: languageName: node linkType: hard +"@figspec/components@npm:^1.0.1": + version: 1.0.1 + resolution: "@figspec/components@npm:1.0.1" + dependencies: + lit: ^2.1.3 + checksum: 74e2c4c6959355efc5d89f224b32ed8207c4885b7d4bbdc2c7c9de6e5ef3e5b80a553fc26ca51eac77b03b6414ec645b147ba64211cf1165e2bcce49ced67fc8 + languageName: node + linkType: hard + +"@figspec/react@npm:^1.0.0": + version: 1.0.3 + resolution: "@figspec/react@npm:1.0.3" + dependencies: + "@figspec/components": ^1.0.1 + "@lit-labs/react": ^1.0.2 + peerDependencies: + react: ^16.14.0 || ^17.0.0 || ^18.0.0 + checksum: d5bbb79e106f522f5b867d0f55de01391edd1011e3f5d5a966ac07a5fca75f499d1d4d40a6186cf0afdc4fc4b49d808eb5d4fcbaf1784401a1ace2865dbc19be + languageName: node + linkType: hard + "@gar/promisify@npm:^1.1.3": version: 1.1.3 resolution: "@gar/promisify@npm:1.1.3" @@ -3912,6 +3933,13 @@ __metadata: languageName: node linkType: hard +"@lit-labs/react@npm:^1.0.2": + version: 1.2.1 + resolution: "@lit-labs/react@npm:1.2.1" + checksum: c92364101348400a06c3eb45a6384ca7d47c32765fdcad892827b360d0bad6cef7916f9a17744f2f471a5da3d7d73750767b885fc1521cd5e5e724badb71f014 + languageName: node + linkType: hard + "@lit-labs/ssr-dom-shim@npm:^1.0.0, @lit-labs/ssr-dom-shim@npm:^1.1.0": version: 1.1.1 resolution: "@lit-labs/ssr-dom-shim@npm:1.1.1" @@ -3919,7 +3947,7 @@ __metadata: languageName: node linkType: hard -"@lit/reactive-element@npm:^1.3.0, @lit/reactive-element@npm:^1.4.0": +"@lit/reactive-element@npm:^1.3.0, @lit/reactive-element@npm:^1.4.0, @lit/reactive-element@npm:^1.6.0": version: 1.6.2 resolution: "@lit/reactive-element@npm:1.6.2" dependencies: @@ -5237,6 +5265,29 @@ __metadata: languageName: unknown linkType: soft +"@storybook/addon-designs@npm:^7.0.0": + version: 7.0.0 + resolution: "@storybook/addon-designs@npm:7.0.0" + dependencies: + "@figspec/react": ^1.0.0 + peerDependencies: + "@storybook/addon-docs": ^7.0.0 + "@storybook/addons": ^7.0.0 + "@storybook/components": ^7.0.0 + "@storybook/manager-api": ^7.0.0 + "@storybook/preview-api": ^7.0.0 + "@storybook/theming": ^7.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + checksum: 7e532334ddd94051e4ada81fffc75ad17f955e5c1a2b1c03a7c6895000b1bade18906069497e4e8cdad960da650273fd95ca9ed6f5cfaad365c4d60bd640438a + languageName: node + linkType: hard + "@storybook/addon-docs@7.1.0-beta.1, @storybook/addon-docs@workspace:*, @storybook/addon-docs@workspace:addons/docs": version: 0.0.0-use.local resolution: "@storybook/addon-docs@workspace:addons/docs" @@ -6509,6 +6560,7 @@ __metadata: resolution: "@storybook/manager@workspace:ui/manager" dependencies: "@fal-works/esbuild-plugin-global-externals": ^2.1.2 + "@storybook/addon-designs": ^7.0.0 "@storybook/addons": 7.1.0-beta.1 "@storybook/api": 7.1.0-beta.1 "@storybook/channel-postmessage": 7.1.0-beta.1 @@ -20582,7 +20634,7 @@ __metadata: languageName: node linkType: hard -"lit-element@npm:^3.2.0": +"lit-element@npm:^3.2.0, lit-element@npm:^3.3.0": version: 3.3.2 resolution: "lit-element@npm:3.3.2" dependencies: @@ -20613,6 +20665,17 @@ __metadata: languageName: node linkType: hard +"lit@npm:^2.1.3": + version: 2.7.6 + resolution: "lit@npm:2.7.6" + dependencies: + "@lit/reactive-element": ^1.6.0 + lit-element: ^3.3.0 + lit-html: ^2.7.0 + checksum: bfd629c6eff8e6086200d0c0904c7a20a4d1dab21d1016d40cc8591d00d972171537e8466ca4eae8c5f227f2c5d2ef2ab9a9fe3587e024a493c93614c928b6fe + languageName: node + linkType: hard + "load-json-file@npm:6.2.0": version: 6.2.0 resolution: "load-json-file@npm:6.2.0"