From bd7cc6ac385b9b6f2e200c58b83d5ebc7a742d79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 24 Mar 2023 23:22:49 +0900 Subject: [PATCH] docs: note about Storybook --- CONTRIBUTING.md | 84 +++++++++++++++++++ packages/frontend/.storybook/main.ts | 12 +-- .../src/components/MkCaptcha.stories.impl.ts | 2 + .../src/components/MkCaptcha.stories.ts | 30 +------ .../global/MkAvatar.stories.impl.ts | 1 - .../src/components/global/MkAvatar.stories.ts | 8 -- 6 files changed, 90 insertions(+), 47 deletions(-) create mode 100644 packages/frontend/src/components/MkCaptcha.stories.impl.ts diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 887d17961f..7f8ed0922f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -203,6 +203,90 @@ niraxは、Misskeyで使用しているオリジナルのフロントエンド vue-routerとの最大の違いは、niraxは複数のルーターが存在することを許可している点です。 これにより、アプリ内ウィンドウでブラウザとは個別にルーティングすることなどが可能になります。 +## Storybook + +Misskey uses [Storybook](https://storybook.js.org/) for UI development. + +### Setup + +```bash +cd path/to/packages/frontend +pnpm tsc -p .storybook && (node .storybook/generate.js & node .storybook/preload-locale.js & node .storybook/preload-theme.js) +``` + +### Run + +```bash +cd path/to/packages/frontend +pnpm storybook dev +``` + +### Usage + +When you create a new component (in this example, `MyComponent.vue`), the story file (`MyComponent.stories.ts`) will be automatically generated by the `.storybook/generate.js` script. +You can override the default story by creating a impl story file (`MyComponent.stories.impl.ts`). + +```ts +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +/* eslint-disable import/no-duplicates */ +import { StoryObj } from '@storybook/vue3'; +import MyComponent from './MyComponent.vue'; +export const Default = { + render(args) { + return { + components: { + MyComponent, + }, + setup() { + return { + args, + }; + }, + computed: { + props() { + return { + ...args, + }; + }, + }, + template: '', + }; + }, + args: { + foo: 'bar', + }, + parameters: { + layout: 'centered', + }, +} satisfies StoryObj; +``` + +If you want to opt-out from the automatic generation, create a `MyComponent.stories.impl.ts` file and add the following line to the file. + +```ts +import MyComponent from './MyComponent.vue'; +void MyComponent; +``` + +You can use msw to mock API requests in the storybook. Creating a `MyComponent.stories.msw.ts` file and add the following line to the file. + +```ts +import { rest } from 'msw'; +export const handlers = [ + rest.post('/api/notes/timeline', (req, res, ctx) => { + return res( + ctx.json({ + notes: [], + users: [], + hasNext: false, + }) + ); + }), +]; +``` + +Don't forget to re-run the `.storybook/generate.js` script after adding, editing, or removing the above files. + ## Notes ### How to resolve conflictions occurred at pnpm-lock.yaml? diff --git a/packages/frontend/.storybook/main.ts b/packages/frontend/.storybook/main.ts index 90cc57536f..c58b6f1d70 100644 --- a/packages/frontend/.storybook/main.ts +++ b/packages/frontend/.storybook/main.ts @@ -1,7 +1,6 @@ import { resolve } from 'node:path'; import type { StorybookConfig } from '@storybook/vue3-vite'; import { mergeConfig } from 'vite'; -import { getConfig } from '../vite.config'; const config = { stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], addons: [ @@ -22,18 +21,9 @@ const config = { disableTelemetry: true, }, async viteFinal(config, options) { - const { plugins, build: { rollupOptions, ...build }, ...original } = getConfig(); - console.dir(config, {depth:Infinity}); - console.dir(original, {depth:Infinity}); - const x = mergeConfig(config, { - ...original, - build, + return mergeConfig(config, { assetsInclude: [resolve(__dirname, '../node_modules/@tabler/icons-webfont/**/*.{css,eot,ttf,woff,woff2}')], - server: { - hmr: false, - }, }); - return x; }, } satisfies StorybookConfig; export default config; diff --git a/packages/frontend/src/components/MkCaptcha.stories.impl.ts b/packages/frontend/src/components/MkCaptcha.stories.impl.ts new file mode 100644 index 0000000000..6ac437a277 --- /dev/null +++ b/packages/frontend/src/components/MkCaptcha.stories.impl.ts @@ -0,0 +1,2 @@ +import MkCaptcha from './MkCaptcha.vue'; +void MkCaptcha; diff --git a/packages/frontend/src/components/MkCaptcha.stories.ts b/packages/frontend/src/components/MkCaptcha.stories.ts index 78db7287ae..680c0387cc 100644 --- a/packages/frontend/src/components/MkCaptcha.stories.ts +++ b/packages/frontend/src/components/MkCaptcha.stories.ts @@ -1,34 +1,10 @@ /* eslint-disable @typescript-eslint/explicit-function-return-type */ /* eslint-disable import/no-default-export */ -import { Meta, StoryObj } from '@storybook/vue3'; -import MkCaptcha from './MkCaptcha.vue'; +import { Meta } from '@storybook/vue3'; const meta = { title: 'components/MkCaptcha', component: MkCaptcha, } satisfies Meta; -export const Default = { - render(args) { - return { - components: { - MkCaptcha, - }, - setup() { - return { - args, - }; - }, - computed: { - props() { - return { - ...args, - }; - }, - }, - template: '', - }; - }, - parameters: { - layout: 'centered', - }, -} satisfies StoryObj; export default meta; +import MkCaptcha from './MkCaptcha.vue'; +void MkCaptcha; diff --git a/packages/frontend/src/components/global/MkAvatar.stories.impl.ts b/packages/frontend/src/components/global/MkAvatar.stories.impl.ts index ca3db80b2e..6de5768af8 100644 --- a/packages/frontend/src/components/global/MkAvatar.stories.impl.ts +++ b/packages/frontend/src/components/global/MkAvatar.stories.impl.ts @@ -1,5 +1,4 @@ /* eslint-disable @typescript-eslint/explicit-function-return-type */ -/* eslint-disable import/no-default-export */ /* eslint-disable import/no-duplicates */ import { StoryObj } from '@storybook/vue3'; import MkAvatar from './MkAvatar.vue'; diff --git a/packages/frontend/src/components/global/MkAvatar.stories.ts b/packages/frontend/src/components/global/MkAvatar.stories.ts index 6cd9ca0a9b..4d819982ee 100644 --- a/packages/frontend/src/components/global/MkAvatar.stories.ts +++ b/packages/frontend/src/components/global/MkAvatar.stories.ts @@ -7,7 +7,6 @@ const meta = { } satisfies Meta; export default meta; /* eslint-disable @typescript-eslint/explicit-function-return-type */ -/* eslint-disable import/no-default-export */ /* eslint-disable import/no-duplicates */ import { StoryObj } from '@storybook/vue3'; import MkAvatar from './MkAvatar.vue'; @@ -68,13 +67,6 @@ export const ProfilePageCat = { user: { ...ProfilePage.args.user, isCat: true, - // avatarUrl: 'https://millionlive-theaterdays.idolmaster-official.jp/assets/data/webp/common/footer/icon_app.png.webp', - // avatarUrl: 'https://cdn.imastodon.net/accounts/avatars/000/144/021/original/8137afa4114ab85f.png', - // avatarUrl: 'https://avatars.githubusercontent.com/u/4439005?v=4', - // avatarUrl: 'https://avatars.githubusercontent.com/u/7973572?v=4', - // avatarUrl: 'https://avatars.githubusercontent.com/u/6533808?v=4', - // avatarUrl: 'https://avatars.githubusercontent.com/u/7106976?v=4', - avatarUrl: 'https://avatars.githubusercontent.com/u/3396686?v=4', }, }, };