diff --git a/examples/with-storybook/.babelrc b/examples/with-storybook/.babelrc deleted file mode 100644 index 9fcef0394fdf0b..00000000000000 --- a/examples/with-storybook/.babelrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "presets": ["next/babel"], - "plugins": [] -} diff --git a/examples/with-storybook/.gitignore b/examples/with-storybook/.gitignore index 5f31e17fdd42c8..8f322f0d8f4957 100644 --- a/examples/with-storybook/.gitignore +++ b/examples/with-storybook/.gitignore @@ -25,13 +25,11 @@ yarn-debug.log* yarn-error.log* # local env files -.env.local -.env.development.local -.env.test.local -.env.production.local +.env*.local # vercel .vercel -# Storybook -/storybook-static +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/examples/with-storybook/.storybook/main.js b/examples/with-storybook/.storybook/main.js deleted file mode 100644 index 974c2f95aac9f5..00000000000000 --- a/examples/with-storybook/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../stories/*.stories.@(ts|tsx|js|jsx|mdx)'], - addons: ['@storybook/addon-links', '@storybook/addon-essentials'], -} diff --git a/examples/with-storybook/.storybook/main.ts b/examples/with-storybook/.storybook/main.ts new file mode 100644 index 00000000000000..85a041f8706785 --- /dev/null +++ b/examples/with-storybook/.storybook/main.ts @@ -0,0 +1,17 @@ +import type { StorybookConfig } from '@storybook/nextjs'; +const config: StorybookConfig = { + stories: ['../stories/**/*.mdx', '../stories/**/*.stories.@(js|jsx|ts|tsx)'], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + ], + framework: { + name: '@storybook/nextjs', + options: {}, + }, + docs: { + autodocs: 'tag', + }, +}; +export default config; diff --git a/examples/with-storybook/.storybook/preview.js b/examples/with-storybook/.storybook/preview.js deleted file mode 100644 index 2108b794032921..00000000000000 --- a/examples/with-storybook/.storybook/preview.js +++ /dev/null @@ -1,16 +0,0 @@ -export const parameters = { - options: { - storySort: (a, b) => { - // We want the Welcome story at the top - if (b[1].kind === 'Welcome') { - return 1 - } - - // Sort the other stories by ID - // https://github.com/storybookjs/storybook/issues/548#issuecomment-530305279 - return a[1].kind === b[1].kind - ? 0 - : a[1].id.localeCompare(b[1].id, { numeric: true }) - }, - }, -} diff --git a/examples/with-storybook/.storybook/preview.ts b/examples/with-storybook/.storybook/preview.ts new file mode 100644 index 00000000000000..8c2a141ca698dc --- /dev/null +++ b/examples/with-storybook/.storybook/preview.ts @@ -0,0 +1,15 @@ +import type { Preview } from '@storybook/react'; + +const preview: Preview = { + parameters: { + actions: { argTypesRegex: '^on[A-Z].*' }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, + }, +}; + +export default preview; diff --git a/examples/with-storybook/README.md b/examples/with-storybook/README.md index 7720759c589354..40602f3b7a5a7b 100644 --- a/examples/with-storybook/README.md +++ b/examples/with-storybook/README.md @@ -2,32 +2,28 @@ This example shows a default set up of Storybook. Also included in the example is a custom component included in both Storybook and the Next.js application. -### TypeScript - -As of v6.0, Storybook has built-in TypeScript support, so no configuration is needed. If you want to customize the default configuration, refer to the [TypeScript docs](https://storybook.js.org/docs/react/configure/typescript). - -## Preview - -Preview the example live on [StackBlitz](http://stackblitz.com/): - -[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/vercel/next.js/tree/canary/examples/with-storybook) - ## Deploy your own -Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example): +Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example) or preview live with [StackBlitz](https://stackblitz.com/github/vercel/next.js/tree/canary/examples/with-storybook) -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-storybook&project-name=with-storybook&repository-name=with-storybook) +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-storybook&project-name=with-storybook&repository-name=with-storybook) ## How to use -Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example: +Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example: ```bash npx create-next-app --example with-storybook with-storybook-app -# or +``` + +```bash yarn create next-app --example with-storybook with-storybook-app ``` +```bash +pnpm create next-app --example with-storybook with-storybook-app +``` + ### Run Storybook ```bash @@ -44,4 +40,4 @@ npm run build-storybook yarn build-storybook ``` -You can use [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) to deploy Storybook. Specify `storybook-static` as the output directory. +You can use [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) to deploy Storybook. Specify `storybook-static` as the output directory. \ No newline at end of file diff --git a/examples/with-storybook/app/api/hello/route.ts b/examples/with-storybook/app/api/hello/route.ts new file mode 100644 index 00000000000000..d1cc6ee25fedf4 --- /dev/null +++ b/examples/with-storybook/app/api/hello/route.ts @@ -0,0 +1,3 @@ +export async function GET(request: Request) { + return new Response('Hello, Next.js!') +} diff --git a/examples/with-storybook/app/favicon.ico b/examples/with-storybook/app/favicon.ico new file mode 100644 index 00000000000000..718d6fea4835ec Binary files /dev/null and b/examples/with-storybook/app/favicon.ico differ diff --git a/examples/with-storybook/app/globals.css b/examples/with-storybook/app/globals.css new file mode 100644 index 00000000000000..d4f491e152dd0a --- /dev/null +++ b/examples/with-storybook/app/globals.css @@ -0,0 +1,107 @@ +:root { + --max-width: 1100px; + --border-radius: 12px; + --font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono', + 'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro', + 'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace; + + --foreground-rgb: 0, 0, 0; + --background-start-rgb: 214, 219, 220; + --background-end-rgb: 255, 255, 255; + + --primary-glow: conic-gradient( + from 180deg at 50% 50%, + #16abff33 0deg, + #0885ff33 55deg, + #54d6ff33 120deg, + #0071ff33 160deg, + transparent 360deg + ); + --secondary-glow: radial-gradient( + rgba(255, 255, 255, 1), + rgba(255, 255, 255, 0) + ); + + --tile-start-rgb: 239, 245, 249; + --tile-end-rgb: 228, 232, 233; + --tile-border: conic-gradient( + #00000080, + #00000040, + #00000030, + #00000020, + #00000010, + #00000010, + #00000080 + ); + + --callout-rgb: 238, 240, 241; + --callout-border-rgb: 172, 175, 176; + --card-rgb: 180, 185, 188; + --card-border-rgb: 131, 134, 135; +} + +@media (prefers-color-scheme: dark) { + :root { + --foreground-rgb: 255, 255, 255; + --background-start-rgb: 0, 0, 0; + --background-end-rgb: 0, 0, 0; + + --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0)); + --secondary-glow: linear-gradient( + to bottom right, + rgba(1, 65, 255, 0), + rgba(1, 65, 255, 0), + rgba(1, 65, 255, 0.3) + ); + + --tile-start-rgb: 2, 13, 46; + --tile-end-rgb: 2, 5, 19; + --tile-border: conic-gradient( + #ffffff80, + #ffffff40, + #ffffff30, + #ffffff20, + #ffffff10, + #ffffff10, + #ffffff80 + ); + + --callout-rgb: 20, 20, 20; + --callout-border-rgb: 108, 108, 108; + --card-rgb: 100, 100, 100; + --card-border-rgb: 200, 200, 200; + } +} + +* { + box-sizing: border-box; + padding: 0; + margin: 0; +} + +html, +body { + max-width: 100vw; + overflow-x: hidden; +} + +body { + color: rgb(var(--foreground-rgb)); + background: linear-gradient( + to bottom, + transparent, + rgb(var(--background-end-rgb)) + ) + rgb(var(--background-start-rgb)); +} + +a { + color: inherit; + text-decoration: none; +} + +@media (prefers-color-scheme: dark) { + html { + color-scheme: dark; + } +} diff --git a/examples/with-storybook/app/layout.tsx b/examples/with-storybook/app/layout.tsx new file mode 100644 index 00000000000000..3d9d72318cec6f --- /dev/null +++ b/examples/with-storybook/app/layout.tsx @@ -0,0 +1,18 @@ +import './globals.css' + +export const metadata = { + title: 'Create Next App', + description: 'Generated by create next app', +} + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} diff --git a/examples/with-storybook/app/page.module.css b/examples/with-storybook/app/page.module.css new file mode 100644 index 00000000000000..9411a5e6f26a57 --- /dev/null +++ b/examples/with-storybook/app/page.module.css @@ -0,0 +1,229 @@ +.main { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + padding: 6rem; + min-height: 100vh; +} + +.description { + display: inherit; + justify-content: inherit; + align-items: inherit; + font-size: 0.85rem; + max-width: var(--max-width); + width: 100%; + z-index: 2; + font-family: var(--font-mono); +} + +.description a { + display: flex; + justify-content: center; + align-items: center; + gap: 0.5rem; +} + +.description p { + position: relative; + margin: 0; + padding: 1rem; + background-color: rgba(var(--callout-rgb), 0.5); + border: 1px solid rgba(var(--callout-border-rgb), 0.3); + border-radius: var(--border-radius); +} + +.code { + font-weight: 700; + font-family: var(--font-mono); +} + +.grid { + display: grid; + grid-template-columns: repeat(4, minmax(25%, auto)); + width: var(--max-width); + max-width: 100%; +} + +.card { + padding: 1rem 1.2rem; + border-radius: var(--border-radius); + background: rgba(var(--card-rgb), 0); + border: 1px solid rgba(var(--card-border-rgb), 0); + transition: background 200ms, border 200ms; +} + +.card span { + display: inline-block; + transition: transform 200ms; +} + +.card h2 { + font-weight: 600; + margin-bottom: 0.7rem; +} + +.card p { + margin: 0; + opacity: 0.6; + font-size: 0.9rem; + line-height: 1.5; + max-width: 30ch; +} + +.center { + display: flex; + justify-content: center; + align-items: center; + position: relative; + padding: 4rem 0; +} + +.center::before { + background: var(--secondary-glow); + border-radius: 50%; + width: 480px; + height: 360px; + margin-left: -400px; +} + +.center::after { + background: var(--primary-glow); + width: 240px; + height: 180px; + z-index: -1; +} + +.center::before, +.center::after { + content: ''; + left: 50%; + position: absolute; + filter: blur(45px); + transform: translateZ(0); +} + +.logo { + position: relative; +} +/* Enable hover only on non-touch devices */ +@media (hover: hover) and (pointer: fine) { + .card:hover { + background: rgba(var(--card-rgb), 0.1); + border: 1px solid rgba(var(--card-border-rgb), 0.15); + } + + .card:hover span { + transform: translateX(4px); + } +} + +@media (prefers-reduced-motion) { + .card:hover span { + transform: none; + } +} + +/* Mobile */ +@media (max-width: 700px) { + .content { + padding: 4rem; + } + + .grid { + grid-template-columns: 1fr; + margin-bottom: 120px; + max-width: 320px; + text-align: center; + } + + .card { + padding: 1rem 2.5rem; + } + + .card h2 { + margin-bottom: 0.5rem; + } + + .center { + padding: 8rem 0 6rem; + } + + .center::before { + transform: none; + height: 300px; + } + + .description { + font-size: 0.8rem; + } + + .description a { + padding: 1rem; + } + + .description p, + .description div { + display: flex; + justify-content: center; + position: fixed; + width: 100%; + } + + .description p { + align-items: center; + inset: 0 0 auto; + padding: 2rem 1rem 1.4rem; + border-radius: 0; + border: none; + border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25); + background: linear-gradient( + to bottom, + rgba(var(--background-start-rgb), 1), + rgba(var(--callout-rgb), 0.5) + ); + background-clip: padding-box; + backdrop-filter: blur(24px); + } + + .description div { + align-items: flex-end; + pointer-events: none; + inset: auto 0 0; + padding: 2rem; + height: 200px; + background: linear-gradient( + to bottom, + transparent 0%, + rgb(var(--background-end-rgb)) 40% + ); + z-index: 1; + } +} + +/* Tablet and Smaller Desktop */ +@media (min-width: 701px) and (max-width: 1120px) { + .grid { + grid-template-columns: repeat(2, 50%); + } +} + +@media (prefers-color-scheme: dark) { + .vercelLogo { + filter: invert(1); + } + + .logo { + filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70); + } +} + +@keyframes rotate { + from { + transform: rotate(360deg); + } + to { + transform: rotate(0deg); + } +} diff --git a/examples/with-storybook/app/page.tsx b/examples/with-storybook/app/page.tsx new file mode 100644 index 00000000000000..01946f7979e18f --- /dev/null +++ b/examples/with-storybook/app/page.tsx @@ -0,0 +1,102 @@ +import Image from 'next/image' +import { Inter } from 'next/font/google' +import styles from './page.module.css' + +const inter = Inter({ subsets: ['latin'] }) + +export default function Home() { + return ( +
+
+

+ Get started by editing  + app/page.tsx +

+
+ + By{' '} + Vercel Logo + +
+
+ +
+ Next.js Logo +
+ +
+ +

+ Docs -> +

+

+ Find in-depth information about Next.js features and API. +

+
+ + +

+ Learn -> +

+

+ Learn about Next.js in an interactive course with quizzes! +

+
+ + +

+ Templates -> +

+

Explore the Next.js 13 playground.

+
+ + +

+ Deploy -> +

+

+ Instantly deploy your Next.js site to a shareable URL with Vercel. +

+
+
+
+ ) +} diff --git a/examples/with-storybook/components/index.js b/examples/with-storybook/components/index.js deleted file mode 100644 index 8f5129010b9b0e..00000000000000 --- a/examples/with-storybook/components/index.js +++ /dev/null @@ -1,3 +0,0 @@ -export default function Home() { - return
Hello World
-} diff --git a/examples/with-storybook/next.config.js b/examples/with-storybook/next.config.js new file mode 100644 index 00000000000000..dafb0c88e961e6 --- /dev/null +++ b/examples/with-storybook/next.config.js @@ -0,0 +1,8 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + experimental: { + appDir: true, + }, +} + +module.exports = nextConfig diff --git a/examples/with-storybook/package.json b/examples/with-storybook/package.json index ceec9bcfecda8b..cdeaf72dce012d 100644 --- a/examples/with-storybook/package.json +++ b/examples/with-storybook/package.json @@ -1,26 +1,35 @@ { - "name": "with-storybook", - "version": "1.0.0", - "main": "index.js", + "name": "storybook-app", + "version": "0.1.0", + "private": true, "scripts": { - "dev": "next", + "dev": "next dev", "build": "next build", "start": "next start", - "storybook": "start-storybook -p 6006", - "build-storybook": "build-storybook -s public/", - "serve-storybook": "serve storybook-static" + "lint": "next lint", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build" }, "dependencies": { - "next": "latest", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "@types/node": "18.15.12", + "@types/react": "18.0.37", + "@types/react-dom": "18.0.11", + "next": "13.3.0", + "react": "18.2.0", + "react-dom": "18.2.0", + "typescript": "5.0.4" }, - "license": "MIT", "devDependencies": { - "@storybook/addon-essentials": "6.0.26", - "@storybook/addon-links": "6.0.26", - "@storybook/react": "6.0.26", - "babel-loader": "^8.0.5", - "serve": "11.3.2" + "@storybook/addon-essentials": "^7.0.6", + "@storybook/addon-interactions": "^7.0.6", + "@storybook/addon-links": "^7.0.6", + "@storybook/blocks": "^7.0.6", + "@storybook/nextjs": "^7.0.6", + "@storybook/react": "^7.0.6", + "@storybook/testing-library": "^0.0.14-next.2", + "storybook": "^7.0.6" + }, + "engines": { + "node": ">=16" } } diff --git a/examples/with-storybook/pages/index.js b/examples/with-storybook/pages/index.js deleted file mode 100644 index 37e7e01d2c6424..00000000000000 --- a/examples/with-storybook/pages/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import HelloWorld from '../components' - -export default function Home() { - return ( -
-

Simple Storybook Example

- -
- ) -} diff --git a/examples/with-storybook/public/next.svg b/examples/with-storybook/public/next.svg new file mode 100644 index 00000000000000..5174b28c565c28 --- /dev/null +++ b/examples/with-storybook/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/with-storybook/public/serve.json b/examples/with-storybook/public/serve.json deleted file mode 100644 index 0967ef424bce67..00000000000000 --- a/examples/with-storybook/public/serve.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/examples/with-storybook/public/vercel.svg b/examples/with-storybook/public/vercel.svg new file mode 100644 index 00000000000000..d2f84222734f27 --- /dev/null +++ b/examples/with-storybook/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/with-storybook/stories/Button.stories.ts b/examples/with-storybook/stories/Button.stories.ts new file mode 100644 index 00000000000000..eeb81284b44254 --- /dev/null +++ b/examples/with-storybook/stories/Button.stories.ts @@ -0,0 +1,46 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import { Button } from './Button'; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction +const meta: Meta = { + title: 'Example/Button', + component: Button, + tags: ['autodocs'], + argTypes: { + backgroundColor: { + control: 'color', + }, + }, +}; + +export default meta; +type Story = StoryObj; + +// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args +export const Primary: Story = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary: Story = { + args: { + label: 'Button', + }, +}; + +export const Large: Story = { + args: { + size: 'large', + label: 'Button', + }, +}; + +export const Small: Story = { + args: { + size: 'small', + label: 'Button', + }, +}; diff --git a/examples/with-storybook/stories/Button.tsx b/examples/with-storybook/stories/Button.tsx new file mode 100644 index 00000000000000..e3cb2f231141a4 --- /dev/null +++ b/examples/with-storybook/stories/Button.tsx @@ -0,0 +1,52 @@ +import React from 'react'; +import './button.css'; + +interface ButtonProps { + /** + * Is this the principal call to action on the page? + */ + primary?: boolean; + /** + * What background color to use + */ + backgroundColor?: string; + /** + * How large should the button be? + */ + size?: 'small' | 'medium' | 'large'; + /** + * Button contents + */ + label: string; + /** + * Optional click handler + */ + onClick?: () => void; +} + +/** + * Primary UI component for user interaction + */ +export const Button = ({ + primary = false, + size = 'medium', + backgroundColor, + label, + ...props +}: ButtonProps) => { + const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary'; + return ( + + ); +}; diff --git a/examples/with-storybook/stories/Header.stories.ts b/examples/with-storybook/stories/Header.stories.ts new file mode 100644 index 00000000000000..448685eab0eb91 --- /dev/null +++ b/examples/with-storybook/stories/Header.stories.ts @@ -0,0 +1,26 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { Header } from './Header'; + +const meta: Meta = { + title: 'Example/Header', + component: Header, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs + tags: ['autodocs'], + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout + layout: 'fullscreen', + }, +}; + +export default meta; +type Story = StoryObj; + +export const LoggedIn: Story = { + args: { + user: { + name: 'Jane Doe', + }, + }, +}; + +export const LoggedOut: Story = {}; diff --git a/examples/with-storybook/stories/Header.tsx b/examples/with-storybook/stories/Header.tsx new file mode 100644 index 00000000000000..dc3f3c19c31a8b --- /dev/null +++ b/examples/with-storybook/stories/Header.tsx @@ -0,0 +1,56 @@ +import React from 'react'; + +import { Button } from './Button'; +import './header.css'; + +type User = { + name: string; +}; + +interface HeaderProps { + user?: User; + onLogin: () => void; + onLogout: () => void; + onCreateAccount: () => void; +} + +export const Header = ({ user, onLogin, onLogout, onCreateAccount }: HeaderProps) => ( +
+
+
+ + + + + + + +

Acme

+
+
+ {user ? ( + <> + + Welcome, {user.name}! + +
+
+
+); diff --git a/examples/with-storybook/stories/Introduction.mdx b/examples/with-storybook/stories/Introduction.mdx new file mode 100644 index 00000000000000..7055076a527345 --- /dev/null +++ b/examples/with-storybook/stories/Introduction.mdx @@ -0,0 +1,230 @@ +import { Meta } from '@storybook/blocks'; +import Image from 'next/image'; + +import Code from './assets/code-brackets.svg'; +import Colors from './assets/colors.svg'; +import Comments from './assets/comments.svg'; +import Direction from './assets/direction.svg'; +import Flow from './assets/flow.svg'; +import Plugin from './assets/plugin.svg'; +import Repo from './assets/repo.svg'; +import StackAlt from './assets/stackalt.svg'; + + + + + +# Welcome to Storybook + +Storybook helps you build UI components in isolation from your app's business logic, data, and context. +That makes it easy to develop hard-to-reach states. Save these UI states as **stories** to revisit during development, testing, or QA. + +Browse example stories now by navigating to them in the sidebar. +View their code in the `stories` directory to learn how they work. +We recommend building UIs with a [**component-driven**](https://componentdriven.org) process starting with atomic components and ending with pages. + +
Configure
+ +
+ +
+ plugin +
+ + Presets for popular tools + Easy setup for TypeScript, SCSS and more. + +
+ +
+ Build +
+ + Build configuration + How to customize webpack and Babel + +
+ +
+ colors +
+ + Styling + How to load and configure CSS libraries + +
+ +
+ flow +
+ + Data + Providers and mocking for data libraries + +
+
+ +
Learn
+ +
+ +
+ repo +
+ + Storybook documentation + Configure, customize, and extend + +
+ +
+ direction +
+ + In-depth guides + Best practices from leading teams + +
+ +
+ code +
+ + GitHub project + View the source and add issues + +
+ +
+ comments +
+ + Discord chat + Chat with maintainers and the community + +
+
+ +
+ TipEdit the Markdown in stories/Introduction.mdx +
diff --git a/examples/with-storybook/stories/Page.stories.ts b/examples/with-storybook/stories/Page.stories.ts new file mode 100644 index 00000000000000..0e48941ab14969 --- /dev/null +++ b/examples/with-storybook/stories/Page.stories.ts @@ -0,0 +1,29 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { within, userEvent } from '@storybook/testing-library'; + +import { Page } from './Page'; + +const meta: Meta = { + title: 'Example/Page', + component: Page, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout + layout: 'fullscreen', + }, +}; + +export default meta; +type Story = StoryObj; + +export const LoggedOut: Story = {}; + +// More on interaction testing: https://storybook.js.org/docs/react/writing-tests/interaction-testing +export const LoggedIn: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const loginButton = await canvas.getByRole('button', { + name: /Log in/i, + }); + await userEvent.click(loginButton); + }, +}; diff --git a/examples/with-storybook/stories/Page.tsx b/examples/with-storybook/stories/Page.tsx new file mode 100644 index 00000000000000..ec054e81389573 --- /dev/null +++ b/examples/with-storybook/stories/Page.tsx @@ -0,0 +1,73 @@ +import React from 'react'; + +import { Header } from './Header'; +import './page.css'; + +type User = { + name: string; +}; + +export const Page: React.FC = () => { + const [user, setUser] = React.useState(); + + return ( +
+
setUser({ name: 'Jane Doe' })} + onLogout={() => setUser(undefined)} + onCreateAccount={() => setUser({ name: 'Jane Doe' })} + /> + +
+

Pages in Storybook

+

+ We recommend building UIs with a{' '} + + component-driven + {' '} + process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page + data in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at{' '} + + Storybook tutorials + + . Read more in the{' '} + + docs + + . +

+
+ Tip Adjust the width of the canvas with the{' '} + + + + + + Viewports addon in the toolbar +
+
+
+ ); +}; diff --git a/examples/with-storybook/stories/assets/code-brackets.svg b/examples/with-storybook/stories/assets/code-brackets.svg new file mode 100644 index 00000000000000..73de9477600103 --- /dev/null +++ b/examples/with-storybook/stories/assets/code-brackets.svg @@ -0,0 +1 @@ +illustration/code-brackets \ No newline at end of file diff --git a/examples/with-storybook/stories/assets/colors.svg b/examples/with-storybook/stories/assets/colors.svg new file mode 100644 index 00000000000000..17d58d516e149d --- /dev/null +++ b/examples/with-storybook/stories/assets/colors.svg @@ -0,0 +1 @@ +illustration/colors \ No newline at end of file diff --git a/examples/with-storybook/stories/assets/comments.svg b/examples/with-storybook/stories/assets/comments.svg new file mode 100644 index 00000000000000..6493a139f523ee --- /dev/null +++ b/examples/with-storybook/stories/assets/comments.svg @@ -0,0 +1 @@ +illustration/comments \ No newline at end of file diff --git a/examples/with-storybook/stories/assets/direction.svg b/examples/with-storybook/stories/assets/direction.svg new file mode 100644 index 00000000000000..65676ac2722946 --- /dev/null +++ b/examples/with-storybook/stories/assets/direction.svg @@ -0,0 +1 @@ +illustration/direction \ No newline at end of file diff --git a/examples/with-storybook/stories/assets/flow.svg b/examples/with-storybook/stories/assets/flow.svg new file mode 100644 index 00000000000000..8ac27db403c236 --- /dev/null +++ b/examples/with-storybook/stories/assets/flow.svg @@ -0,0 +1 @@ +illustration/flow \ No newline at end of file diff --git a/examples/with-storybook/stories/assets/plugin.svg b/examples/with-storybook/stories/assets/plugin.svg new file mode 100644 index 00000000000000..29e5c690c0a250 --- /dev/null +++ b/examples/with-storybook/stories/assets/plugin.svg @@ -0,0 +1 @@ +illustration/plugin \ No newline at end of file diff --git a/examples/with-storybook/stories/assets/repo.svg b/examples/with-storybook/stories/assets/repo.svg new file mode 100644 index 00000000000000..f386ee902c1fe3 --- /dev/null +++ b/examples/with-storybook/stories/assets/repo.svg @@ -0,0 +1 @@ +illustration/repo \ No newline at end of file diff --git a/examples/with-storybook/stories/assets/stackalt.svg b/examples/with-storybook/stories/assets/stackalt.svg new file mode 100644 index 00000000000000..9b7ad2743506eb --- /dev/null +++ b/examples/with-storybook/stories/assets/stackalt.svg @@ -0,0 +1 @@ +illustration/stackalt \ No newline at end of file diff --git a/examples/with-storybook/stories/button.css b/examples/with-storybook/stories/button.css new file mode 100644 index 00000000000000..dc91dc76370b78 --- /dev/null +++ b/examples/with-storybook/stories/button.css @@ -0,0 +1,30 @@ +.storybook-button { + font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 700; + border: 0; + border-radius: 3em; + cursor: pointer; + display: inline-block; + line-height: 1; +} +.storybook-button--primary { + color: white; + background-color: #1ea7fd; +} +.storybook-button--secondary { + color: #333; + background-color: transparent; + box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset; +} +.storybook-button--small { + font-size: 12px; + padding: 10px 16px; +} +.storybook-button--medium { + font-size: 14px; + padding: 11px 20px; +} +.storybook-button--large { + font-size: 16px; + padding: 12px 24px; +} diff --git a/examples/with-storybook/stories/button.stories.js b/examples/with-storybook/stories/button.stories.js deleted file mode 100644 index a8b486c538d106..00000000000000 --- a/examples/with-storybook/stories/button.stories.js +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react' -import { Button } from '@storybook/react/demo' - -export default { - title: 'Button', - argTypes: { onClick: { action: 'clicked' } }, -} - -const TemplateWithText = (args) => - -const TemplateWithEmoji = (args) => ( - -) - -export const withText = TemplateWithText.bind({}) - -withText.args = {} - -export const withSomeEmoji = TemplateWithEmoji.bind({}) - -withSomeEmoji.args = {} diff --git a/examples/with-storybook/stories/header.css b/examples/with-storybook/stories/header.css new file mode 100644 index 00000000000000..44c549da27ced7 --- /dev/null +++ b/examples/with-storybook/stories/header.css @@ -0,0 +1,32 @@ +.wrapper { + font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + padding: 15px 20px; + display: flex; + align-items: center; + justify-content: space-between; +} + +svg { + display: inline-block; + vertical-align: top; +} + +h1 { + font-weight: 700; + font-size: 20px; + line-height: 1; + margin: 6px 0 6px 10px; + display: inline-block; + vertical-align: top; +} + +button + button { + margin-left: 10px; +} + +.welcome { + color: #333; + font-size: 14px; + margin-right: 10px; +} diff --git a/examples/with-storybook/stories/helloWorld.stories.js b/examples/with-storybook/stories/helloWorld.stories.js deleted file mode 100644 index 1c524fc556c66f..00000000000000 --- a/examples/with-storybook/stories/helloWorld.stories.js +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react' -import HelloWorld from '../components' - -export default { title: 'Hello World' } - -export const simpleComponent = () => diff --git a/examples/with-storybook/stories/page.css b/examples/with-storybook/stories/page.css new file mode 100644 index 00000000000000..fb64fe46294386 --- /dev/null +++ b/examples/with-storybook/stories/page.css @@ -0,0 +1,69 @@ +section { + font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 24px; + padding: 48px 20px; + margin: 0 auto; + max-width: 600px; + color: #333; +} + +section h2 { + font-weight: 700; + font-size: 32px; + line-height: 1; + margin: 0 0 4px; + display: inline-block; + vertical-align: top; +} + +section p { + margin: 1em 0; +} + +section a { + text-decoration: none; + color: #1ea7fd; +} + +section ul { + padding-left: 30px; + margin: 1em 0; +} + +section li { + margin-bottom: 8px; +} + +section .tip { + display: inline-block; + border-radius: 1em; + font-size: 11px; + line-height: 12px; + font-weight: 700; + background: #e7fdd8; + color: #66bf3c; + padding: 4px 12px; + margin-right: 10px; + vertical-align: top; +} + +section .tip-wrapper { + font-size: 13px; + line-height: 20px; + margin-top: 40px; + margin-bottom: 40px; +} + +section .tip-wrapper svg { + display: inline-block; + height: 12px; + width: 12px; + margin-right: 4px; + vertical-align: top; + margin-top: 3px; +} + +section .tip-wrapper svg path { + fill: #1ea7fd; +} diff --git a/examples/with-storybook/stories/welcome.stories.js b/examples/with-storybook/stories/welcome.stories.js deleted file mode 100644 index 2466b9882ddfc9..00000000000000 --- a/examples/with-storybook/stories/welcome.stories.js +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' -import { linkTo } from '@storybook/addon-links' -import { Welcome } from '@storybook/react/demo' - -export default { title: 'Welcome' } - -export const toStorybook = () => diff --git a/examples/with-storybook/tsconfig.json b/examples/with-storybook/tsconfig.json new file mode 100644 index 00000000000000..e06a4454ab0627 --- /dev/null +++ b/examples/with-storybook/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/examples/with-storybook/vercel.json b/examples/with-storybook/vercel.json new file mode 100644 index 00000000000000..6ed08762802904 --- /dev/null +++ b/examples/with-storybook/vercel.json @@ -0,0 +1,4 @@ +{ + "framework": "storybook", + "buildCommand": "storybook build" +} diff --git a/packages/next-swc/native/next-swc.darwin-arm64.node b/packages/next-swc/native/next-swc.darwin-arm64.node new file mode 100644 index 00000000000000..ab37d725cdee77 Binary files /dev/null and b/packages/next-swc/native/next-swc.darwin-arm64.node differ